{"version":3,"file":"main.1e750bb052563c79.js","mappings":"g8BAAAA,0HAAwBA,uECYjB,IAAMC,gBAAe,MAAtB,MAAOA,iBAOXC,YAAoBC,GAAwCC,IAAxCC,uBAAwCA,eAN5DA,cAAU,EACVA,cAAU,EACVA,aAAS,EACTA,gBAAY,CAGiE,CAE7EC,WACED,KAAKD,OAAOG,OAAOC,QAAKC,+CAAWC,IAAML,KAAKM,yBAAyBD,MAAoBE,WAC7F,CAEMD,yBAAyBE,IAAiB,sJAC1CA,cAAgBC,kDACDD,GAAKE,MAAMC,KAAKC,YAAYJ,KAAKK,WACjCC,0DACfC,GAAKC,SAAU,GAEfD,GAAKC,SAAU,EACXD,GAAKE,SAAWF,GAAKG,cACjBH,GAAKI,gBACDJ,GAAKE,SAAWF,GAAKG,UAC/BH,GAAKG,SAAU,QACTH,GAAKK,eAGhB,EAd6C,EAehD,CAEcA,aAAU,sJACtB,MAAMC,GAAWC,GAAKxB,eAAeyB,kBAAkBC,SAEvD,QAAiBC,IAAbJ,GAAwB,CAC1B,MAAMK,EAAM,GAAGC,oFAAyCN,WAClDO,MAAMF,GACTG,KAAMC,GACEA,EAASC,QAEjBF,KAAI,yIAAC,UAAOE,GACXT,GAAKd,KAAOuB,EAAKC,QAAQ,SAAUX,UAC7BC,GAAKH,cACb,GAAC,mDAHI,GAGJ,CACJ,EAbqB,EAcxB,CAEcA,eAAY,0JACxB,QAAkBM,IAAdQ,OAAKzB,OAAuByB,OAAKhB,OAAQ,OACpCiB,KAAKD,OAAKzB,MAEjB,MAAM2B,qBAAuBC,SAASC,qBAAqB,UAC3D,GAAIF,qBAAqBG,OAAQ,CAC/B,MAAMC,GAAWC,YAAY,KAC0C,SAAjEC,iBAAiBN,qBAAqB,QAAIV,GAAWiB,UACvDT,OAAKU,WAAY,EACjBV,OAAKhB,QAAS,EACdgB,OAAKf,SAAU,EACf0B,cAAcL,IAAQ,EAEvB,GAAE,EAER,EAfuB,EAgB1B,CAACM,uDA9DUjD,kBAAekD,4SAAflD,iBAAemD,8GDZ5BpD,yGAASA,ovCCYIC,gBAAe,+HCFrB,IAAMoD,GAAgB,MAAvB,MAAOA,EAPbnD,cAQWG,UAAgB,GAC1B6C,kDAFYG,EAAgB,sCAAhBA,EAAgBD,iKCV7BpD,sBAAqBA,mEDQTsD,KAAYC,wfAEXF,CAAgB,qDERtB,MAAMG,EAA8B,CACzCC,MAAO,CAAEC,GAAI,KAAMC,GAAI,SACvBC,WAAY,CAAEF,GAAI,cAAeC,GAAI,cACrCE,WAAY,CAAEH,GAAI,WAAYC,GAAI,cAClCG,gBAAiB,CAAEJ,GAAI,cAAeC,GAAI,mBAC1CI,YAAa,CAAEL,GAAI,sBAAuBC,GAAI,eAC9CK,YAAa,CAAEN,GAAI,QAASC,GAAI,eAChCM,OAAQ,CAAEP,GAAI,MAAOC,GAAI,UACzBO,WAAY,CAAER,GAAI,QAASC,GAAI,cAC/BQ,MAAO,CAAET,GAAI,SAAUC,GAAI,SAC3BS,QAAS,CAAEV,GAAI,UAAWC,GAAI,WAC9BU,YAAa,CAAEX,GAAI,eAAgBC,GAAI,eACvCW,mBAAoB,CAAEZ,GAAI,mBAAoBC,GAAI,sBAClDY,QAAS,CAAEb,GAAI,UAAWC,GAAI,WAC9Ba,iBAAkB,CAAEd,GAAI,gBAAiBC,GAAI,oBAC7Cc,UAAW,CAAEf,GAAI,aAAcC,GAAI,aACnCe,UAAW,CAAEhB,GAAI,YAAaC,GAAI,aAClCgB,KAAM,CAAEjB,GAAI,OAAQC,GAAI,QACxBiB,QAAS,CAAElB,GAAI,UAAWC,GAAI,WAC9BkB,OAAQ,CAAEnB,GAAI,QAASC,GAAI,UAC3BmB,UAAW,CAAEpB,GAAI,YAAaC,GAAI,aAClCoB,OAAQ,CAAErB,GAAI,aAAcC,GAAI,UAChCqB,aAAc,CAAEtB,GAAI,YAAaC,GAAI,aACrCsB,cAAe,CAAEvB,GAAI,iBAAkBC,GAAI,iBAC3CuB,OAAQ,CAAExB,GAAI,WAAYC,GAAI,UAC9BwB,UAAW,CAAEzB,GAAI,QAASC,GAAI,aAC9ByB,OAAQ,CAAE1B,GAAI,aAAcC,GAAI,UAChC0B,KAAM,CAAE3B,GAAI,OAAQC,GAAI,QACxB2B,KAAM,CAAE5B,GAAI,QAASC,GAAI,QACzB4B,cAAe,CAAE7B,GAAI,iBAAkBC,GAAI,gBAC3C6B,YAAa,CAAE9B,GAAI,aAAcC,GAAI,eACrC8B,KAAM,CAAE/B,GAAI,QAASC,GAAI,QACzB+B,KAAM,CAAEhC,GAAI,OAAQC,GAAI,QACxBgC,MAAO,CAAEjC,GAAI,WAAYC,GAAI,SAC7BiC,cAAe,CAAElC,GAAI,cAAeC,GAAI,iBACxCkC,YAAa,CAAEnC,GAAI,SAAUC,GAAI,UACjCmC,QAAS,CAAEpC,GAAI,OAAQC,GAAI,WAC3BoC,OAAQ,CAAErC,GAAI,YAAaC,GAAI,UAC/BqC,SAAU,CAAEtC,GAAI,MAAOC,GAAI,YAC3BsC,IAAK,CAAEvC,GAAI,MAAOC,GAAI,OACtBuC,MAAO,CAAExC,GAAI,UAAWC,GAAI,SAC5BwC,OAAQ,CAAEzC,GAAI,QAASC,GAAI,UAC3ByC,OAAQ,CAAE1C,GAAI,UAAWC,GAAI,UAC7B0C,QAAS,CAAE3C,GAAI,aAAcC,GAAI,WACjC2C,KAAM,CAAE5C,GAAI,MAAOC,GAAI,QACvB4C,QAAS,CAAE7C,GAAI,UAAWC,GAAI,4DC/CzB,IAAK6C,EAMX,aANWA,QAAmB,KAC7BA,YACAA,mCACAA,+BACAA,sBACAA,YALUA,EAAZ,IAAYA,GAMX,oDCNM,IAAKC,EAqBX,aArBWA,QAAe,KACzBA,kBACAA,gBACAA,4BACAA,0BACAA,gBACAA,4BACAA,oBACAA,cACAA,0BACAA,gBACAA,4BACAA,wBACAA,kBACAA,kBACAA,kBACAA,wBACAA,wBACAA,0BACAA,gCACAA,sBApBUA,EAAZ,IAAYA,GAqBX,oDCrBM,IAAKC,EAmBX,aAnBWA,QAAa,KACvBA,sCACAA,0CACAA,kBACAA,kBACAA,kBACAA,oBACAA,kBACAA,gCACAA,sCACAA,0BACAA,wBACAA,gCACAA,oBACAA,sBACAA,8BACAA,4BACAA,4BACAA,oBAlBUA,EAAZ,IAAYA,GAmBX,oDCnBM,IAAKC,EAgIX,aAhIWA,QAAQ,KAClBA,eACAA,cAGAA,kBAGAA,gCACAA,mCACAA,gCACAA,kCACAA,kCACAA,oCACAA,sCACAA,0CAEAA,gCACAA,kCACAA,kCACAA,sCACAA,0CAEAA,wBACAA,0BACAA,0BACAA,8BACAA,kCACAA,gCACAA,8BACAA,kCAGAA,gCACAA,sCAGAA,sCAGAA,+CACAA,4DAGAA,oCACAA,0BAEAA,gDACAA,0CAEAA,4DAGAA,mDACAA,6DACAA,uCAGAA,8DACAA,kEACAA,gDACAA,4DACAA,4EAKAA,oCACAA,oDACAA,oDACAA,wDACAA,oCACAA,wCACAA,wCACAA,4DACAA,4DAGAA,kCACAA,wCACAA,wCAGAA,wBACAA,kDACAA,wCAGAA,wCAGAA,4CACAA,0CACAA,oCACAA,4CACAA,wDACAA,sEACAA,wCACAA,wCACAA,wCACAA,sCACAA,0CACAA,gDAGAA,sDACAA,8DACAA,8EACAA,4FAGAA,oCACAA,wCACAA,kCAGAA,sCACAA,kCACAA,8BACAA,8BACAA,wCACAA,8CACAA,oCACAA,sCACAA,4CACAA,mDACAA,4CACAA,gCA/HUA,EAAZ,IAAYA,GAgIX,oDChIM,IAAKC,EAEX,OAFWA,MAAU,KACpBA,YADUA,GAEX,mDCFM,IAAKC,EAKX,aALWA,QAAY,KACtBA,kBACAA,cACAA,gBACAA,oBAJUA,EAAZ,IAAYA,GAKX,4DCLM,IAAK1F,EA0CX,aA1CWA,QAAY,KAEtBA,sBACAA,4BAGAA,iCACAA,gDACAA,wCACAA,qCACAA,2BAGAA,6BACAA,iCACAA,gDACAA,uBACAA,qBACAA,cACAA,mCACAA,0CACAA,0CACAA,4CACAA,4CAGAA,yBACAA,wCACAA,+BACAA,8CACAA,oCAGAA,0DACAA,2CAGAA,sCAGAA,gBACAA,uBAzCUA,EAAZ,IAAYA,GA0CX,GAEW2F,EAMX,aANWA,QAAkB,KAC5BA,gBACAA,cACAA,0BACAA,sBACAA,oBALUA,EAAZ,IAAYA,GAMX,oDClDM,IAAKC,EAMX,aANWA,QAAkB,KAC5BA,UACAA,YACAA,cACAA,gBACAA,0BALUA,EAAZ,IAAYA,GAMX,oDCNM,IAAKC,EAQX,aARWA,QAAe,KACzBA,oBACAA,4BACAA,wBACAA,kBACAA,UACAA,sBACAA,gBAPUA,EAAZ,IAAYA,GAQX,oDCRM,IAAKC,EAOX,aAPWA,QAAmB,KAC7BA,cACAA,gBACAA,oBACAA,kBACAA,gBACAA,gBANUA,EAAZ,IAAYA,GAOX,oDCPM,IAAKC,EAkDX,aAlDWA,QAAe,KACzBA,gDACAA,8CAEAA,uCAEAA,2BAEAA,2BACAA,+BACAA,uBAEAA,UACAA,UACAA,UACAA,UACAA,uBACAA,oDACAA,sBACAA,gBACAA,gBACAA,gCACAA,mDACAA,iDACAA,sCACAA,iDACAA,mCACAA,mDACAA,+BACAA,oCAGAA,mCACAA,+DAGAA,2BACAA,uCACAA,6BAGAA,qCACAA,+BAGAA,gCACAA,2BAGAA,sBAjDUA,EAAZ,IAAYA,GAkDX,2DClDM,IAAKC,EAKX,aALWA,QAAmB,KAC7BA,uBACAA,gBACAA,kBACAA,gBAJUA,EAAZ,IAAYA,GAKX,GAEWC,EAIX,aAJWA,QAAmB,KAC7BA,YACAA,gBACAA,kBAHUA,EAAZ,IAAYA,GAIX,kECPM,IAAMC,EAAwB,MAA/B,MAAOA,EACXC,OAAOC,GACL,GAAIA,EAAOC,kBAAmB,CAC5B,MACMC,EAAQF,EAAOC,kBAAqC,QAC1D,YAAc1F,IAAV2F,EACK,GAEFA,GAASF,EAAOG,IAEzB,OAAOH,EAAOG,GAChB,CAACxE,kDAXUmE,EAAwB,wCAAxBA,EAAwBM,QAAxBN,EAAwB,mBAAxBA,CAAwB,6GCQ9B,IAAMO,EAAc,MAArB,MAAOA,EACX1H,YAAoB2H,qBAA2B,CAE/CC,oBAAoBC,EAA4BC,GAS9C,MAR4B,CAC1BC,eAAgB,CACdC,KAAMhB,iBACNiB,iBAAkB,GAEpBC,MAAOL,EAIX,CAEAM,qBAAqBN,EAA2CC,EAAuBM,GACrF,MAAMC,EAAyB,GAE/B,IAAKR,EAEH,OAAOQ,EAET,UAAWC,MAAQT,EACjBQ,EAAOE,KAAK,CACVC,GAAIF,GAAKG,GACTC,MAAOJ,GAAKK,MACZC,SAAUN,GAAKO,SACfC,YAAa3I,KAAKwH,YAAYoB,QAAQT,GAAKU,aAC3CC,MAAOX,GAAKY,MACZC,IAAK,GAAGrH,oBAA4BwG,GAAKzG,MAAMuG,GAAe,KAC9DgB,gBAAgB,EAChBC,WAAY9C,eACZ+C,aAAYxB,EACZyB,MAAOjB,GAAKkB,QAIhB,YAAK5B,oBAAoBS,EAAQP,GAE1BO,CACT,CAEAoB,mBAAmB5B,EAAyCC,EAAuBM,GACjF,MAAMC,EAAyB,GAC/BR,EAAW6B,QAASC,KAClB,MAAMrB,GAAqB,CACzBE,GAAImB,GAAgBC,SAASnB,GAC7BQ,MAAOU,GAAgBC,SAASV,MAChCC,IAAK,GAAGrH,oBAA4B6H,GAAgBC,SAAS/H,MAAMuG,GAAe,KAClFU,YAAaa,GAAgBC,SAASZ,YACtCa,MAAOF,GAAgBC,SAASE,MAChClB,SAAUe,GAAgBC,SAASf,SACnCH,MAAOiB,GAAgBC,SAASjB,MAChC1C,OAAQ0D,GAAgBC,SAASG,OACjCR,MAAOI,GAAgBC,SAASJ,MAChCrD,QAASwD,GAAgBC,SAASI,QAClC9E,OAAQyE,GAAgBC,SAASK,OACjCC,SAAUP,GAAgBQ,OAC1Bb,aAAYxB,EACZsB,iBAAgBtB,EAChBuB,WAAY9C,gBAGd8B,EAAOE,KAAKD,GAAI,GAElB,MAAMA,GAAsB,CAC1BP,eAAgB,CACdC,KAAMhB,iBACNiB,iBAAkB,GAEpBC,MAAOG,GAGT,YAAKT,oBAAoBS,EAAQP,GAE1BQ,EACT,CAACtF,kDA5EU0E,GAAc0C,qDAAd1C,EAAcD,QAAdC,EAAc,qBAFb,gBAEDA,CAAc,oECLpB,IAAM2C,EAAoB,MAA3B,MAAOA,EACXC,yBAAyBC,GACvB,MAAMlC,EAA4B,GAClC,GAAIkC,GAAa9H,OACf,UAAW+H,KAAcD,EACvBlC,EAAOE,KAAK,CACVC,GAAIgC,EAAWhC,GACfiC,OAAQ,CACNjC,GAAIgC,EAAWE,QAAQlC,GACvBmC,KAAMH,EAAWE,QAAQC,KACzB3C,KAAMwC,EAAWxC,MAEnB4C,MAAO,CACLpC,GAAIgC,EAAWK,WAAWrC,GAC1BS,MAAOuB,EAAWK,WAAW5B,MAC7BH,YAAa0B,EAAWK,WAAW/B,YACnCgC,UAAWN,EAAWK,WAAWC,UACjCC,SAAUP,EAAWK,WAAWE,SAChCC,KAAMR,EAAWK,WAAWG,KAC5BhD,KAAMwC,EAAWK,WAAW7C,KAC5BiD,WAAYT,EAAWK,WAAWI,YAEpChC,MAAOuB,EAAWvB,MAClBiC,KAAM,GACNC,MAAOX,EAAWW,MAClBjH,aAAStC,EACT0H,WAAYkB,EAAWlB,aAI7B,OAAOjB,CACT,CAACrF,kDA/BUqH,EAAoB,wCAApBA,EAAoB5C,QAApB4C,EAAoB,qBAFnB,gBAEDA,CAAoB,oECA1B,IAAMe,EAAoB,MAA3B,MAAOA,EACXC,4BAA4BC,EAA2BC,GACrD,MAAMlD,EAAoC,GAC1C,UAAWC,KAAQgD,EACjBjD,EAAOE,KAAK,CACViD,KAAMlD,EAAKkD,KACXvC,MAAOX,EAAKW,MACZiC,KAAM5C,EAAK4C,KACXO,SAAUF,GAAUG,KAAMC,GAAYA,EAAQH,OAASlD,EAAKkD,QAAS,IAIzE,OAAOnD,CACT,CAEAuD,QAAQC,GACN,OAAOA,GAAcC,IAAKtL,GAAML,KAAK2L,IAAItL,GAC3C,CAEAsL,IAAIC,GACF,MAAO,CACLvD,GAAIuD,EAAYtD,GAChBQ,MAAO8C,EAAY7C,MACnBsC,KAAMO,EAAYC,KAClBd,KAAMa,EAAYE,KAEtB,CAACjJ,kDA1BUoI,EAAoB,wCAApBA,EAAoB3D,QAApB2D,EAAoB,qBAFnB,gBAEDA,CAAoB,sHCU1B,IAAMc,EAAiB,MAAxB,MAAOA,EACXlM,YACUmM,EACAC,EACAC,GAFAlM,qBACAA,kBACAA,yBACP,CAEHmM,iBAAiBC,GACf,MAAMlE,EAA2B,GACjC,GAAIkE,EAAO9J,OACT,UAAW+J,KAASD,EACd/F,IAAcgG,EAAMC,OAAuCD,EAAME,MAAMjK,SAIzE+J,EAAME,MAAQF,EAAME,MAAMC,OACvBrE,IACEkE,EAAMC,OAASjG,kBAA2D,SAA7B8B,GAAKsE,MAAMC,eACzDL,EAAMC,OAASjG,kBAEnB6B,EAAOE,KAAK,CACVU,MAAO,aAAauD,EAAMC,OAC1BK,SAAUxJ,IAAakJ,EAAMC,OAAoChJ,GACjEuE,KAAMxB,IAAcgG,EAAMC,MAC1BvE,MAAOsE,EAAME,MAAMZ,IAAKxD,KACtB,IAAIyE,GACJ,OACEA,GADEP,EAAMC,OAASjG,kBACH,CACZyC,MAAO9I,KAAKkM,mBAAmBW,QAAQ,mBAAmB1E,GAAKsE,SAC/DK,MAAO3E,GAAKd,IACZ0F,MAAO5E,GAAK6E,MACZ1B,SAAUnD,GAAKiD,UAERiB,EAAMC,OAASjG,iBACV,CACZyC,MAAO9I,KAAKkM,mBAAmBW,QAAQ,sBACvCC,MAAO3E,GAAKd,IACZ0F,MAAO5E,GAAK6E,MACZ1B,SAAUnD,GAAKiD,UAGH,CACZtC,MAAOX,GAAKsE,MACZK,MAAO3E,GAAKd,IACZ0F,MAAO5E,GAAK6E,MACZ1B,SAAUnD,GAAKiD,UAGZwB,KAETxH,OAAMpF,KAAKgM,cAAciB,mCACvB9J,IAAakJ,EAAMC,MACnBnJ,aAQV,OAAO+E,CACT,CAEAgF,uBAAuBC,EAAeC,GACpC,MAAMlF,EAA8B,CAClCmF,YAAa,GACbnJ,QAAS,GACToJ,MAAO,GACPC,gBAAiB,IAEnB,GAAIH,EAAaI,kBACf,UAAWrF,MAAQiF,EAAaI,kBAC1BrF,GAAKsF,gBAAkBN,GACzBjF,EAAOmF,YAAYjF,KAAKD,GAAKsF,eAInC,GAAIL,EAAaM,YACf,UAAWvF,MAAQiF,EAAaM,YAC9B,GAAIvF,GAAKwF,KAAM,CACb,MAAMA,GAAO3N,KAAKiM,WAAW2B,gBAAgBzF,GAAKwF,MAClDzF,EAAOoF,MAAMlF,KAAKuF,GAAI,CAK5B,OAAOzF,CACT,CAACrF,kDAvFUkJ,GAAiB9B,2EAAjB8B,EAAiBzE,QAAjByE,EAAiB,qBAFhB,gBAEDA,CAAiB,oECjBlB8B,EAKX,aALWA,QAAkB,KAC5BA,UACAA,YACAA,YACAA,gBAJUA,EAAZ,IAAYA,GAKX,wBCKM,IAAMC,EAAsB,MAA7B,MAAOA,EACXjO,YAAoBkO,EAAwCC,GAAxChO,sBAAwCA,gBAA8B,CAE1FiO,yBAAyBC,GACvB,MAAMhG,EAAqB,GAC3B,IAAIiG,GACJ,GAAInO,KAAK+N,eAAeK,WAAY,CAClC,IAAIC,GACAH,EAAa5L,SACf6L,GAAID,EAAaI,KAAMnG,IAASA,GAAKN,OAASgG,OAC9CQ,GAAIH,EAAaI,KAAMnG,IAASA,GAAKN,OAASgG,QAG5CM,IACFjG,EAAOE,KAAKpI,KAAKuO,WAAWJ,GAAGN,QAG7BQ,IACFnG,EAAOE,KAAKpI,KAAKuO,WAAWF,GAAGR,OAAuB,MAE/C7N,KAAK+N,eAAeS,gBACzBN,EAAa5L,SACf6L,GAAID,EAAaI,KAAMnG,IAASA,GAAKN,OAASgG,UAE5CM,IACFjG,EAAOE,KAAKpI,KAAKuO,WAAWJ,GAAGN,WAGnC,OAAO3F,CACT,CAEAuG,0BAA0BP,GACxB,IAAKA,GAAwC,IAAxBA,EAAa5L,OAChC,MAAO,GAGT,MAAM4F,EAAqB,GAC3B,GAAIlI,KAAK+N,eAAeK,WAAY,CAClC,MAAMM,GAASR,EAAaI,KAAMnG,IAASA,GAAKmE,OAASuB,OACnDc,GAAST,EAAaI,KAAMnG,IAASA,GAAKmE,OAASuB,OAErDa,IACFxG,EAAOE,KAAKpI,KAAK4O,YAAYF,GAAQb,QAEnCc,IACFzG,EAAOE,KAAKpI,KAAK4O,YAAYD,GAAQd,OAAuB,SAErD7N,KAAK+N,eAAeS,cAAe,CAC5C,MAAMK,GAASX,EAAaI,KAAMnG,IAASA,GAAKmE,OAASuB,SAErDgB,IACF3G,EAAOE,KAAKpI,KAAK4O,YAAYC,GAAQhB,SAAyB,CAGlE,OAAO3F,CACT,CAEAqG,WAAW/C,EAAmBc,GAC5B,GAAId,EAAS,CACX,MAAMsD,GAAatD,EAAQ1C,MAAMiG,MAAM,KACvC,GAAID,GAAWxM,OAAQ,CACrB,MAAMyG,GAAQ+F,GAAW,GACnBrC,GAAQqC,GAAW,IAAM,IAC/B,MAAO,CACLhG,MAAO9I,KAAKgO,UAAUnB,QAAQ,kBAAkB9D,KAAS,CACvDiG,QAASjG,KAEX+D,MAAOL,GACP5E,KAAM2D,EAAQ3D,OAIpB,MAAO,CACLiB,MAAOwD,EACPQ,MAAO,IACPjF,KAAMyE,EAEV,CAEAsC,YAAYpD,EAAoBc,GAC9B,GAAId,EAAS,CACX,MAAMsD,GAAatD,EAAQzC,MAAMgG,MAAM,KACvC,GAAID,GAAWxM,OAAQ,CACrB,MAAMyG,GAAQ+F,GAAW,GACnBrC,GAAQqC,GAAW,IAAM,IAC/B,MAAO,CACLhG,MAAO9I,KAAKgO,UAAUnB,QAAQ,kBAAkB9D,KAAS,CACvDiG,QAASjG,KAEX+D,MAAOL,GACP5E,KAAM2D,EAAQc,OAIpB,MAAO,CACLxD,MAAOwD,EACPQ,MAAO,IACPjF,KAAMyE,EAEV,CAACzJ,kDAnGUiL,GAAsBmB,gEAAtBnB,EAAsBxG,QAAtBwG,EAAsB,qBAFrB,gBAEDA,CAAsB,6BCA5B,IAAMoB,EAAU,MAAjB,MAAOA,EACXrP,YACUsP,EACAC,EACAC,IAFArP,8BACAA,4BACAA,mBACP,CAEHsP,eAAe3B,EAAiB4B,GAC9B,MAAO,CACLlH,GAAIsF,EAAKtF,GACTgD,KAAMsC,EAAKtC,KACXmE,SAAU7B,EAAKhJ,aACf8F,MAAOkD,EAAKjD,WACZvB,WAAYwE,EAAKxE,WACjBL,MAAO6E,EAAK7E,MACZ2G,QAAS9B,EAAK+B,MACdC,SAAUJ,EAAa,IAAM5B,GAAMgC,SACnCC,aAAc5P,KAAKmP,uBAAuBlB,yBAAyBN,EAAKiC,cACxEC,YAAalC,EAAKkC,aAAe,GAErC,CAEAjC,gBAAgBD,EAAkB4B,GAChC,MAAO,CACLlH,GAAIsF,EAAKrF,GACT+C,KAAMsC,EAAK9B,KACX2D,SAAU7B,EAAKmC,aACfrF,MAAOzK,KAAKqP,YAAY1D,IAAIgC,EAAKoC,YACjC5G,WAAYwE,EAAKqC,WACjBlH,MAAO6E,EAAK5E,MACZ0G,QAAS9B,EAAKsC,MACdN,SAAUJ,EAAa,IAAM5B,GAAMuC,SACnCN,aAAc5P,KAAKmP,uBAAuBV,0BAA0Bd,EAAKO,cACzE2B,YAAa7P,KAAKoP,qBAAqB3D,QAAQkC,EAAKwC,aAExD,CAEAC,gBAAgBC,EAAoBd,GAClC,OAAOc,EAAM1E,IAAKtL,IAAML,KAAKsP,eAAejP,GAAGkP,GACjD,CAEAe,iBAAiBD,EAAqBd,GACpC,OAAOc,EAAM1E,IAAKtL,IAAML,KAAK4N,gBAAgBvN,GAAGkP,GAClD,CAAC1M,kDA3CUqM,GAAUD,uEAAVC,EAAU5H,QAAV4H,EAAU,qBAFT,gBAEDA,CAAU,wICAhB,IAAMqB,EAAoB,MAA3B,MAAOA,EACX1Q,YAAoB2Q,EAA4DC,IAA5DzQ,gCAA4DA,mBAA2B,CAE3G0Q,iBAAiBnE,GACf,GAAIvM,KAAKyQ,YAAYE,YAAcpE,EAAMjK,OAAQ,CAC/C,MAAMsO,GAAMrE,EAAMZ,IAAKxD,IAASA,GAAKE,IACrCrI,KAAKwQ,yBACFK,sBAAsBD,IACtBzQ,QACC2Q,KAAW,KACTvE,EAAMZ,IAAKxD,IAAUA,GAAKc,gBAAiB,GACpC8H,OAGVxQ,UAAWC,KACV,UAAW2H,MAAQoE,EACjBpE,GAAKgB,WAAa3I,GAAK8N,KAAM0C,IAASA,GAAK3I,KAAOF,GAAKE,KAAKc,WAC5DhB,GAAKc,gBAAiB,GAEzB,CAEP,CAEAgI,iBAAiB1E,GACf,GAAIvM,KAAKyQ,YAAYE,YAAcpE,EAAMjK,OAAQ,CAC/C,MAAMsO,GAAMrE,EAAMZ,IAAKxD,IAASA,GAAKE,IACrCrI,KAAKwQ,yBACFU,sBAAsBN,IACtBzQ,QACC2Q,KAAW,KACTvE,EAAMZ,IAAKxD,IAAUA,GAAKc,gBAAiB,GACpC8H,OAGVxQ,UAAWC,KACV,UAAW2H,MAAQoE,EACjBpE,GAAKgB,WAAa3I,GAAK8N,KAAM0C,IAASA,GAAK3I,KAAOF,GAAKE,KAAKc,WAC5DhB,GAAKc,gBAAiB,GAEzB,CAEP,CAEAkI,mBAAmB5E,GACjB,OAAOvM,KAAKoR,YAAY7E,EAAO,SACjC,CAEA8E,sBAAsB9E,GACpB,OAAOvM,KAAKoR,YAAY7E,EAAO,WACjC,CAEQ6E,YAAY7E,EAAoBD,IACtC,GAAItM,KAAKyQ,YAAYE,YAAcpE,EAAMjK,OAAQ,CAC/C,MAAMsO,GAAMrE,EAAMZ,IAAKxD,IAASA,GAAKE,IAOrC,OAJW,aAATiE,GACItM,KAAKwQ,yBAAyBc,2BAA2BV,IACzD5Q,KAAKwQ,yBAAyBe,uBAAuBX,KAE5CzQ,QACbqR,MAAKC,KACH,UAAWtJ,MAAQoE,EACjBpE,GAAKgB,WAAasI,GAAUnD,KAAM0C,IAASA,GAAK3I,KAAOF,GAAKE,KAAKc,WACjEhB,GAAKc,gBAAiB,KAEzB,EACD6H,KAAW,KACTvE,EAAMhD,QAASpB,IAAUA,GAAKc,gBAAiB,IAAK,EAC7CyI,OAAG,MACX,EACD/F,KAAI,KAAM,GAAK,CAInB,SAAO+F,OAAG,EACZ,CAAC7O,oDA5EU0N,GAAoBoB,+DAApBpB,EAAoBjJ,QAApBiJ,EAAoB,qBAFnB,gBAEDA,CAAoB,wMCW1B,IAAMqB,GAAmB,MAA1B,MAAOA,GACX/R,YACUmM,GACA+B,GACA8D,GACArB,GACAC,EACAqB,GACA9D,GACAqB,IAPArP,sBACAA,uBACAA,qBACAA,iCACAA,mBACAA,qBACAA,kBACAA,mBACP,CAEH+R,kBAAkBhJ,GAAeuD,IAC/B,OAAIA,KAASjG,uBACJrG,KAAKgO,UAAUnB,QAAQ,qBAAqB9D,KAAS,CAC1DiG,QAASjG,KAEFuD,KAASjG,WACXrG,KAAKgO,UAAUnB,QAAQ,aAAa9D,KAAS,CAAEiG,QAASjG,KAExDA,EAEX,CAEAoD,iBAAiBC,IACf,MAAMlE,GAA2B,GACjC,GAAIkE,GAAO9J,OACT,UAAW+J,MAASD,GACd/F,IAAcgG,GAAMC,OAAuCD,GAAME,MAAMjK,QACzE4F,GAAOE,KAAK,CACVU,MAAO9I,KAAKgO,UAAUnB,QAAQ,aAAaR,GAAMC,OAAQ,CACvD0C,QAAS3C,GAAMC,OAEjBK,SAAUxJ,IAAakJ,GAAMC,OAAoChJ,GACjEuE,KAAMxB,IAAcgG,GAAMC,MAC1BvE,MAAOsE,GAAME,MAAMZ,IAAKxD,MACtBW,MAAO9I,KAAK+R,kBAAkB5J,GAAKsE,MAAOJ,GAAMC,MAChDQ,MAAO3E,GAAKd,IACZ0F,MAAO5E,GAAK6E,MACZ1B,SAAUnD,GAAKiD,YAEjBhG,OAAMpF,KAAKgM,cAAciB,mCACvB9J,IAAakJ,GAAMC,MACnBnJ,YAQV,OAAO+E,EACT,CAEAgF,uBAAuBC,GAAeC,IACpC,MAAMlF,GAA8B,CAClCmF,YAAa,GACbnJ,QAAS,GACToJ,MAAO,GACPC,gBAAiB,IAEnB,GAAIH,GAAaI,kBACf,UAAWrF,MAAQiF,GAAaI,kBAC1BrF,GAAKsF,gBAAkBN,IACzBjF,GAAOmF,YAAYjF,KAAKD,GAAKsF,eAKnC,GAAIL,GAAaM,YACf,UAAWvF,MAAQiF,GAAaM,YAC1BvF,GAAK6J,QACP9J,GAAOhE,QAAQkE,KAAK,CAClBG,MAAOvI,KAAKqP,YAAY1D,IAAIxD,GAAK6J,OAAOxJ,OACxCH,GAAIF,GAAK6J,OAAO1J,GAChBvD,OAAQ/E,KAAK8R,aAAaG,sBAAsB9J,GAAK6J,OAAOlI,QAC5DoI,YAAa/J,GAAK6J,OAAOG,YACzBrJ,MAAOX,GAAK6J,OAAOjJ,MACnBC,IAAK,GAAGhJ,KAAK+N,eAAexM,kBAAkB6Q,WAAWjK,GAAK6J,OAAOtQ,MACrEqI,SAAU5B,GAAK6B,OACff,gBAAgB,EAChBC,WAAY9C,YACZiM,SAAUrS,KAAK6R,aAAaS,kBAAkBnK,GAAK6J,OAAOO,UAMlE,GAAIvS,KAAKyQ,YAAYE,YAAczI,GAAOhE,QAAQ5B,OAAQ,CACxD,MAAMsO,GAAM1I,GAAOhE,QAAQyH,IAAKxD,GAASA,EAAKE,IAC9CrI,KAAKwQ,yBACFe,uBAAuBX,IACvBzQ,QACC2Q,KAAY0B,IACVtK,GAAOhE,QAAQyH,IAAKxD,IAAUA,GAAKc,gBAAiB,GAC7C8H,QAGVxQ,UAAWC,IACV,GAAIA,EACF,UAAW2H,MAAQD,GAAOhE,QACxBiE,GAAKgB,WAAa3I,EAAK8N,KAAM0C,IAASA,GAAK3I,KAAOF,GAAKE,KAAKc,WAC5DhB,GAAKc,gBAAiB,GAG3B,CAGL,OAAOf,EACT,CAACrF,oDA7GU+O,IAAmBa,oIAAnBb,GAAmBtK,QAAnBsK,GAAmB,qBAFlB,gBAEDA,EAAmB,8LCUzB,IAAMc,GAAgB,MAAvB,MAAOA,GACX7S,YACUkO,GACA8D,GACAc,GACAb,GACA9D,GACAhC,EACAxE,IANAxH,uBACAA,qBACAA,uBACAA,qBACAA,kBACAA,qBACAA,mBACP,CAEH4S,uBACEC,GACAC,GACAC,GACArL,IA+DA,MA7DyC,CACvC,CACEiF,SAAUxJ,eACV6P,SAAU5M,aACV6M,OAAQJ,GAAQvQ,OAChB4B,QAAS,CACP0D,eAAgB,CACdC,KAAMhB,eACNiB,iBAAkB,GAEpBC,MAAO/H,KAAK6R,aAAaqB,kBAAkBL,IAAS,EAAM,kCAE5DM,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBP,GAAQvQ,OACxB+Q,MAAO,EACPC,SAAU,IAEZC,aAAa,GAEf,CACE5G,SAAUxJ,aACV6P,SAAU5M,WACVP,MAAO7F,KAAKwT,iBAAiBV,IAAO,EAAM,+BAC1CG,OAAQH,GAAMxQ,OACd6Q,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBN,GAAMxQ,OACtB+Q,MAAO,EACPC,SAAU,IAEZC,aAAa,GAEf,CACE5G,SAAUxJ,kBACV6P,SAAU5M,gBACV7C,WAAYvD,KAAK2S,eAAerJ,mBAAmB5B,IAAY,EAAM,qCACrEuL,OAAQvL,GAAWpF,OACnB6Q,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgB1L,GAAWpF,OAC3B+Q,MAAO,EACPC,SAAU,IAEZC,aAAa,GAEf,CACE5G,SAAUxJ,mBACV6P,SAAU5M,iBACVqN,MAAOzT,KAAK0T,iBAAiBX,IAAO,EAAM,qCAC1CE,OAAQF,GAAMzQ,OACd6Q,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBL,GAAMzQ,OACtB+Q,MAAO,EACPC,SAAU,IAEZC,aAAa,GAKnB,CAEAI,sBAAsBC,IAuIpB,MAtImC,CACjC,CACE9K,MAAO9I,KAAKgO,UAAUnB,QAAQ,sBAC9BgH,KAAM,CACJ,CACElH,SAAUxJ,aACV6P,SAAU5M,WACVP,MAAO7F,KAAK8T,gBAAgBF,GAAYG,QAAQC,WAAOvS,EAAW,6BAClE0R,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYD,MAAMhH,MAC9CqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYD,MAAME,aAE7C,CACEvH,SAAUxJ,cACV6P,SAAU5M,YACV+N,MAAOnU,KAAKoU,gBAAgBR,GAAYG,QAAQM,OAAQjO,aACxD+M,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYI,OAAOrH,MAC/CqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYI,OAAOH,aAE9C,CACEvH,SAAUxJ,cACV6P,SAAU5M,YACV+N,MAAOnU,KAAKoU,gBAAgBR,GAAYG,QAAQO,OAAQlO,aACxD+M,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYK,OAAOtH,MAC/CqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYK,OAAOJ,aAE9C,CACEvH,SAAUxJ,cACV6P,SAAU5M,YACV+N,MAAOnU,KAAKoU,gBAAgBR,GAAYG,QAAQQ,OAAQnO,aACxD+M,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYM,OAAOvH,MAC/CqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYM,OAAOL,aAE9C,CACEvH,SAAUxJ,iBACV6P,SAAU5M,eACV+N,MAAOnU,KAAKoU,gBAAgBR,GAAYG,QAAQS,UAAWpO,gBAC3D+M,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYO,UAAUxH,MAClDqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYO,UAAUN,aAEjD,CACEvH,SAAUxJ,iBACV6P,SAAU5M,eACV+N,MAAOnU,KAAKoU,gBAAgBR,GAAYG,QAAQU,UAAWrO,gBAC3D+M,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYQ,UAAUzH,MAClDqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYQ,UAAUP,eAIrD,CACEpL,MAAO9I,KAAKgO,UAAUnB,QAAQ,qBAC9BgH,KAAM,CACJ,CACElH,SAAUxJ,eACV6P,SAAU5M,aACVlC,QAAS,CACP0D,eAAgB,CACdC,KAAMhB,eACNiB,iBAAkB,GAEpBC,MAAO/H,KAAK6R,aAAa6C,mBACvBd,GAAYf,QAAQA,aACpBpR,EACA,gCAGJ0R,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYpB,QAAQ7F,MAChDqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYpB,QAAQqB,aAE/C,CACEvH,SAAUxJ,kBACV6P,SAAU5M,gBACV7C,WAAYvD,KAAK2S,eAAerJ,mBAC9BsK,GAAYf,QAAQnL,gBACpBjG,EACA,kCAEF0R,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYvM,WAAWsF,MACnDqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYvM,WAAWwM,aAElD,CACEvH,SAAUxJ,mBACV6P,SAAU5M,iBACVqN,MAAOzT,KAAK2U,gBAAgBf,GAAYf,QAAQ+B,iBAAanT,EAAW,mCACxE0R,WAAY,CACVtL,KAAM/G,kBACNsS,eAAgBQ,GAAYK,YAAYW,YAAY5H,MACpDqG,MAAO,EACPC,SAAU,IAEZC,YAAaK,GAAYK,YAAYW,YAAYV,eAM3D,CAEAJ,gBAAgBhB,GAAgCnL,GAAuBM,IACrE,MAAMC,GAAqB,GAC3B,UAAWnG,MAAQ+Q,GACjB5K,GAAOE,KAAK,CACVC,GAAItG,GAAK8S,KAAKvM,GACdQ,MAAO/G,GAAK8S,KAAK9L,MACjBvE,OAAQzC,GAAK8S,KAAKC,OAAOxS,OACrBP,GAAK8S,KAAKC,OAAOnJ,IAAKxD,GACpBnI,KAAKgO,UAAUnB,QAAQ,aAAa1E,IAAQ,CAC1C6G,QAAS7G,KAGb,GACJpD,OAAQ/E,KAAK8R,aAAaG,sBAAsBlQ,GAAK8S,KAAK/K,QAC1DiL,QAAShT,GAAK8S,KAAKhL,QAAU9H,GAAK8S,KAAKhL,QAAU,GACjDmL,YAAajT,GAAK8S,KAAKI,YACvBC,YAAanT,GAAK8S,KAAKM,gBACvBC,gBAAiBrT,GAAK8S,KAAKQ,gBAC3BC,OAA6B,UAArBvT,GAAK8S,KAAKU,YAAqB9T,EAAYM,GAAK8S,KAAKU,OAC7DC,QAASzT,GAAK8S,KAAKY,QACnBzM,IACyB,iBAAvBjH,GAAK8S,KAAKhU,SACN,GAAGc,oBAA4BI,GAAK8S,KAAKnT,MAAMuG,IAAe,KAC9D,GAAGjI,KAAK+N,eAAexM,kBAAkB6Q,WAAWrQ,GAAK8S,KAAKnT,MAAMuG,IAAe,KACzF8B,SAAUhI,GAAKiI,OACff,iBAAgBtB,GAChBuB,WAAY9C,WACZ+C,aAAYxB,GACZ+N,WAAY3T,GAAK8S,KAAKc,WACtBC,OAAQ5V,KAAKwH,YAAYoB,QAAQ7G,GAAK8S,KAAKgB,sBAG/C,OAAO3N,EACT,CACAsL,iBAAiBV,GAAiCnL,GAAuBM,IACvE,MAAMC,GAAqB,GAC3B,UAAWnG,MAAQ+Q,GACjB5K,GAAOE,KAAK,CACVC,GAAItG,GAAKsD,KAAKgD,GACdS,MAAO/G,GAAKsD,KAAKyD,MACjBtE,OAAQzC,GAAKsD,KAAKb,OAAOlC,OACrBP,GAAKsD,KAAKb,OAAOmH,IAAKxD,GACpBnI,KAAKgO,UAAUnB,QAAQ,aAAa1E,IAAQ,CAC1C6G,QAAS7G,KAGb,GACJpD,OAAQ/E,KAAK8R,aAAaG,sBAAsBlQ,GAAKsD,KAAKN,QAC1DgQ,QAAShT,GAAKsD,KAAKW,QAAUjE,GAAKsD,KAAKW,QAAU,GACjDgP,YAAajT,GAAKsD,KAAK2P,YACvBE,YAAanT,GAAKsD,KAAKyQ,gBACvBV,gBAAiBrT,GAAKsD,KAAK+P,gBAC3BE,OAA6B,UAArBvT,GAAKsD,KAAKiQ,YAAqB7T,EAAYM,GAAKsD,KAAKiQ,OAC7DE,QAASzT,GAAKsD,KAAKmQ,QACnBxM,IACyB,iBAAvBjH,GAAKsD,KAAK0Q,SACN,GAAGpU,oBAA4BI,GAAKsD,KAAK2D,MAAMf,IAAe,KAC9D,GAAGjI,KAAK+N,eAAexM,kBAAkB6Q,WAAWrQ,GAAKsD,KAAK2D,MAAMf,IAAe,KACzF8B,SAAUhI,GAAKiU,OACf/M,iBAAgBtB,GAChBuB,WAAY9C,WACZ+C,aAAYxB,GACZ+N,WAAY3T,GAAKsD,KAAKqQ,aAG1B,OAAOxN,EACT,CAEAyM,gBAAgB5B,GAAsCpL,GAAuBM,IAC3E,MAAMC,GAAqB,GAC3B,UAAW+N,MAAQlD,GAAO,CACxB,MAAM5K,EAAiB,CACrBE,GAAI4N,GAAKC,WAAW5N,GACpBQ,MAAOmN,GAAKC,WAAWnN,MACvBiM,YAAaiB,GAAKC,WAAWjB,YAC7BkB,mBAAoBnW,KAAKgO,UAAUnB,QAAQ,qBAAqBoJ,GAAKC,WAAWE,oBAAqB,CACnGpH,QAASiH,GAAKC,WAAWE,oBAE3BhN,MAAO6M,GAAKC,WAAW7M,MACvBL,IAAK,GAAGhJ,KAAK+N,eAAexM,kBAAkB6Q,WAAW6D,GAAKC,WAAWxU,MAAMuG,IAAe,KAC9F8B,SAAUkM,GAAKjM,OACff,iBAAgBtB,GAChBuB,WAAY9C,iBACZ+C,aAAYxB,IAEkB,yBAA5BQ,EAAKgO,qBACPhO,EAAKkO,kBAAoB,iBAAiBJ,GAAKC,WAAWE,kBAAkB1J,qBAE9ExE,GAAOE,KAAKD,EAAI,CAElB,OAAOD,EACT,CACAwL,iBAAiBX,GAAuCpL,GAAuBM,IAC7E,MAAMC,GAAqB,GAC3B,UAAW+N,MAAQlD,GAAO,CACxB,MAAM5K,EAAiB,CACrBE,GAAI4N,GAAKK,WAAWjO,GACpBS,MAAOmN,GAAKK,WAAWxN,MACvBkM,YAAaiB,GAAKK,WAAWtB,YAC7BmB,mBAAoBnW,KAAKgO,UAAUnB,QAAQ,qBAAqBoJ,GAAKK,WAAWC,oBAAqB,CACnGvH,QAASiH,GAAKK,WAAWC,oBAE3BnN,MAAO6M,GAAKK,WAAWlN,MACvBJ,IAAK,GAAGhJ,KAAK+N,eAAexM,kBAAkB6Q,WAAW6D,GAAKK,WAAWtN,MAAMf,IAAe,KAC9F8B,SAAUkM,GAAKD,OACf/M,iBAAgBtB,GAChBuB,WAAY9C,iBACZ+C,aAAYxB,IAEkB,yBAA5BQ,EAAKgO,qBACPhO,EAAKkO,kBAAoB,iBAAiBJ,GAAKK,WAAWC,kBAAkB7J,qBAE9ExE,GAAOE,KAAKD,EAAI,CAElB,OAAOD,EACT,CAEAkM,gBAAgBoC,GAAkClK,IAChD,MAAMpE,GAAsB,GAC5B,IAAIuO,IAAmB,EACnBC,IAAa,EACbpK,KAASlG,aAGFkG,KAASlG,aAGTkG,KAASlG,aALlBqQ,IAAmB,EACnBC,IAAa,GAOJpK,KAASlG,gBAClBqQ,IAAmB,EACnBC,IAAa,GACJpK,KAASlG,iBAClBqQ,IAAmB,EACnBC,IAAa,GAGf,UAAWC,KAASH,GAAQ,CAC1B,IAAI9N,GAYAkO,GAXJ,GAAID,EAAME,kBAAmB,CAC3B,MAAMC,GAAa,CAACC,GAAwBC,GAAa1U,MAC/C,IAAI2U,MAAM3U,GAAS,GAAG4U,KAAKF,IAAOD,IAAgBI,OAAO7U,IAE7D8U,GAAUC,KAAKC,MAAMX,EAAME,kBAAoB,IAC/CU,GAAUZ,EAAME,kBAA8B,GAAVO,GACpCI,GAAQV,GAAWM,GAAS,IAAK,GAAK,IAAMN,GAAWS,GAAS,IAAK,GAC3E7O,GAAW1I,KAAKgO,UAAUnB,QAAQ,oBAAqB,CACrD4K,OAAQD,IACT,CAGClL,KAASlG,eACXuQ,EAAMe,KAAO,+CAA+Cf,EAAMgB,aACzDrL,KAASlG,YAClBuQ,EAAMe,KAAOf,EAAMiB,cACVtL,KAASlG,iBAClBwQ,GAAM5W,KAAKgM,cAAc6L,eAAelB,EAAMrK,OAEhD,MAAMnE,GAAkB,CACtB2P,cAAenB,EAAMiB,cACrB3O,gBAAgB,EAChBzE,OAAQmS,EAAM7B,OAAS6B,EAAM7B,OAAS,GACtCzM,GAAIsO,EAAMoB,QACVC,SAAUrB,EAAMsB,SAAWtB,EAAMsB,SAAW,GAC5ClT,OAAQ/E,KAAK8R,aAAaG,sBAAsB0E,EAAM7M,QACtDZ,WAAYoD,GACZzB,KAAM8L,EAAMe,KACZ/R,SAAUgR,EAAMuB,SAAWvB,EAAMuB,SAAW,GAC5CpP,MAAO6N,EAAM5N,MACb4B,UAAWgM,EAAMwB,UACjB1P,SAAUC,GACVS,YAAY,EACZY,SAAU4M,EAAM3M,OAChB5E,MAAM,EACNgT,iBAAkB3B,GAClB4B,WAAY3B,GACZjM,MACE6B,KAASlG,aAA0BuQ,EAAM2B,SACpC,CACClG,SAAUuE,EAAM2B,SAChBxN,WAAY,CACVyN,OAAQ5B,EAAM6B,YAAYC,OAC1BC,MAAO/B,EAAM6B,YAAYG,OAE3B9N,UAAMpJ,EACNoG,KAAM,cAERpG,EACNmX,IAAKhC,IAEP1O,GAAOE,KAAKD,GAAI,CAElB,OAAOD,EACT,CAEA2Q,kBAAkBjF,GAAyCkF,GAAmB7Q,IACxE6Q,IAAK5U,UACP4U,GAAI5U,QAAQ6D,MAAQ/H,KAAK6R,aAAa6C,mBAAmBd,GAAYf,QAAQA,aAASpR,EAAWwG,KAG/F6Q,KACFA,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYpB,QAAQ7F,MAEpE,CAEA+L,qBAAqBnF,GAAyCkF,GAAmB7Q,IAC3E6Q,KACFA,GAAIvV,WAAavD,KAAK2S,eAAerJ,mBAAmBsK,GAAYf,QAAQnL,gBAAYjG,EAAWwG,IACnG6Q,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYvM,WAAWsF,MAEvE,CAEAgM,gBAAgBpF,GAAyCkF,GAAmB7Q,IACtE6Q,KACFA,GAAIjT,MAAQ7F,KAAK8T,gBAAgBF,GAAYG,QAAQC,WAAOvS,EAAWwG,IACvE6Q,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYD,MAAMhH,MAElE,CAEAiM,gBAAgBrF,GAAyCkF,GAAmB7Q,IACtE6Q,KACFA,GAAIrF,MAAQzT,KAAK2U,gBAAgBf,GAAYf,QAAQ+B,iBAAanT,EAAWwG,IAC7E6Q,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYW,YAAY5H,MAExE,CAEAkM,iBAAiBtF,GAAyCkF,IACpDA,KACFA,GAAI3E,MAAQnU,KAAKoU,gBAAgBR,GAAYG,QAAQM,OAAQjO,aAC7D0S,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYI,OAAOrH,MAEnE,CAEAmM,iBAAiBvF,GAAyCkF,IACpDA,KACFA,GAAI3E,MAAQnU,KAAKoU,gBAAgBR,GAAYG,QAAQO,OAAQlO,aAC7D0S,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYK,OAAOtH,MAEnE,CAEAoM,iBAAiBxF,GAAyCkF,IACpDA,KACFA,GAAI3E,MAAQnU,KAAKoU,gBAAgBR,GAAYG,QAAQQ,OAAQnO,aAC7D0S,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYM,OAAOvH,MAEnE,CAEAqM,oBAAoBzF,GAAyCkF,IACvDA,KACFA,GAAI3E,MAAQnU,KAAKoU,gBAAgBR,GAAYG,QAAQS,UAAWpO,gBAChE0S,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYO,UAAUxH,MAEtE,CAEAsM,oBAAoB1F,GAAyCkF,IACvDA,KACFA,GAAI3E,MAAQnU,KAAKoU,gBAAgBR,GAAYG,QAAQU,UAAWrO,gBAChE0S,GAAI3F,WAAWC,eAAiBQ,GAAYK,YAAYQ,UAAUzH,MAEtE,CAACnK,oDA/dU6P,IAAgBD,uHAAhBC,GAAgBpL,QAAhBoL,GAAgB,qBAFf,gBAEDA,EAAgB,2ICdtB,IAAM6G,EAAY,MAAnB,MAAOA,EACX1Z,YACUkO,EACA/B,GACA8F,GACAtK,GACAwG,GACAqB,IALArP,sBACAA,sBACAA,qBACAA,oBACAA,kBACAA,mBACP,CAEHkT,kBAAkBL,EAAoClL,GAAuBM,IAC3E,MAAMC,GAAwB,GAC9B,IAAK2K,EAEH,OAAO3K,GAET,UAAWC,MAAQ0K,EACjB3K,GAAOE,KAAK,CACVC,GAAIF,GAAKqR,OAAOnR,GAChBE,MAAOJ,GAAKqR,OAAOjR,MACnBI,YAAa3I,KAAKwH,YAAYoB,QAAQT,GAAKqR,OAAO7Q,aAClD5D,OAAQ/E,KAAK8R,aAAaG,sBAAsB9J,GAAKqR,OAAOzU,QAC5DmN,YAAa/J,GAAKqR,OAAOtH,YACzBpJ,MAAOX,GAAKqR,OAAO1Q,MACnB2Q,YAAazZ,KAAKgM,cAAc0N,eAAevR,GAAKqR,OAAO1Q,MAAO,IAClEE,IAAK,GAAGhJ,KAAK+N,eAAexM,kBAAkB6Q,WAAWjK,GAAKqR,OAAOxQ,MAAMf,IAAe,KAC1F8B,SAAU5B,GAAK6N,OACf/M,gBAAgB,EAChBC,WAAY9C,YACZuT,sBAAuB3Z,KAAKgM,cAAc4N,yBAAyBzR,GAAKqR,OAAO/Q,UAC/E4J,SAAUrS,KAAKsS,kBAAkBnK,GAAKqR,OAAOK,QAC7C1Q,WAAYxB,GACZmS,kBAAmB3R,GAAKqR,OAAOM,kBAC3B,CACEhR,MAAO9I,KAAKgO,UAAUnB,QAAQ,uCAAwC,CACpEkN,KAAM/Z,KAAKgO,UAAUnB,QAAQ,yBAAyBH,gBAExD/D,YAAa3I,KAAKwH,YAAYoB,QAAQT,GAAKqR,OAAOM,oBAAsB,SAE1ErY,IAIR,OAAOyG,EACT,CAEAwM,mBAAmB7B,EAAqClL,GAAuBM,IAC7E,MAAMC,GAAwB,GAE9B,IAAK2K,EAEH,OAAO3K,GAET,UAAWC,MAAQ0K,EACjB3K,GAAOE,KAAK,CACVC,GAAIF,GAAK6J,OAAO1J,GAChBC,MAAOvI,KAAKqP,YAAY1D,IAAIxD,GAAK6J,OAAOxJ,OACxCG,YAAa3I,KAAKwH,YAAYoB,QAAQT,GAAK6J,OAAOnJ,aAClD9D,OAAQ/E,KAAK8R,aAAaG,sBAAsB9J,GAAK6J,OAAOlI,QAC5DoI,YAAa/J,GAAK6J,OAAOG,YACzBrJ,MAAOX,GAAK6J,OAAOjJ,MACnB0Q,YAAazZ,KAAKgM,cAAc0N,eAAevR,GAAK6J,OAAOjJ,MAAO,IAClEC,IAAK,GAAGhJ,KAAK+N,eAAexM,kBAAkB6Q,WAAWjK,GAAK6J,OAAOtQ,MAAMuG,IAAe,KAC1F8B,SAAU5B,GAAK6B,OACff,gBAAgB,EAChBC,WAAY9C,YACZuT,sBAAuB3Z,KAAKgM,cAAc4N,yBAAyBzR,GAAK6J,OAAOtJ,UAC/E2J,SAAUrS,KAAKsS,kBAAkBnK,GAAK6J,OAAOO,QAC7CpJ,WAAYxB,GACZmS,kBAAmB3R,GAAK6J,OAAOgI,kBAC3B,CACElR,MAAO9I,KAAKgO,UAAUnB,QAAQ,uCAAwC,CACpEkN,KAAM/Z,KAAKgO,UAAUnB,QAAQ,yBAAyBH,gBAExD/D,YAAa3I,KAAKwH,YAAYoB,QAAQT,GAAK6J,OAAOgI,oBAAsB,SAE1EvY,IAIR,OAAOyG,EACT,CAEAoK,kBAAkBC,GAChB,QAAoB,UAAXA,GAAiC,aAAXA,EACjC,CAAC1P,oDArFU0W,GAAYzW,4GAAZyW,EAAYjS,QAAZiS,EAAY,qBAFX,gBAEDA,CAAY,iICJlB,IAAMU,EAAe,MAAtB,MAAOA,EACXpa,YACU2H,EACAwE,EACAkO,IAFAla,mBACAA,qBACAA,wBACP,CAEHma,oBAAoBC,GAClB,MAAO,CACL1Q,MAAO0Q,EAAQzQ,MACfoL,QAASqF,EAAQC,QAAQ1O,IAAKqF,KAC5B3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,cAERyB,GAAI+R,EAAQ9R,GAAGgS,WACfnR,WAAYiR,EAAQpK,WACpBlH,MAAOsR,EAAQrR,MACfjD,OAAQsU,EAAQxQ,OAAO+B,IAAKqF,KAC1B3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,aAERgP,OAAQ5V,KAAKwH,YAAYoB,QAAQ5I,KAAKwH,YAAY+S,aAAaH,EAAQI,OAAQ,MAC/EC,gBAAiBza,KAAKwH,YAAYoB,QAAQwR,EAAQM,iBAClDC,YAAa3a,KAAKgM,cAAc4O,iBAAiB,IAAIC,KAAKT,EAAQU,cAClErQ,MAAO2P,EAAQW,MACfC,QAASZ,EAAQa,iBAAiB3Y,OAC9B,CACE4Y,SAAUlb,KAAKmb,qBAAqBf,EAAQa,iBAC5CrT,eAAgB,CACdC,KAAMhB,eACNuU,WAAW,EACXtT,iBAAkB,EAClBgB,MAAO9I,KAAKka,iBAAiBrN,QAAQ,iCAGzCpL,EACJuH,IAAKoR,EAAQiB,UACTrb,KAAKgM,cAAcsP,aAAalB,EAAQiB,WACxC,IAAIva,iBAA0BsZ,EAAQ9R,KAE9C,CAEA6S,qBAAqBI,GACnB,MAAMrT,EAAuB,GAC7BqT,SAAShS,QAAS6Q,KAChBlS,EAAOE,KAAKpI,KAAKma,oBAAoBC,IAAQ,GAExClS,CACT,CAACrF,kDAlDUoX,GAAehQ,8EAAfgQ,EAAe3S,QAAf2S,EAAe,qBAFd,gBAEDA,CAAe,6GCFrB,IAAMuB,EAAkB,MAAzB,MAAOA,EACX3b,YAAoB2H,EAAkCwE,GAAlChM,mBAAkCA,oBAA+B,CAErFyb,uBAAuBvF,EAA8BwF,GACnD,MAAO,CACLrT,GAAI6N,EAAW5N,GACfxC,OAAQoQ,EAAWtM,QAAQtH,OACvB4T,EAAWtM,OAAO+B,IAAKqF,KACrB3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,aAER,GACJmO,QAASmB,EAAWmE,SAAS/X,OACzB4T,EAAWmE,QAAQ1O,IAAKqF,KACtB3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,cAER,GACJ+U,gBAAiBzF,EAAW0F,gBAC5BC,WAAY3F,EAAW4F,YAAYxZ,OAC/B4T,EAAW4F,WAAWnQ,IAAKqF,KACzB4H,IAAK5Y,KAAKgM,cAAc6L,eAAe7G,EAAK+K,eAC5CC,SAAUhL,EAAKiL,SACfnT,MAAOkI,EAAKjI,MACZC,IAAKgI,EAAKtP,IACVwa,QAASlL,EAAKmL,QACdC,cAAepL,EAAKqL,iBAEtB,GACJjY,UAAW8R,EAAW1B,WAAWlS,OAC7B4T,EAAW1B,UAAU7I,IAAKqF,KACxB4H,IAAK5Y,KAAKgM,cAAc6L,eAAe7G,EAAK+K,eAC5CC,SAAUhL,EAAKiL,SACfnT,MAAOkI,EAAKjI,MACZC,IAAKgI,EAAKtP,IACVwa,QAASlL,EAAKmL,QACdC,cAAepL,EAAKqL,iBAEtB,GACJlT,WAAY+M,EAAWlG,WACvBjL,OAAQmR,EAAWpM,QAAQxH,OACvB4T,EAAWpM,OAAO6B,IAAKqF,KACrB3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,aAER,GACJ+T,YAAazE,EAAW4E,YAAc,IAAID,KAAK3E,EAAW4E,kBAAerZ,EACzEkE,SAAUuQ,EAAWgC,SAAS5V,OAC1B4T,EAAWgC,SAASvM,IAAK2Q,KACvBjU,GAAIiU,EAAQhU,GACZQ,MAAOwT,EAAQvT,MACfwT,gBAAiBD,EAAQE,gBACzBC,UAAWH,EAAQI,UACnB7U,KAAMjB,eAER,GACJ+V,iBAAkBzG,EAAW0G,kBAAkBta,OAC3C4T,EAAW0G,iBAAiBjR,IAAKqF,KAC/B4H,IAAK5Y,KAAKgM,cAAc6L,eAAe7G,EAAK+K,eAC5CC,SAAUhL,EAAKiL,SACfnT,MAAOkI,EAAKjI,MACZC,IAAKgI,EAAKtP,IACVwa,QAASlL,EAAKmL,QACdC,cAAepL,EAAKqL,iBAEtB,GACJzG,OAAQ5V,KAAKwH,YAAYoB,QAAQ5I,KAAKwH,YAAY+S,aAAarE,EAAWsE,OAAQkB,IAClFmB,OAAQ3G,EAAW4G,QAAQxa,OACvB4T,EAAW4G,OAAOnR,IAAKqF,KACrB3I,GAAI2I,EAAK1I,GACTQ,MAAOkI,EAAKjI,MACZlB,KAAMjB,aAER,GACJkC,MAAOoN,EAAWnN,MAClBgU,UAAW7G,EAAW8G,UACtBhU,IAAKkN,EAAWmF,UACZ,IAAIrb,KAAKgM,cAAcsP,aAAapF,EAAWmF,aAC/C,IAAIva,oBAA6BoV,EAAW5N,KAChDlD,MAAM,EACN6X,YAAa/G,EAAWgH,YACxBC,UACGjH,EAAW4F,YAAYxZ,QAAU4T,EAAW1B,WAAWlS,QAAU4T,EAAW0G,kBAAkBta,QAAU,EAE/G,CAEA8a,wBAAwBxI,EAAkC8G,GACxD,MAAMxT,EAA0B,GAChC0M,UAAarL,QAAS6Q,IACpBlS,EAAOE,KAAKpI,KAAKyb,uBAAuBrB,EAASsB,GAAS,GAErDxT,CACT,CAACrF,kDA/FU2Y,GAAkB1Y,+DAAlB0Y,EAAkBlU,QAAlBkU,EAAkB,qBAFjB,gBAEDA,CAAkB,oECLxB,IAAM6B,EAAW,MAAlB,MAAOA,EACX1R,IAAI2R,GACF,GAAKA,EAIL,MAAO,CACLjV,GAAIiV,EAAOhV,GACXQ,MAAOwU,EAAOvU,MACdJ,YAAa2U,EAAOzU,YACpB8B,UAAW2S,EAAOnF,UAClBvN,SAAU0S,EAAOC,SACjB1S,KAAMyS,EAAO5F,KACb7P,KAAMyV,EAAOhR,KACbxB,WAAYwS,EAAO9E,WAAa,CAAEE,MAAO4E,EAAO9E,WAAWG,MAAOJ,OAAQ+E,EAAO9E,WAAWC,aAAWhX,EACvG2Q,SAAUkL,EAAOhF,SACjBkF,aAAcF,EAAOG,aACrBpS,KAAMiS,EAAOzR,KACbmQ,SAAUsB,EAAOrB,SACjByB,SAAUJ,EAAOK,SAErB,CAAC9a,kDArBUwa,EAAW,wCAAXA,EAAW/V,QAAX+V,EAAW,qBAFV,gBAEDA,CAAW,kGCOjB,IAAMO,EAAiB,MAAxB,MAAOA,EAAiB/a,kDAAjB+a,EAAiB,uCAAjBA,IAAiB/a,yCAHlBI,KAAc4a,IAAYC,cAGzBF,CAAiB,oQCP9B,MAAMG,EAAe,qBAERC,KAAqBC,MAAa,GAAGF,wBAErCG,MAA6BD,MACxC,GAAGF,4BACHI,SAGWC,KAAqBH,MAChC,GAAGF,4BACHI,SAGWE,KAAkCJ,MAC7C,GAAGF,iCACHI,SAGWG,KAAmBL,MAAa,GAAGF,oCAA6CI,SAEhFI,KAAgBN,MAAa,GAAGF,2BAAoCI,SAEpEK,KAAwBP,MACnC,GAAGF,uCACHI,SAGWM,KAAoBR,MAAa,GAAGF,kCAA2CI,SAE/EO,KAA4BT,MACvC,GAAGF,iCACHI,SAGWQ,KAAiCV,MAC5C,GAAGF,gCACHI,SAGWS,MAA0BX,MAAa,yCAEvCY,MAAiCZ,MAC5C,oCACAE,SAEWW,MAAiCb,MAC5C,qEACAE,SAEWY,MAAkCd,MAC7C,qCACAE,SAGWa,MAAkCf,MAC7C,qCACAE,SAGWc,MAAsChB,MACjD,sDACAE,SAGWe,MAAoCjB,MAC/C,4DACAE,SAGWgB,MAAoClB,MAC/C,4DACAE,SAGWiB,MAA2BnB,MACtC,8BACAE,SAGWkB,KAAkBpB,MAAa,qBAAmBE,SAElDmB,MAAyBrB,MACpC,4BACAE,8ICxFI,SAAUoB,EAAiBhK,IAC/B,IAAIiK,GACAC,GACJ,MAAMC,OAAY7E,MAAO8E,UAEzB,OAAQpK,IACN,KAAK7O,QACH8Y,GAAaE,EAAQ,KACrBD,GAAU,IAAI5E,KAAK2E,IACnB,MACF,KAAK9Y,QACH8Y,GAAaE,EAAQ,MACrBD,GAAU,IAAI5E,KAAK2E,IACnB,MACF,KAAK9Y,UACH8Y,GAAaE,EAAQ,OACrBD,GAAU,IAAI5E,KAAK2E,IACnB,MACF,KAAK9Y,SACH8Y,GAAaE,EAAQ,OACrBD,GAAU,IAAI5E,KAAK2E,IACnB,MACF,KAAK9Y,eACH8Y,GAAaE,EAAQ,QACrBD,GAAU,IAAI5E,KAAK2E,IACnB,MACF,QAEEA,GAAaE,EAAQ,OACrBD,GAAU,IAAI5E,KAAK2E,IAGvB,MAAO,GAAGC,GAAQG,iBAAiBtF,cAAcmF,GAAQI,cAAgB,KAAKJ,GAAQK,cACxF,0FCVO,IAAMC,GAA4B,MAAnC,MAAOA,GACXlgB,YACUoM,GACA+T,EACAC,GACAlS,GACAmS,GACAC,GACAC,IANApgB,mBACAA,gBACAA,mBACAA,uBACAA,cACAA,6BACAA,uBAIVA,2BAAqBqgB,MAAa,IAChCrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAA+C,EACtD/O,MAAI,IAAMxR,KAAKogB,eAAeI,MAAMja,YAAgB,EACpDka,KAAS,IACPzgB,KAAKigB,WACFS,UAAoC,qCAAqC1gB,KAAK2gB,eAC9ExgB,QACCwL,KAAKnL,IACH+f,KAAuD,CACrD/f,KAAMA,GAAK0H,WACX,EAEJsJ,MAAI,IAAMxR,KAAKogB,eAAeQ,KAAKra,cACpC,EAELuK,KAAY+P,KACV7gB,KAAKogB,eAAeQ,KAAKra,WAAe,EACjCmL,MACL6O,KAA4D,CAC1DM,gBAaV7gB,4BAAsBqgB,MAAa,IACjCrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAAqD,EAC5DO,MAAiB,IAAM9gB,KAAKkgB,MAAMa,OAAOC,QAAgC,EACzExP,MAAI,IAAMxR,KAAKogB,eAAeI,MAAMja,YAAgB,EACpDka,KAAS,EAAEjgB,GAAMygB,MACRjhB,KAAKigB,WACTiB,SAAqC,4CAA6C,CACjFC,OAAQ3gB,GAAK4gB,cAAcC,QAC3BC,eAAgBthB,KAAKuhB,iBACrBC,WAAYhhB,GAAK4gB,cAAcK,WAC/BC,SAAUlhB,GAAK4gB,cAAcO,SAC7BC,UAAWX,GACXY,QAAS,KAEV1hB,QACCwL,KAAKmW,KACH9hB,KAAKogB,eAAeQ,KAAKra,UAClBga,KAA6D,CAClEuB,qBAEH,EACDhR,KAAY+P,KACV7gB,KAAKogB,eAAeQ,KAAKra,WAAe,EACjCmL,MACL6O,KAA6D,CAC3DM,kBAShB7gB,4BAAsBqgB,MAAa,IACjCrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAAoD,EAC3DO,MAAiB,IAAM9gB,KAAKkgB,MAAMa,OAAOgB,QAAuB,EAChEtB,KAAS,EAAEjgB,GAAMwhB,MACfhiB,KAAKigB,WACFiB,SAAgC,+BAAgC,CAC/DC,OAAQa,IAAQX,QAChBC,eAAgBthB,KAAKuhB,iBACrBC,WAAYQ,IAAQP,aAErBthB,QACCwL,KAAKsW,KACH,MAAMC,GAAqBliB,KAAKmgB,qBAAqBhW,yBAAyB8X,IAC9E,OAAO1B,KAA4D,CAAE2B,uBAAoB,IAC1F,EACDpR,KAAY+P,OACVnP,MACE6O,KAA4D,CAC1DM,iBAShB7gB,yBAAmBqgB,MAAa,IAC9BrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAA4C,EACnDO,MAAiB,IAAM9gB,KAAKkgB,MAAMa,OAAOC,QAAgC,EACzEP,KAAS,EAAEjgB,GAAM+U,MACfvV,KAAKigB,WACFkC,QACC,kDACE3hB,GAAK4hB,yBACYpiB,KAAKuhB,8BAA8BhM,MAEvDpV,QACCwL,KAAK0W,KACH,MAAMC,GAAkBtiB,KAAKiM,WAAWmE,gBAAgBiS,GAAaE,iBAErE,IAAIC,GAA6B,GAEjC,OAAIH,GAAaI,gBAAkBJ,GAAaI,eAAengB,SAC7DkgB,GAAgBxiB,KAAKiM,WAAWmE,gBAAgBiS,GAAaI,iBAGxDlC,KAAoD,CACzD+B,mBACAE,kBACD,IACF,EACD1R,KAAY+P,OACVnP,MACE6O,KAA6D,CAC3DM,iBAShB7gB,2BAAqBqgB,MAAa,IAChCrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAA8C,EACrDO,MAAiB,IAAM,CAAC9gB,KAAKkgB,MAAMa,OAAOgB,SAAwB,EAClEtB,KAAS,EAAEjgB,GAAMwhB,MAAY,CAC3BzB,KAAsD,CACpDa,cAAe,CACbC,QAASW,IAAQX,SAAW,GAC5BI,WAAYO,IAAQP,aAAc,EAClCE,SAAUK,IAAQL,UAAY,UAOxC3hB,uBAAiBqgB,MAAa,IAC5BrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAA0C,EACjD5U,KAAKnL,IACI+f,KAAmD,CACxD/f,KAAM+e,EAAiB/e,GAAKA,WAMpCR,0BAAoBqgB,MAAa,IAC/BrgB,KAAKggB,SAAS7f,QACZmgB,MAAOC,OAA6C,EACpD5U,KAAKnL,IACI+f,KAA+C,CACpD/f,KAAM+e,EAAiB/e,GAAKA,UAzKjC,CA+KK+gB,iBACN,OAAOvhB,KAAK+N,eAAexM,kBAAkBmhB,YAC/C,CAEQ/B,YACN,OAAO3gB,KAAK+N,eAAexM,kBAAkB8G,EAC/C,CAACxF,kDA9LUkd,IAA4B9Q,+HAA5B8Q,GAA4BzY,QAA5ByY,GAA4B,mBAA5BA,EAA4B,wFCnBlC,MAAM4C,EAA6B,uBAkE7BC,KAAkCC,MAbqB,CAClEzB,mBAAe3f,EACfqhB,qBAAiBrhB,EACjBshB,gBAAiB,GACjBC,eAAgB,GAChBC,qBAAsB,GACtBC,qBAAiBzhB,EACjB0hB,SAAU,GACVC,eAAgB,GAChBd,gBAAiB,GACjBE,cAAe,KAIfa,EACAC,MAAG/C,KAAkE,CAAC7f,EAAO6iB,SAEtE7iB,EACH0iB,eAAgB1iB,EAAM0iB,eACnBzX,IAAKxD,QAAeA,KACpBwD,IAAKxD,GACAA,EAAKE,KAAOkb,EAAOjb,GACd,IACFH,EACHgB,WAAYoa,EAAO/iB,MAGd2H,OAIhB,EACDmb,MAAG/C,KAAgE,CAAC7f,EAAO6iB,SAEpE7iB,EACH4hB,gBAAiB5hB,EAAM4hB,gBACpB3W,IAAKxD,QAAeA,KACpBwD,IAAKxD,GACAA,EAAKE,KAAOkb,EAAOjb,GACd,IACFH,EACHgB,WAAYoa,EAAO/iB,MAGd2H,OAIhB,EACDmb,MAAG/C,KAAgE,CAAC7f,EAAO6iB,SAEpE7iB,EACH8hB,cAAe9hB,EAAM8hB,cAClB7W,IAAKxD,QAAeA,KACpBwD,IAAKxD,GACAA,EAAKE,KAAOkb,EAAOjb,GACd,IACFH,EACHgB,WAAYoa,EAAO/iB,MAGd2H,OAIhB,EACDmb,MAAG/C,KAA6D,CAAC7f,EAAO6iB,SACnE7iB,EACH0iB,eAAgBG,EAAOrB,uBACvB,EACFoB,MAAG/C,KAA+C,CAAC7f,EAAO6iB,SACrD7iB,EACHsiB,eAAgBO,EAAO/iB,SACvB,EACF8iB,MAAG/C,KAAgD,CAAC7f,EAAO6iB,SACtD7iB,EACHuiB,qBAAsBM,EAAO/iB,SAC7B,EACF8iB,MAAG/C,KAA4C,CAAC7f,EAAO6iB,SAClD7iB,EACHsiB,eAAgBO,EAAO/iB,SACvB,EACF8iB,MAAG/C,KAAoD,CAAC7f,EAAO6iB,SAC1D7iB,EACHuiB,qBAAsBM,EAAO/iB,SAC7B,EACF8iB,MAAG/C,KAAwD,CAAC7f,EAAO6iB,SAC9D7iB,EACHwiB,gBAAiBK,EAAO/iB,SACxB,EACF8iB,MAAG/C,KAA8D,CAAC7f,EAAO6iB,KACvE,MAAMC,EAAgB,IAAID,EAAOzB,cACjC0B,SAAcC,KAAKC,GACZ,IACFhjB,EACHyiB,SAAUK,MAEb,EACDF,MAAG/C,KAAyD,CAAC7f,EAAO6iB,SAC/D7iB,EACH0gB,cAAemC,EAAOnC,kBACtB,EACFkC,MAAG/C,KAA8D,CAAC7f,EAAO6iB,SACpE7iB,EACHqiB,gBAAiBQ,EAAOI,YACxB,EACFL,MAAG/C,KAAiD,CAAC7f,EAAO6iB,SACvD7iB,EACHoiB,gBAAiBS,EAAOK,YACxB,EACFN,MAAG/C,KAAqD,CAAC7f,EAAO6iB,SAC3D7iB,EACH4hB,gBAAiBiB,EAAOjB,gBACxBE,cAAee,EAAOf,kBAIpB,SAAUqB,EAAQnjB,EAA2C6iB,GACjE,OAAOX,EAAgCliB,EAAO6iB,EAChD,CAEA,SAASG,EAAkBvV,EAA6BE,GACtD,MAAMyV,EAAU3V,EAAE4V,YAAYC,cAAc3V,EAAE0V,YAAa,QAAS,CAClEE,YAAa,SAEf,OAAIH,EAAU,EACL,EAELA,EAAU,GACL,EAEFA,CACT,mLC5LA,MAAMI,KAA0BC,MAA8CxB,MAEjEyB,MAAwBC,MAAeH,EAA0BxjB,IAAUA,GAAMwiB,iBAEjFnB,KAAyBsC,MAAeH,EAA0BxjB,IAAUA,GAAM0gB,eAElFkD,KAA2BD,MAAeH,EAA0BxjB,IAAUA,GAAMoiB,iBACpFyB,KAA6BF,MAAeC,EAA2B5jB,IAAUA,IAAO8jB,QACxFC,KAA+BJ,MAAeC,EAA2B5jB,IAAUA,IAAOqjB,aAE1FW,KAA4BL,MAAeH,EAA0BxjB,IAAUA,GAAMsiB,gBACrFhC,KAAkCqD,MAC7CH,EACCxjB,IAAUA,GAAMuiB,sBAGN0B,KAAwBN,MAAeH,EAA0BxjB,IAAUA,GAAMyiB,UACjFyB,KAA6BP,MAAeH,EAA0BxjB,IAAUA,GAAMqiB,iBAEtF8B,MAA0BR,MAAeH,EAA0BxjB,IAAUA,GAAM0iB,gBACnF0B,MAAwBT,MAAeH,EAA0BxjB,IAAUA,GAAM4hB,iBACjFyC,MAAsBV,MAAeH,EAA0BxjB,IAAUA,GAAM8hB,4GCXrF,IAAM1E,EAAiB,MAAxB,MAAOA,EAAiBjb,kDAAjBib,EAAiB,uCAAjBA,IAAiBjb,yCAHlBI,KAAc4a,IAAYmH,eAGzBlH,CAAiB,0RCZ5Bne,qBAGEA,8DAASA,+BAAqB,GAI9BA,gBACFA,qCANEA,4BAGAA,mGAEwBA,mIAE1BA,kBASEA,mEAAYA,sBAAgB,EAA5BA,CAA6B,4DACjBA,sBAAgB,EAD5BA,CAA6B,6DAEhBA,uBAAiB,EAF9BA,CAA6B,6DAGhBA,uBAAiB,GAC/BA,qCAXCA,4BAGAA,6BAAwB,qCAAxBA,CAAwB,yEAY1BA,sBAGEA,8DAASA,2BAAiB,GAI1BA,gBACFA,qCANEA,4BAGAA,+FAEwBA,+EAlC5BA,kBACEA,2BASAA,yBAcAA,qBACEA,gBACFA,SACAA,4BASFA,kCAlCKA,uEASAA,mCAayBA,qCACFA,4CAGvBA,wECRE,IAAMslB,GAA6B,MAApC,MAAOA,GAyBXplB,YACSqlB,GACCC,GACAC,EACAC,IAHDrlB,2BACCA,yBACAA,kBACAA,mBAvBDA,eAAW,EACXA,gBAAY,EACZA,gBAAY,EAOrBA,aAAS,EAETA,aAAwB,CACtBslB,UAAU,EACVC,YAAY,EACZC,oBAAoB,EACpBC,SAAU,CAAC,UAAW,QAAS,QAC/BC,SAAU,CAAC,QAQV,CAEHzlB,WAEID,KAAK2lB,OADH3lB,KAAK4lB,IACO,CACZA,IAAK5lB,KAAK4lB,IACVtZ,KAAM,kBAGM7K,EAEhBzB,KAAKmI,KAAO,CACVN,KAAM7H,KAAKsM,KACXuZ,MAAO7lB,KAAK8lB,MAAQ9lB,KAAK8lB,MAAQ,GACjCC,WAAY/lB,KAAKgmB,WACjBC,SAAUjmB,KAAKkmB,SACfC,UAAWnmB,KAAKomB,UAChBC,gBAAiBrmB,KAAKsmB,gBAE1B,CAEAC,cACMvmB,KAAKmI,OACPnI,KAAKmI,KAAO,CACVN,KAAM7H,KAAKsM,KACXuZ,MAAO7lB,KAAK8lB,OAAS,GACrBC,WAAY/lB,KAAKgmB,WACjBC,SAAUjmB,KAAKkmB,SACfC,UAAWnmB,KAAKomB,UAChBC,gBAAiBrmB,KAAKsmB,kBAGtBtmB,KAAKmI,QACHnI,KAAKmI,KAAKN,OAAS1B,UAA4BnG,KAAKmI,KAAKN,OAAS1B,qBACpEnG,KAAKmI,KAAK4d,YAAYxc,QAASid,KACzBxmB,KAAKmI,MACPnI,KAAKmlB,iBAAiBsB,eAAeD,GAAUE,OAAQ1mB,KAAKmI,KAAKN,KAAI,IAIvE7H,KAAKmI,KAAKge,WAAanmB,KAAKmI,KAAK8d,WACnCjmB,KAAK2mB,UAGX,CAEMC,cAAW,sCACf7lB,GAAK8lB,iBACD9lB,GAAKoH,QACHpH,GAAKoH,KAAKN,OAAS1B,UAA4BpF,GAAKoH,KAAKN,OAAS1B,qBACpEpF,GAAKoH,KAAK4d,YAAYxc,QAASid,KACzBzlB,GAAKoH,MACPpH,GAAKokB,iBAAiBsB,eAAeD,GAAUE,OAAQ3lB,GAAKoH,KAAKN,KAAI,GAIvE9G,GAAK+lB,eACD/lB,GAAKmkB,mBAAmB6B,aAAahmB,GAAK+lB,OAAQ/lB,GAAK6kB,MAE3D7kB,GAAKoH,KAAKN,OAAS1B,UACrBpF,GAAKmkB,mBAAmB8B,aAGxBjmB,GAAKoH,KAAKN,OAAS1B,oBACnBpF,GAAKoH,KAAKN,OAAS1B,0BAEbpF,GAAKmkB,mBAAmB+B,wBAAuB,IAExD,EAtBc,EAuBjB,CAEAJ,iBACM7mB,KAAKknB,iBACPtkB,cAAc5C,KAAKknB,iBAEjBlnB,KAAKmnB,gBACPvkB,cAAc5C,KAAKmnB,eAEvB,CAEAC,SAASC,IAAW,YAClBrnB,KAAKmnB,eAAiB3kB,aAAW,OAAC,YAChC,GAAI6kB,GAAM3e,WACJpH,GAAK6lB,gBACPvkB,cAActB,GAAK6lB,gBAErB7lB,GAAKL,QAAS,EACdK,GAAKwlB,OAASO,SAER/lB,GAAK4jB,mBAAmBoC,UAAUhmB,GAAKwlB,OAAQxlB,GAAKskB,KACtDtkB,GAAK6G,OACH7G,GAAK6G,KAAKge,WAAa7kB,GAAK6G,KAAK8d,SACnC3kB,GAAKqlB,UACIrlB,GAAK6G,KAAK0d,OACnBvkB,GAAKimB,0BAA0BjmB,GAAK6G,KAAK0d,MAAOvkB,GAAKwlB,OAAOU,aAG1DlmB,GAAKmmB,YAAW,CAClB,MAAMjc,EAAUlK,GAAK+jB,WAAWqC,cAAc9mB,WAC1C4K,GACFA,EAAQmc,OAAK,CAKvB,GAAG,IACL,CAEMC,SAASP,IAAgB,4CACvBplB,GAAKijB,mBAAmB2C,kBAAkB5lB,GAAK2jB,KAEjD3jB,GAAKkG,OACPlG,GAAKilB,gBAAkB1kB,YAAY,KACjCP,GAAK0kB,SAAO,EACX,KAEC1kB,GAAKkG,KAAKN,OAAS1B,SACrBlE,GAAKmjB,WAAW0C,oBAAoBxhB,eAC3BrE,GAAKkG,KAAKN,OAAS1B,oBAC5BlE,GAAKmjB,WAAW0C,oBAAoBxhB,oBAIxCrE,GAAKijB,mBAAmB6C,iBAAiBV,GAAO,EAfnB,EAgB/B,CAEAE,0BAA0BzB,GAA2B0B,IACnD,GAAIxnB,KAAKmI,KAAM,CACb,MAAM6f,EAAWlC,GACdna,IAAKxD,IACG8f,SAAS9f,GAAK+f,SAASC,KAAM,IAAM,KAE3C3b,OAAQrE,IAASA,GAAOqf,IACrBY,GAAOtC,GACVna,IAAKxD,IACG8f,SAAS9f,GAAK+f,SAASC,KAAM,IAAM,KAE3C7Z,KAAMnG,IAASA,GAAOqf,IAEzBxnB,KAAKmI,KAAKke,gBAAkB,CAC1BgC,kBAAiBL,EAAS1lB,OAC1BgmB,cAAaF,IAGnB,CAEAzB,UACE,GAAI3mB,KAAKmI,MAAQnI,KAAK8mB,OAAQ,CAC5B,MAAMU,GAAcnQ,KAAKkR,MAAwC,KAAjCvoB,KAAK8mB,QAAQU,aAAe,IAE1DxnB,KAAKmI,KAAK8d,WACTjmB,KAAK8mB,OAAO0B,UACZxoB,KAAKmI,KAAKN,OAAS1B,UAA4BnG,KAAKmI,KAAKN,OAAS1B,sBAEnEnG,KAAKmI,KAAK8d,UAAW,EACrBjmB,KAAK8mB,OAAO2B,QAEVzoB,KAAKmI,KAAK0d,QACZ7lB,KAAKunB,0BAA0BvnB,KAAKmI,KAAK0d,MAAO7lB,KAAK8mB,OAAOU,cACxDxnB,KAAKmI,KAAKN,OAAS1B,UAA4BnG,KAAKmI,KAAKN,OAAS1B,qBACpEnG,KAAKmlB,iBAAiBuD,cACpB1oB,KAAKmI,KAAK0d,MACV2B,GACAxnB,KAAK8mB,OAAO0B,QACZxoB,KAAKmI,KAAKN,KACV7H,KAAKmI,KAAK4d,YAAU,CAK9B,CAEA4C,UAAUtB,IACRrnB,KAAK6mB,iBACD7mB,KAAKmI,OAASnI,KAAKmI,KAAKge,WAAanmB,KAAKmI,KAAK8d,YACjDjmB,KAAK2mB,UAE8B,IAA/BU,GAAMuB,OAAOC,KAAKngB,UAAkB2e,GAAMuB,OAAOC,KAAKngB,WAAa2e,GAAMuB,OAAOC,KAAKrB,YACnFxnB,KAAKmI,KAAKN,OAAS1B,SACrBnG,KAAKolB,WAAW0C,oBAAoBxhB,gBAC3BtG,KAAKmI,KAAKN,OAAS1B,oBAC5BnG,KAAKolB,WAAW0C,oBAAoBxhB,oBAGlCtG,KAAKmI,KAAKN,OAAS1B,SACrBnG,KAAKolB,WAAW0C,oBAAoBxhB,gBAC3BtG,KAAKmI,KAAKN,OAAS1B,oBAC5BnG,KAAKolB,WAAW0C,oBAAoBxhB,qBAK1CtG,KAAKklB,mBAAmB6C,iBAAiBV,GAC3C,CAEAyB,UAAUzB,IACRrnB,KAAK6mB,iBACD7mB,KAAKmI,MAAQnI,KAAK8mB,SACpB9mB,KAAK8mB,OAAOU,YAAc,EACtBxnB,KAAKmI,KAAKN,OAAS1B,UACrBnG,KAAKmI,KAAK4d,YAAYxc,QAASid,KACzBxmB,KAAKmI,MACPnI,KAAKmlB,iBAAiBsB,eAAeD,GAAUE,OAAQ1mB,KAAKmI,KAAKN,KAAI,GAGrE7H,KAAKmI,KAAK0d,OACZ7lB,KAAKunB,0BAA0BvnB,KAAKmI,KAAK0d,MAAO7lB,KAAK8mB,OAAOU,cAG9DxnB,KAAK2mB,UAGX,CAEAoC,sBACE,GAAI/oB,KAAKmI,MAAQnI,KAAK8mB,QAAU9mB,KAAKmI,MAAM0d,MAAO,CAChD,MAAMmD,GAAQhpB,KAAKmI,KAAK0d,MAAMla,IAAKxD,IAC1B8f,SAAS9f,GAAK+f,SAASC,KAAM,IAAM,KACzC3b,OAAQrE,IAASA,IAAQnI,KAAK8mB,QAAQU,aAAe,IACxD,GAAIwB,GAAM1mB,OAAQ,CAChBtC,KAAK8mB,OAAOU,YAAcwB,GAAMA,GAAM1mB,OAAS,GAG7CtC,KAAK8mB,OAAOU,YAFVxnB,KAAK8mB,OAAO0B,SAAWQ,GAAM1mB,OAAS,EAEd0mB,GAAMA,GAAM1mB,OAAS,GAErB0mB,GAAMA,GAAM1mB,OAAS,GAEjD,MAAMklB,GAAcnQ,KAAKkR,MAAgC,IAA1BvoB,KAAK8mB,OAAOU,aAC3CxnB,KAAKmlB,iBAAiBuD,cACpB1oB,KAAKmI,KAAK0d,MACV2B,GACAxnB,KAAK8mB,OAAO0B,QACZxoB,KAAKmI,KAAKN,KACV7H,KAAKmI,KAAK4d,WAAU,CAGxB/lB,KAAKunB,0BAA0BvnB,KAAKmI,KAAK0d,MAAO7lB,KAAK8mB,OAAOU,aACxDxnB,KAAKmI,KAAKN,OAAS1B,SACrBnG,KAAKolB,WAAW0C,oBAAoBxhB,oBAC3BtG,KAAKmI,KAAKN,OAAS1B,oBAC5BnG,KAAKolB,WAAW0C,oBAAoBxhB,uBAA2B,CAGrE,CAEA2iB,kBACE,GAAIjpB,KAAKmI,MAAQnI,KAAK8mB,QAAU9mB,KAAKmI,MAAM0d,MAAO,CAChD,MAAMmD,GAAQhpB,KAAKmI,KAAK0d,MAAMla,IAAKxD,IAC1B8f,SAAS9f,GAAK+f,SAASC,KAAM,IAAM,KACzC7Z,KAAMnG,IAASA,IAAQnI,KAAK8mB,QAAQU,aAAe,IACtD,QAAc/lB,IAAVunB,GAAqB,CACvBhpB,KAAK8mB,OAAOU,YAAcwB,GAC1B,IAAIE,GAAW,EACf,KAAOlpB,KAAK8mB,OAAOU,YAAcwB,IAC/BE,IAAY,KACZlpB,KAAK8mB,OAAOU,YAAcxnB,KAAK8mB,OAAOU,YAAc0B,GAEtD,MAAM1B,EAAcnQ,KAAKkR,MAAgC,IAA1BvoB,KAAK8mB,OAAOU,aAC3CxnB,KAAKmlB,iBAAiBuD,cACpB1oB,KAAKmI,KAAK0d,MACV2B,EACAxnB,KAAK8mB,OAAO0B,QACZxoB,KAAKmI,KAAKN,KACV7H,KAAKmI,KAAK4d,WAAU,CAGxB/lB,KAAKunB,0BAA0BvnB,KAAKmI,KAAK0d,MAAO7lB,KAAK8mB,OAAOU,aACxDxnB,KAAKmI,KAAKN,OAAS1B,SACrBnG,KAAKolB,WAAW0C,oBAAoBxhB,kBAC3BtG,KAAKmI,KAAKN,OAAS1B,oBAC5BnG,KAAKolB,WAAW0C,oBAAoBxhB,qBAAyB,CAGnE,CAACzD,oDA/SUoiB,IAA6BkE,2FAA7BlE,GAA6BliB,ylCDpB1CpD,+BAAMA,8pCCoBOslB,EAA6B,yKCoDnC,IAAMpH,EAAU,MAAjB,MAAOA,GAAUhb,oDAAVgb,GAAU,sCAAVA,KAAUhb,yCARV,CACT,CAAEumB,QAASC,OAAQC,SAAUC,QAC7B,CACEH,QAASI,KACTC,SAAUziB,MAEb0iB,SAlCCzmB,KACA0mB,MACAC,IACAC,KACAC,aAAwB,CAAEC,QAAS,iBACnCC,KACAC,KACAC,KACAC,gBAGAP,IACAD,MACAE,KACAC,KAEAM,KAEAF,KAQAC,eAUStM,EAAU,0HClEnBle,iBAAqCA,gBAACA,kCALxCA,SACEA,eAAK,WACIA,SAAgBA,QACvBA,gBAAMA,SAAgBA,UAExBA,wBACFA,2CAJWA,wBACDA,wBAEgBA,oDAN5BA,iBACEA,gCAOFA,8BAPiCA,mCCO1B,IAAM0qB,EAAyB,MAAhC,MAAOA,EAAyBxnB,kDAAzBwnB,EAAyB,sCAAzBA,EAAyBtnB,+RDRtCpD,4BAAMA,qnDCQO0qB,CAAyB,6QCClC1qB,SACEA,kBAA8B,cAO1BA,4EAAUA,gCAAmC,GAN/CA,QAQAA,oBACEA,SACAA,gBAAMA,SAAsBA,YAGlCA,mDAZMA,wDAGAA,uBACAA,kCAGkBA,yDAClBA,gCACMA,uDAbdA,SACEA,iCAgBFA,gCAhBuCA,0CCYlC,IAAM2qB,GAA+B,MAAtC,MAAOA,GAMXzqB,YACkCW,GACxB+pB,GACAxqB,GACAyqB,GACApb,GACAgW,IALwBplB,aACxBA,kBACAA,eACAA,8BACAA,6BACAA,mBATVA,WAAQ,EAWNA,KAAKmI,KAAOnI,KAAKQ,IACnB,CAEMP,WAAQ,sCACZc,GAAKhB,OAAOG,OAAOC,QAAKsqB,KAAK,IAAIlqB,UAAU,KACzCQ,GAAKwpB,UAAUG,OAAK,GAGtB,MAAMva,SAAW,EAASwa,KAAe5pB,GAAKypB,sBAAsBI,kBAEpE,GAAI7pB,GAAKoH,KAAKE,GAAI,CAChB,MAAMwiB,GAAa9pB,GAAKypB,sBAAsBM,eAAe/pB,GAAKoH,KAAKE,IACvE,IAAI+C,GAEAyf,KACFzf,SAAQ,EAASuf,KAAeE,IAChC9pB,GAAKoP,YAAcpP,GAAKqO,qBAAqBlE,4BAA4BiF,GAAa/E,IAAQ,CAIlGrK,GAAKgqB,cAAe,EAjBR,EAkBd,CAEAA,eACM/qB,KAAKmQ,aAAa7N,SACpBtC,KAAKgrB,UAAYhrB,KAAKirB,MAAQjrB,KAAKmQ,YAAY3D,OAAQhB,IAAYA,GAAQF,UAAUhJ,OAEzF,CAEM4oB,gBAAgB7D,GAAc8D,IAAmC,sCACrE,MAAMC,GAAS/D,GAAM+D,QAEE,IAAnBA,GAAOC,QACL/pB,GAAK0pB,WAAa1pB,GAAK6G,KAAKE,IAC9B8iB,GAAW7f,UAAW,QACtB,EAAMqf,KAAerpB,GAAKkpB,sBAAsBc,uBAAuBhqB,GAAK6G,KAAKE,GAAI8iB,GAAW9f,MAAQ,KAExG/J,GAAK8jB,WAAW0C,oBAAoBxhB,0CAA+C,CACjFqH,KAAMrM,GAAK6G,KAAKW,MAChByiB,IAAKJ,GAAWriB,UAGlBsiB,GAAOC,SAAU,EACjBF,GAAW7f,UAAW,GAEfhK,GAAK6G,KAAKE,KACnB8iB,GAAW7f,UAAW,QACtB,EAAMqf,KAAerpB,GAAKkpB,sBAAsBgB,0BAA0BlqB,GAAK6G,KAAKE,GAAI8iB,GAAW9f,MAAQ,KAC3G/J,GAAK8jB,WAAW0C,oBAAoBxhB,iDAAsD,CACxFqH,KAAMrM,GAAK6G,KAAKW,MAChByiB,IAAKJ,GAAWriB,SAGpBxH,GAAKypB,cAAe,EAxBiD,EAyBvE,CAEAU,aACEzrB,KAAKuqB,UAAUG,OACjB,CAAC7nB,oDAxEUynB,IAA+Brb,MAOhCyc,MAAezc,iGAPdqb,GAA+BvnB,+aDrB5CpD,oBAAQA,gCAASgsB,eAAY,GAC3BhsB,eACFA,QACAA,gBAAuBA,8BAAyDA,QAChFA,iBACAA,aAAGA,8BAAgEA,QACnEA,iBACAA,kBACEA,kCAkBFA,QACAA,kBACAA,kBAAyB,eACGA,gCAASgsB,eAAY,GAAEhsB,gCAA6CA,kBA5BtEA,gDAEHA,mEAEpBA,iFAGcA,sCAqBkCA,yzDCRtC2qB,EAA+B,gOClBtC3qB,SACEA,eAAgEA,4DAASA,uBAAa,GACpFA,WACFA,QACAA,WACFA,2DAJKA,2EACaA,sCAAwB,+CAE1BA,sCAA2B,6EAG3CA,SACEA,WACFA,6CADgBA,sCAAwB,6EAT1CA,SACEA,iCAOAA,iCAGFA,iCAViBA,gDAOAA,6EAKjBA,SACEA,WACFA,6CADgBA,sCAAwB,6EAhB5CA,SACEA,iBACEA,iCAaAA,iCAGFA,QACFA,gCAjBmBA,2DAaAA,iEAQfA,+CACAA,yEAAqCA,yEACrCA,yEAA0CA,qEAExCA,sBAA8EA,wDAC9EA,sBAAyEA,6DAF3EA,kBACEA,uBACAA,uBACFA,qDAFMA,oEACAA,6FAENA,SACEA,kBAAmB,YACEA,SAAgBA,UAEvCA,0CAFuBA,uDAGvBA,SACEA,gBAAqD,YAEjDA,gBACAA,kBAAmBA,SAAgBA,YAGzCA,0CAN8BA,qCAEAA,8CACLA,uDAMzBA,kBACEA,kBACFA,2CADmCA,kEAM9BA,sBAAyDA,iEAH9DA,oBAA6C,YAA7CA,CAA6C,UAEnCA,SAAgBA,QACrBA,uBACHA,6CAFQA,yBACDA,8DAMPA,SACEA,kBACFA,sCAEEA,eACEA,gBAAuDA,SACzDA,qCAD0BA,yCAA+BA,wDAF3DA,kBACEA,yBAGFA,2CAH0BA,mEAMxBA,eACEA,SACFA,qCADEA,8DAHJA,kBAAqF,YACrDA,8BAAmCA,QACjEA,yBAGFA,2CAJgCA,6CACFA,uEAZhCA,SACEA,uCACAA,iCAGAA,yBAKAA,yBAMFA,2CAf4BA,wCACXA,4FAGTA,qDAKAA,2FAtBVA,SACEA,yBAGAA,kBACAA,2BAMAA,kBACAA,iCAiBFA,qDA5BiCA,0CAIJA,gCAOZA,+HAlCjBA,iBACEA,wBACAA,wBACAA,wBACAA,yBAIAA,iCAKAA,iCAQFA,QACAA,yEArBwBA,kCACHA,gCACKA,gCAClBA,mCAISA,4CAKAA,mCASFA,+HA0DPA,iBAAuDA,4DAASA,8BAAoB,GAClFA,8BACFA,eADEA,2GAEFA,iBAAqEA,4DAASA,0BAAgB,GAC5FA,8BACFA,eADEA,mGAfRA,eAA0C,eAItCA,iEAAcA,sBAAY,EAA1BA,CAA2B,2DACbA,sBAAY,GAE1BA,gBACFA,QACAA,0BAAiD,QAE7CA,wBAGAA,wBAGFA,WAAK,wCAfLA,uCAKwBA,uCAIWA,yCAGAA,2GA5BzCA,kBACEA,8BAMmB,2DAOnBA,wBAoBFA,qDAhCIA,yDAA+B,kDAA/BA,CAA+B,gCAA/BA,CAA+B,WAA/BA,CAA+B,kBAO/BA,2BAAc,iBAAdA,CAAc,iDAKVA,0GAdRA,iEAAMA,2BCxDD,IAAMisB,GAAiB,MAAxB,MAAOA,GAQX/rB,YACUgsB,GACAC,GACAC,GACAtb,GACA2U,IAJAplB,4BACAA,eACAA,4BACAA,oBACAA,mBAXDA,sBAAkB,EAG3BA,UAAOA,KAAKyQ,YAAYE,WACxB3Q,qBAAiB,CAQd,CAEHC,WACED,KAAKgsB,eAAyC,MAAxBhsB,KAAKmI,MAAMwH,QACnC,CAKMsc,iBAAc,sCACdlrB,GAAKoH,MAAME,KACTtH,GAAK0kB,UAAU5d,OAAShB,wBAC1B,EAAM8jB,KAAe5pB,GAAKgrB,oBAAoBG,gBAAgBnrB,GAAKoH,KAAKE,GAAI,GAAI,IAChFtH,GAAKqkB,WAAW0C,oBAAoBxhB,kCAAuC,CAAEqH,KAAM5M,GAAKoH,KAAKW,eAE7F,EAAM6hB,KAAe5pB,GAAK8qB,oBAAoBM,gBAAgBprB,GAAKoH,KAAKE,IAAI,IAG1EtH,GAAK0kB,UAAU5d,OAAShB,mBAC1B9F,GAAKqkB,WAAW0C,oBAAoBxhB,8BAAmC,CACrEqH,KAAM5M,GAAKoH,KAAKW,QAGrB,EAdiB,EAepB,CAEAsjB,qBACE,MAAMC,GAAe,IAAIC,KACzBD,GAAaE,cAAe,EAC5BF,GAAaG,WAAY,EACzBH,GAAaI,cAAe,EAC5BJ,GAAa7rB,KAAOR,KAAKmI,KACzBnI,KAAK8rB,OAAOY,KAAKpC,GAAiC+B,GACpD,CAEIxlB,sBACF,OAAOA,GACT,CAEIT,sBACF,OAAOA,GACT,CAEAumB,aACEvqB,SAASwqB,gBAAgBC,UAAUC,IAAI,eACzC,CAEAC,aACE3qB,SAASwqB,gBAAgBC,UAAUG,OAAO,eAC5C,CAEAC,cACEjtB,KAAKolB,WAAW0C,oBAAoBxhB,eAAoB,CACtDqH,KAAM3N,KAAKmI,MAAMW,MACjBwD,KAAMtM,KAAKsM,MAEf,CAEIxL,mBACF,OAAOA,GACT,CAAC+B,oDA1EU+oB,IAAiB3c,mGAAjB2c,GAAiB7oB,+rDDrB9BpD,iCAqBAA,2CAuDAA,kDA5EeA,0gICqBFisB,EAAiB,wHCdvB,IAAMsB,EAAiB,MAAxB,MAAOA,EALbrtB,cAOYG,aAAU,IAAImtB,MAExBC,SAAS3gB,GACPzM,KAAKqtB,QAAQC,KAAK7gB,EACpB,CAAC5J,kDANUqqB,EAAiB,sCAAjBA,EAAiBnqB,wTCP9BpD,mBAAqC,aACZA,yDAAqB,2BAAWgsB,qBAAiB,GAAxEhsB,QACAA,aACEA,kBACFA,QACAA,gBACEA,SACFA,iBANuBA,oCAEKA,knGDIjButB,CAAiB,yOEe1BvtB,sCAEEA,mCACAA,+NCTC,IAAM4tB,GAAiB,MAAxB,MAAOA,GAeX1tB,YACU2tB,GACAC,EACA1tB,GACAgO,GACA2f,GACAC,IALA3tB,wBACAA,0BACAA,eACAA,uBACAA,6BACAA,2BApBDA,QAAaA,KAAK4tB,eAClB5tB,kBAAc,EAMdA,eAAW,EACXA,cAAW,GAEXA,yBAAqB,EAE9BA,YAAQ,CASL,CAEHC,WACED,KAAKwtB,gBAAgBK,MAAMttB,UAAWkM,KACpCzM,KAAK8tB,aAAerhB,KAGtBzM,KAAKytB,mBAAmBM,OAAOxtB,UAAWC,KACpCA,IAAkC,WAA1BR,KAAK8tB,cAAczlB,IAC7BrI,KAAKwtB,gBAAgBQ,gBAEvBhuB,KAAKiuB,MAAQztB,IAEjB,CAEA0tB,mBACkB,WAAZluB,KAAKsI,IACPtI,KAAKytB,mBAAmBM,OAAO5tB,QAAKsqB,KAAK,IAAIlqB,UAAWC,KAClDA,IACER,KAAKa,WAAaC,mBAA8Bd,KAAKa,WAAaC,iBACpEd,KAAKD,OAAOouB,SAAS,CAACnuB,KAAKouB,YAAW,GAM5CpuB,KAAKytB,mBAAmBY,YAAYluB,QAAKsqB,KAAK,IAAIlqB,UAAWC,KACvDA,KACER,KAAKa,WAAaC,mBAA8Bd,KAAK+N,eAAeugB,YACtEtuB,KAAKuuB,4BAEJvuB,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,gBACvDxO,KAAKa,WAAaC,iBAElBd,KAAKwuB,+BAA4B,IAMvCxuB,KAAKwtB,gBAAgBiB,eAAezuB,KAAKsI,GAAItI,KAAK0uB,YAEtD,CAKQF,+BACDxuB,KAAK2tB,mBAAmBgB,QAAQC,eACnC5uB,KAAK2tB,mBAAmBkB,oBAGtB7uB,KAAKouB,aAAe7E,OAAOuF,SAASC,UACtC/uB,KAAKgvB,oBAET,CAMQT,2BACDvuB,KAAK0tB,qBAAqBiB,QAAQC,eACrC5uB,KAAK0tB,qBAAqBmB,oBAE5B7uB,KAAKgvB,oBACP,CAKQA,qBACNhvB,KAAKwtB,gBAAgBiB,eAAezuB,KAAKsI,GAAItI,KAAK0uB,YAAa1uB,KAAKivB,OACtE,CAEArB,eACE,IAAIsB,QAAQrU,MAAO8E,UACfwP,SAAaC,YAAgB,KAAeA,YAAYC,KAA2B,IAApBD,YAAYC,OAAiB,EAChG,MAAO,uCAAuCrtB,QAAQ,QAAUstB,KAC9D,IAAIC,GAAoB,GAAhBlY,KAAKmY,SACb,OAAIN,GAAI,GAENK,IAAKL,GAAIK,IAAK,GAAK,EACnBL,GAAI7X,KAAKC,MAAM4X,GAAI,MAGnBK,IAAKJ,EAAKI,IAAK,GAAK,EACpBJ,EAAK9X,KAAKC,MAAM6X,EAAK,MAET,MAANG,GAAYC,GAAS,EAAJA,GAAW,GAAKjV,SAAS,GAAE,EAExD,CAACzX,kDAjHU0qB,IAAiBkC,0GAAjBlC,GAAiBxqB,uiBDhB9BpD,iBAKC,cAaGA,gCAASgsB,qBAAkB,kEAG3BhsB,SACAA,sBAKFA,QACAA,iBACEA,WACFA,iBA1BAA,8HADAA,sEADAA,kBAMEA,iCACAA,kRAcGA,mCAKyBA,w0JCZnB4tB,EAAiB,mLCTvB,IAAMmC,GAAiB,MAAxB,MAAOA,GACX7vB,YAAoBogB,sBAAyB,CAE7C0P,YAAYrnB,IAKV,OAAOtI,KAAKigB,WAAW2P,YAAkC,kCAJvB,CAChCC,UAAWvnB,GACX0H,YAAY,GAGhB,CAEA8f,eAAeD,IACb,OAAO7vB,KAAKigB,WAAW8P,cAAoC,qCAAuCF,GACpG,CAAChtB,oDAbU6sB,IAAiBzgB,oDAAjBygB,GAAiBpoB,QAAjBooB,GAAiB,qBAFhB,gBAEDA,EAAiB,oKCP9B/vB,oBAMEA,2DAASA,2BAAiB,GAE1BA,gBACEA,eACFA,SAAO,2BALPA,oBAFAA,iCAA8B,wBAM+BA,yCAAnCA,yCCmBrB,IAAMqwB,EAAiB,MAAxB,MAAOA,GAcXnwB,YACS4Q,GACCD,GAC2Byf,GAC3BC,GACAC,GACAC,GACAlQ,GACAlS,GACAqiB,GACAC,GACAlL,IAVDplB,oBACCA,iCAC2BA,iBAC3BA,4BACAA,sCACAA,0BACAA,cACAA,kBACAA,yBACAA,gCACAA,mBArBDA,WAAO,EAKRA,gBAAY,EACZA,mBAA2C,CACjDuwB,WAAY,sBAeX,CAESC,aACV,OAAOxwB,KAAKiwB,SAASQ,IAAIC,KAC3B,CAEMC,kBAAe,sCACnB,GAAI5vB,GAAK0P,YAAYE,aAAe5P,GAAK6vB,UAWvC,OAVA7vB,GAAK6vB,WAAY,EAEjB7vB,GAAKqkB,WAAW0C,oBAAoB/mB,GAAKiP,WAAa1J,sBAA4BA,mBAAwB,CACxGgC,GAAIvH,GAAKuH,GACTS,MAAOhI,GAAKgI,MACZuD,KAAMvL,GAAKuL,KACXukB,QAAS9vB,GAAK8vB,QACdC,UAAW/vB,GAAKiP,aAGVjP,GAAKuL,MACX,KAAKlG,UACHrF,GAAKiP,iBAAmBjP,GAAKgwB,4BAA8BhwB,GAAKiwB,mBAChE,MACF,KAAK5qB,gBACHrF,GAAKiP,iBAAmBjP,GAAKkwB,4BAA8BlwB,GAAKmwB,mBAChE,MACF,KAAK9qB,YACHrF,GAAKiP,iBAAmBjP,GAAKowB,8BAAgCpwB,GAAKqwB,qBAClE,MACF,KAAKhrB,UACHrF,GAAKiP,iBAAmBjP,GAAKswB,8BAAgCtwB,GAAKuwB,sBAClE,MACF,KAAKlrB,gBACHrF,GAAKiP,iBAAmBjP,GAAKwwB,oCAAsCxwB,GAAKywB,4BACxE,MAEF,KAAKprB,eACHrF,GAAKiP,iBAAmBjP,GAAK0wB,kCAAoC1wB,GAAK2wB,0BACtE,MAEF,KAAKtrB,eACL,KAAKA,kBACHrF,GAAKiP,iBAAmBjP,GAAK4wB,0BAA4B5wB,GAAK6wB,iBAEnE,EArCkB,EAsCrB,CAEcF,0BAAuB,sCAC9BpwB,GAAKgH,WAIV,EAAMqiB,KAAerpB,GAAKgvB,wBAAwBuB,aAAavwB,GAAKgH,KAEpEhH,GAAKwwB,0BACLxwB,GAAKywB,SAAS,2BAA2B,EARN,EASrC,CAEcN,4BAAyB,sCAChCxvB,GAAKqG,WAIV,EAAMqiB,KAAe1oB,GAAKquB,wBAAwB0B,eAAe/vB,GAAKqG,KACtErG,GAAK6vB,0BAA0B,EANM,EAOvC,CAEcd,mBAAgB,sCACvBiB,GAAK3pB,WAIV,EAAMqiB,KAAesH,GAAKzhB,yBAAyB0hB,gBAAgBD,GAAK3pB,KAExE2pB,GAAKH,0BACLG,GAAKF,SAAS,uBAAuB,EART,EAS9B,CAEchB,sBAAmB,sCAC1BoB,GAAK7pB,WAIV,EAAMqiB,KAAewH,GAAK3hB,yBAAyB4hB,mBAAmBD,GAAK7pB,KAC3E6pB,GAAKL,0BAA0B,EANA,EAOjC,CAEcb,sBAAmB,sCAC1BoB,GAAK/pB,WAIV,EAAMqiB,KAAe0H,GAAK7hB,yBAAyB8hB,mBAAmBD,GAAK/pB,KAC3E+pB,GAAKP,0BAA0B,EANA,EAOjC,CAEcZ,mBAAgB,sCACvBqB,GAAKjqB,WAIV,EAAMqiB,KAAe4H,GAAK/hB,yBAAyBgiB,gBAAgBD,GAAKjqB,KAExEiqB,GAAKT,0BACLS,GAAKR,SAAS,uBAAuB,EART,EAS9B,CAEcZ,wBAAqB,sCAC5BsB,GAAKnqB,WAIV,EAAMqiB,KAAe8H,GAAKjiB,yBAAyBkiB,qBAAqBD,GAAKnqB,KAC7EmqB,GAAKX,0BAA0B,EANE,EAOnC,CAEcV,qBAAkB,sCACzBuB,GAAKrqB,WAIV,EAAMqiB,KAAegI,GAAKniB,yBAAyBoiB,kBAAkBD,GAAKrqB,KAE1EqqB,GAAKb,0BACLa,GAAKZ,SAAS,yBAAyB,EART,EAShC,CAEcH,iBAAc,sCAC1B,IAAKiB,GAAKvqB,GACR,OAQF,IAAIyR,SALJ,EAAM4Q,KAAekI,GAAKzC,kBAAkBT,YAAYkD,GAAKvqB,KAC7DuqB,GAAK7iB,YAAc6iB,GAAK7iB,iBAClB6iB,GAAKxC,iBAAiByC,uBAAuBD,GAAKvqB,IAExDuqB,GAAKjC,WAAY,EAGf7W,GAAO8Y,GAAK7kB,UAAUnB,QADpBgmB,GAAKvmB,OAASlG,eACc,yBAEA,6BAGhCysB,GAAKd,SAAShY,GAAM,EAjBM,EAkB5B,CAEc4X,oBAAiB,sCACxBoB,GAAKzqB,WAIV,EAAMqiB,KAAeoI,GAAK3C,kBAAkBN,eAAeiD,GAAKzqB,KAChEyqB,GAAK/iB,YAAc+iB,GAAK/iB,iBAClB+iB,GAAK1C,iBAAiByC,uBAAuBC,GAAKzqB,IACxDyqB,GAAKnC,WAAY,EAAM,EARM,EAS/B,CAEcU,sBAAmB,sCAC1B0B,GAAK1qB,WAIV,EAAMqiB,KAAeqI,GAAK9C,oBAAoB+C,mBAAmBD,GAAK1qB,KAClE0qB,GAAKnC,SAAWmC,GAAKnC,UAAYhqB,kBACnCmsB,GAAK9S,MAAMgT,YACT/T,MAAkC,CAChC3e,MAAOwyB,GAAKhjB,WACZ1H,GAAI0qB,GAAK1qB,MAGJ0qB,GAAKnC,SAAWmC,GAAKnC,UAAYhqB,kBAC1CmsB,GAAK9S,MAAMgT,YACThU,MAAkC,CAChC1e,MAAOwyB,GAAKhjB,WACZ1H,GAAI0qB,GAAK1qB,MAKf0qB,GAAKlB,0BAELkB,GAAKjB,SAAS,uBAAuB,EAxBN,EAyBjC,CAEcV,wBAAqB,sCAC5B8B,GAAK7qB,WAIV,EAAMqiB,KAAewI,GAAKjD,oBAAoBkD,wBAAwBD,GAAK7qB,KAEvE6qB,GAAKtC,SAAWsC,GAAKtC,UAAYhqB,kBACnCssB,GAAKjT,MAAMgT,YACT/T,MAAkC,CAChC3e,MAAO2yB,GAAKnjB,WACZ1H,GAAI6qB,GAAK7qB,MAGJ6qB,GAAKtC,SAAWsC,GAAKtC,UAAYhqB,kBAC1CssB,GAAKjT,MAAMgT,YACThU,MAAkC,CAChC1e,MAAO2yB,GAAKnjB,WACZ1H,GAAI6qB,GAAK7qB,MAKf6qB,GAAKrB,0BAA0B,EAvBE,EAwBnC,CAEcN,4BAAyB,sCAChC6B,GAAK/qB,WAIV,EAAMqiB,KAAe0I,GAAKlD,8BAA8BmD,yBAAyBD,GAAK/qB,KACtF+qB,GAAKnT,MAAMgT,YACTjU,MAAoC,CAClCze,MAAO6yB,GAAKrjB,WACZ1H,GAAI+qB,GAAK/qB,MAIb+qB,GAAKvB,0BAELuB,GAAKtB,SAAS,iCAAiC,EAfV,EAgBvC,CAEcR,8BAA2B,sCAClCgC,GAAKjrB,WAIV,EAAMqiB,KAAe4I,GAAKpD,8BAA8BqD,8BAA8BD,GAAKjrB,KAC3FirB,GAAKrT,MAAMgT,YACTjU,MAAoC,CAClCze,MAAO+yB,GAAKvjB,WACZ1H,GAAIirB,GAAKjrB,MAIbirB,GAAKzB,0BAA0B,EAbQ,EAczC,CAEQA,0BACN9xB,KAAKgQ,YAAchQ,KAAKgQ,WACxBhQ,KAAK4wB,WAAY,CACnB,CAEQmB,SAAS0B,IACfzzB,KAAKwwB,OAAOkD,KACV1zB,KAAKgO,UAAUnB,QAAQ,8BAA+B,CACpDkN,KAAM/Z,KAAKgO,UAAUnB,QAAQ4mB,MAE/B,GACAzzB,KAAK2zB,cAET,CAAC9wB,oDA3RUmtB,IAAiB/gB,6BAiBlB2kB,OAAQ3kB,oIAjBP+gB,GAAiBjtB,8ZD5B9BpD,iCACGA,6uDC2BUqwB,EAAiB,qQCjBxBrwB,gBAAwC,UACnBA,SAAgBA,kCAAhBA,0EAUrBA,iBAEEA,wEAASA,kBAAsBk0B,mCAA0CA,8BAAkC,GAE3Gl0B,8BAA0G,UAClGA,SAAsBA,WAAO,+BADQA,qCACrCA,qEA3BhBA,eAAuB,cAInBA,wDAAcm0B,uBAAcn0B,qCAA2B,EAAvDA,CAAwD,yDAC1CA,sBAAY,GAE1BA,eACFA,QACAA,wBAAuE,QAEnEA,uBAGAA,gBACEA,0DAASA,mCAAyB,GAIlCA,eACAA,gBAAMA,gCAAyDA,UAEjEA,wBAQFA,WAAK,sCA5BLA,sCAKwBA,8CAIjBA,qCAMHA,8EAEwBA,8CAClBA,oEAGiBA,0CCPxB,IAAMo0B,GAA6B,MAApC,MAAOA,GAQXl0B,YACU4Q,EACAujB,GACAC,GACA7O,GACAlL,IAJAla,mBACAA,8BACAA,sBACAA,mBACAA,yBARVA,eAAqBA,KAAKyQ,YAAYyjB,SASnC,CAEHvH,aACEvqB,SAASwqB,gBAAgBC,UAAUC,IAAI,eACzC,CAEAC,aACE3qB,SAASwqB,gBAAgBC,UAAUG,OAAO,eAC5C,CAKAmH,4BACMn0B,KAAKoK,aAAa9H,QAGtBtC,KAAKg0B,sBAAsBI,kCAAkC7zB,UAAW6J,IACtEpK,KAAKoK,YAAcA,EAAYuB,IAAKxD,MAEhCkD,KAAMlD,GAAKE,GACXS,MAAOX,GAAKW,MACZwC,UAAU,KAGdtL,KAAKoK,YAAYb,QAASc,KACxBrK,KAAKq0B,sBAAsBhqB,GAAU,EACtC,EAEL,CAMAgqB,sBAAsBlsB,GACpBnI,KAAKg0B,sBAAsBM,qBAAqBnsB,EAAKkD,MAAM9K,UAAW8P,KAChEA,GAAM/B,KAAM0C,IAASA,GAAK3I,KAAOrI,KAAKsI,MACxCH,EAAKmD,UAAW,IAGtB,CAEMipB,uBAAuBlqB,GAAuB,4CAClD,EAAMsgB,KAAe5pB,GAAKizB,sBAAsBQ,oBAAoBnqB,EAAWgB,KAAMtK,GAAKuH,KAC1F+B,EAAWiB,UAAW,EACtBvK,GAAKkzB,cAAcQ,QACjB1zB,GAAKmZ,iBAAiBrN,QAAQ,yCAA0C,CACtE6nB,UAAW3zB,GAAKgI,MAChB4rB,gBAAiBtqB,EAAWvB,SAGhC/H,GAAKszB,sBAAsBhqB,GAE3BtJ,GAAKqkB,WAAW0C,oBAAoBxhB,sBAA4B,CAC9DqH,KAAM5M,GAAKgI,OACV,EAb+C,EAcpD,CAEM6rB,4BAA4BvqB,GAAuB,4CACvD,EAAMsgB,KAAerpB,GAAK0yB,sBAAsBa,yBAAyBxqB,EAAWgB,KAAM/J,GAAKgH,KAC/F+B,EAAWiB,UAAW,EACtBhK,GAAK2yB,cAAcQ,QACjBnzB,GAAK4Y,iBAAiBrN,QAAQ,4CAA6C,CACzE6nB,UAAWpzB,GAAKyH,MAChB4rB,gBAAiBtqB,EAAWvB,SAIhCxH,GAAK+yB,sBAAsBhqB,GAE3B/I,GAAK8jB,WAAW0C,oBAAoBxhB,2BAAiC,CACnEqH,KAAMrM,GAAKyH,OACV,EAdoD,EAezD,CAEA+rB,0BACE90B,KAAKolB,WAAW0C,oBAAoBxhB,sBAA4B,CAC9DqH,KAAM3N,KAAK+I,OAEf,CAEIjI,mBACF,OAAOA,IACT,CAAC+B,oDAlGUkxB,IAA6B9pB,iGAA7B8pB,GAA6BhxB,8mBDhB1CpD,+BAAMA,24CCgBOo0B,EAA6B,+WCZlBp0B,qBAAyDA,oCCK1E,IAAMo1B,GAAwB,MAA/B,MAAOA,GAAwBlyB,oDAAxBkyB,GAAwB,sCAAxBA,GAAwBhyB,uYDTrCpD,iBACEA,8BACAA,iBAAqB,aAEhBA,SAAiBA,sBACnBA,QACDA,iBAAyB,gCAE3BA,kBAPkBA,+BAAa,uBAAbA,CAAa,yBAG1BA,qCAAqBA,wCAGEA,yJCEjBo1B,EAAwB,wFCN/Bp1B,+CACAA,+DAGEA,oFAGAA,sBAA8CA,2DAKlDA,oBAAgDA,SAAiBA,gCAAjBA,6DAI9CA,oBAA+DA,SAAsBA,gCAAtBA,kEAO/DA,kBACEA,SACFA,qCADEA,yDANJA,SACEA,kBACAA,kBACEA,8BACFA,QACAA,yBAGFA,gCALIA,yDAEuBA,4CClBxB,IAAMq1B,GAA0B,MAAjC,MAAOA,GAA0BnyB,oDAA1BmyB,GAA0B,sCAA1BA,GAA0BjyB,mxBDRvCpD,iBAA0B,UAA1BA,CAA0B,SAGpBA,wBACAA,wBAKAA,iBACEA,sBACFA,YAGJA,iBACEA,0BACAA,mBAAgCA,UAAgBA,QAChDA,kBACAA,mBACEA,4BACFA,QACAA,mCASFA,kBA3BUA,sCAEHA,qCAKGA,wCAKqBA,sCACGA,8BAGtBA,6DAEKA,quCCbNq1B,EAA0B,mDCNnCr1B,sBAAgFA,0DAkBhFA,qBACEA,8BACFA,gBADEA,qFAEFA,qBACEA,gBACFA,gBAD0BA,oEAE1BA,qBACEA,gBACFA,gBAD0BA,uFAE1BA,qBAGEA,4DAASA,sBAAY,GAErBA,gBACFA,eAD0BA,8FAjC5BA,oBAAsBA,8DAAYA,iBAAO,GACvCA,sBACAA,mBAGEA,iGAA0B,uDAOjBA,qCAA6B,EAPtCA,CAA0B,qDAQjBA,mBAAS,6CAXpBA,QAiBAA,2BAGAA,2BAGAA,2BAGAA,2BAOFA,kCAlCMA,uEAIFA,0CAA0B,iIAcnBA,uEAGAA,uEAGAA,yCAKNA,mHAYGA,iBAAmEA,yEAASA,yBAAiB,GAC3FA,SACFA,uCADEA,yDALNA,SACEA,oBAAsCA,8BAA4CA,QAClFA,kBACAA,iBACEA,wBAGFA,QACFA,iCAPwCA,sDAGfA,iFAMvBA,SACEA,kBACFA,sDAKIA,iBAAiE,UAG7DA,yEAASA,iCAAyB,GAMlCA,yCACFA,SAAI,gCARFA,oCAO4BA,wDAZpCA,SACEA,kBACAA,iBACEA,wBAYFA,QACFA,iCAbyBA,gFAR3BA,SACEA,kCAGAA,oBAAsCA,8BAAoDA,QAC1FA,kCAiBFA,iCArBiBA,0DAGuBA,8DACvBA,iFAmBfA,SACEA,kBACFA,sCAKIA,iBAA+D,UAQ3DA,uCACFA,mDAPEA,sEAM0BA,0BAAa,gEAX/CA,SACEA,kBACAA,iBACEA,wBAWFA,QACFA,iCAZyBA,8EAR3BA,SACEA,kCAGAA,oBAAsCA,8BAAkDA,QACxFA,kCAgBFA,iCApBiBA,0DAGuBA,4DACvBA,kFAtCnBA,kBACEA,kCASAA,kCAuBAA,kCAsBFA,gCAtDiBA,0DASAA,sDAuBAA,qDCvCd,IAAMs1B,GAAsB,MAA7B,MAAOA,GAqBXp1B,YACU6tB,GACAC,GACA0C,GACA6E,GACAC,GACAp1B,GACAytB,GACAzf,GACAqX,IARAplB,6BACAA,2BACAA,yBACAA,4BACAA,0BACAA,eACAA,wBACAA,uBACAA,mBA1BVA,YAAQ,EACRA,qBAAiB,EAEjBA,uBAAoB,IAAIo1B,IAExBp1B,iBAAc,GACdA,kBAAe,GACfA,wBAAsC,CACpC6H,KAAMhB,cACNwuB,aAAa,EACbvtB,iBAAkB,GAIpB9H,WAAQA,KAAK+N,eAAeunB,KAAO,OAAS,QAC5Ct1B,iBAAcA,KAAK+N,eAAexM,kBAAkBg0B,WAYjD,CAEH3O,cACE5mB,KAAKw1B,qBAAqBC,cAC1Bz1B,KAAK01B,0BAA0BD,aACjC,CAEAx1B,WACE,OAAQD,KAAKsM,MACX,KAAKxL,gBACHd,KAAKw1B,oBAAsBx1B,KAAK2tB,mBAAmBgI,MAAMp1B,UAAWC,KAClER,KAAK2uB,QAAUnuB,GACfR,KAAK41B,aAAe51B,KAAK2uB,QAAQrpB,QAEnC,MAEF,KAAKxE,kBACHd,KAAKw1B,oBAAsBx1B,KAAK0tB,qBAAqBiI,MAAMp1B,UAAWC,KACpER,KAAK2uB,QAAUnuB,GACfR,KAAK41B,aAAe51B,KAAK2uB,QAAQrpB,QAEnC,MAEF,KAAKxE,wBACL,KAAKA,8BACHd,KAAKw1B,oBAAsBx1B,KAAKqwB,iBAAiBsF,MAAMp1B,UAAWC,KAChER,KAAK2uB,QAAUnuB,GACfR,KAAK41B,aAAe51B,KAAK2uB,QAAQrpB,QAMvCtF,KAAK61B,kBAAkB11B,QAAK21B,KAAa,MAAMv1B,UAAWw1B,KACxD,GAAI/1B,KAAKg2B,eAGP,OAFAh2B,KAAKg2B,gBAAiB,OACtBh2B,KAAKoN,kBAAe3L,GAGlBs0B,IAAeA,GAAYzzB,QAAU,GACnCtC,KAAK01B,0BACP11B,KAAK01B,yBAAyBD,cAE5Bz1B,KAAKsM,OAASxL,gBAChBd,KAAK01B,yBAA2B11B,KAAK2tB,mBAAmBsI,sBAAsBF,IAAax1B,UACxF6M,KAEC,GADApN,KAAKoN,aAAepN,KAAKm1B,kBAAkBjoB,uBAAuB6oB,GAAa3oB,IAC3EpN,KAAKg2B,eAGP,OAFAh2B,KAAKg2B,gBAAiB,OACtBh2B,KAAKoN,kBAAe3L,GASpBzB,KAAK2nB,SALL3nB,KAAKoN,aAAaC,YAAY/K,QAC9BtC,KAAKoN,aAAalJ,QAAQ5B,QAC1BtC,KAAKoN,aAAaE,MAAMhL,QACxBtC,KAAKoN,aAAaG,gBAAgBjL,QAMpCtC,KAAKg2B,gBAAiB,GAEvBnV,KAEC7gB,KAAKoN,kBAAe3L,EACpBzB,KAAK2nB,OAAQ,EACb3nB,KAAKg2B,gBAAiB,IAGjBh2B,KAAKsM,OAASxL,oBACvBd,KAAK01B,yBAA2B11B,KAAK0tB,qBAClCuI,sBAAsBF,IACtB51B,QACC2Q,KAAW,KAET9Q,KAAKoN,kBAAe3L,EACbsP,OAGVxQ,UAAW6M,KAEV,GADApN,KAAKoN,aAAepN,KAAKk1B,oBAAoBhoB,uBAAuB6oB,GAAa3oB,IAC7EpN,KAAKg2B,eAGP,OAFAh2B,KAAKg2B,gBAAiB,OACtBh2B,KAAKoN,kBAAe3L,GASpBzB,KAAK2nB,SALL3nB,KAAKoN,aAAaC,YAAY/K,QAC9BtC,KAAKoN,aAAalJ,QAAQ5B,QAC1BtC,KAAKoN,aAAaE,MAAMhL,QACxBtC,KAAKoN,aAAaG,gBAAgBjL,OAIrB,KAMrBtC,KAAKoN,kBAAe3L,GAG1B,CAEMy0B,QAAQ/oB,GAAeka,IAAoB,sCAC/C,IAAI8O,GAAehpB,GAAMipB,OACH,KAAlB/O,GAAMgP,SACRt1B,GAAK4mB,OAAQ,EACb5mB,GAAKi1B,gBAAiB,EAClBj1B,GAAK4tB,UACP5tB,GAAK4tB,QAAQrpB,MAAQ6wB,UAEjBp1B,GAAKoM,SACFpM,GAAKu1B,cAAgBH,KAC9Bp1B,GAAKu1B,YAAcH,GACnBp1B,GAAK80B,kBAAkBzN,KAAKrnB,GAAKu1B,aAClC,EAZ8C,EAajD,CAEAC,WAEIv2B,KAAKoN,cAAcC,YAAY/K,QAC/BtC,KAAKoN,cAAclJ,QAAQ5B,QAC3BtC,KAAKoN,cAAcE,MAAMhL,QACzBtC,KAAKoN,cAAcG,gBAAgBjL,UAEnCtC,KAAK2nB,OAAQ,EAEjB,CAEA6O,oBAAoBruB,IAClBnI,KAAKolB,WAAW0C,oBAAoBxhB,gCAAsC,CAAEyC,MAAOZ,GAAKW,OAC1F,CAEA2tB,aACEz2B,KAAK41B,aAAe,GACpB51B,KAAKs2B,YAAc,GACft2B,KAAKsM,OAASxL,gBAChBd,KAAK2tB,mBAAmB8I,aACfz2B,KAAKsM,OAASxL,mBACvBd,KAAK0tB,qBAAqB+I,aAE5Bz2B,KAAKoN,kBAAe3L,CACtB,CAEMi1B,YAAYvpB,IAAa,sCAC7B7L,GAAKs0B,aAAezoB,SACd7L,GAAK6L,OAAQ,EAFU,EAG/B,CAEMA,QAAK,sCACLlL,GAAK0sB,UACP1sB,GAAK0sB,QAAQrpB,MAAQrD,GAAK2zB,aAEtB3zB,GAAKmsB,aAAe7E,OAAOuF,SAASC,UAAa9sB,GAAKmsB,YAcxDnsB,GAAKurB,gBAAgBQ,sBAEf/rB,GAAKlC,OAAOouB,SAAS,CAAClsB,GAAKmsB,aAEjCnsB,GAAK0lB,OAAQ,EACT1lB,GAAKqK,OAASxL,gBAChBmB,GAAK0rB,mBAAmBxgB,QACflL,GAAKqK,OAASxL,kBACvBmB,GAAKyrB,qBAAqBvgB,QAE1BlL,GAAK0sB,UACJ1sB,GAAKqK,OAASxL,sBAAiCmB,GAAKqK,OAASxL,iCAExDmB,GAAKouB,iBAAiBsG,OAAO10B,GAAK0sB,QAAQrpB,UA1BlDrD,GAAK0lB,OAAQ,EACT1lB,GAAKqK,OAASxL,gBAChBmB,GAAK0rB,mBAAmBxgB,QACflL,GAAKqK,OAASxL,kBACvBmB,GAAKyrB,qBAAqBvgB,SAE1BlL,GAAKqK,OAASxL,sBACdmB,GAAKqK,OAASxL,yBACdmB,GAAKqK,OAASxL,uCAERmB,GAAKouB,iBAAiBsG,OAAO10B,GAAK0sB,QAAQrpB,SAmBrD,EAlCQ,EAmCX,CAGAsxB,cAAcxL,IACPA,GAAOyL,QAAQ,2BAClB72B,KAAK2nB,OAAQ,EAEjB,CAEAmP,YAAYtkB,IAEM,IAAZA,GAAEukB,QADSvkB,GAAE4Y,OACYyL,QAAQ,2BACnC72B,KAAK2nB,OAAQ,EAEjB,CAEI7mB,mBACF,OAAOA,GACT,CAEI6F,sBACF,OAAOA,GACT,CAAC9D,oDAjPUoyB,IAAsBhmB,kJAAtBgmB,GAAsBlyB,qHAAtB4oB,2BAA4B,wCAA5BA,kBAAmB,o/CDhChChsB,eACEA,2BAoCAA,eACEA,wBAwDFA,kBA9FGA,6BAAyB,oCACrBA,kCAoCFA,mCACGA,kpWCNGs1B,EAAsB,mGCnB5B,IAAM+B,EAAmB,MAA1B,MAAOA,EAAmBn0B,kDAAnBm0B,EAAmB,uCAAnBA,IAAmBn0B,yCAHpBI,KAAc4a,IAAYmM,eAGzBgN,CAAmB,oECRzB,IAAMC,EAAmB,MAA1B,MAAOA,EACXC,UAAUzqB,GACR,OAAIA,IACFA,EAAQ,OAASA,EAAQ,KAEpBA,GAAS,EAClB,CAAC5J,kDANUo0B,EAAmB,8DAAnBA,EAAmBE,iBAAnBF,CAAmB,8ECGzB,IAAMG,EAAa,MAApB,MAAOA,GACXF,UAAU1uB,EAAoBmQ,EAAgBF,EAAiB4e,EAAe9Z,GAC5E,IAAK/U,GAAwB,UAAfA,EAAMX,KAClB,MAAO,GAET,IAAIyvB,EACAC,EACJ,MAAMC,GAAsB,CAACC,EAAmBC,KAEvC,GADeD,EAAYC,IACPD,EAG7B,GAAIjvB,EAAMsC,WAAY,CACpB,IAAK6N,GAASF,EAAQ,CACpB,MAAMkf,EAAaH,GAAoBhvB,EAAMsC,WAAWyN,OAAQE,GAChE6e,EAAuB9uB,EAAMsC,WAAW4N,MAAQif,EAElD,GAAIhf,IAAUF,EAAQ,CACpB,MAAMkf,EAAaH,GAAoBhvB,EAAMsC,WAAW4N,MAAOC,GAC/D4e,EAAwB/uB,EAAMsC,WAAWyN,OAASof,GAE/Chf,IAAUF,IACb6e,EAAuB9uB,EAAMsC,WAAW4N,MACxC6e,EAAwB/uB,EAAMsC,WAAWyN,QAI7C,MAAMqf,GAAUP,EAAiB,QAATA,EAAiB,MAAQ,OAAU,MACrDQ,GAAWlf,GAAgB2e,EAC3BQ,GAAYrf,GAAkB8e,EACpC,IAAKM,KAAaC,GAChB,MAAO,GAET,MAAMC,GAAeD,GAAYD,GAC3BG,GAAer2B,sBAA8B,CAACwM,EAAoBE,KAC/DgJ,KAAK4gB,IAAI5pB,GAAE6pB,MAAQH,IAAgB1gB,KAAK4gB,IAAI9pB,EAAE+pB,MAAQH,IAAgB1pB,GAAIF,GAE7EgqB,GAAsBx2B,oBAA6B6Q,GAAMA,EAAE0lB,QAAUF,GAAaE,QAAQptB,WAChG,IAAKqtB,GACH,MAAO,GAET,MAAMC,GAAoBD,GAAoBE,OAAO,CAAClqB,EAAsBE,KAC5DgJ,KAAK4gB,IAAI5pB,GAAEqK,MAAQmf,IACnBxgB,KAAK4gB,IAAI9pB,EAAEuK,MAAQmf,KACDxpB,GAAEqK,OAASmf,GAAWxpB,GAAIF,GAItDuJ,GAAOlP,EAAM4J,SACf5J,EAAM4J,UACL5J,EAAMqC,MAAMytB,SAAS,SAAW9vB,EAAMqC,KACvClJ,kBAA4B6G,EAAMqC,KAClCrC,EAAMqC,KAEV0S,UAAY/U,EAAMoC,SAAWpC,EAAMoC,SAAW,OAAO8B,cAE9C,GAAGgL,MAASkgB,MAAWQ,GAAkB1f,SAAS0f,GAAkB7f,UAAUgF,GACvF,CAAC1a,kDAzDUu0B,GAAa,wDAAbA,GAAaD,iBAAbC,EAAa,oECoCnB,IAAMxN,EAAgB,MAAvB,MAAOA,EAAgB/mB,kDAAhB+mB,EAAgB,sCAAhBA,IAAgB/mB,yCAAhB+mB,CAAgB,oECvCtB,IAAM2O,EAAY,MAAnB,MAAOA,EACXrB,UAAUzqB,EAAe+rB,EAAQ,GAAIC,EAAW,OAC9C,MAAMC,EAAY14B,KAAK24B,MAAMlsB,GAE7B,OAAOisB,EAAUp2B,OAASk2B,EAAQE,EAAUE,UAAU,EAAGJ,GAASC,EAAWC,CAG/E,CAEAC,MAAME,GAEJ,OADY,IAAIC,WAAYC,gBAAgBF,EAAM,aACvCG,KAAKC,aAAe,EACjC,CAACp2B,kDAZU01B,EAAY,uDAAZA,EAAYpB,iBAAZoB,CAAY,oECAlB,IAAMW,EAAgB,MAAvB,MAAOA,EACXhC,UACEzqB,EACAkM,EACAF,EACA4e,EACA7a,EACA2c,GAEA,MAAMC,EAAaD,GAAW,GAE9B,GAAI1sB,EAAO,CACT,MAAM4sB,EAAiB,GACvB,IAAIC,GAAa,GAEb/P,OAAOgQ,SACTF,EAAejxB,KAAK,eAElBoU,GACF6c,EAAejxB,KAAK,WAAaoU,GAEnC6c,EAAejxB,KAAK,WAAWgxB,KAC3BzgB,GACF0gB,EAAejxB,KAAK,SAASuQ,KAE3BF,GACF4gB,EAAejxB,KAAK,UAAUqQ,KAEnB,SAAT4e,GACFgC,EAAejxB,KAAK,QAAUivB,GAE5BgC,EAAe/2B,SACjBg3B,GAAa,IAAMD,EAAeniB,KAAK,MAEzCzK,GAAgB6sB,GAElB,OAAO7sB,GAAS,EAClB,CAAC5J,kDArCUq2B,EAAgB,2DAAhBA,EAAgB/B,iBAAhB+B,CAAgB,kGCOtB,IAAMM,EAAuB,MAA9B,MAAOA,EACX35B,YAAoB45B,EAAyBC,GAAzB15B,WAAyBA,mBAErCA,iBAAc,UAFqD,CAI3E25B,wCAEE,OAAO35B,KAAKy5B,IACTtX,QACC,kCAAkCniB,KAAK05B,YAAYn4B,kBAAkBmhB,gBAEtEviB,QAAKwL,KAAKjE,GAAe1H,KAAK45B,8BAA8BlyB,IACjE,CAEAmqB,aAAavpB,GACX,OAAOtI,KAAKy5B,IAAIvY,SAAiB,qCAAqC5Y,iBAAkBtI,KAAK65B,cAC/F,CAEA7H,eAAe1pB,GACb,OAAOtI,KAAKy5B,IAAIK,WAAmB,0CAA0CxxB,iBAAkBtI,KAAK65B,cACtG,CAEQD,8BAA8BlyB,GACpC,IAAKA,EACH,OAGF,MAAMqyB,EAAoC,GAC1CryB,SAAW6B,QAASE,IAClBswB,EAAK3xB,KAAK,CACRqB,SAAU,CACRnB,GAAImB,EAASpB,GACbK,SAAU,CAAEsxB,MAAOvwB,EAAShB,SAASwxB,MAAO7iB,QAAS3N,EAAShB,SAASyxB,SACvEvwB,MAAOF,EAASC,MAChBI,OAAQL,EAAS1E,OACjBgE,MAAOU,EAASX,MAChBc,OAAQH,EAAS3D,OACjBuD,MAAOI,EAASL,MAChB1H,IAAK+H,EAAST,IACdR,MAAOiB,EAASlB,MACZ,CACEmP,KAAMjO,EAASlB,MAAMsC,KACrByB,KAAM7C,EAASlB,MAAMV,KACrByQ,SAAU7O,EAASlB,MAAM6J,SACzBqL,aAAchU,EAASlB,MAAMiV,aAC7BrF,UAAW1O,EAASlB,MAAMoC,UAC1B9B,YAAaY,EAASlB,MAAMI,YAC5B6P,WAAY/O,EAASlB,MAAMuC,WACvB,CAAE6N,MAAOlP,EAASlB,MAAMuC,WAAW4N,MAAOD,OAAQhP,EAASlB,MAAMuC,WAAWyN,aAC5E9W,EACJwa,SAAUxS,EAASlB,MAAMyT,SACzB2B,SAAUlU,EAASlB,MAAMmV,SACzBH,SAAU9T,EAASlB,MAAMqC,SACzBtC,GAAImB,EAASlB,MAAMF,GACnBwD,KAAMpC,EAASlB,MAAM8C,KACrBtC,MAAOU,EAASlB,MAAMO,YAExBrH,EACJoI,QAASJ,EAASzD,QAClB6C,YAAaY,EAASd,aAExBwxB,YAAY,EACZC,YAAY,GACb,GAGIL,CACT,CAACl3B,kDAnEU22B,GAAuB12B,gEAAvB02B,EAAuBlyB,QAAvBkyB,EAAuB,qBAFtB,gBAEDA,CAAuB,+HCD7B,IAAMa,EAA6B,MAApC,MAAOA,EAIXx6B,YAAoB45B,EAAyBhpB,EAAkC1C,IAA3D/N,WAAyBA,mBAAkCA,uBAHvEA,UAAO,IAAIs6B,IAAqC,GACxDt6B,WAAQA,KAAKQ,KAAK+5B,eAIVv6B,aAAS,CAF+F,CAGhHw6B,aACE,MAAMle,EAAU,IAAIge,IAAuB,GAC3C,OAAKt6B,KAAKiB,OAiBRqb,EAAQ8L,MAAK,GAhBbpoB,KAAK8qB,iBACF3qB,QACC2Q,KAAY+P,IACVvE,EAAQ8L,MAAK,GACNrX,OAGVxQ,UAAWC,IACNA,GACF8b,EAAQ8L,MAAK,GACbpoB,KAAKiB,QAAS,GAEdqb,EAAQ8L,MAAK,EAAK,GAMnB9L,CACT,CAEAwO,iBACE,MAAMxO,EAAU,IAAIge,IAAuB,GAC3C,OACEt6B,KAAKyQ,YAAYE,YACjB3Q,KAAKyQ,YAAYyjB,YAChBl0B,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,eAEvDxO,KAAKy5B,IACFtX,QACC,+CAA+CniB,KAAK+N,eAAexM,kBAAkBmhB,gBAEtFviB,QACC2Q,KAAY+P,IACVvE,EAAQ8L,MAAK,GACNrX,OAGVxQ,UAAWC,IACV8b,EAAQ8L,MAAK,GACbpoB,KAAKQ,KAAK4nB,KAAK5nB,GAAQ,GAAE,IAG7BR,KAAKQ,KAAK4nB,KAAK,IACf9L,EAAQ8L,MAAK,IAER9L,CACT,CAEAgX,yBAAyBhrB,GACvB,OAAOtI,KAAKy5B,IAAIvY,SAAiB,yCAAyC5Y,KAAMnI,QAC9EwL,MAAKzD,IACHlI,KAAK8qB,iBACE5iB,IAGb,CAEAsrB,8BAA8BlrB,GAC5B,OAAOtI,KAAKy5B,IAAIK,WAAmB,8CAA8CxxB,KAAMnI,QACrFwL,MAAKzD,IACHlI,KAAK8qB,iBACE5iB,IAGb,CAACrF,kDA3EUw3B,GAA6BI,2EAA7BJ,EAA6B/yB,QAA7B+yB,EAA6B,qBAF5B,gBAEDA,CAA6B,sHCOnC,IAAMK,EAAqB,MAA5B,MAAOA,EACX76B,YACU45B,EACAxtB,EACAkU,EACA1P,GACA1C,IAJA/N,WACAA,kBACAA,4BACAA,oBACAA,sBACP,CAEHywB,IAAInoB,GACF,OAAOtI,KAAKy5B,IAAItX,QAA6B,sBAAsB7Z,IACrE,CAEAqyB,OAAO3B,GACL,OAAOh5B,KAAKy5B,IAAIvY,SAA8B,wBAAyB8X,EACzE,CAEA4B,KAAK5B,GACH,OAAOh5B,KAAKy5B,IAAIoB,QAA6B,wBAAyB7B,EACxE,CAEA8B,OAAOxyB,GACL,OAAOtI,KAAKy5B,IAAIK,WAAmB,yBAAyBxxB,IAC9D,CAEAyyB,aAAazyB,GACX,OAAOtI,KAAKy5B,IAAIuB,UAAkB,8BAA8B1yB,IAClE,CAMA2yB,uBACE,IAAIv5B,EACJ,OACEA,EADE1B,KAAKyQ,YAAYyjB,UACb,mDAAmDl0B,KAAK+N,eAAexM,kBAAkBmhB,eACtF1iB,KAAKyQ,YAAYyqB,UACpB,wDAAwDl7B,KAAK+N,eAAexM,kBAAkBmhB,eAE9F,uCAAuC1iB,KAAK+N,eAAexM,kBAAkBmhB,eAE9E1iB,KAAKy5B,IACTtX,QAA+BzgB,GAC/BvB,QAAKwL,KAAKvB,GAAgBpK,KAAKmgB,qBAAqBhW,yBAAyBC,IAClF,CAMAkqB,qBAAqBhsB,GACnB,OAAOtI,KAAKy5B,IACTtX,QAAqB,4BAA4B7Z,KACjDnI,QAAKwL,KAAK0E,GAAUrQ,KAAKiM,WAAWmE,gBAAgBC,IACzD,CAEAmkB,oBAAoB2G,EAAsBC,GACxC,OAAOp7B,KAAKy5B,IAAIvY,SAAiB,2BAA4B,CAC3Dma,UAAWF,EACXG,OAAQF,GAEZ,CAEAvG,yBAAyBsG,EAAsBC,GAC7C,OAAOp7B,KAAKy5B,IAAIK,WAAmB,gCAAiC,CAClEuB,UAAWF,EACXG,OAAQF,GAEZ,CAEAG,kBAAkBJ,GAChB,OAAOn7B,KAAKy5B,IAAItX,QACd,uCAAuCgZ,oBAA+Bn7B,KAAK+N,eAAexM,kBAAkBmhB,0BAA0B1iB,KAAK+N,eAAexM,kBAAkB8G,KAEhL,CAEAmzB,oBAAoBL,EAAsBM,GACxC,OAAOz7B,KAAKy5B,IAAIvY,SAAiB,2BAA4B,CAC3Dma,UAAWF,EACXha,OAAQsa,GAEZ,CAEAC,yBAAyBP,EAAsBM,GAC7C,OAAOz7B,KAAKy5B,IAAIK,WAAmB,gCAAiC,CAClEuB,UAAWF,EACXha,OAAQsa,GAEZ,CAEAE,YAAYrzB,GACV,OAAOtI,KAAKy5B,IAAItX,QAAmB,4BAA4B7Z,IACjE,CAEAszB,kBAAkBC,GAQhB,MAPgC,CAC9B,CACEC,SAAS,EACTC,UAAU,KACPF,GAIT,CAEAG,2BAA2BC,EAAgB/6B,GACzC,MAAMV,EAA+B,GAErC,QAAS07B,GAAQ,EAAGA,GAAQD,EAAQC,KAClC17B,EAAK4H,KAAK,CAAE0zB,SAAS,EAAMK,QAASj7B,IAAW,IAEjD,OAAOV,CACT,CAOA4zB,gCAAgC7hB,EAAiB,GAC/C,OAAOvS,KAAKy5B,IACTtX,QACC,yCAAyCniB,KAAK+N,eAAexM,kBAAkBmhB,uBAAuBnQ,KAEvGpS,QAAKwL,KAAKvB,GAAgBpK,KAAKmgB,qBAAqBhW,yBAAyBC,IAClF,CAACvH,kDA9HU63B,GAAqBzwB,kGAArBywB,EAAqBpzB,QAArBozB,EAAqB,qBAFpB,gBAEDA,CAAqB,4GCN3B,IAAM0B,EAAmB,MAA1B,MAAOA,EAIXv8B,YACUogB,EACAxP,EACA1C,GAFA/N,kBACAA,mBACAA,sBANFA,UAAO,IAAIs6B,IAA2B,GAC9Ct6B,WAAQA,KAAKQ,KAAK+5B,eAQVv6B,aAAS,CAFd,CAGHw6B,aACE,MAAMle,EAAU,IAAIge,IAAuB,GAC3C,OAAKt6B,KAAKiB,OAeRqb,EAAQ8L,MAAK,GAdbpoB,KAAK8qB,iBAAiBvqB,UACnBC,IACKA,GACF8b,EAAQ8L,MAAK,GACbpoB,KAAKiB,QAAS,GAEdqb,EAAQ8L,MAAK,EAAK,EAGrBvH,IACCvE,EAAQ8L,MAAK,EAAK,GAMjB9L,CACT,CAEAwO,iBACE,MAAMxO,EAAU,IAAIge,IAAuB,GAC3C,OAAIt6B,KAAKyQ,YAAYE,aAAe3Q,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,eACxFxO,KAAKigB,WACFkC,QACC,0CAA0CniB,KAAK+N,eAAexM,kBAAkBmhB,gBAEjFniB,UACEC,IACCR,KAAKQ,KAAK4nB,KAAK5nB,GAAQ,IACvB8b,EAAQ8L,MAAK,EAAI,EAElBvH,IACCvE,EAAQ8L,MAAK,EAAK,GAIxB9L,EAAQ8L,MAAK,GAER9L,CACT,CAEA4P,gBAAgBkP,EAAgBlrB,EAAkBmsB,GAMhD,OAAOr8B,KAAKigB,WAAWiB,SAAiB,4BALR,CAC9Boa,OAAQF,EACRzrB,SAAUO,EACVosB,WAAYD,IAE6Dl8B,QACzEwL,KAAKzD,KACHlI,KAAK8qB,iBACE5iB,KAGb,CAACrF,kDAnEUu5B,GAAmBnyB,6EAAnBmyB,EAAmB90B,QAAnB80B,EAAmB,qBAFlB,gBAEDA,CAAmB,4GCDzB,IAAMG,EAAmB,MAA1B,MAAOA,EAIX18B,YAAoB45B,EAAyBhpB,EAAkC1C,GAA3D/N,WAAyBA,mBAAkCA,sBAHvEA,UAAO,IAAIs6B,IAA2B,GAC9Ct6B,WAAQA,KAAKQ,KAAK+5B,eAIVv6B,aAAS,CAF+F,CAIhHw6B,aACE,MAAMle,EAAU,IAAIge,IAAuB,GAC3C,OAAKt6B,KAAKiB,OAeRqb,EAAQ8L,MAAK,GAdbpoB,KAAK8qB,iBAAiBvqB,UACnBC,IACKA,GACF8b,EAAQ8L,MAAK,GACbpoB,KAAKiB,QAAS,GAEdqb,EAAQ8L,MAAK,EAAK,EAGrBvH,IACCvE,EAAQ8L,MAAK,EAAK,GAMjB9L,CACT,CAEAwO,iBACE,MAAMxO,EAAU,IAAIge,IAAuB,GAC3C,OAAIt6B,KAAKyQ,YAAYE,aAAe3Q,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,eACxFxO,KAAKy5B,IACFtX,QACC,wCAAwCniB,KAAK+N,eAAexM,kBAAkBmhB,gBAE/EniB,UACEC,IACC8b,EAAQ8L,MAAK,GACbpoB,KAAKQ,KAAK4nB,KAAK5nB,GAAQ,GAAE,EAE1BqgB,IACCvE,EAAQ8L,MAAK,EAAK,GAIxB9L,EAAQ8L,MAAK,GAER9L,CACT,CAEA2W,mBAAmB3qB,GACjB,OAAOtI,KAAKy5B,IAAIvY,SAAc,mCAAmC5Y,KAAMnI,QACrEwL,KAAKzD,IACHlI,KAAK8qB,iBACE5iB,IAGb,CAEAkrB,wBAAwB9qB,GACtB,OAAOtI,KAAKy5B,IAAIK,WAAgB,wCAAwCxxB,KAAMnI,QAC5EwL,KAAKzD,IACHlI,KAAK8qB,iBACE5iB,IAGb,CAACrF,kDApEU05B,GAAmBtyB,6EAAnBsyB,EAAmBj1B,QAAnBi1B,EAAmB,qBAFlB,gBAEDA,CAAmB,sHCAzB,IAAMC,EAAmB,MAA1B,MAAOA,EAUX38B,YACUogB,EACAxP,EACA1C,GAFA/N,kBACAA,mBACAA,sBAZFA,UAAO,IAAIs6B,IAA2B,GACtCt6B,aAAS,EAEjBA,WAAQA,KAAKQ,KAAK+5B,cAUf,CARHkC,gBAAgBn0B,GACd,SAAOoJ,OAAG,EACZ,CAQA8oB,aACE,MAAMle,EAAU,IAAIge,IAAuB,GAC3C,OAAKt6B,KAAKiB,OAeRqb,EAAQ8L,MAAK,GAdbpoB,KAAK8qB,iBAAiBvqB,UACnBC,IACKA,GACF8b,EAAQ8L,MAAK,GACbpoB,KAAKiB,QAAS,GAEdqb,EAAQ8L,MAAK,EAAK,EAGrBvH,IACCvE,EAAQ8L,MAAK,EAAK,GAMjB9L,CACT,CAEAwO,iBACE,MAAMxO,EAAU,IAAIge,IAAuB,GAC3C,OAAIt6B,KAAKyQ,YAAYE,aAAe3Q,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,eACxFxO,KAAKigB,WACFkC,QACC,wCAAwCniB,KAAK+N,eAAexM,kBAAkBmhB,gBAE/EniB,UACEC,IACCR,KAAKQ,KAAK4nB,KAAK5nB,GAAQ,IACvB8b,EAAQ8L,MAAK,EAAI,EAElBvH,IACCvE,EAAQ8L,MAAK,EAAK,GAIxB9L,EAAQ8L,MAAK,GAER9L,CACT,CAEA6P,gBAAgB7jB,EAAY5H,GAC1B,OAAOV,KAAKigB,WACTiB,SAAiB,2BAA2B5Y,cAAe5H,KAC3DP,QAAKqR,KAAI,IAAMxR,KAAK8qB,kBACzB,CAACjoB,kDAhEU25B,GAAmB/M,+EAAnB+M,EAAmBl1B,QAAnBk1B,EAAmB,qBAFlB,gBAEDA,CAAmB,oHCEzB,IAAME,EAAqB,MAA5B,MAAOA,EAIX78B,YAAoBogB,qBAHZjgB,UAAO,IAAIo1B,IACnBp1B,WAAQA,KAAKQ,KAAK+5B,cAE2B,CAE7CzP,eAAesQ,GACb,OAAOp7B,KAAKigB,WAAWkC,QAA8B,GAAGniB,KAAK28B,4BAA4BvB,KAAUj7B,QACjGqR,KAAKhR,IACHR,KAAKQ,KAAK4nB,KACR,CACE/f,GAAI+yB,EACJvrB,YAAarP,GACD,GAItB,CAEAoqB,iBACE,OAAO5qB,KAAKigB,WAAWkC,QAA8BniB,KAAK48B,kBAC5D,CAEAtR,uBAAuB8P,EAAgByB,GAMrC,OAAO78B,KAAKigB,WAAWiB,SAAiBlhB,KAAK88B,0BALhC,CACXxB,OAAQF,EACR/vB,KAAMwxB,IAGsE18B,QAC5E48B,KAAe/8B,KAAK8qB,eAAesQ,KAAO,EAC1C5pB,KAAI,EAAEwrB,GAAGC,MAAoBj9B,KAAKQ,KAAK4nB,KAAK,CAAE/f,GAAI+yB,EAAQvrB,YAAaotB,OAAiB,EACxFtxB,MAAI,EAAEzD,GAAQ80B,MAAO90B,IAEzB,CAEAsjB,0BAA0B4P,EAAgByB,GAKxC,OAAO78B,KAAKigB,WAAW6Z,WAAmB95B,KAAKk9B,6BAJlC,CACX5B,OAAQF,EACR/vB,KAAMwxB,IAE2E18B,QACjF48B,KAAe/8B,KAAK8qB,eAAesQ,KAAO,EAC1C5pB,KAAI,EAAEwrB,GAAGC,MAAoBj9B,KAAKQ,KAAK4nB,KAAK,CAAE/f,GAAI+yB,EAAQvrB,YAAaotB,OAAiB,EACxFtxB,MAAI,EAAEzD,GAAQ80B,MAAO90B,IAEzB,CAEAi1B,yBAAyB/B,GACvB,OAAOp7B,KAAKigB,WAAWkC,QAAoC,GAAGniB,KAAKo9B,8BAA8BhC,IACnG,CAEIwB,wBACF,MAAO,mCACT,CAEID,gCACF,MAAO,wCACT,CAEIG,gCACF,MAAO,+BACT,CAEII,mCACF,MAAO,iCACT,CAEIE,kCACF,MAAO,oCACT,CAACv6B,kDAtEU65B,GAAqBjN,oDAArBiN,EAAqBp1B,QAArBo1B,EAAqB,qBAFpB,gBAEDA,CAAqB,oPCgB3B,IAAMW,GAAkB,MAAzB,MAAOA,GAMXx9B,YACUmM,EACA+B,GACAyf,GACSsB,GACT2K,GACAhpB,GACA0kB,GACAlpB,GACAqxB,GACAC,GACAvvB,IAVAhO,qBACAA,uBACAA,wBACSA,iBACTA,YACAA,oBACAA,0BACAA,mBACAA,yBACAA,oBACAA,kBAdFA,UAAO,IAAIs6B,IAAmC,GACtDt6B,WAAQA,KAAKQ,KAAK+5B,eAehBv6B,KAAK2uB,QAAU,CACbC,eAAe,EACf4O,cAAc,EACdC,SAAUz9B,KAAKyQ,YAAYE,WAC3BwrB,SAAS,EACT72B,MAAO,GACPo4B,WAAY,CACVpc,eAAgBthB,KAAK+N,eAAexM,kBAAkBmhB,cAAgB,GACtEib,IAAK,GACLC,KAAM,EACNt4B,MAAO,GACPu4B,WAAY,IACZh6B,WAAY,GACZM,iBAAkB,GAClBO,OAAQ,GACRa,cAAe,GACfT,UAAW,GACXF,cAAe,GACfD,aAAc,GACdm5B,aAAc,IAEhBC,YAAQt8B,EACR6L,WAAO7L,EACPu8B,iBAAav8B,GAEfzB,KAAKs9B,iBAAiBW,WAAW,KAC3Bj+B,KAAK2uB,UACP3uB,KAAK2uB,QAAQC,eAAgB,EAC7B5uB,KAAK2uB,QAAQ6O,cAAe,IAGlC,CAEA3O,oBACE,MAAMqP,EAAWl+B,KAAKgM,cAAcmyB,cAAch7B,YAAuB,GAEzEnD,KAAK2uB,QAAQrpB,MAAQ44B,EACrBl+B,KAAK2uB,QAAQ+O,WAAWp4B,MAAQ44B,GAAsB,IAEtDl+B,KAAK2uB,QAAQ+O,WAAWE,KAAO,EAC/B59B,KAAK2uB,QAAQ+O,WAAW75B,WAAa7D,KAAKgM,cAAcoyB,wBAAwBj7B,gBAChFnD,KAAK2uB,QAAQ+O,WAAWv5B,iBAAmBnE,KAAKgM,cAAcoyB,wBAC5Dj7B,sBAEFnD,KAAK2uB,QAAQ+O,WAAWn4B,cAAgBvF,KAAKgM,cAAcoyB,wBAAwBj7B,mBACnFnD,KAAK2uB,QAAQ+O,WAAWh5B,OAAS1E,KAAKgM,cAAcoyB,wBAAwBj7B,YAC5EnD,KAAK2uB,QAAQ+O,WAAW54B,UAAY9E,KAAKgM,cAAcoyB,wBAAwBj7B,eAC/EnD,KAAK2uB,QAAQ+O,WAAW94B,cAAgB5E,KAAKgM,cAAcoyB,wBAAwBj7B,mBACnFnD,KAAK2uB,QAAQ+O,WAAW/4B,aAAe3E,KAAKgM,cAAcqyB,kCACxDl7B,kBAEFnD,KAAK2uB,QAAQ+O,WAAWI,aAAe99B,KAAKgM,cAAcoyB,wBAAwBj7B,iBAElFnD,KAAK2uB,QAAQC,eAAgB,EAC7B5uB,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QACtB,CAEA2P,mBACEt+B,KAAKu+B,kBACFp+B,QACC2Q,KAAY+P,IACV7gB,KAAKu9B,YAAYiB,UAAUjV,OAAOuF,SAASC,SAAUlO,EAAMtO,QACpDxB,OAGVxQ,UAAWC,IACVR,KAAK2uB,QAAQrhB,MAAQ,CACnB1F,eAAgB,CACdE,iBAAkB,EAClBD,KAAMhB,aACNuU,WAAW,EACXtS,MAAO9I,KAAKgO,UAAUnB,QAAQ,kBAC9B4xB,MAAOj+B,EAAKwM,OAEdjF,MAAOvH,EAAKk+B,QAAU1+B,KAAKiM,WAAWqE,iBAAiB9P,EAAKk+B,SAAW,GACvEvrB,WAAY,CACVtL,KAAM/G,iBACNsS,eAAgB5S,EAAKwM,MACrBqG,MAAO,EACPC,SAAUtT,KAAK2uB,QAAQ+O,WAAWC,MAGtC39B,KAAK2uB,QAAQoP,OAAS/9B,KAAKm1B,kBAAkBhpB,iBAAiB3L,EAAK4L,QACnEpM,KAAK2uB,QAAQ6O,cAAe,EAC5Bx9B,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QAAO,EAEjC,CAEA4P,kBACE,OAAOv+B,KAAKy5B,IAAIkF,eAAwC,mBAAoB3+B,KAAK2uB,QAAQ+O,WAC3F,CAEAzH,sBAAsB9oB,GAQpB,OAAOnN,KAAKy5B,IAAIkF,eAAoD,6BAP/B,CACnCC,OAAO,EACPtd,eAAgBthB,KAAK+N,eAAexM,kBAAkBmhB,cAAgB,GACtEpd,MAAO6H,EACPwwB,IAAK,GAIT,CAEAkB,eAAeC,GACb,IAAI53B,GAAS,IAAI63B,KAEjB73B,GAASlH,KAAKg/B,qBAAqB93B,IAEnCA,GAASlH,KAAKi/B,yBAAyB/3B,IAEnC43B,EACF9+B,KAAK8uB,SAASgQ,aAAavV,OAAOuF,SAASC,SAAU7nB,GAAOoT,YAE5Dta,KAAK8uB,SAASoQ,GAAG3V,OAAOuF,SAASC,SAAU7nB,GAAOoT,WAEtD,CAEQ2kB,yBAAyB/3B,GAC/B,MAAsC,MAAlClH,KAAK2uB,QAAQ+O,WAAWp4B,OAAiBtF,KAAK2uB,QAAQ+O,WAAWp4B,QACnE4B,EAASA,EAAOi4B,OAAOh8B,aAAuBnD,KAAK2uB,QAAQ+O,WAAWp4B,QAGpEtF,KAAK2uB,QAAQ+O,WAAWn4B,cAAcjD,SACxC4E,EAASA,EAAOi4B,OACdh8B,qBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWn4B,iBAI7DvF,KAAK2uB,QAAQ+O,WAAW75B,WAAWvB,SACrC4E,EAASA,EAAOi4B,OACdh8B,kBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW75B,cAI7D7D,KAAK2uB,QAAQ+O,WAAWv5B,iBAAiB7B,SAC3C4E,EAASA,EAAOi4B,OACdh8B,wBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWv5B,oBAI7DnE,KAAK2uB,QAAQ+O,WAAWh5B,OAAOpC,SACjC4E,EAASA,EAAOi4B,OACdh8B,cACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWh5B,UAI7D1E,KAAK2uB,QAAQ+O,WAAW54B,UAAUxC,SACpC4E,EAASA,EAAOi4B,OACdh8B,iBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW54B,aAI7D9E,KAAK2uB,QAAQ+O,WAAW94B,cAActC,SACxC4E,EAASA,EAAOi4B,OACdh8B,qBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW94B,iBAI7D5E,KAAK2uB,QAAQ+O,WAAW/4B,aAAarC,SACvC4E,EAASA,EAAOi4B,OAAOh8B,oBAA8BnD,KAAK2uB,QAAQ+O,WAAW/4B,aAAauS,KAAK,OAG7FlX,KAAK2uB,QAAQ+O,WAAWI,aAAax7B,SACvC4E,EAASA,EAAOi4B,OACdh8B,mBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWI,gBAI1D52B,CACT,CAEQ83B,qBAAqB93B,GAC3B,GAAIlH,KAAK2uB,QAAQoP,OACf,UAAW1xB,MAASrM,KAAK2uB,QAAQoP,OAC3B1xB,GAAMjH,OACR8B,EAASA,EAAOi4B,OAAO9yB,GAAMM,SAAWxJ,YAAsB,SAIpE,OAAO+D,CACT,CAEAiG,QACEnN,KAAK2uB,QAAQ+O,WAAWp4B,MAAQtF,KAAK2uB,QAAQrpB,MAAQtF,KAAK2uB,QAAQrpB,MAAQ,IAC1EtF,KAAK22B,QACP,CAEAF,aACEz2B,KAAK2uB,QAAQrpB,MAAQ,GACrBtF,KAAKmN,OACP,CAEAwpB,OAAO3I,GACDA,GACFhuB,KAAKwtB,gBAAgBQ,gBAEvBhuB,KAAK2uB,QAAQwN,SAAU,EACvBn8B,KAAK6+B,iBACL7+B,KAAKu+B,kBACFp+B,QACC2Q,KAAW,KACT9Q,KAAK2uB,QAAQwN,SAAU,EAChBprB,OAGVxQ,UAAWC,IAASR,KAAKq/B,yBAAyB7+B,IACvD,CAEQ6+B,yBAAyB7+B,GAC3BR,KAAK2uB,QAAQrhB,QACftN,KAAK2uB,QAAQrhB,MAAMvF,MAAQvH,EAAKk+B,QAAU1+B,KAAKiM,WAAWqE,iBAAiB9P,EAAKk+B,SAAW,GACvF1+B,KAAK2uB,QAAQrhB,MAAM6F,aACrBnT,KAAK2uB,QAAQrhB,MAAM6F,WAAWC,eAAiB5S,EAAKwM,OAEtDhN,KAAK2uB,QAAQrhB,MAAM1F,eAAe62B,MAAQj+B,EAAKwM,OAEjDhN,KAAK2uB,QAAQoP,OAAS/9B,KAAKm1B,kBAAkBhpB,iBAAiB3L,EAAK4L,QACnEpM,KAAK2uB,QAAQwN,SAAU,EACvBn8B,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QACtB,CAEA2Q,YAAYjzB,GACV,OAAQA,EAAMxE,MACZ,KAAKxB,eACHrG,KAAK2uB,QAAQ+O,WAAW75B,WAAa7D,KAAKu/B,SAASlzB,EAAMtE,OACzD,MACF,KAAK1B,qBACHrG,KAAK2uB,QAAQ+O,WAAWv5B,iBAAmBnE,KAAKu/B,SAASlzB,EAAMtE,OAC/D,MACF,KAAK1B,WACHrG,KAAK2uB,QAAQ+O,WAAWh5B,OAAS1E,KAAKu/B,SAASlzB,EAAMtE,OACrD,MACF,KAAK1B,cACHrG,KAAK2uB,QAAQ+O,WAAW54B,UAAY9E,KAAKu/B,SAASlzB,EAAMtE,OACxD,MACF,KAAK1B,kBACHrG,KAAK2uB,QAAQ+O,WAAW94B,cAAgB5E,KAAKu/B,SAASlzB,EAAMtE,OAC5D,MACF,KAAK1B,gBACHrG,KAAK2uB,QAAQ+O,WAAWI,aAAe99B,KAAKu/B,SAASlzB,EAAMtE,OAC3D,MACF,KAAK1B,kBACHrG,KAAK2uB,QAAQ+O,WAAWn4B,cAAgBvF,KAAKu/B,SAASlzB,EAAMtE,OAC5D,MACF,KAAK1B,iBACHrG,KAAK2uB,QAAQ+O,WAAW/4B,aAAe0H,EAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IACzFxD,IAAsC,SAA7BA,GAAK2E,MAAMJ,eAM7B,CAEQ6yB,SAASnzB,GACf,OAAOA,EAAOI,OAAQH,KAA6B,IAAnBA,GAAMf,UAAmBK,IAAKU,IAAUA,GAAMS,MAChF,CAEA0yB,gBAAgBnzB,GACdrM,KAAK2uB,SAASoP,QAAQpyB,IAAKqF,KAEvBA,GAAK5L,KADH4L,GAAKlI,QAAUuD,EAAMvD,QACVuD,EAAMjH,IAEP,GAGhBpF,KAAK6+B,gBACP,CAEAY,QAIE,GAHAz/B,KAAK2uB,QAAQrpB,MAAQ,GACrBtF,KAAK2uB,QAAQ+O,WAAWp4B,MAAQ,IAE5BtF,KAAK2uB,QAAQoP,OACf,UAAW1xB,KAASrM,KAAK2uB,QAAQoP,OAAQ,CACvC1xB,EAAMjH,MAAO,EACb,UAAW+C,MAAQkE,EAAMtE,MACvBI,GAAKmD,UAAW,EAKtBtL,KAAK2uB,QAAQ+O,WAAWE,KAAO,EAE/B59B,KAAK2uB,QAAQ+O,WAAW75B,WAAa,GACrC7D,KAAK2uB,QAAQ+O,WAAWv5B,iBAAmB,GAC3CnE,KAAK2uB,QAAQ+O,WAAWh5B,OAAS,GACjC1E,KAAK2uB,QAAQ+O,WAAW54B,UAAY,GACpC9E,KAAK2uB,QAAQ+O,WAAW94B,cAAgB,GACxC5E,KAAK2uB,QAAQ+O,WAAW/4B,aAAe,GACvC3E,KAAK2uB,QAAQ+O,WAAWI,aAAe,GACvC99B,KAAK2uB,QAAQ+O,WAAWn4B,cAAgB,GAExCvF,KAAK22B,QACP,CAEA+I,UAAUtzB,GACRpM,KAAK2uB,QAAQoP,OAAS3xB,EACtBA,GAAQ7C,QAAS8C,KACfrM,KAAKs/B,YAAYjzB,GAAK,GAExBrM,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QACtB,CAEAgR,WAAWC,GACL5/B,KAAK2uB,SAASrhB,OAAO6F,aACvBnT,KAAK2uB,QAAQrhB,MAAM6F,WAAWE,MAAQusB,GAExC5/B,KAAK2uB,QAAQ+O,WAAWE,MAAQgC,EAAY,GAAK5/B,KAAK2uB,QAAQ+O,WAAWC,IACzEpU,OAAOsW,OAAO,EAAG,GACjB7/B,KAAK22B,QACP,CAAC9zB,oDAjVUw6B,IAAkByC,8KAAlBzC,GAAkB/1B,QAAlB+1B,GAAkB,qBAFjB,gBAEDA,EAAkB,yFChBxB,IAAM0C,GAAwB,MAA/B,MAAOA,EACXlgC,YAAoBogB,EAAgClS,GAAhC/N,kBAAgCA,qBAAiC,CAErFsR,2BAA2BV,GACzB,OAAO5Q,KAAKigB,WAAWiB,SAA0B,qCAAsCtQ,EACzF,CAEAW,uBAAuBX,GACrB,OAAO5Q,KAAKigB,WAAWiB,SAA0B,qCAAsCtQ,EACzF,CAEAC,sBAAsBD,GACpB,OAAO5Q,KAAKigB,WAAWiB,SAA0B,oCAAqCtQ,EACxF,CAEAM,sBAAsBN,GACpB,OAAO5Q,KAAKigB,WAAWiB,SAA0B,mCAAoCtQ,EACvF,CAEAovB,qCACE,OAAOhgC,KAAKigB,WAAWkC,QACrB,+BAA+BniB,KAAK+N,eAAexM,kBAAkBmhB,eAEzE,CAEAud,mCACE,OAAOjgC,KAAKigB,WAAWkC,QACrB,oCAAoCniB,KAAK+N,eAAexM,kBAAkBmhB,eAE9E,CAEAwd,wCACE,OAAOlgC,KAAKigB,WAAWkC,QACrB,mCAAmCniB,KAAK+N,eAAexM,kBAAkBmhB,eAE7E,CAEAkQ,kBAAkBtqB,GAChB,OAAOtI,KAAKigB,WAAWiB,SAAiB,iCAAiC5Y,IAC3E,CAEA4pB,gBAAgB5pB,GACd,OAAOtI,KAAKigB,WAAWiB,SAAiB,sCAAsC5Y,IAChF,CAEAkqB,gBAAgBlqB,GACd,OAAOtI,KAAKigB,WAAWiB,SAAiB,qCAAqC5Y,IAC/E,CAEAoqB,qBAAqBpqB,GACnB,OAAOtI,KAAKigB,WAAW6Z,WAAmB,sCAAsCxxB,IAClF,CAEA8pB,mBAAmB9pB,GACjB,OAAOtI,KAAKigB,WAAW6Z,WAAmB,2CAA2CxxB,IACvF,CAEAgqB,mBAAmBhqB,GACjB,OAAOtI,KAAKigB,WAAW6Z,WAAmB,0CAA0CxxB,IACtF,CAACzF,kDA3DUk9B,GAAwB5W,+DAAxB4W,EAAwBz4B,QAAxBy4B,EAAwB,qBAFvB,gBAEDA,CAAwB,ySCmB9B,IAAMI,GAAoB,MAA3B,MAAOA,GAMXtgC,YACUugC,GACAC,GACAr0B,GACA+B,GACAyf,GACA0H,GACSpG,GACT2K,GACAhpB,GACAjJ,GACA81B,GACApjB,GACAqjB,IAZAv9B,6BACAA,yBACAA,sBACAA,uBACAA,wBACAA,4BACSA,iBACTA,YACAA,oBACAA,oBACAA,yBACAA,yBACAA,oBAhBFA,UAAO,IAAIs6B,IAAqC,GACxDt6B,WAAQA,KAAKQ,KAAK+5B,eAiBhB,MAAMzhB,GAAM9Y,KAAKgM,cAAcmyB,cAAch7B,SAC7CnD,KAAK2uB,QAAU,CACbC,eAAe,EACf4O,cAAc,EACdC,SAAUz9B,KAAKyQ,YAAYE,WAC3B2vB,SAAU,EACVC,cAAe,EACfpE,SAAS,EACT72B,MAAO,GACPo4B,WAAY,CACVpc,eAAgBthB,KAAK+N,eAAexM,kBAAkBmhB,cAAgB,GACtE8d,SACEr9B,iBAA4B2V,IAAO3V,iBAA4B2V,GAC3D1S,YACAA,UACNu3B,IAAK,GACLC,KAAM,EACNt4B,MAAO,IACPH,aAAa,EACb1B,gBAAiB,GACjBQ,mBAAoB,GACpBO,OAAQ,GACRO,OAAQ,GACRe,OAAQ,GACRE,QAAS,GACTL,SAAU,GACVk4B,WAAY,KAEd4C,UAAW,GACX1C,YAAQt8B,EACRi/B,iBAAaj/B,EACbk/B,gBAAYl/B,EACZ0D,YAAa,CACX2D,MACE9I,KAAKwH,YAAYoB,QAEX5I,KAAKka,iBAAiBrN,QAD1B7M,KAAKyQ,YAAYE,WACiB,4CACA,gDAC/B,GACPiwB,SAAS,IAGb5gC,KAAK2uB,QAAQ+O,WAAWC,IAAM39B,KAAK6gC,cACnC7gC,KAAKs9B,iBAAiBW,WAAW,KAC3Bj+B,KAAK2uB,UACP3uB,KAAK2uB,QAAQC,eAAgB,EAC7B5uB,KAAK2uB,QAAQ6O,cAAe,IAGlC,CAEA3O,oBACE,MAAMiS,GAAmB9gC,KAAKgM,cAAcmyB,cAAch7B,iBAEpD+6B,GAAWl+B,KAAKgM,cAAcmyB,cAAch7B,YAAuB,IACzEnD,KAAK2uB,QAAQrpB,MAAqB,MAAb44B,GAAmBA,GAAW,GACnDl+B,KAAK2uB,QAAQ+O,WAAWp4B,MAAQ44B,GAC5Bl+B,KAAK+N,eAAexM,kBAAkBw/B,oBACxC/gC,KAAK2uB,QAAQ+O,WAAWv4B,YAAc27B,GAAwC,UAArBA,GAA+B9gC,KAAK2uB,QAAQ8O,SACrGz9B,KAAK2uB,QAAQxpB,YAAYy7B,QAAU5gC,KAAK2uB,QAAQ+O,WAAWv4B,aAE7D,MAAM2T,GAAM9Y,KAAKgM,cAAcmyB,cAAch7B,SAG3CnD,KAAK2uB,QAAQ+O,WAAW8C,SADtB1nB,IAEqD,UAArD9Y,KAAKgM,cAAcg1B,WAAW79B,IAAc2V,KACxC9Y,KAAKgM,cAAcg1B,WAAW79B,IAAc2V,KAGf1S,UAErCpG,KAAK2uB,QAAQ+O,WAAWC,IAAM39B,KAAK6gC,cAEnC,MAAMI,GAAUjhC,KAAKgM,cAAcmyB,cAAch7B,UACjDnD,KAAK2uB,QAAQ+O,WAAWE,KAAOqD,IAC1BjhC,KAAKgM,cAAck1B,YAAYD,GAAS,GAAK,GAAKjhC,KAAK2uB,QAAQ+O,WAAWC,IAC3E,EACJ39B,KAAK2uB,QAAQ+O,WAAWj6B,gBAAkBzD,KAAKgM,cAAcoyB,wBAAwBj7B,qBACrFnD,KAAK2uB,QAAQ+O,WAAWz5B,mBAAqBjE,KAAKgM,cAAcoyB,wBAC9Dj7B,wBAEFnD,KAAK2uB,QAAQ+O,WAAWl5B,OAASxE,KAAKgM,cAAcoyB,wBAAwBj7B,YAC5EnD,KAAK2uB,QAAQ+O,WAAW34B,OAAS/E,KAAKgM,cAAcoyB,wBAAwBj7B,YAC5EnD,KAAK2uB,QAAQ+O,WAAW53B,OAAS9F,KAAKgM,cAAcoyB,wBAAwBj7B,YAC5EnD,KAAK2uB,QAAQ+O,WAAW13B,QAAUhG,KAAKgM,cAAcoyB,wBAAwBj7B,aAC7EnD,KAAK2uB,QAAQ+O,WAAW/3B,SAAW3F,KAAKgM,cAAcoyB,wBAAwBj7B,cAE9EnD,KAAK2uB,QAAQC,eAAgB,EAC7B5uB,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QACtB,CAEA2P,mBACEt+B,KAAKu+B,kBACFp+B,QACC2Q,KAAY+P,KACV7gB,KAAKu9B,YAAYiB,UAAUjV,OAAOuF,SAASC,SAAUlO,GAAMtO,QAEpDxB,OACR,EACDS,KAAKhR,KACHR,KAAK2uB,QAAQ8R,UAAYzgC,KAAKqgC,iBAAiB1sB,sBAAsBnT,IACrER,KAAK2uB,QAAQoP,OAAS/9B,KAAKk1B,oBAAoB/oB,iBAAiB3L,GAAK4L,QACrEpM,KAAK2uB,QAAQ+R,YAAclgC,GAAKyT,YAChCjU,KAAK2uB,QAAQgS,WAAa3gC,KAAKmhC,gBAE3BnhC,KAAK2uB,QAAQgS,aACf3gC,KAAK2uB,QAAQgS,WAAWxtB,WAAWE,MAAQrT,KAAK2uB,QAAQ+O,WAAWE,KAAO59B,KAAK2uB,QAAQ+O,WAAWC,IAAM,MAE3G,EACDv9B,KAAU,IAAMJ,KAAKohC,iBAEtB7gC,UAAU,KACTP,KAAK2uB,QAAQ6O,cAAe,EAC5Bx9B,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QAAO,EAEjC,CAEQwS,gBACN,IAAIR,GAAsC3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACrEA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,aACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,WAEnC,OAAIpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,gBACvCu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,mBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,iBAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,YAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,eACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,aAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,eAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,kBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,gBAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,WAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,YAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,WAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,YAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,WAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,YAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,cAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,iBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,eAC1BpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,gBAC9Cu6B,GAAa3gC,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IACxCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,iBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,gBAE9Bu6B,EACT,CAEApC,kBACE,OAAOv+B,KAAKy5B,IAAIkF,eAA2C,oBAAqB3+B,KAAK2uB,QAAQ+O,WAC/F,CAEAzH,sBAAsB9oB,IAQpB,OAAOnN,KAAKy5B,IAAIkF,eAAsD,+BAPjC,CACnCC,OAAO,EACPtd,eAAgBthB,KAAK+N,eAAexM,kBAAkBmhB,cAAgB,GACtEpd,MAAO6H,GACPwwB,IAAK,GAIT,CAEAkB,eAAeC,IACb,IAAI53B,GAAS,IAAI63B,KAgBjB,GAdI/+B,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,WAAyBpG,KAAK2uB,QAAQgS,aAC7Ez5B,GAASA,GAAOi4B,OAAOh8B,WAAqBnD,KAAK2uB,QAAQgS,WAAWh0B,YAInE3M,KAAK2uB,QAAQ8O,WAAaz9B,KAAK2uB,QAAQ+O,WAAWv4B,cACjDnF,KAAK2uB,QAAQ8O,UAAYz9B,KAAK2uB,QAAQ+O,WAAWv4B,eAEnD+B,GAASA,GAAOi4B,OAAOh8B,oBAA6B,IAGhB,MAAlCnD,KAAK2uB,QAAQ+O,WAAWp4B,OAAiBtF,KAAK2uB,QAAQ+O,WAAWp4B,QACnE4B,GAASA,GAAOi4B,OAAOh8B,aAAuBnD,KAAK2uB,QAAQ+O,WAAWp4B,QAEpEtF,KAAK2uB,QAAQoP,OACf,UAAW1xB,MAASrM,KAAK2uB,QAAQoP,OAC3B1xB,GAAMjH,OACR8B,GAASA,GAAOi4B,OAAO9yB,GAAMM,SAAWxJ,YAAsB,SAKhEnD,KAAK2uB,QAAQ+O,WAAWj6B,iBAAiBnB,SAC3C4E,GAASA,GAAOi4B,OACdh8B,uBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWj6B,mBAG7DzD,KAAK2uB,QAAQ+O,WAAWz5B,oBAAoB3B,SAC9C4E,GAASA,GAAOi4B,OACdh8B,0BACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWz5B,sBAG7DjE,KAAK2uB,QAAQ+O,WAAWl5B,QAAQlC,SAClC4E,GAASA,GAAOi4B,OACdh8B,cACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWl5B,UAG7DxE,KAAK2uB,QAAQ+O,WAAW34B,QAAQzC,SAClC4E,GAASA,GAAOi4B,OACdh8B,cACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW34B,UAG7D/E,KAAK2uB,QAAQ+O,WAAW53B,QAAQxD,SAClC4E,GAASA,GAAOi4B,OACdh8B,cACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW53B,UAG7D9F,KAAK2uB,QAAQ+O,WAAW13B,SAAS1D,SACnC4E,GAASA,GAAOi4B,OACdh8B,eACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW13B,WAG7DhG,KAAK2uB,QAAQ+O,WAAW/3B,UAAUrD,SACpC4E,GAASA,GAAOi4B,OACdh8B,gBACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAW/3B,YAG7D3F,KAAK2uB,QAAQ+O,WAAWx3B,SAAS5D,SACnC4E,GAASA,GAAOi4B,OACdh8B,eACAnD,KAAKgM,cAAcozB,kBAAkBp/B,KAAK2uB,QAAQ+O,WAAWx3B,WAI7DlG,KAAK2uB,QAAQ+O,WAAWE,OAC1B12B,GAASA,GAAOi4B,OACdh8B,aACCnD,KAAK2uB,QAAQ+O,WAAWE,KAAO59B,KAAK2uB,QAAQ+O,WAAWC,IAAM,GAAGrjB,aAIjEwkB,GACF9+B,KAAK8uB,SAASgQ,aAAavV,OAAOuF,SAASC,SAAU7nB,GAAOoT,YAE5Dta,KAAK8uB,SAASoQ,GAAG3V,OAAOuF,SAASC,SAAU7nB,GAAOoT,WAEtD,CAEAqlB,WAAWC,IACL5/B,KAAK2uB,QAAQgS,aACf3gC,KAAK2uB,QAAQgS,WAAWxtB,WAAWE,MAAQusB,GAC3C5/B,KAAK2uB,QAAQ+O,WAAWE,MAAQgC,GAAY,GAAK5/B,KAAK2uB,QAAQ+O,WAAWC,IACzE39B,KAAK2uB,QAAQ+O,WAAW8C,SAAWxgC,KAAK2uB,QAAQgS,WAAW3tB,SAC3DhT,KAAK2uB,QAAQ+O,WAAWC,IAAM39B,KAAK6gC,cACnCtX,OAAOsW,OAAO,EAAG,GACjB7/B,KAAK22B,SAET,CAEA0K,UAAUvoB,IACR9Y,KAAK2uB,QAAQgS,WAAa7nB,GAC1B9Y,KAAK2uB,QAAQ+O,WAAW8C,SAAW1nB,GAAI9F,SACvChT,KAAK2uB,QAAQ+O,WAAWC,IAAM39B,KAAK6gC,cACnC7gC,KAAK2uB,QAAQ+O,WAAWE,MAAQ9kB,GAAI3F,WAAWE,MAAQ,GAAKrT,KAAK2uB,QAAQ+O,WAAWC,IACpF39B,KAAK22B,QACP,CAEA2K,kBAAkBjW,IAChBrrB,KAAK2uB,QAAQxpB,YAAYy7B,QAAUvV,GACnCrrB,KAAK2uB,QAAQ+O,WAAWv4B,YAAckmB,GACtCrrB,KAAKuhC,iBACLvhC,KAAK22B,QACP,CAEMyK,eAAY,sCAChB,MAAMvuB,GAAU9R,GAAK4tB,QAAQ8R,UAAUnyB,KAAMjO,IAC3CA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,eACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,cAA0BlC,QACvD4O,GAAQ/R,GAAK4tB,QAAQ8R,UAAUnyB,KAAMjO,IACzCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,aACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,YAAwBP,MAErDkN,GAAQhS,GAAK4tB,QAAQ8R,UAAUnyB,KAAMjO,IACzCA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,mBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,kBAA8BqN,MAE3D/L,GAAa3G,GAAK4tB,QAAQ8R,UAAUnyB,KAAMjO,IAC9CA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,kBACjCyN,KAAKvF,KAAMjO,IAAMA,GAAE2S,WAAa5M,iBAA6B7C,WAE5DxC,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,gBAA8BsB,IAAYK,MAAMzF,aACvF,EAAMqoB,KAAe5pB,GAAKq/B,qBAAqB/uB,sBAAsB3J,GAAWK,QACvEhH,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,iBAA+B2M,IAAOzQ,OACpFvB,GAAKq/B,qBAAqBnvB,iBAAiB8B,IAClChS,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,aAA2ByM,IAAS9K,MAAMzF,aACxF,EAAMqoB,KAAe5pB,GAAKq/B,qBAAqBjvB,mBAAmB0B,GAAQ9K,QACjEhH,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,YAErCrF,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,YAErCrF,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,YAErCrF,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,eAErCrF,GAAK4tB,QAAQ+O,WAAW8C,WAAap6B,eAErC0M,IACT/R,GAAKq/B,qBAAqB1vB,iBAAiBoC,GAC5C,EAlCe,EAmClB,CAEA3F,QACEnN,KAAKuhC,iBACLvhC,KAAK2uB,QAAQ+O,WAAWp4B,MAA+B,KAAvBtF,KAAK2uB,QAAQrpB,MAAe,IAAMtF,KAAK2uB,QAAQrpB,MAC/EtF,KAAK22B,QACP,CAEAF,aACEz2B,KAAK2uB,QAAQrpB,MAAQ,GACrBtF,KAAKmN,OACP,CAEAwpB,SACE32B,KAAKwtB,gBAAgBQ,gBACrBhuB,KAAK2uB,QAAQwN,SAAU,EACvBn8B,KAAK6+B,iBAEL7+B,KAAKu+B,kBACFp+B,QACC2Q,KAAW,KACT9Q,KAAK2uB,QAAQwN,SAAU,EAChBprB,OACR,EACDS,KAAKhR,KACHR,KAAKwhC,YAAYhhC,IACjBR,KAAK2uB,QAAQoP,OAAS/9B,KAAKk1B,oBAAoB/oB,iBAAiB3L,GAAK4L,QACrEpM,KAAK2uB,QAAQ+R,YAAclgC,GAAKyT,eACjC,EACD7T,KAAU,IAAMJ,KAAKohC,iBAEtB7gC,UAAU,KACTP,KAAK2uB,QAAQwN,SAAU,EACvBn8B,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,QAAO,EAEjC,CAEQ6S,YAAYhhC,IAClBR,KAAKqgC,iBAAiBxnB,kBACpBrY,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,eAA2ByN,KAAKvF,KAClGjO,IAAMA,GAAE2S,WAAa5M,aAExB,+BAEFpG,KAAKqgC,iBAAiBpnB,gBACpBzY,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,mBAA+ByN,KAAKvF,KACtGjO,IAAMA,GAAE2S,WAAa5M,iBAExB,mCAEFpG,KAAKqgC,iBAAiBtnB,qBACpBvY,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,kBAA8ByN,KAAKvF,KACrGjO,IAAMA,GAAE2S,WAAa5M,gBAExB,kCAEFpG,KAAKqgC,iBAAiBrnB,gBACpBxY,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,aAAyByN,KAAKvF,KAChGjO,IAAMA,GAAE2S,WAAa5M,WAExB,6BAGFpG,KAAKqgC,iBAAiBnnB,iBACpB1Y,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cAA0ByN,KAAKvF,KACjGjO,IAAMA,GAAE2S,WAAa5M,aAG1BpG,KAAKqgC,iBAAiBlnB,iBACpB3Y,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cAA0ByN,KAAKvF,KACjGjO,IAAMA,GAAE2S,WAAa5M,aAG1BpG,KAAKqgC,iBAAiBjnB,iBACpB5Y,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,cAA0ByN,KAAKvF,KACjGjO,IAAMA,GAAE2S,WAAa5M,aAG1BpG,KAAKqgC,iBAAiBhnB,oBACpB7Y,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,iBAA6ByN,KAAKvF,KACpGjO,IAAMA,GAAE2S,WAAa5M,gBAG1BpG,KAAKqgC,iBAAiB/mB,oBACpB9Y,GACAR,KAAK2uB,QAAQ8R,UAAUnyB,KAAMjO,IAAMA,GAAEwT,KAAKvF,KAAM4gB,IAAMA,GAAElc,WAAa5M,iBAA6ByN,KAAKvF,KACpGjO,IAAMA,GAAE2S,WAAa5M,eAG5B,CAEAk5B,YAAYjzB,IACNA,GAAMxE,OAASxB,qBACjBrG,KAAK2uB,QAAQ+O,WAAWj6B,gBAAkB4I,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IAC3FA,GAAK2E,OAELT,GAAMxE,OAASxB,wBACxBrG,KAAK2uB,QAAQ+O,WAAWz5B,mBAAqBoI,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IAC9FA,GAAK2E,OAELT,GAAMxE,OAASxB,YACxBrG,KAAK2uB,QAAQ+O,WAAWl5B,OAAS6H,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IAClFA,GAAK2E,OAELT,GAAMxE,OAASxB,YACxBrG,KAAK2uB,QAAQ+O,WAAW34B,OAASsH,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IAClFA,GAAK2E,OAELT,GAAMxE,OAASxB,YACxBrG,KAAK2uB,QAAQ+O,WAAW53B,OAASuG,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IAClFA,GAAK2E,OAELT,GAAMxE,OAASxB,aACxBrG,KAAK2uB,QAAQ+O,WAAW13B,QAAUqG,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IACnFA,GAAK2E,OAELT,GAAMxE,OAASxB,cACxBrG,KAAK2uB,QAAQ+O,WAAW/3B,SAAW0G,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IACpFA,GAAK2E,OAELT,GAAMxE,OAASxB,eACxBrG,KAAK2uB,QAAQ+O,WAAWx3B,QAAUmG,GAAMtE,MAAMyE,OAAQrE,KAA2B,IAAlBA,GAAKmD,UAAmBK,IAAKxD,IACnFA,GAAK2E,QAGhB9M,KAAKuhC,iBACLvhC,KAAK22B,QACP,CAEA6I,gBAAgBnzB,IACdA,GAAMjH,MAAQiH,GAAMjH,KACpBpF,KAAK6+B,gBACP,CAEA0C,iBACE,UAAWE,MAASzhC,KAAK2uB,QAAQ8R,UAC/B,UAAW3nB,MAAO2oB,GAAM5tB,KACtBiF,GAAI3F,WAAWE,MAAQ,EAGvBrT,KAAK2uB,QAAQgS,aACf3gC,KAAK2uB,QAAQgS,WAAWxtB,WAAWE,MAAQ,GAE7CrT,KAAK2uB,QAAQ+O,WAAWE,KAAO,CACjC,CAEA6B,QACEz/B,KAAK2uB,QAAQrpB,MAAQ,GACrBtF,KAAK2uB,QAAQ+O,WAAWp4B,MAAQ,IAChCtF,KAAK0hC,cACL1hC,KAAK22B,QACP,CAEA+K,cACE,GAAI1hC,KAAK2uB,QAAQoP,OACf,UAAW1xB,MAASrM,KAAK2uB,QAAQoP,OAAQ,CACvC1xB,GAAMjH,MAAO,EACb,UAAW+C,MAAQkE,GAAMtE,MACvBI,GAAKmD,UAAW,EAKtBtL,KAAKuhC,iBACLvhC,KAAK2uB,QAAQ+O,WAAWE,KAAO,EAC/B59B,KAAK2uB,QAAQ+O,WAAWj6B,gBAAkB,GAC1CzD,KAAK2uB,QAAQ+O,WAAWz5B,mBAAqB,GAC7CjE,KAAK2uB,QAAQ+O,WAAWl5B,OAAS,GACjCxE,KAAK2uB,QAAQ+O,WAAW34B,OAAS,GACjC/E,KAAK2uB,QAAQ+O,WAAW53B,OAAS,GACjC9F,KAAK2uB,QAAQ+O,WAAW13B,QAAU,GAClChG,KAAK2uB,QAAQ+O,WAAW/3B,SAAW,EACrC,CAEAk7B,cACE,OACE7gC,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,aACrCpG,KAAK2uB,QAAQ+O,WAAW8C,WAAap6B,eAE9B,GAEA,EAEX,CAACvD,oDAthBUs9B,IAAoBwB,wMAApBxB,GAAoB74B,QAApB64B,GAAoB,qBAFnB,gBAEDA,EAAoB,wOCrB1B,IAAMyB,GAAe,MAAtB,MAAOA,GACX/hC,YAAoBgiC,GAAgDC,IAAhD9hC,2BAAgDA,uBAAmC,CAEvG+hC,kBAAkBvhC,IAChB,MAAO,CACLuD,QAASvD,GAAKwhC,WAAW1/B,OACrB9B,GAAKwhC,UAAUr2B,IAAKxD,MAClBE,GAAIF,GAAKG,GACTQ,MAAOX,GAAKY,MACZuC,SAAUnD,GAAKiD,SACfvD,KAAMjB,UACNmG,MAAO5E,GAAK85B,cAEd,GACJt8B,SAAUnF,GAAK0hC,aAAa5/B,OACxB9B,GAAK0hC,YAAYv2B,IAAKxD,MACpBE,GAAIF,GAAKG,GACTQ,MAAOX,GAAKY,MACZuC,SAAUnD,GAAKiD,SACfmR,gBAAiBpU,GAAKqU,gBACtBC,UAAWtU,GAAKuU,UAChB7U,KAAMjB,YACNmG,MAAO5E,GAAK85B,cAEd,GACJn8B,OAAQtF,GAAK2hC,WAAW7/B,OACpB9B,GAAK2hC,UAAUx2B,IAAKxD,MAClBE,GAAIF,GAAKG,GACTQ,MAAOX,GAAKY,MACZuC,SAAUnD,GAAKiD,SACfvD,KAAMjB,UACNmG,MAAO5E,GAAK85B,cAEd,GACJv+B,YAAalD,GAAKoU,aAAatS,OAC3BtC,KAAK6hC,mBAAmBzkB,wBAAwB5c,GAAKoU,YAAa,KAClE,GACJsG,SAAU1a,GAAK+a,UAAUjZ,OAAStC,KAAK8hC,gBAAgB3mB,qBAAqB3a,GAAK+a,UAAY,GAC7FpI,WAAY,CACVC,eAAgB5S,GAAK4hC,WAAWC,eAChChvB,MAAO7S,GAAK4hC,WAAWxC,UACvBtsB,SAAU9S,GAAK4hC,WAAWE,SAC1Bz6B,KAAM/G,sBAGZ,CAAC+B,oDA7CU++B,IAAe3yB,mEAAf2yB,GAAet6B,QAAfs6B,GAAe,qBAFd,gBAEDA,EAAe,0ECcrB,IAAMW,GAAgB,MAAvB,MAAOA,GAMX1iC,YACUmM,GACAsxB,GACSxO,GACT0T,GACAviB,GACAsd,GACAvvB,GACAyC,GACA1Q,GACA0iC,GACArd,GACArX,IAXA/N,sBACAA,yBACSA,iBACTA,wBACAA,mBACAA,oBACAA,kBACAA,oBACAA,eACAA,sBACAA,mBACAA,uBAfFA,UAAO,IAAIs6B,IAAiC,GACpDt6B,WAAQA,KAAKQ,KAAK+5B,eAgBhBv6B,KAAKs9B,iBAAiBW,WAAW,KAC/Bj+B,KAAK0iC,sBAAoB,EAE7B,CAEAA,uBACM1iC,KAAK2uB,UACP3uB,KAAK2uB,QAAQgU,QAAS,EAE1B,CAEQ9T,kBAAkBhuB,GAAwByH,IAChD,IAAIS,GACA8wB,GACAh5B,KAAaC,sBACfiI,GAAQ/I,KAAKgO,UAAUnB,QAAQ,wBAC/BgtB,GAAczzB,iBACLvF,KAAaC,yBAAoCD,KAAaC,+BACvEiI,GAAQ/I,KAAKgO,UAAUnB,QAAQ,2BAC/BgtB,GAAczzB,oBACLvF,KAAaC,qBACtB+4B,GAAczzB,eAEZyzB,KACF75B,KAAK2uB,QAAU,CACb5Y,SAAUlV,GACV+hC,YAAa/I,GACb/wB,MAAOC,GACP45B,QAAQ,EACRxG,SAAS,EACTuB,WAAY,CACVr1B,GAAIC,GACJu6B,UAAW,EACXC,WAAY,GACZC,eAAgB,GAChBC,gBAAiB,GACjBC,iBAAkB,GAClBC,kBAAczhC,GAEhB6D,MAAO,GACP69B,WACEtiC,KAAaC,yBAAoCD,KAAaC,8BAChEsiC,qBACEviC,KAAaC,yBAAoCD,KAAaC,8BAChEuiC,gBAAiB,GACjBH,aAAc,CACZtC,SAAS,EACT93B,MAAO9I,KAAKgO,UAAUnB,QAAQ,uCAGlC7M,KAAKQ,KAAK4nB,KAAKpoB,KAAK2uB,SAExB,CAEM6L,WAAW35B,GAAwByH,IAAW,sCAElD,GADAvH,GAAK8tB,kBAAkBhuB,GAAUyH,IAC7BvH,GAAK4tB,QAAS,CAChB,GAAI9tB,KAAaC,yBAAoCD,KAAaC,8BAAwC,CACxG,MAAMwiC,GAAkBviC,GAAKiL,cAAcoyB,wBAAwBj7B,UAE/DmgC,GAAgBhhC,SAClBvB,GAAK4tB,QAAQ0U,gBAAkBC,GAAgB33B,IAAKxD,IAAS8f,SAAS9f,GAAM,IAAE,CAIlF,MAAM+1B,GAAmBn9B,GAAKiL,cAAcmyB,cAAch7B,YAAuB,IACjFpC,GAAK4tB,QAAQrpB,MAAqB,MAAb44B,GAAmBA,GAAW,GACnDn9B,GAAK4tB,QAAQ+O,WAAWoF,WAAa5E,GAErCn9B,GAAK4tB,QAAQ+O,WAAWwF,eAAeniC,GAAK0P,YAAYE,YACa,SAAjE5P,GAAKiL,cAAcmyB,cAAch7B,mBAErCpC,GAAK4tB,QAAQuU,aAAatC,QAAU7/B,GAAK4tB,QAAQ+O,WAAWwF,aAE5D,MAAMruB,GAAO9T,GAAKiL,cAAcmyB,cAAch7B,UAC1C0R,KACF9T,GAAK4tB,QAAQ+O,WAAWmF,UAAY9hC,GAAKiL,cAAck1B,YAAYrsB,GAAM,IAG3E9T,GAAK4tB,QAAQ+O,WAAWqF,eAAiBhiC,GAAKiL,cAC3CoyB,wBAAwBj7B,YACxBwI,IAAKxD,IAAS8f,SAAS9f,GAAM,IAChCpH,GAAK4tB,QAAQ+O,WAAWsF,gBAAkBjiC,GAAKiL,cAC5CoyB,wBAAwBj7B,aACxBwI,IAAKxD,IAAS8f,SAAS9f,GAAM,IAChCpH,GAAK4tB,QAAQ+O,WAAWuF,iBAAmBliC,GAAKiL,cAC7CoyB,wBAAwBj7B,cACxBwI,IAAKxD,IAAS8f,SAAS9f,GAAM,UAE1BpH,GAAK41B,QAAM,CAEZ,EArC2C,EAsCpD,CAEMF,aAAU,sCACVn1B,GAAKqtB,UACPrtB,GAAKqtB,QAAQrpB,MAAQ,SACfhE,GAAKq1B,SACZ,EAJa,EAKhB,CAEMA,OAAOxpB,IAAc,sCACzB,GAAIlL,GAAK0sB,QAAS,CAChB1sB,GAAK0sB,QAAQ+O,WAAWoF,WAAa31B,IAAgBlL,GAAK0sB,QAAQrpB,MAClE,MAAMi+B,GAAOthC,GAAKuhC,aACdD,WACF,EAAM5Y,KACJ4Y,GAAKpjC,QACH2Q,KAAY+P,KACV5e,GAAKs7B,YAAYiB,UAAUjV,OAAOuF,SAASC,SAAUlO,GAAMtO,QACpDxB,OACR,EACDS,KAAKhR,KACH,GAAIyB,GAAK0sB,QAAS,CACZ1sB,GAAK0sB,QAAQ5Y,WAAajV,qBAC5BmB,GAAK0sB,QAAQ7lB,MAAQtI,GAAKijC,SAAS16B,OAErC9G,GAAK0sB,QAAQ+U,KAAOzhC,GAAKugC,gBAAgBT,kBAAkBvhC,KAEzDyB,GAAK0sB,QAAQ5Y,WAAajV,yBAC1BmB,GAAK0sB,QAAQ5Y,WAAajV,gCAE1BmB,GAAK0sB,QAAQ0U,gBAAgB95B,QAASjB,KACpC,MAAM4N,GAAajU,GAAK0sB,SAAS+U,MAAMhgC,YAAY4K,KAAMnG,IAASA,GAAKE,KAAOC,IAC1E4N,KACFA,GAAW9Q,MAAO,KAIxB,MAAMkX,GAAUra,GAAK0sB,QAAQ+U,KAAK/9B,SAAS2I,KAAMnG,KAA2B,IAAlBA,GAAKmD,UAC/DrJ,GAAK0sB,QAAQgV,+BAAiCrnB,IAASC,gBACvDta,GAAK0sB,QAAQiV,yBAA2BtnB,IAASG,UACjDxa,GAAK48B,gBAAe,GACpB58B,GAAK0sB,QAAQgU,QAAS,EACtB1gC,GAAKzB,KAAK4nB,KAAKnmB,GAAK0sB,QAAO,MAGhC,CAGN,EAvCwB,EAwC3B,CAEMkV,eAAY,sCACZ5R,GAAKtD,UACPsD,GAAKtD,QAAQ+O,WAAWqF,eAAiB,GACzC9Q,GAAKtD,QAAQ+O,WAAWsF,gBAAkB,GAC1C/Q,GAAKtD,QAAQ+O,WAAWuF,iBAAmB,SACrChR,GAAK0E,SACZ,EANe,EAOlB,CAEA6M,aACE,GAAIxjC,KAAK2uB,QAAS,CAChB,MAAMqK,GAAO,CACX1wB,GAAItI,KAAK2uB,QAAQ+O,WAAWr1B,GAC5Bu3B,UAAW5/B,KAAK2uB,QAAQ+O,WAAWmF,UACnCiB,eAAgB9jC,KAAK2uB,QAAQ+O,WAAWqF,eACxCgB,iBAAkB/jC,KAAK2uB,QAAQ+O,WAAWuF,iBAC1Ce,gBAAiBhkC,KAAK2uB,QAAQ+O,WAAWsF,gBACzCiB,WAAYjkC,KAAK2uB,QAAQ+O,WAAWoF,WACpCoB,aAAclkC,KAAK2uB,QAAQ+O,WAAWwF,aACtCiB,mBAA0E,OAAtDnkC,KAAK+N,eAAexM,kBAAkBg0B,aAE5D,GACEv1B,KAAK2uB,QAAQ5Y,WAAajV,yBAC1Bd,KAAK2uB,QAAQ5Y,WAAajV,8BAE1B,OAAOd,KAAKigB,WAAW2P,YACrB,oCAAoC5vB,KAAK+N,eAAexM,kBAAkB8G,KAC1E2wB,IAEG,GAAIh5B,KAAK2uB,QAAQ5Y,WAAajV,qBACnC,OAAOd,KAAKigB,WAAW2P,YACrB,iCAAiC5vB,KAAK+N,eAAexM,kBAAkB8G,KACvE2wB,IAEG,GAAIh5B,KAAK2uB,QAAQ5Y,WAAajV,mBACnC,OAAOd,KAAKigB,WAAW2P,YAA2B,mCAAoCoJ,GAAI,CAIhG,CAEA6F,eAAeC,IACb,GAAI9+B,KAAK2uB,QAEP,GADa3uB,KAAKgM,cAAcmyB,cAAch7B,UAwCvC,CACL,MAAM+D,GAAS,IAAIk9B,gBAAgB7a,OAAOuF,SAAS6H,QACnDzvB,GAAO4zB,OAAO33B,aACdnD,KAAK8uB,SAASgQ,aAAavV,OAAOuF,SAASC,SAAU7nB,GAAOoT,WAAU,KA1C7D,CACT,IAAIpT,GAAS,IAAI63B,KAE0B,MAAvC/+B,KAAK2uB,QAAQ+O,WAAWoF,YAA6D,KAAvC9iC,KAAK2uB,QAAQ+O,WAAWoF,aACxE57B,GAASA,GAAOi4B,OAAOh8B,aAAuBnD,KAAK2uB,QAAQ+O,WAAWoF,aAGpE9iC,KAAKyQ,YAAYE,YAAc3Q,KAAK2uB,QAAQ+O,WAAWwF,eACzDh8B,GAASA,GAAOi4B,OAAOh8B,qBAA+BnD,KAAK2uB,QAAQ+O,WAAWwF,aAAa5oB,aAGzFta,KAAK2uB,QAAQ+O,WAAWqF,eAAezgC,SACzC4E,GAASA,GAAOi4B,OAAOh8B,cAAwBnD,KAAK2uB,QAAQ+O,WAAWqF,eAAe7rB,KAAK,OAGzFlX,KAAK2uB,QAAQ+O,WAAWsF,gBAAgB1gC,SAC1C4E,GAASA,GAAOi4B,OAAOh8B,eAAyBnD,KAAK2uB,QAAQ+O,WAAWsF,gBAAgB9rB,KAAK,OAG3FlX,KAAK2uB,QAAQ+O,WAAWuF,iBAAiB3gC,SAC3C4E,GAASA,GAAOi4B,OAAOh8B,gBAA0BnD,KAAK2uB,QAAQ+O,WAAWuF,iBAAiB/rB,KAAK,OAG7FlX,KAAK2uB,QAAQ+O,WAAWmF,UAAY,IACtC37B,GAASA,GAAOi4B,OAAOh8B,YAAsBnD,KAAK2uB,QAAQ+O,WAAWmF,UAAUvoB,aAGjF,MAAMgpB,GAAkBtjC,KAAK2uB,QAAQ+U,MAAMhgC,YAAY8I,OAAQrE,KAAuB,IAAdA,GAAK/C,MAAeuG,IAAKxD,IACxFA,GAAKE,IAEVi7B,IAAiBhhC,SACnB4E,GAASA,GAAOi4B,OAAOh8B,YAAsBmgC,GAAgBhpB,aAG3DwkB,GACF9+B,KAAK8uB,SAASgQ,aAAavV,OAAOuF,SAASC,SAAU7nB,GAAOoT,YAE5Dta,KAAK8uB,SAASoQ,GAAG3V,OAAOuF,SAASC,SAAU7nB,GAAOoT,WAAU,CAQpE,CAEA+pB,oBACMrkC,KAAK2uB,UACP3uB,KAAK2uB,QAAQ2V,aAAetkC,KAAK2uB,QAAQ2V,YACzCtkC,KAAKolB,WAAW0C,oBAAoBxhB,qBAA2B,CAC7Di+B,QAASvkC,KAAK2uB,QAAQ2V,cAG5B,CAEME,oBAAoBh4B,IAAmB,sCAC3C,GAAI2lB,GAAKxD,SAAS+U,KAAM,EAEpBvR,GAAKxD,QAAQ5Y,WAAajV,yBAC1BqxB,GAAKxD,QAAQ5Y,WAAajV,iCAE1BqxB,GAAKxD,QAAQ+O,WAAWsF,gBAAkB,GAC1C7Q,GAAKxD,QAAQ+O,WAAWqF,eAAiB,IAE3C5Q,GAAKxD,QAAQ+U,KAAK/9B,SAAWwsB,GAAKxD,QAAQ+U,KAAK/9B,SAASgG,IAAKxD,KAEzDA,GAAKmD,SADHnD,GAAKE,KAAOmE,GAAOnE,IACJF,GAAKmD,SAENnD,GAAKE,KAAOmE,GAAOnE,GAE9BF,KAET,MAAM6I,GAAOmhB,GAAKxD,QAAQ+U,KAAK/9B,SAAS2I,KAAMnG,IAASA,GAAKE,KAAOmE,GAAOnE,IACtE2I,KACEA,GAAK1F,UACP6mB,GAAKxD,QAAQ+O,WAAWuF,iBAAmB,CAACjyB,GAAK3I,IACjD8pB,GAAKxD,QAAQgV,+BAAiC3yB,GAAKuL,gBACnD4V,GAAKxD,QAAQiV,yBAA2B5yB,GAAKyL,YAE7C0V,GAAKxD,QAAQ+O,WAAWuF,iBAAmB,GAC3C9Q,GAAKxD,QAAQgV,oCAAiCliC,EAC9C0wB,GAAKxD,QAAQiV,8BAA2BniC,GAE1C0wB,GAAKxD,QAAQ+O,WAAWmF,UAAY,QAC9B1Q,GAAKwE,SACXxE,GAAK0M,iBAAc,CAEtB,EAhC0C,EAiC7C,CAEM4F,aAAaj4B,IAAmB,sCACpC,GAAI6lB,GAAK1D,QAAS,CAChB,IAAI3d,GACAxE,GAAO3E,OAASjB,UAClBoK,GAAOqhB,GAAK1D,QAAQ+U,MAAM59B,OAAOwI,KAAMnG,IAASA,GAAKE,KAAOmE,GAAOnE,IAC1DmE,GAAO3E,OAASjB,UACzBoK,GAAOqhB,GAAK1D,QAAQ+U,MAAM3/B,QAAQuK,KAAMnG,IAASA,GAAKE,KAAOmE,GAAOnE,IAC3DmE,GAAO3E,OAASjB,cACzBoK,GAAOqhB,GAAK1D,QAAQ+U,MAAM/9B,SAAS2I,KAAMnG,IAASA,GAAKE,KAAOmE,GAAOnE,KAEnE2I,KACFA,GAAK1F,UAAY0F,GAAK1F,SAClB0F,GAAK1F,SACHkB,GAAO3E,OAASjB,UAClByrB,GAAK1D,QAAQ+O,WAAWqF,eAAe36B,KAAK4I,GAAK3I,IACxCmE,GAAO3E,OAASjB,UACzByrB,GAAK1D,QAAQ+O,WAAWsF,gBAAgB56B,KAAK4I,GAAK3I,IACzCmE,GAAO3E,OAASjB,aACzByrB,GAAK1D,QAAQ+O,WAAWuF,iBAAiB76B,KAAK4I,GAAK3I,IAGjDmE,GAAO3E,OAASjB,UAClByrB,GAAK1D,QAAQ+O,WAAWqF,eAAiB1Q,GAAK1D,QAAQ+O,WAAWqF,eAAev2B,OAC7ErE,IAASA,KAAS6I,IAAM3I,IAElBmE,GAAO3E,OAASjB,UACzByrB,GAAK1D,QAAQ+O,WAAWsF,gBAAkB3Q,GAAK1D,QAAQ+O,WAAWsF,gBAAgBx2B,OAC/ErE,IAASA,KAAS6I,IAAM3I,IAElBmE,GAAO3E,OAASjB,cACzByrB,GAAK1D,QAAQ+O,WAAWuF,iBAAmB5Q,GAAK1D,QAAQ+O,WAAWuF,iBAAiBz2B,OACjFrE,IAASA,KAAS6I,IAAM3I,KAI/BgqB,GAAK1D,QAAQ+O,WAAWmF,UAAY,QAC9BxQ,GAAKsE,SACXtE,GAAKwM,iBAAc,CAEtB,EAvCmC,EAwCtC,CAEA6F,kBAAkBxuB,IACZlW,KAAK2uB,UACHzY,GAAW9Q,KACbpF,KAAK2uB,QAAQ0U,gBAAgBj7B,KAAK8N,GAAW7N,IAE7CrI,KAAK2uB,QAAQ0U,gBAAkBrjC,KAAK2uB,QAAQ0U,gBAAgB72B,OAAQrE,IAASA,KAAS+N,GAAW7N,IAEnGrI,KAAK6+B,iBAET,CAEMc,WAAWC,IAAiB,sCAC5BrN,GAAK5D,SAAS+U,OAChBnR,GAAK5D,QAAQ+U,KAAKvwB,WAAWE,MAAQusB,GACrCrN,GAAK5D,QAAQ+O,WAAWmF,UAAYjD,GACpCrW,OAAOsW,OAAO,EAAG,SACXtN,GAAKoE,SACZ,EAN+B,EAOlC,CAEMgO,mBAAmBtZ,IAAgB,sCACnCoH,GAAK9D,UACP8D,GAAK9D,QAAQ+O,WAAWwF,aAAe7X,SACjCoH,GAAKkE,SACZ,EAJsC,EAKzC,CAEM7D,uBAAuBxqB,IAAU,sCACrC,GAAIqqB,GAAKhE,QAAS,CAChB,MAAM3F,GACJ2J,GAAKhE,QAAQ+U,MAAMxoB,SAAS5M,KAAMnG,IAASA,GAAKE,GAAGiS,aAAehS,KAClEqqB,GAAKhE,QAAQ+U,MAAMhgC,YAAY4K,KAAMnG,IAASA,GAAKE,GAAGiS,aAAehS,IAEnE0gB,KACFA,GAAM7f,YAAc6f,GAAM7f,aAIzBwpB,GAAKhE,QAAQ+U,MAAMxoB,SAAS5M,KAAMnG,IAASA,GAAKgB,cAChDwpB,GAAKhE,QAAQ+U,MAAMhgC,YAAY4K,KAAMnG,IAASA,GAAKgB,cAEpDwpB,GAAKhE,QAAQuU,aAAatC,SAAU,EACpCjO,GAAKhE,QAAQ+O,WAAWwF,cAAe,QACjCvQ,GAAKgE,SAAM,CAEpB,EAlBoC,EAmBvC,CAEMiO,mBAAmBrZ,IAAgB,sCACvC,MAAM7pB,SAAG,EAASipB,KAAekI,GAAK4P,cAAcoC,yBACpD,IAAI39B,GAAS,IAAI63B,KAEbxT,GAAI1jB,OAASjB,UACfM,GAASA,GAAOi4B,OAAOh8B,eAAyBooB,GAAIljB,IAC3CkjB,GAAI1jB,OAASjB,YACtBM,GAASA,GAAOi4B,OAAOh8B,cAAwBooB,GAAIljB,KAGrDnB,GAASA,GAAOi4B,OAAOh8B,aAAsB,SAEvC0vB,GAAK9yB,OAAO+kC,cAAc,GAAGpjC,MAAOwF,GAAOoT,aAAc,CAC7DyqB,oBAAoB,GACnB,EAdoC,EAezC,CAEMC,gBAAgBzZ,IAAgB,sCACpC,MAAM7pB,SAAG,EAASipB,KAAeoI,GAAK0P,cAAcwC,sBAEpD,IAAI/9B,GAAS,IAAI63B,KAEbxT,GAAI1jB,OAASjB,YACfM,GAASA,GAAOi4B,OAAOh8B,cAAwBooB,GAAIljB,KAErDnB,GAASA,GAAOi4B,OAAOh8B,aAAsB,SAEvC4vB,GAAKhzB,OAAO+kC,cAAc,GAAGpjC,MAAOwF,GAAOoT,aAAc,CAC7DyqB,oBAAoB,GACnB,EAZiC,EAatC,CAACliC,oDAlaU0/B,IAAgBtzB,yMAAhBszB,GAAgBj7B,QAAhBi7B,GAAgB,qBAFf,gBAEDA,EAAgB,oGCzBzB2C,EAA4B,mBAAXC,QAAoD,iBAApBA,OAAOC,SAAwB,SAAUC,IAAO,cAAcA,EAAK,EAAI,SAAUA,IAAO,OAAOA,IAAyB,mBAAXF,QAAyBE,GAAIxlC,cAAgBslC,QAAUE,KAAQF,OAAOG,UAAY,gBAAkBD,EAAK,EAGvQE,EAAiBhc,OAAOic,OAExBA,EAAS,CAAC,EAEVC,EAAwB,GAG5Blc,OAAOic,OAASA,EAGhB,IAAI5Y,EAAkBrD,OAAOnnB,SAASwqB,gBAIlC8Y,EAAYnc,OAAOoc,UAAUD,UAAUh5B,cAGvCk5B,EAAa,CAAC,WAAY,QAAS,UAAW,cAAe,UAAW,QAAS,UAAW,QAAS,OAAQ,OAAQ,UAAW,SAAU,QAAS,WA+IvJ,SAAStN,EAASuN,GAAUC,IAC1B,OAAoC,IAA7BD,GAASE,QAAQD,GAC1B,CAGA,SAASx3B,GAAKw3B,IACZ,OAAOxN,EAASoN,EAAWI,GAC7B,CAGA,SAASE,GAASC,IAChB,OAAOrZ,EAAgBqZ,UAAUC,MAAM,IAAIC,OAAOF,GAAW,KAC/D,CAGA,SAASG,GAASH,IAChB,IAAII,GAAoB,KACnBL,GAASC,MACZI,GAAoBzZ,EAAgBqZ,UAAUjkC,QAAQ,aAAc,IACpE4qB,EAAgBqZ,UAAYI,GAAoB,IAAMJ,GAE1D,CAGA,SAASK,GAAYL,IACfD,GAASC,MACXrZ,EAAgBqZ,UAAYrZ,EAAgBqZ,UAAUjkC,QAAQ,IAAMikC,GAAW,IAEnF,CA6DA,SAASM,KACHf,EAAOgB,aACTF,GAAY,YACZF,GAAS,aACTK,GAA4B,eAE5BH,GAAY,aACZF,GAAS,YACTK,GAA4B,aAE9BC,IACF,CAEA,SAASD,GAA4BE,IACnC,QAASzK,GAAQ,EAAGA,GAAQuJ,EAAsBnjC,OAAQ45B,KACxDuJ,EAAsBvJ,IAAOyK,GAEjC,CApPAnB,EAAOoB,MAAQ,WACb,OAAOt4B,GAAK,MACd,EAEAk3B,EAAOqB,IAAM,WACX,OAAOrB,EAAOsB,UAAYtB,EAAOuB,QAAUvB,EAAOwB,MACpD,EAEAxB,EAAOsB,OAAS,WACd,OAAQtB,EAAOyB,WAAa34B,GAAK,SACnC,EAEAk3B,EAAOuB,KAAO,WACZ,OAAOz4B,GAAK,OACd,EAEAk3B,EAAOwB,KAAO,WACZ,IAAIE,GAAoC,aAAvBvB,UAAUwB,UAA2BxB,UAAUyB,eAAiB,EACjF,OAAO94B,GAAK,SAAW44B,EACzB,EAEA1B,EAAO6B,QAAU,WACf,OAAQ7B,EAAOyB,WAAa34B,GAAK,UACnC,EAEAk3B,EAAO8B,aAAe,WACpB,OAAO9B,EAAO6B,WAAa/4B,GAAK,SAClC,EAEAk3B,EAAO+B,cAAgB,WACrB,OAAO/B,EAAO6B,YAAc/4B,GAAK,SACnC,EAEAk3B,EAAOgC,WAAa,WAClB,OAAOl5B,GAAK,eAAiBA,GAAK,OACpC,EAEAk3B,EAAOiC,gBAAkB,WACvB,OAAOjC,EAAOgC,eAAiBl5B,GAAK,SACtC,EAEAk3B,EAAOkC,iBAAmB,WACxB,OAAOlC,EAAOgC,cAAgBl5B,GAAK,SACrC,EAEAk3B,EAAOyB,QAAU,WACf,OAAO34B,GAAK,UACd,EAEAk3B,EAAOmC,aAAe,WACpB,OAAOnC,EAAOyB,WAAa34B,GAAK,QAClC,EAEAk3B,EAAOoC,cAAgB,WACrB,OAAOpC,EAAOyB,WAAa34B,GAAK,WAAak3B,EAAOmC,cACtD,EAEAnC,EAAOqC,KAAO,WACZ,OAAQv5B,GAAK,YAAcA,GAAK,aAAeA,GAAK,OACtD,EAEAk3B,EAAOsC,UAAY,WACjB,OAAOtC,EAAOqC,QAAUv5B,GAAK,SAC/B,EAEAk3B,EAAOuC,WAAa,WAClB,OAAOvC,EAAOqC,QAAUv5B,GAAK,SAC/B,EAEAk3B,EAAOwC,MAAQ,WACb,OAAO15B,GAAK,QACd,EAEAk3B,EAAOyC,QAAU,WACf,OAAO1e,OAAO0e,SAAiC,UAAtBnZ,SAASoZ,QACpC,EAEA1C,EAAO2C,WAAa,WAClB,MAAmC,WAA5BjD,EAAQ3b,OAAO6e,QACxB,EAEA5C,EAAO6C,OAAS,WACd,OAAO7C,EAAO8B,gBAAkB9B,EAAOsB,UAAYtB,EAAOuB,QAAUvB,EAAOmC,gBAAkBnC,EAAOiC,mBAAqBjC,EAAOsC,aAAetC,EAAOwC,OACxJ,EAEAxC,EAAO8C,OAAS,WACd,OAAO9C,EAAOwB,QAAUxB,EAAO+B,iBAAmB/B,EAAOkC,oBAAsBlC,EAAOoC,iBAAmBpC,EAAOuC,YAClH,EAEAvC,EAAO+C,QAAU,WACf,OAAQ/C,EAAO8C,WAAa9C,EAAO6C,QACrC,EAEA7C,EAAOI,WAAa,WAElB,QADI4C,GAAI,EACDA,GAAI5C,EAAWtjC,QAAQ,CAC5B,GAAIgM,GAAKs3B,EAAW4C,KAClB,OAAO,EAETA,KAEF,OAAO,CACT,EAEAhD,EAAOiD,SAAW,WAChB,OAAIC,OAAOC,aAAeC,OAAOtD,UAAUuD,eAAeC,KAAKvf,OAAQ,uBAC9D+O,EAASoQ,OAAOC,YAAYr8B,KAAM,YAEvCk5B,EAAOqB,OAAS+B,OAAOtD,UAAUuD,eAAeC,KAAKvf,OAAQ,eACvB,KAAjClS,KAAK4gB,IAAI1O,OAAOof,aAElBpf,OAAOwf,YAAcxf,OAAOyf,WAAa,CAClD,EAEAxD,EAAOgB,UAAY,WACjB,OAAIkC,OAAOC,aAAeC,OAAOtD,UAAUuD,eAAeC,KAAKvf,OAAQ,uBAC9D+O,EAASoQ,OAAOC,YAAYr8B,KAAM,aAEvCk5B,EAAOqB,OAAS+B,OAAOtD,UAAUuD,eAAeC,KAAKvf,OAAQ,eACvB,KAAjClS,KAAK4gB,IAAI1O,OAAOof,aAElBpf,OAAOwf,YAAcxf,OAAOyf,WAAa,CAClD,EAOAxD,EAAOyD,WAAa,WAClB1f,cAAOic,OAASD,EACTvlC,IACT,EAyCIwlC,EAAOqB,MACLrB,EAAOwB,OACTZ,GAAS,mBACAZ,EAAOsB,SAChBV,GAAS,qBACAZ,EAAOuB,QAChBX,GAAS,mBAEFZ,EAAOoB,QAChBR,GAAS,iBACAZ,EAAO6B,UACZ7B,EAAO+B,gBACTnB,GAAS,kBAETA,GAAS,kBAEFZ,EAAOgC,aACZhC,EAAOkC,mBACTtB,GAAS,qBAETA,GAAS,qBAEFZ,EAAOyB,UACZzB,EAAOoC,gBACTxB,GAAS,kBACAZ,EAAOmC,eAChBvB,GAAS,kBAETA,GAAS,mBAEFZ,EAAOqC,OACZrC,EAAOuC,aACT3B,GAAS,eAETA,GAAS,eAEFZ,EAAOwC,QAChB5B,GAAS,gBACAZ,EAAO2C,aAChB/B,GAAS,eACAZ,EAAOI,aAChBQ,GAAS,cACAZ,EAAO+C,WAChBnC,GAAS,WAGPZ,EAAOyC,WACT7B,GAAS,WA0BXZ,EAAO0D,oBAAsB,SAAUC,IACpB,mBAANA,IACT1D,EAAsBr9B,KAAK+gC,GAE/B,EAIA,IAAIC,GAAmB,SAmBvB,SAASC,GAAUC,IACjB,QAASd,GAAI,EAAGA,GAAIc,GAAIhnC,OAAQkmC,KAC9B,GAAIhD,EAAO8D,GAAId,OACb,OAAOc,GAAId,IAGf,MAAO,SACT,CAKA,SAAS9B,KACPlB,EAAOmD,YAAcU,GAAU,CAAC,WAAY,aAC9C,CAhCIT,OAAOtD,UAAUuD,eAAeC,KAAKvf,OAAQ,yBAC/C6f,GAAmB,qBAIjB7f,OAAOggB,iBACThgB,OAAOggB,iBAAiBH,GAAkB7C,IAAmB,GACpDhd,OAAOigB,YAChBjgB,OAAOigB,YAAYJ,GAAkB7C,IAErChd,OAAO6f,IAAoB7C,GAG7BA,KAcAf,EAAOl5B,KAAO+8B,GAAU,CAAC,SAAU,SAAU,YAC7C7D,EAAOiE,GAAKJ,GAAU,CAAC,MAAO,SAAU,OAAQ,OAAQ,UAAW,aAAc,QAAS,UAAW,OAAQ,QAAS,eAMtH3C,KAEA,QAAelB,mLC3SR,IAAMkE,GAAuB,MAA9B,MAAOA,GACXC,4BAA4BpoC,IA0C1B,MAzCmC,CACjC8G,GAAI9G,GAAkB+G,GAAGgS,WACzBlI,SAAU,GACVw3B,MAAOroC,GAAkBsoC,OAAS,GAClCtU,YAAah0B,GAAkBuoC,SAC/BpnB,aAAcnhB,GAAkBwoC,eAAe,GAAGC,WAClDC,SAAU1oC,GAAkB2oC,MAAM57B,KAAMjO,IAAMA,GAAEiM,OAAS9F,eAAuC,IAAfnG,GAAE8pC,WAAoB7hC,GACvG8hC,WAAY7oC,GAAkB2oC,MAAM57B,KAAMjO,IAAMA,GAAEiM,OAAS9F,YAAoC,IAAfnG,GAAE8pC,WAAoB7hC,GACtGQ,MAAOvH,GAAkBwY,KACzBswB,aAAc9oC,GAAkB+oC,cAAgB,UAChDC,iBAAkBhpC,GAAkBipC,kBAAoB,UACxDC,eAAgBlpC,GAAkBmpC,gBAAkB,UACpDC,mBAAoBppC,GAAkBqpC,oBAAsB,UAC5DC,oBAAqBtpC,GAAkBupC,qBAAuB,UAC9DC,cAAexpC,GAAkBypC,eAAiB,UAClDC,cAAe1pC,GAAkB2pC,eAAiB,UAClD1pC,SAAUD,GAAkBF,SAC5B8pC,aAAcnrC,KAAKorC,sBAAsB7pC,IACzC8pC,WAAY9pC,GAAkB+pC,WAAW3/B,IAAKxD,MAE1CE,GAAIF,GAAKG,GACTijC,WAAYpjC,GAAKqjC,WAAWlxB,cAGhCmxB,qBAAsBlqC,GAAkBmqC,2BACxCC,mBAAoBpqC,GAAkBqqC,UACtCC,YAAatqC,GAAkBuqC,UAAYvqC,GAAkBuqC,UAAUxjC,QAAK7G,EAC5EsqC,kBAAmB/rC,KAAKgsC,qBAAqBzqC,GAAkB0qC,gBAC/DC,KACE3qC,GAAkB4qC,cAAgB5qC,GAAkB6qC,mBAChD,CACE/D,OAAQ9mC,GAAkB6qC,yBAAsB3qC,EAChDuN,QAASzN,GAAkB4qC,mBAAgB1qC,QAE7CA,EACN4qC,SAAU9qC,GAAkB+qC,gBAC5BvL,kBAAmBx/B,GAAkBw/B,kBAMzC,CAEAiL,qBAAqBvmB,IACnB,IAAKA,GACH,OAEF,MAAMvd,GAA6B,GACnC,UAAWC,MAAQsd,IAAU8mB,WAAW5d,QAAS,CAC/C,MAAMmb,GAA6B,CACjC0C,MAAOrkC,GAAKskC,MACZC,MAAOvkC,GAAKwkC,MACZC,QAASzkC,GAAK0kC,QACdC,MAAO3kC,GAAK4kC,MACZC,mBAAoB7kC,GAAK8kC,mBACzBC,YAAa/kC,GAAKglC,YAAcntC,KAAKotC,sBAAsBjlC,GAAKglC,kBAAe1rC,EAC/E4rC,UAAWllC,GAAKmlC,UAAYttC,KAAKotC,sBAAsBjlC,GAAKmlC,gBAAa7rC,EACzE8rC,aAAcplC,GAAKqlC,aACfrlC,GAAKqlC,aAAa7hC,IAAKqF,IACdhR,KAAKotC,sBAAsBp8B,KAEpC,IAEN9I,GAAOE,KAAK0hC,GAAQ,CAEtB,OAAO5hC,EACT,CAEAklC,sBAAsBjlC,IAKpB,MAJoC,CAClCE,GAAIF,GAAK6hC,WACTlhC,MAAOX,GAAKY,MAGhB,CAEAqiC,sBAAsB7pC,IACpB,MAAM2G,GAA4B,CAChCulC,uBAAwB,GACxBlD,iBAAkB,GAClBmD,yBAA0B,GAC1B/C,mBAAoB,IAGtB,OACEziC,GAAOulC,uBADLlsC,GAAkBosC,6BACYpsC,GAAkBosC,6BAElBpsC,GAAkB+oC,aAIlDpiC,GAAOqiC,iBADLhpC,GAAkBqsC,uBACMrsC,GAAkBqsC,uBAElB,UAG1B1lC,GAAOwlC,yBADLnsC,GAAkBssC,+BACctsC,GAAkBssC,+BAEhDtsC,GAAkBosC,6BACcpsC,GAAkBosC,6BAElBpsC,GAAkB+oC,aAKtDpiC,GAAOyiC,mBADLppC,GAAkBusC,yBACQvsC,GAAkBusC,yBAE1CvsC,GAAkBqsC,uBACQrsC,GAAkBqsC,uBAElB,UAIzB1lC,EACT,CAACrF,oDAvHU6mC,GAAuB,yCAAvBA,GAAuBpiC,QAAvBoiC,GAAuB,qBAFtB,gBAEDA,EAAuB,+BCI7B,IAAMqE,GAAc,MAArB,MAAOA,GAGXluC,YACUqa,GACA+F,GACA+tB,GACAv9B,GACAw9B,GACAjiC,GACAkiC,GACAC,GACAle,GACkB7tB,IATlBpC,yBACAA,mBACAA,gCACAA,oBACAA,mBACAA,sBACAA,gCACAA,wBACAA,iBACkBA,iBAZ5BA,uBAAoBA,KAAKouC,6BAatB,CAEIA,8BACL,MAAO,CACLxE,MAAO,GACPS,aAAc,UACdE,iBAAkB,UAClBE,eAAgB,UAChBE,mBAAoB,UACpBE,oBAAqB,UACrBE,cAAe,UACfE,cAAe,UACfI,WAAY,GACZgB,SAAU,KACVtL,mBAAmB,EAEvB,CAEMsN,OAAI,sCACR9kB,OAAO+kB,GAAK/kB,OAAO+kB,SAAUzzB,MAAO8E,UACpC4J,OAAOgQ,QAAUx4B,GAAKwtC,aACtBhlB,OAAOilB,cAAe,EACtBjlB,OAAOklB,eAAiB1tC,GAAK2tC,oBAC7BnlB,OAAO1I,MAAQ0I,OAAO1I,MACtB0I,OAAOic,OAASA,EAEhBmJ,aAAaC,WAAW,qBAClB7tC,GAAK8tC,SAAU,EATb,EAUV,CAEAC,QAAQC,GAAuBC,IAE7BhvC,KAAKoC,SAASwqB,gBAAgBqiB,aAAa,OAAQF,IAEnD,MAAMG,GAAiB,CAAC,QAAQH,MAChC,IAAII,GAAWnvC,KAAKka,iBAAiBk1B,IAAI,QAAQL,MAEjD,OAAQC,IACN,KAAKroC,gBACL,KAAKA,aACHuoC,GAAe9mC,KAAK,eAAe2mC,MACnCI,GAAWnvC,KAAKka,iBAAiBk1B,IAAI,eAAeL,MACpD,MACF,KAAKpoC,aACHuoC,GAAe9mC,KAAK,YAAY2mC,MAChCI,GAAWnvC,KAAKka,iBAAiBk1B,IAAI,YAAYL,MAIrD,YAAK70B,iBAAiBm1B,SAASH,IAC/BlvC,KAAKka,iBAAiBo1B,eAAe,QAAQP,MAEtCI,EACT,CAEcN,UAAO,sCACnB,SAAOlkB,MACLrpB,GAAK2e,WACFsvB,WAAkC,0BAA0BjuC,GAAKkuC,YAAYluC,GAAKmP,YAAYg/B,YAC9FtvC,QACCqR,MAAKk+B,IAAYpuC,GAAKC,kBAAoBD,GAAK0sC,wBAAwBrE,4BAA4B+F,MAAQ,EAC3G/jC,MAAK+jC,IAAWpuC,GAAK0sC,wBAAwBrE,4BAA4B+F,MAAO,EAChFl+B,MAAI,KACElQ,GAAKC,kBAAkBg0B,aAAej0B,GAAKC,kBAAkBuH,QAC/DxH,GAAKquC,mBAAmBruC,GAAKC,kBAAkBg0B,YAAaj0B,GAAKC,kBAAkBuH,OAE/ExH,GAAKC,kBAAkBg0B,aACzBj0B,GAAKsuC,cAActuC,GAAKC,kBAAkBg0B,aAGxCj0B,GAAKC,kBAAkBg0B,aACzBj0B,GAAKuuC,SAASvuC,GAAKC,kBAAkBg0B,aAGvCj0B,GAAKwuC,sBAGcxuC,GAAK2uB,SAASQ,IAAIsf,MAC1BC,wBAAwB1uC,GAAKC,kBAAkBkqC,sBAAoB,IAEjF,EACDrrC,MAAU,IACRkB,GAAKwtC,QACHxtC,GAAKC,kBAAkB8qC,UAAY1qC,sBACnCL,GAAKC,kBAAkBg0B,eACxB,EAEHn1B,MAAU,OAAM6vC,MAAI,MAAQ3uC,GAAKC,kBAAkBmhB,aAAcphB,GAAK4uC,eAAW,EAAIx+B,YAAGjQ,KCxC5F,SAAU0uC,GAASC,GAAsCC,KAC7D,IAAIX,GAEFA,GADEU,IAA0C,iBAAlBA,GACjBA,GAEA,CACPpjC,MAAOojC,IAGX,MAAQpjC,SAAQqjC,IAAUC,SAAuBC,mBAAiB,GAAUb,GAE5E,OAAO1iC,IAAS,EACZwjC,QACAC,MAAQ,CAAC9qB,GAAQ+qB,MACf,IACIC,GADAC,GAAQ,EAEZ,MAAMC,GAAoB,KACxB,IAAIC,IAAY,EAChBH,GAAWhrB,GAAOplB,aAChBwwC,MACEL,GACCjkC,KAEK8jC,KACFK,GAAQ,GAEVF,GAAWtoB,KAAK3b,GAAK,OAGvBhL,EACCuvC,KACC,GAAIJ,KAAU5jC,GAAO,CAEnB,MAAMikC,GAAQ,KACRN,IACFA,GAASlb,cACTkb,GAAW,KACXE,MAEAC,IAAY,GAIhB,GAAa,MAATR,GAAe,CAIjB,MAAMY,GAA4B,iBAAVZ,IAAU,EAAWa,MAAMb,KAAK,EAAIc,OAAUd,GAAMU,GAAKJ,KAC3ES,MAAqBN,MACzBL,GACA,KAIEW,GAAmB5b,cACnBwb,IAAK,EAEP,KAGEP,GAAWY,UAAQ,GAGvBJ,GAAS3wC,UAAU8wC,GAAkB,MAGrCJ,IAAK,MAKPP,GAAW7vB,MAAMmwB,GAAG,IAKxBF,KACFH,GAASlb,cACTkb,GAAW,KACXE,KAAiB,EAGrBA,IAAiB,EAEzB,CD3CUV,CAAM,IAAC,EACP3+B,MAAK8G,KAIH,GAHIhX,GAAKC,mBAAqB+W,KAC5BhX,GAAKC,kBAAkB6Q,SAAWkG,IAEhCiR,OAAO1I,OAAO0wB,QAChB,MAAMhoB,OAAO1I,SAIrB,EA3CiB,EA4CrB,CAEQqvB,cACN,OAAOlwC,KAAKigB,WAAWkC,QAAgB,2BAA2BniB,KAAKuB,kBAAkBmhB,eAC3F,CAEQotB,sBACF9vC,KAAKwxC,qBAAuBxxC,KAAKuB,mBAAmBoqC,qBACtD3rC,KAAKkuC,wBAAwBuD,MAAMzxC,KAAKuB,kBAAkBoqC,oBAC1D3rC,KAAKkuC,wBAAwBwD,WAEjC,CAOc/B,mBAAmBX,GAA8Bj1B,IAAY,sCACzE,MAAM43B,IAAoC,IAArB1vC,GAAKqsB,YAAuB0gB,GAAc,MAAQj1B,GAAOi1B,SAE9E,EAAMrkB,MACJ1oB,GAAKgsC,WAAW1K,KAAW5hC,0BAAmC,0BAA2B,CACvFiwC,iBAAiB,EACjBC,YAAaF,KAEf,EARuE,EAS3E,CAEQ9B,SAASb,IACXA,KAAgBroC,OAClBvE,SAASwqB,gBAAgBC,UAAUC,IAAI,cAEvC1qB,SAASwqB,gBAAgBC,UAAUC,IAAI,cAE3C,CAEO8iB,cAAcZ,IACnB,MAAM8C,GAAO1vC,SAAS0vC,KAChBC,GAAO3vC,SAAS4vC,cAAc,QAEpCD,GAAKzlC,KAAO,WACZylC,GAAKE,IAAM,aAGX,IAAIC,GAAO,GACX,OAAQlD,IACN,KAAKroC,cACHurC,GAAO,MACP,MACF,KAAKvrC,gBACL,KAAKA,aACHurC,GAAO,MACPlyC,KAAKmuC,gBAAgBgE,aAAa,CAChCC,OAAQ,QACR7lC,MAAO,CACL,CACEwN,KAAM,kBACNs4B,OAAQryC,KAAKuB,kBAAkB8oC,aAC/BiI,cAAc,EACdC,SAAU,CAAC,GAAI,GAAI,GAAI,KAEzB,CACEx4B,KAAM,kBACNs4B,OAAQryC,KAAKuB,kBAAkB8oC,aAC/BiI,cAAc,EACdC,SAAU,CAAC,GAAI,GAAI,GAAI,KAEzB,CACEx4B,KAAM,UACNs4B,OAAQ,WAEV,CACEt4B,KAAM,QACNs4B,OAAQ,WAEV,CACEt4B,KAAM,OACNs4B,OAAQ,UACRC,cAAc,EACdC,SAAU,CAAC,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,QAIjD,MACF,KAAK5rC,OACHurC,GAAO,KACP,MACF,KAAKvrC,aACHurC,GAAO,WACP,MACF,QACEA,GAAO,MAOX,GAJAH,GAAKG,KAAO,GAAGlyC,KAAKgM,cAAcwmC,cAAgB,GAAK,cAAcN,iBAAmB3oB,OAAO+kB,KAE/FwD,GAAKW,YAAYV,IAEb/xC,KAAKuB,kBAAmB,CAC1B,MAAMupC,GAAsB9qC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkBspC,qBACzEK,GAAgBlrC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkB0pC,eACnED,GAAgBhrC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkBwpC,eACnET,GAAetqC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkB8oC,cAClEG,GAAmBxqC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkBgpC,kBACtEG,GAAiB1qC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkBkpC,gBACpEG,GAAqB5qC,KAAKgM,cAAc0mC,SAAS1yC,KAAKuB,kBAAkBopC,oBAE1EG,IACF1oC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,qBAAsB9H,IAE/DI,IACF9oC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,eAAgB1H,IAEzDF,IACF5oC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,eAAgB5H,IAEzDV,IACFloC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,6BAA8BtI,IAEvEE,IACFpoC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,uBAAwBpI,IAEjEE,IACFtoC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,+BAAgClI,IAEzEE,IACFxoC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,yBAA0BhI,GAAkB,CAG7F,CAEY4E,eACV,OAAOxvC,KAAKgM,cAAcwmC,cAAgB7wC,mBAA4B4nB,OAAOuF,SAAS+jB,QACxF,CAEAC,aAAatH,IACX,OAAOxrC,KAAKuB,kBAAkB8pC,WAAW/8B,KAAMnG,IAASA,GAAKojC,aAAeC,KAAanjC,EAC3F,CAEQqmC,oBAEN,MAAMqE,GAAQ3wC,SAAS4vC,cAAc,OACrCe,GAAMJ,MAAMK,WAAa,SACzBD,GAAMJ,MAAMM,SAAW,SACvB7wC,SAAS42B,KAAKyZ,YAAYM,IAG1B,MAAMG,GAAQ9wC,SAAS4vC,cAAc,OACrCe,GAAMN,YAAYS,IAGlB,MAAMzE,GAAiBsE,GAAMI,YAAcD,GAAMC,YAGjDJ,UAAMK,YAAYC,YAAYN,IACvBtE,EACT,CAEQF,aACN,MAAMv9B,GAAO5O,SAAS4vC,cAAc,UAEpC,SAAOhhC,GAAKsiC,aAActiC,GAAKsiC,WAAW,QAE2B,IAA5DtiC,GAAKuiC,UAAU,cAAcxN,QAAQ,kBAKhD,CAEOyN,SAAS3J,IAKd7pC,KAAKigB,WAAWwzB,oBAA6B,cAJhC,CACX7J,MAAOC,KAGyDtpC,UAAWspC,KACvEA,IAAOvnC,QACTtC,KAAKyQ,YAAY+iC,SAAS3J,GAAK,EAGrC,CAEIvU,WACF,OAAOt1B,KAAKuB,kBAAkBg0B,cAAgB5uB,MAChD,CACIyH,iBACF,OAAOpO,KAAKuB,kBAAkBg0B,cAAgB5uB,YAChD,CACI6H,oBACF,OAAOxO,KAAKuB,kBAAkBg0B,cAAgB5uB,eAChD,CACI2nB,kBACF,OAAOtuB,KAAKuB,kBAAkBg0B,cAAgB5uB,aAChD,CAEI6qC,0BACF,QAA0B,cAAtB1iB,SAAS+jB,WAA4B7yC,KAAKuB,kBAAkBoqC,mBAIlE,CAEA+H,gBAAgBj7B,IACdzY,KAAKuB,kBAAkBoyC,aAAel7B,EACxC,CAAC5V,oDA9TUkrC,IAAc9+B,kIAaf2kC,MAAQ,yCAbP7F,GAAczmC,QAAdymC,GAAc,qBAFb,gBAEDA,EAAc,8EEdpB,IAAM8F,EAAkB,MAAzB,MAAOA,GAHbh0C,cAIUG,UAAO,IAAIs6B,IAAuB,GAC1Ct6B,WAAQA,KAAKQ,KAAK+5B,eAElBuZ,eAAevnC,GACTA,GACFvM,KAAKQ,KAAK4nB,KAAK7b,EAEnB,CAAC1J,kDARUgxC,GAAkB,wCAAlBA,GAAkBvsC,QAAlBusC,GAAkB,qBAFjB,gBAEDA,EAAkB,yFCAxB,IAAME,GAAkB,MAAzB,MAAOA,EAgBXl0C,YAAoBm0C,EAAgDC,GAAhDj0C,0BAAgDA,oBAf5DA,WAAQ,IAAIk0C,KAAyB,GAC7Cl0C,YAASA,KAAKm0C,MAAM5Z,eAEZv6B,YAAS,IAAIk0C,KAAyB,GAC9Cl0C,aAAUA,KAAKo0C,OAAO7Z,eAEdv6B,WAAQ,IAAIk0C,KAAyB,GAC7Cl0C,YAASA,KAAKiuB,MAAMsM,eAEZv6B,YAAS,IAAIk0C,KAAyB,GAC9Cl0C,aAAUA,KAAKq0C,OAAO9Z,eAEdv6B,gBAAa,IAAIk0C,KAAyB,GAClDl0C,iBAAcA,KAAKs0C,WAAW/Z,eAG5B,MAAMga,EAAwB,CAAC,iBAAkB,qBAAsB,qBAAsB,uBAEzFv0C,KAAKi0C,aAAaO,WAAWD,EAAY,IAAIE,SAC/Cz0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,IACPpoB,KAAKi0C,aAAaO,WAAWD,EAAY,IAAIE,SACtDz0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IACZpoB,KAAKi0C,aAAaO,WAAWD,EAAY,IAAIE,SACtDz0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IACZpoB,KAAKi0C,aAAaO,WAAWD,EAAY,IAAIE,UACtDz0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IAGvBpoB,KAAKg0C,mBAAmBU,QAAQH,GAAah0C,UAAW2H,IAClDA,EAAOusC,UACLvsC,EAAOqsC,YAAYA,EAAY,KACjCv0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,IACPlgB,EAAOqsC,YAAYA,EAAY,KACxCv0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IACZlgB,EAAOqsC,YAAYA,EAAY,KACxCv0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IACZlgB,EAAOqsC,YAAYA,EAAY,MACxCv0C,KAAKq0C,OAAOjsB,MAAK,GACjBpoB,KAAKiuB,MAAM7F,MAAK,GAChBpoB,KAAKo0C,OAAOhsB,MAAK,GACjBpoB,KAAKm0C,MAAM/rB,MAAK,GAEhBpoB,KAAKs0C,WAAWlsB,MAAK,IAAI,EAIjC,CAACvlB,kDA9EUkxC,GAAkB5qB,gEAAlB4qB,EAAkBzsC,QAAlBysC,EAAkB,qBAFjB,gBAEDA,CAAkB,yFCCxB,IAAMY,GAAe,MAAtB,MAAOA,EAHb90C,cAIUG,UAAO,IAAIk0C,SAAuCzyC,GAC1DzB,WAAQA,KAAK0sB,KAAK6N,eAElBv6B,eAAsB,GAEtB40C,aAAatsC,EAAYomB,GAKvB1uB,KAAK0sB,KAAKtE,KAJkB,CAC1B/f,GAAIC,EACJusC,YAAanmB,GAGjB,CAEAV,gBACEhuB,KAAK0sB,KAAKtE,UAAK3mB,EACjB,CAEAgtB,eAAenmB,EAAYomB,EAAuBO,GAChDjvB,KAAK0sB,KAAKvsB,QAAKsqB,KAAK,IAAIlqB,UAAWmsB,IAE/B1sB,KAAK0sB,KAAKtE,KADR9f,IAAOokB,GAAMrkB,IAAa,KAAPC,OACN7G,EAEa,CAC1B4G,GAAIC,EACJusC,YAAanmB,EACbomB,OAAQ7lB,GAEa,EAG7B,CAACpsB,kDA/BU8xC,EAAe,wCAAfA,EAAertC,QAAfqtC,EAAe,qBAFd,gBAEDA,CAAe,yFCIrB,IAAMI,GAAsB,MAA7B,MAAOA,UAA8BC,KAClCtoB,KAAQuoB,EAA2DvF,GACxEnmB,OAAOilB,cAAe,EAEtB,MAAMjkB,EAAY2qB,MAAMxoB,KAAKuoB,EAAwBvF,GAErDnlB,SACG4qB,cACAh1C,QAAKsqB,KAAK,IACVlqB,UAAU,KACT6B,SAASwqB,gBAAgBC,UAAUC,IAAI,yBAAwB,GAGnEvC,EACG6qB,cACAj1C,QAAKsqB,KAAK,IACVlqB,UAAU,KACT6B,SAASwqB,gBAAgBC,UAAUG,OAAO,0BAC1CzD,OAAOilB,cAAe,IAGnBjkB,CACT,CAAC1nB,+EAtBUkyC,KAAqBM,GAArBN,EAAqB,EAsB/B,GAtB+BlyC,sCAArBkyC,EAAqBztC,QAArBytC,EAAqB,qBAFpB,gBAEDA,CAAsB,uHCD5B,IAAMO,EAAa,MAApB,MAAOA,EACXz1C,YAAoBkO,EAAwC/B,GAAxChM,sBAAwCA,qBAEpDA,YAAS,IAAIk0C,SAAqCzyC,GAC1DzB,aAAUA,KAAKu1C,OAAOhb,cAHqE,CAM3Fib,UAAUC,EAAiBzG,GACzBhvC,KAAKu1C,OAAOh1C,UAAWg1C,IACrBnzC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,8BAA+B6C,EAAOC,wBAA0B,MAC3GtzC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,wBAAyB6C,EAAOE,kBAAoB,MAE3FJ,EACEvG,IAAgBroC,QAClBvE,SAASwqB,gBAAgB+lB,MAAMC,YAAY,+BAAgC,SAC3ExwC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,yBAA0B,iBAErExwC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,+BAAgC,eAC3ExwC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,yBAA0B,WAGvExwC,SAASwqB,gBAAgB+lB,MAAMC,YAC7B,+BACA6C,EAAOG,yBAA2B,MAEpCxzC,SAASwqB,gBAAgB+lB,MAAMC,YAAY,yBAA0B6C,EAAOI,mBAAqB,MAAI,EAG3G,CAKAC,UAAUj1C,EAAwBk1C,GAW9B/1C,KAAKu1C,OAAOntB,QATZvnB,IAAaC,cACbD,IAAaC,oBACbD,IAAaC,sBACbD,IAAaC,yBACbD,IAAaC,oBACbD,IAAaC,eACbD,IAAaC,kBACZd,KAAK+N,eAAeunB,MAAQygB,GAMjC,CAEAC,cACE,MAAMhH,EAAchvC,KAAK+N,eAAexM,kBAAkBg0B,YACpDkgB,EAAkB,CACtBC,uBAAwB11C,KAAKgM,cAAc0mC,SACzC1yC,KAAK+N,eAAexM,kBAAkB4pC,cAAcsC,wBAEtDkI,iBAAkB31C,KAAKgM,cAAc0mC,SACnC1yC,KAAK+N,eAAexM,kBAAkB4pC,cAAcZ,kBAEtDqL,wBAAyB51C,KAAKgM,cAAc0mC,SAC1C1yC,KAAK+N,eAAexM,kBAAkB4pC,cAAcuC,0BAEtDmI,kBAAmB71C,KAAKgM,cAAc0mC,SACpC1yC,KAAK+N,eAAexM,kBAAkB4pC,cAAcR,qBAIxD3qC,KAAKw1C,UAAUC,EAAQzG,EACzB,CAACnsC,kDApEUyyC,GAAa7lB,iEAAb6lB,EAAahuC,QAAbguC,EAAa,qBAFZ,gBAEDA,CAAa,kGCKnB,IAAMW,EAAa,MAApB,MAAOA,EACXp2C,YAAoBmO,mBAA8B,CAElD0kC,SAASwD,GACP,IAAKA,EACH,OAGF,MAAMhuC,EAAS,4CAA4CiuC,KAAKD,GAChE,OAAOhuC,EAAS,GAAG+f,SAAS/f,EAAO,GAAI,QAAQ+f,SAAS/f,EAAO,GAAI,QAAQ+f,SAAS/f,EAAO,GAAI,WAAQzG,CACzG,CAEA20C,mBAAmBC,EAAeC,GAChC,MAAMC,EAAMtuB,SAASouB,EAAMr0C,QAAQ,IAAK,IAAK,IACvCw0C,EAAMn/B,KAAKkR,MAAM,KAAO+tB,GAGxB/mB,GAAKgnB,GAAO,IAAMC,EAClBnoC,IAAMkoC,GAAO,EAAK,KAAUC,EAC5BC,IAAW,IAANF,GAAkBC,EAG7B,MACE,KAEE,SACoC,OAAnCjnB,EAAI,IAAOA,EAAI,EAAI,EAAIA,EAAK,KACO,KAAnClhB,GAAI,IAAOA,GAAI,EAAI,EAAIA,GAAK,MAC5BooC,GAAI,IAAOA,GAAI,EAAI,EAAIA,GAAK,MAE5Bn8B,SAAS,IACTnD,MAAM,EAEb,CAEAu/B,SAASR,EAAcS,GACrB,IAAKT,EACH,OAGF,MAAM3mB,EAAItH,SAASiuB,EAAI/+B,MAAM,EAAG,GAAI,IAAImD,WAClCm8B,EAAIxuB,SAASiuB,EAAI/+B,MAAM,EAAG,GAAI,IAAImD,WAClCjM,EAAI4Z,SAASiuB,EAAI/+B,MAAM,EAAG,GAAI,IAAImD,WAExC,OAAIq8B,EACK,QAAUpnB,EAAI,KAAOknB,EAAI,KAAOpoC,EAAI,KAAOsoC,EAAMr8B,WAAa,IAE9D,OAASiV,EAAI,KAAOknB,EAAI,KAAOpoC,EAAI,GAE9C,CAGA+vB,wBAAwB9xB,GACtB,IAAIC,EAAQvM,KAAKm+B,cAAc7xB,GAE/B,OAAOC,EACHA,EAAMwC,MAAM,KAAKpD,IAAKxD,GACbyuC,mBAAmBA,mBAAmBzuC,KAE/C,EACN,CAEAi3B,kBAAkByX,GAChB,OAAOA,EAAMlrC,IAAKxD,GAAS2uC,mBAAmB3uC,IAAO+O,KAAK,IAC5D,CAEAmnB,kCAAkC/xB,GAChC,MAAMC,EAAQvM,KAAKm+B,cAAc7xB,GACjC,OAAOC,EAAQA,EAAMwC,MAAM,KAAKpD,IAAKxD,GAAgC,SAAvBA,EAAKuE,eAA4B,EACjF,CAEAqqC,UAAUh9B,GACR,MAAMmsB,EAAQ,IAAIC,OAAO,QAAUpsB,EAAO,YAAYo8B,KAAK/zC,SAAS40C,QACpE,GAAI9Q,EACF,OAAOA,EAAM,EAIjB,CAEA5qB,aAAa5Z,GACX,OAAOA,GAAM,IAAIA,EAAIM,QAAQ,IAAK,KACpC,CAEA6V,eAAeo/B,GACb,OAAQA,EAAUvqC,eAChB,IAAK,OACL,IAAK,OACL,IAAK,OACL,IAAK,OACH,MAAO,qBACT,IAAK,MACH,MAAO,mBACT,IAAK,MACH,MAAO,mBACT,IAAK,MACL,IAAK,OACH,MAAO,oBACT,IAAK,OACL,IAAK,OACL,IAAK,MACH,MAAO,0BACT,QACE,MAAO,eAEb,CAEAkO,iBAAiBs8B,GACf,OAAOA,EAAKC,mBACVn3C,KAAKgO,UAAUnB,QAAQ,qBAAsB,CAC3CmC,QAAS,UAEX,CACEooC,KAAM,UACNC,MAAO,OACPC,IAAK,WAGX,CAEAtW,WAAWjH,EAA2BttB,EAAgB,IACpD,GAAKstB,EAIL,OAAO6O,OAAO2O,QAAQxd,GAAMzrB,KAAK,EAAC,CAAGkpC,KAASA,EAAIn0C,KAAOoJ,GAAS+qC,EAAIl0C,KAAOmJ,KAAS,EACxF,CAEAgrC,iBAAiB9oB,GACf,IAAI+oB,GAAO,EACX,GAAI/oB,EAAQrpB,MACVoyC,UAAO,EACAA,EAET,GAAI/oB,EAAQoP,OACV,UAAW1xB,KAASsiB,EAAQoP,OAE1B,GADA2Z,IAAOrrC,EAAMtE,MAAMyE,OAAQrE,IAA2B,IAAlBA,EAAKmD,UAAmBhJ,OACxDo1C,EACF,MAKN,OAAOA,CACT,CAEAC,gBAAgBC,EAAgBC,GAC9B,MAAMC,EAAOlP,OAAOkP,KAAK/wC,KACnBgxC,EAASnP,OAAOmP,OAAOhxC,KACvBiiB,EAAQ8uB,EAAKE,UAAWxlC,IAAMA,KAAMolC,GAC1C,OAAc,IAAV5uB,EACK+uB,EAAO/uB,GACL6uB,GAGF9wC,QAEX,CAEAkxC,gBAAgBt/B,GACd,MAAMm/B,EAAOlP,OAAOkP,KAAKhxC,KACnBixC,EAASnP,OAAOmP,OAAOjxC,KACvBkiB,EAAQ8uB,EAAKE,UAAWxlC,GAAMA,IAAMmG,GAC1C,OAAc,IAAVqQ,EACK+uB,EAAO/uB,GAEPliB,SAEX,CAEAoxC,0BAA0Bv/B,GACxB,OAAIA,EACK,GAAGA,KAEH,MAEX,CAEA65B,cACE,MAAoC,cAA7BjpB,OAAOuF,SAAS+jB,QACzB,CAEAsF,YAAYz2C,GACV,GAAKA,EAGL,OAAIA,EAAI02C,WAAW,UAAY,IAAIjS,OAAO,mBAAoB,KAAKkS,KAAK32C,MACtEA,EAAM,WAAaA,GAEdA,CACT,CAEA42C,WACE,MAAO,iCAAiCD,KAAK1S,UAAUD,UAAUh5B,cACnE,CAEAw0B,YAAYqX,EAAaC,GACvB,IAAIC,EAAWD,EACf,OAAY,OAARD,GACEA,EAAIj2C,OAAS,IACfm2C,EAAWxwB,SAASswB,EAAK,KAGtBE,CACT,CAEA/+B,eAAe3X,EAAcO,GAC3B,GAAKP,EAGL,OAAO,IAAIw2B,KAAerB,UAAUn1B,EAAMO,EAC5C,CAEAsX,yBAAyBlR,EAAmBgwC,GAC1C,IAAIxwC,EACJ,GAAIQ,EAAU,CACPgwC,IACHhwC,EAAWiwC,YAAajwC,EAAW,GAAM,GAAGkwC,QAAQ,IAAM,GAG5D,MAAMC,EAAsBnwC,EAAS4R,WAAWtY,QAAQ,IAAK,KAE7DkG,EAEMlI,KAAKgO,UAAUnB,QADnBnE,EAAW,EACgB,+BACA,yBADgC,CAAEA,SAAUmwC,GACe,CAE1F,OAAO3wC,CACT,CAGAi2B,cAAc2a,GACZ,MAAMC,EAAY,IAAI3U,gBAAgB7a,OAAOuF,SAAS6H,QACtD,IAAIzuB,EAEJ0gC,cAAO2O,QAAQuB,GAAaE,MAAM,EAAE3xC,EAAKoF,MACvC,MAAMwsC,GAAcF,EAAUtoB,IAAIhkB,GAClC,OAAIwsC,KACF/wC,EAAS+wC,IACF,EAGF,GAGF/wC,CACT,CAEAgxC,mBAAmBn/B,EAAcrY,EAAM6nB,OAAOuF,SAASojB,MACrDn4B,EAAOA,EAAK/X,QAAQ,UAAW,QAG/B,MAAM08B,EADQ,IAAIyH,OAAO,OAASpsB,EAAO,qBACnBo8B,KAAKz0C,GAE3B,OAAKg9B,EACAA,EAAQ,GACNkY,mBAAmBlY,EAAQ,GAAG18B,QAAQ,MAAO,MAD5B,GADH,IAGvB,CAEQm3C,6BAA6B9sC,EAAe+sC,GAClD,OAAOp5C,KAAKk5C,mBAAmB,GAAG7sC,IAAQ+sC,IAC5C,CAEAnsC,mCAAmC6rC,EAA2BM,GAC5D,OACEp5C,KAAKm5C,6BAA6BL,EAAYx1C,GAAI81C,EAAO91C,KACzDtD,KAAKm5C,6BAA6BL,EAAYz1C,GAAI+1C,EAAO/1C,GAE7D,CAACR,kDA5QUozC,GAAanzC,qDAAbmzC,EAAa3uC,QAAb2uC,EAAa,qBAFZ,gBAEDA,CAAa,+ECVnB,IAAMoD,EAAc,MAArB,MAAOA,EACXx5C,YAAoBy5C,mBAA0B,CAE9CpiB,UAAUqiB,GACR,OAAOv5C,KAAKs5C,UAAUE,wBAAwBD,EAChD,CAAC12C,kDALUw2C,GAAcpqC,sEAAdoqC,EAAcliB,iBAAdkiB,CAAc,KCCdI,GAAW,MAAlB,MAAOA,EACX55C,YAAoB65C,sBAA6B,CAEjD9wC,QAAQ7G,GACN,GAAKA,EAGL,OAAO,IAAIs3C,EAAer5C,KAAK05C,cAAcxiB,UAAUn1B,EAAKC,QAAQ,IAAImkC,OAAO,KAAM,KAAM,UAC7F,CAEAzqB,SAAS3Z,EAAcO,GACrB,OAAIA,GAAUP,EAAKO,OAASA,EACnBP,EAAKoV,MAAM,EAAG7U,GAAU,MAExBP,CAEX,CAEAwY,aAAaxY,EAAcO,GACzB,IAAKP,EACH,OAEF,IAAKO,EACH,OAAOP,EAET,IAAI43C,EAAY53C,EAAK62B,UAAU,EAAGt2B,GAElCq3C,EAAYA,EAAU33C,QAAQ,iBAAkB,IAAIo0B,OAEpDujB,EAAYA,EAAU33C,QAAQ,wDAAyD,IAEvF,MAAM43C,EAAsB,iBACtBC,EAAuBD,EAAoBzD,KAAKwD,GACtD,GAA4B,MAAxBE,EAA8B,CAChC,MAAMC,GAAkBD,EAAqB,GAE7C,GAAIC,GAAgBx3C,OAAS,EAAG,CAE9B,MAAMy3C,GAAe,IAAI5T,OAAO,KAAO2T,GAAkB,6CACzD,IAAIE,GAAaL,EACbM,GAAgBF,GAAa5D,KAAK6D,IAElCE,GAAW,KACf,KAAyB,OAAlBD,IACLC,GAAWD,GAAc,GACzBD,GAAaA,GAAWh4C,QAAQ+3C,GAAc,IAC9CE,GAAgBF,GAAa5D,KAAK6D,IAEnB,OAAbE,KACFP,EAAYA,EAAU33C,QAAQ43C,EAAqB,KAAOM,GAAW,KAAG,MAI1EP,EAAYA,EAAU33C,QAAQ43C,EAAqB,GAAE,CAKzD,IAAII,EAAah6C,KAAKm6C,YAAYR,GAClC,MAAMS,GAAqB,+BAC3B,IAAIC,GAAWD,GAAmBjE,KAAK6D,GACvC,IAAIK,GAmBF,OAAOr6C,KAAK0b,SAAS3Z,EAAMO,GAlB3B,KAAoB,OAAb+3C,IAAmB,CACxB,MACEC,GAAUD,GAAS,GAGnBE,GAAWP,EAAWphB,UAAU,EAFrByhB,GAASne,MAFVme,GAAS,GAGK/3C,QAI1B,IAAK,IAAI6jC,OAAO,IAAMmU,GAAU,MAAMjC,KAAKkC,IAAW,CACpDZ,GAAa,QAAU35C,KAAKm6C,YAAYG,IAAW,IACnD,MAGFN,EAAaA,EAAWh4C,QAAQu4C,GAAU,IAE1CF,GAAWD,GAAmBjE,KAAK6D,EAAU,CAMjD,OAAOL,CACT,CAEQQ,YAAY5B,GAClB,MAAMiC,EAAKC,OAAOC,aAAa,KAC/B,IAAIxyC,EAASqwC,EAAIxpC,MAAM,IAAI4rC,UAAUzjC,KAAK,IAC1C,KAAOhP,EAAO69B,QAAQ,MAAO,GAC3B79B,EAASA,EAAOlG,QAAQ,IAAKw4C,GAE/B,KAAOtyC,EAAO69B,QAAQ,MAAO,GAC3B79B,EAASA,EAAOlG,QAAQ,IAAK,KAE/B,KAAOkG,EAAO69B,QAAQyU,IAAM,GAC1BtyC,EAASA,EAAOlG,QAAQw4C,EAAI,KAE9B,OAAOtyC,CACT,CAACrF,kDAnGU42C,GAAWxqC,oDAAXwqC,EAAWnyC,QAAXmyC,EAAW,qBAFV,gBAEDA,CAAW,yFCPZmB,GAKX,aALWA,WAAwB,KAClCA,QACAA,WACAA,WACAA,WAJUA,GAAZ,IAAYA,IAKX,kFCmBM,IAAMC,GAAkB,MAAzB,MAAOA,GA6BXh7C,YACUogB,GACAkF,GACAC,GACAlL,IAHAla,mBACAA,yBACAA,mBACAA,yBAhCFA,UAAO,IAAIk0C,IAA8B,CAC/C4G,QAAS,GACTh2C,UAAW,CACT,CACEuD,GAAIuyC,MACJ9xC,MAAO9I,KAAKka,iBAAiBrN,QAAQ,4BACrC+zB,SAAS,GAEX,CACEv4B,GAAIuyC,MACJ9xC,MAAO9I,KAAKka,iBAAiBrN,QAAQ,4BACrC+zB,SAAS,GAEX,CACEv4B,GAAIuyC,MACJ9xC,MAAO9I,KAAKka,iBAAiBrN,QAAQ,4BACrC+zB,SAAS,GAEX,CACEv4B,GAAIuyC,MACJ9xC,MAAO9I,KAAKka,iBAAiBrN,QAAQ,4BACrC+zB,SAAS,IAGbma,kBAAkB,IAEpB/6C,WAAQA,KAAKQ,KAAK+5B,cAOf,CAEGjT,UAAU0zB,GAAgBp1B,IAAW,sCACzC,MAAMq1B,SAAW,EAAStwB,KAAe5pB,GAAK40B,OAC9CslB,GAAYH,QAAQ1yC,KAAK,CACvB8yC,SAAUF,GACVG,IAAKv1B,KAEP7kB,GAAKP,KAAK4nB,KAAK6yB,GAAa,EANa,EAO3C,CAEMl0B,aAAai0B,GAAgBp1B,IAAW,sCAC5Co1B,GAASp6B,OAET,MAAMq6B,SAAW,EAAStwB,KAAerpB,GAAKq0B,OAC9CslB,GAAYH,QAAUG,GAAYH,QAAQtuC,OAAQg8B,IAAMA,GAAE2S,MAAQv1B,IAClEtkB,GAAKd,KAAK4nB,KAAK6yB,GAAa,EALgB,EAM9C,CAEMh0B,uBAAuBm0B,IAAkB,sCAC7C,MAAMH,SAAW,EAAStwB,KAAe1oB,GAAK0zB,OAC9CslB,GAAYF,iBAAmBK,GAC/Bn5C,GAAKzB,KAAK4nB,KAAK6yB,GAAa,EAHiB,EAI/C,CAEMI,kBAAkB/yC,IAAU,sCAChC,GAAIsgC,OAAOmP,OAAO6C,IAA0BtiB,SAAShwB,IAAiC,CACpF,MAAM2yC,SAAW,EAAStwB,KAAesH,GAAK0D,OAC9CslB,GAAYn2C,UAAYm2C,GAAYn2C,UAAU6G,IAAKxD,MACxCE,GAAIF,GAAKE,GAAIS,MAAOX,GAAKW,MAAO83B,QAASz4B,GAAKE,KAAOC,MAEhE2pB,GAAKzxB,KAAK4nB,KAAK6yB,GAAW,CAC3B,EAP+B,EAQlC,CAEMpzB,kBAAkBjC,IAAW,6CAChB,EAAS+E,KAAewH,GAAKwD,QAClBmlB,QAAQtuC,OAAQrE,IAASA,GAAKgzC,MAAQv1B,IAC1Drc,QAASud,IAAWA,GAAOo0B,SAASI,QAAS,EAHpB,EAInC,CAEMC,YAAS,sCACb,MAAMN,SAAW,EAAStwB,KAAe0H,GAAKsD,OAC9CslB,GAAYO,UAAO/5C,EACnBw5C,GAAYQ,cAAWh6C,EACvBw5C,GAAYS,aAAUj6C,EACtB4wB,GAAK7xB,KAAK4nB,KAAK6yB,GAAa,EALf,EAMf,CAEMU,eAAe31B,IAAwB,sCAC3C,MAAMi1B,SAAW,EAAStwB,KAAe4H,GAAKoD,OAM9CslB,GAAYO,KALwB,CAClC3zC,KAAM1B,SACNy1C,SAAS,EACT71B,WAAYC,IAGdi1B,GAAYY,cAAe,EAC3BtpB,GAAK/xB,KAAK4nB,KAAK6yB,GAAa,EATe,EAU7C,CAEMa,UAAO,sCACX,IAAIb,SAAW,EAAStwB,KAAe8H,GAAKkD,OAC5ClD,GAAKkD,MACFx1B,QACCqM,KAAQrE,KAC2B,IAA1BA,GAAK4yC,mBACb,EACDtwB,KAAK,IAENlqB,UAAWC,KAEV,GADAy6C,GAAcz6C,GACVy6C,GAAYO,MAAML,MAAQF,GAAYY,aAKxC,OAJAZ,GAAYY,cAAe,EAC3BZ,GAAYO,KAAKv1B,UAAW,EAC5Bg1B,GAAYc,kBAAmB,OAC/BtpB,GAAKjyB,KAAK4nB,KAAK6yB,IAGjB,GAAIA,GAAYO,MAAMz1B,YAAYzjB,OAAQ,CACxC,MAAMP,GAAiB,GACvBk5C,GAAYO,KAAKz1B,WAAWxc,QAASid,IACnCzkB,GAAKqG,KAAKoe,EAAUw1B,mBAAmBC,KAAO,IAAG,GAEnD,MAAM/zC,GAASnG,GAAKmV,KAAK,KACnB8hB,GAAO,CACXkjB,SAAUjB,GAAYn2C,UAAUwJ,KAAMnG,IAA0B,IAAjBA,EAAKy4B,UAAmBv4B,GACvE8zC,UAAWj0C,IAGbuqB,GAAKxS,WAAWiB,SAAuB,YAAa8X,IAAMz4B,UAAU,CAClE6nB,KAAOg0B,IACL,MAAMj0C,GAAOsqB,GAAK4pB,iBAChBD,EACAnB,GAAYO,MAAMz1B,YAAc,GAChC5f,SACA80C,GAAYn2C,WACZ,GAEFm2C,GAAYO,KAAOrzC,GACnB8yC,GAAYO,KAAKv1B,UAAW,EAC5Bg1B,GAAYY,cAAe,EAC3BZ,GAAYc,kBAAmB,EAC/BtpB,GAAKjyB,KAAK4nB,KAAK6yB,GAAW,EAE5Bp6B,MAAQu7B,IACNnB,GAAYO,UAAO/5C,EACnBgxB,GAAKjyB,KAAK4nB,KAAK6yB,GAAW,GAE7B,GAEF,EAlDM,EAmDb,CAEMqB,mBAAmBC,GAAmBr2B,IAAiB,sCAC3D,MAAM+0B,SAAW,EAAStwB,KAAegI,GAAKgD,OAC9CslB,GAAYY,aAAeU,GAC3BtB,GAAYc,kBAAmB,EAC3Bd,GAAYO,OACdP,GAAYO,KAAKv1B,SAAWC,IAE9ByM,GAAKnyB,KAAK4nB,KAAK6yB,GAAa,EAP+B,EAQ7D,CAEAuB,WAAW52B,GAAa62B,IACtB,OAAOA,GAAQnuC,KAAMnG,IAASA,GAAKgzC,MAAQv1B,GAC7C,CAEMoB,YAAS,sCACb,MAAMi0B,SAAW,EAAStwB,KAAekI,GAAK8C,OAC9C,GAAIslB,GAAYO,MAAMz1B,YAAck1B,GAAYO,MAAML,IAAK,CACzDF,GAAYO,KAAKr1B,WAAY,EAC7B80B,GAAYO,KAAKv1B,UAAW,EAE5B,MAAMa,GAAS+L,GAAK2pB,WAAWvB,GAAYO,KAAKL,IAAKF,GAAYH,SAC7Dh0B,KACFm0B,GAAYO,KAAKn1B,gBAAkB,CACjCgC,iBAAiB,EACjBC,aAAa,GAEfxB,GAAOo0B,SAASI,QAChBx0B,GAAOo0B,SAAS1zB,YAAc,EAC9ByzB,GAAYO,KAAKz1B,WAAWxc,QAASid,KAC/By0B,GAAYO,MACd3oB,GAAK1N,iBAAiBsB,eAAeD,GAAUE,OAAQu0B,GAAYO,KAAK3zC,KAAI,IAIlFgrB,GAAKryB,KAAK4nB,KAAK6yB,GAAW,CAC3B,EArBY,EAsBf,CAEMyB,aAAU,sCACd,MAAMzB,SAAW,EAAStwB,KAAeoI,GAAK4C,OAC9CslB,GAAYO,UAAO/5C,EACnBsxB,GAAKvyB,KAAK4nB,KAAK6yB,GAAa,EAHd,EAIhB,CAEM0B,WAAWn2B,IAAsB,sCACrC,IAAKA,IAAWw1B,mBAAmBC,KACjC,OAEF,MAAMhB,SAAW,EAAStwB,KAAeqI,GAAK2C,OACxCqD,GAAO,CACXkjB,SAAUjB,GAAYn2C,UAAUwJ,KAAMnG,KAA0B,IAAjBA,GAAKy4B,UAAmBv4B,GACvE8zC,UAAW31B,GAAUw1B,mBAAmBC,KAAKj6C,QAAQ,IAAK,MAE5DgxB,GAAK/S,WAAWiB,SAAuB,YAAa8X,IAAMz4B,UAAW67C,KAKnE,GAJInB,GAAYO,OACdP,GAAYO,KAAKI,SAAU,EAC3BX,GAAYY,cAAe,GAEzBZ,GAAYQ,SAAU,CACxB,GAAIR,GAAYQ,SAASN,IAAK,CAC5B,MAAMr0B,GAASkM,GAAKwpB,WAAWvB,GAAYQ,SAASN,IAAKF,GAAYH,SACjEh0B,IACFA,GAAOo0B,SAASI,OAAK,CAGzBL,GAAYc,kBAAmB,EAEjCd,GAAYS,QAAU1oB,GAAKqpB,iBAAiBD,GAAO,CAAC51B,IAAYA,GAAU3e,KAAMozC,GAAYn2C,WAAW,GACvGm2C,GAAYF,kBAAmB,EAC/B/nB,GAAKxyB,KAAK4nB,KAAK6yB,GAAW,EACzB,EA1BkC,EA2BvC,CAEM2B,gBAAa,sCACjB,MAAM3B,SAAW,EAAStwB,KAAewI,GAAKwC,OAC1CslB,GAAYS,UACVT,GAAYO,OACdP,GAAYO,KAAKI,SAAU,EAC3BX,GAAYO,KAAKv1B,UAAW,EAC5Bg1B,GAAYO,KAAKr1B,WAAY,GAE/B80B,GAAYS,aAAUj6C,EACtB0xB,GAAK3yB,KAAK4nB,KAAK6yB,IAChB,EAVgB,EAWnB,CAEM4B,YAAYj3B,IAAW,sCAC3B,MAAMq1B,SAAW,EAAStwB,KAAe0I,GAAKsC,OAK9CslB,GAAYQ,SAJkB,CAC5BN,IAAKv1B,GACLk3B,qBAAqB,GAGvBzpB,GAAK7yB,KAAK4nB,KAAK6yB,GAAa,EAPD,EAQ7B,CAEM8B,uBAAuBR,GAAmBr2B,IAAiB,sCAC/D,MAAM+0B,SAAW,EAAStwB,KAAe4I,GAAKoC,aACxCpC,GAAKypB,uBAAuB/B,GAAasB,GAAUr2B,IAGvDqN,GAAKnO,WAAW0C,oBADdy0B,GACkCj2C,kBAEAA,mBACrC,EAR8D,EASjE,CAEM22C,kBAAkBj8C,IAAgB,sCACtC,MAAMi6C,SAAW,EAAStwB,KAAeuyB,GAAKvnB,OAE1CslB,GAAYO,OACdP,GAAYO,KAAKI,QAAU56C,GAC3Bk8C,GAAK18C,KAAK4nB,KAAK6yB,IAChB,EANqC,EAOxC,CAEMlzB,iBAAiBV,IAAgB,sCACrC,IAAI81B,GACJ,OAAQ91B,GAAM/a,MACZ,IAAK,QACH6wC,GAAW72C,iBACX,MACF,IAAK,OACH62C,GAAW72C,kBAIX62C,IACFC,GAAKh4B,WAAW0C,oBAAoBq1B,GAAU,CAC5CE,KAAMh2B,GAAMuB,OAAOC,KAAKlD,QAE3B,EAfoC,EAgBvC,CAEQ02B,iBACND,GACAp2B,GACA1Z,GACAgxC,GACAl3B,IAEA,MAAMR,GAAMw2B,GAAMmB,MAAM,GAClBz3B,EAA4B,GAClCs2B,UAAMv2B,MAAMtc,QAASi0C,KACD,aAAdA,GAAKlxC,KACPwZ,EAAM1d,KAAK,CACT8f,SAAUs1B,GACVC,MAAO,KAEc,SAAdD,GAAKlxC,MACdwZ,EAAMA,EAAMxjB,OAAS,GAAGm7C,MAAMr1C,KAAKo1C,GAAI,GAIP,CAClC5B,SAAS,EACTT,IAAKv1B,GACL/d,KAAMyE,GACNuZ,MAAOC,EACPC,WAAYC,GACZG,UAAWC,GACXC,gBAAiB,CACfiC,cAAaxC,EAAMxjB,OACnB+lB,iBAAiB,GAIvB,CAEc20B,uBAAuBx8C,GAAoB+7C,GAAmBr2B,IAAiB,sCAM3F,GALI1lB,GAAKg7C,OACPh7C,GAAKg7C,KAAKI,SAAWW,GACrB/7C,GAAKq7C,cAAe,EACpBr7C,GAAKg7C,KAAKv1B,UAAW,GAEnBzlB,GAAKi7C,UAEP,GADAj7C,GAAKu7C,iBAAmBQ,GACpB/7C,GAAKi7C,SAASN,IAAK,CACrB,MAAMr0B,GAAS42B,GAAKlB,WAAWh8C,GAAKi7C,SAASN,IAAK36C,GAAKs6C,SACnDh0B,KACEZ,SACIY,GAAOo0B,SAASzyB,OAEtB3B,GAAOo0B,SAASI,QAAK,OAK3B96C,GAAKu7C,kBAAmB,EAE1B2B,GAAKl9C,KAAK4nB,KAAK5nB,GAAM,EArBsE,EAsB7F,CAACqC,oDAnVUg4C,IAAkB5rC,uFAAlB4rC,GAAkBvzC,QAAlBuzC,GAAkB,qBAFjB,gBAEDA,EAAkB,oEClBxB,IAAM8C,EAAY,MAAnB,MAAOA,EAIX1rC,sBAAsBnI,GAOpB,IAAKA,IAAWA,GAAQxH,OACtB,OAEF,MAAM9B,EAAiB,GACvB,UAAWo9C,KAAS9zC,EAAQ,CAC1B,MAAM+zC,EAAcD,EAAM1X,MAAM,OAC5B2X,GAAeD,EAAM7X,QAAQ,SAAU,EACzCvlC,EAAK4H,KAAK,CAAE01C,OAAQ71B,SAAS41B,EAAY3mC,KAAK,IAAK,MAEnD1W,EAAK4H,KAAK,CAAEqyC,OAAQmD,GAAO,CAI/Bp9C,EAAKijB,KAAK,CAACtV,EAAGE,KACZ,MAAMhO,EAAI8N,EAAE2vC,OAAS3vC,EAAE2vC,OAAS3vC,EAAEssC,OAASxyB,SAAS9Z,EAAEssC,OAAQ,IAAM,EAC9DsD,GAAI1vC,EAAEyvC,OAASzvC,EAAEyvC,OAASzvC,EAAEosC,OAASxyB,SAAS5Z,EAAEosC,OAAQ,IAAM,EACpE,OAAIp6C,EAAI09C,IACC,EACE19C,EAAI09C,GACN,EAEF,IAGT,MAAMzM,EAAqB,GAC3B,IAAI0M,EAAoB,GAExB,MAAMC,EAAgB,KACpB,GAAID,EAAQ17C,OAAQ,CAClB,MAAM47C,EAAQF,EAAQ,GAChBG,EAAQH,EAAQA,EAAQ17C,OAAS,GAErCgvC,EAASlpC,KADP81C,IAAUC,EACE,GAAGD,YAEH,GAAGA,MAAUC,aAE7BH,EAAU,KAIdx9C,SAAK+I,QAAQ,CAACpB,EAAM+zB,UACEz6B,IAAhB0G,EAAK21C,OACHE,EAAQ17C,QAEN6F,EAAK21C,OAAS,IADCE,EAAQA,EAAQ17C,OAAS,IAI1C27C,IACAD,EAAQ51C,KAAKD,EAAK21C,SAGpBE,EAAQ51C,KAAKD,EAAK21C,SAGpBG,IACI91C,EAAKsyC,QACPnJ,EAASlpC,KAAKD,EAAKsyC,QAAM,GAI/BwD,IACO3M,EAASp6B,KAAK,MACvB,CAACrU,kDAzEU86C,EAAY,wCAAZA,EAAYr2C,QAAZq2C,EAAY,qBAFX,gBAEDA,CAAY,yFCElB,IAAMS,GAAa,MAApB,MAAOA,EAsBXv+C,YAAoB45B,EAAyBhpB,GAAzBzQ,WAAyBA,mBArBrCA,UAAO,IAAIs6B,IAA0B,GAC7Ct6B,WAAQA,KAAKQ,KAAK+5B,eAEVv6B,gBAAa,IAAIs6B,IAAsB,GAC/Ct6B,iBAAcA,KAAKouB,WAAWmM,eAEtBv6B,kBAAe,IAAIs6B,IAAsB,GACjDt6B,mBAAgBA,KAAKq+C,aAAa9jB,eAE1Bv6B,6BAA0B,IAAIs6B,IAAsB,GAC5Dt6B,8BAA2BA,KAAKs+C,wBAAwB/jB,eAEhDv6B,yBAAsB,IAAIs6B,IAAsB,GACxDt6B,0BAAuBA,KAAKu+C,oBAAoBhkB,eAExCv6B,yBAAsB,IAAIs6B,IAAsB,GACxDt6B,0BAAuBA,KAAKw+C,oBAAoBjkB,eAExCv6B,4BAAyB,IAAIs6B,IAAsB,GAC3Dt6B,6BAA0BA,KAAKy+C,uBAAuBlkB,cAEkB,CAExEmkB,UAAUC,GACR,YAAKllB,IACF8V,WAAuB,2BAA2BoP,KAAU3+C,KAAKyQ,YAAYg/B,YAC7ElvC,UAAWC,IACVR,KAAKQ,KAAK4nB,KAAK5nB,EAAI,GAEhBR,KAAKQ,IACd,CAEAo+C,WAAWl9C,GACLA,GACF1B,KAAKouB,WAAWhG,KAAK1mB,EAEzB,CAEAm9C,wBAAwBn9C,GAClBA,GACF1B,KAAKs+C,wBAAwBl2B,KAAK1mB,EAEtC,CAEA0/B,aAAa1/B,GACPA,GACF1B,KAAKq+C,aAAaj2B,KAAK1mB,EAE3B,CAEAo9C,oBAAoBp9C,GACdA,GACF1B,KAAKu+C,oBAAoBn2B,KAAK1mB,EAElC,CAEAq9C,oBAAoBr9C,GACdA,GACF1B,KAAKw+C,oBAAoBp2B,KAAK1mB,EAElC,CAEAs9C,uBAAuBt9C,GACjBA,GACF1B,KAAKy+C,uBAAuBr2B,KAAK1mB,EAErC,CAACmB,kDAnEUu7C,GAAaj1B,gEAAbi1B,EAAa92C,QAAb82C,EAAa,qBAFZ,gBAEDA,CAAa,qNCYnB,IAAMa,GAAW,MAAlB,MAAOA,GASXp/C,YACUogB,GACAxP,GACA1C,GACAhO,EACAm/C,GACA13C,GACAi7B,GACAvoB,IAPAla,mBACAA,oBACAA,uBACAA,cACAA,sBACAA,oBACAA,sBACAA,yBAhBFA,UAAO,IAAIs6B,IAA2B,GAC9Ct6B,kBAAeA,KAAK6U,KAAK0lB,eAEjBv6B,kBAAe,IAAIs6B,IAA4B,GACvDt6B,mBAAgBA,KAAKm/C,aAAa5kB,eAE1Bv6B,0BAAuBA,KAAKo/C,cAAcj/C,QAAKC,KAAWC,IAAML,KAAKq/C,SAASh/C,MAAKE,WAWxF,CAEH++C,gBAAgBH,IACdn/C,KAAKm/C,aAAa/2B,KAAK+2B,GACzB,CAEME,SAASF,IAA0B,4CACvC,EAAMx0B,KACJ5pB,GAAKkf,WAAWsvB,WACd,qCAAqCxuC,GAAK0P,YAAYg/B,YAAY0P,GAAaI,UAC7Ex+C,GAAKgN,eAAexM,kBAAkBC,UAAY,OAIrDK,KAAMgT,KACqD,aAAtD9T,GAAKgN,eAAexM,kBAAkBg0B,cACpC1gB,GAAKhU,WAAaC,0BACpB+T,GAAKhU,SAAWC,+BAEd+T,GAAKhU,WAAaC,mBACpB+T,GAAKhU,SAAWC,yBAIpBC,GAAK8T,KAAKuT,KAAKvT,IAYb9T,GAAKhB,OAAOouB,SATZtZ,GAAKhU,WAAaC,iBAClB+T,GAAKhU,WAAaC,eAClB+T,GAAKhU,WAAaC,WACjB+T,GAAKhU,SAMe,CAACgU,GAAKhU,UAJN,CAACC,iBAIgB,CACpCikC,oBAAoB,GACrB,GAGJya,MAAOhtC,KACN,GAAI2sC,GAAaM,UAEf,YADA1+C,GAAKy9B,UAAU2gB,GAAaO,QAAS,KAGvC,MAAMC,EAAgB,cAChBC,GAAoB,kBACpBvB,GAAe,YACfjwB,GAAa,UACbyxB,GAAmB,iBACnBC,GAAiB,eAEvB,GACEX,GAAaI,SAAWI,GACxBR,GAAaI,SAAWK,IACxBT,GAAaI,SAAWlB,IACxBc,GAAaI,SAAWnxB,IACxB+wB,GAAaI,SAAWM,IACxBV,GAAaI,SAAWO,GACxB,CACA,MAAMC,GAAUC,WAAW,KACzBj/C,GAAKy9B,UAAU2gB,GAAaO,QAAS,IAAG,EACvC,KAECP,GAAaI,SAAWI,EAC1B5+C,GAAK0hC,cAAcwd,qBAAqB1/C,UAAWmB,KACjDw+C,aAAaH,IACbh/C,GAAKhB,OAAOouB,SAAS,CAACzsB,IAAI,GAEnBy9C,GAAaI,SAAWK,GACjC7+C,GAAK0hC,cAAc0d,yBAAyB5/C,UAAWmB,KACrDw+C,aAAaH,IACbh/C,GAAKhB,OAAOouB,SAAS,CAACzsB,IAAI,GAEnBy9C,GAAaI,SAAWlB,GACjCt9C,GAAK0hC,cAAc2d,cAAc7/C,UAAWmB,KAC1Cw+C,aAAaH,IACbh/C,GAAKhB,OAAOouB,SAAS,CAACzsB,IAAI,IAG5By9C,GAAaI,SAAWnxB,IACxB+wB,GAAaI,SAAWM,IACxBV,GAAaI,SAAWO,KAExB/+C,GAAK0hC,cAAc4d,YAAY9/C,UAAWmB,KACxCw+C,aAAaH,IACbh/C,GAAKhB,OAAOouB,SAAS,CAACzsB,IAAI,EAC3B,MAGHX,GAAKy9B,UAAU2gB,GAAaO,QAASltC,GAAED,OAAM,EAE9C,EAvFkC,EAwFzC,CAEMisB,UAAUkhB,GAAiBlU,IAAkB,sCACjD,IAAI8U,EAAiB9U,GAAWlxB,WAMhC,GAJKgmC,IACHA,EAAiB,OAGI,QAAnBA,EAA0B,CAC5Bh/C,GAAKyM,eAAeqgC,8BAEpB9sC,GAAKyM,eAAe6hC,cAAcjpC,eAElC,MAAMoJ,GAAyB,CAC7BjF,WAAY,CAAE4N,MAAO,KAAMH,OAAQ,KACnC3N,SAAU,MACVvC,GAAI,yBACJwC,KAAM,+BACN/B,MAAO,kBACPjB,KAAM,SAGF04C,GAAsB,CAC1Bj0C,KAAMzF,oBACNgyB,KAAMv3B,GAAKkG,YAAYoB,QAAQ,MAAMtH,GAAK4Y,iBAAiBrN,QAAQ,gCA6BrE,OA1BAvL,GAAKuT,KAAKuT,KAAK,CACbo4B,KAAM,CACJC,UAAW,SACXC,aAAc,SACdC,SAAU,mCAEVhoC,MAAO,SACPioC,mBAAoBt/C,GAAK49C,cAAchoB,UAAUnnB,GAAY,OAG/D8wC,WAAY,CACV,CACEC,QAAS,CACP,CACEC,YAAa,CAACR,IACd5nC,MAAO,MAGXqoC,UAAW,SACXroC,MAAO,uBAIPrX,GAAKvB,OAAOouB,SAAS,CAACrtB,cAAwB,CAClDikC,oBAAoB,IAEtB,CAEqB,QAAnBub,IAEFA,EAAiB,OAGnB,IAAIW,GAAc3/C,GAAKyM,eAAe+kC,aAAawN,GAC9CW,KACHA,GAAc3/C,GAAKyM,eAAe+kC,aAAa,QAE7CwN,GAAkBW,IACpB3/C,GAAKg+C,gBAAgB,CACnBC,OAAQ0B,GAAY3mC,WACpBolC,QAASA,GACTD,WAAW,GAEd,EArEgD,EAsEnD,CAEA74B,cACE5mB,KAAKkhD,sBAAsBzrB,aAC7B,CAAC5yB,oDA5LUo8C,IAAWkC,uIAAXlC,GAAW33C,QAAX23C,GAAW,qBAFV,gBAEDA,EAAW,8ECfjB,IAAMmC,EAAa,MAApB,MAAOA,GAEXvhD,YAAsCwhD,oBAD9BrhD,aAAoB,EACgC,CAE5DshD,KAAKC,GACH,MAAMC,EAA+B,GAErCD,SAAQh4C,QAASk4C,IAEf,GADczhD,KAAKuhD,QAAQjzC,KAAMnG,GAASA,IAASs5C,GACxC,CACT,MAAMC,EAAU,IAAIC,QAAiB,CAACC,EAASC,KAC7CD,EAAQ,CAAEzG,IAAKsG,EAAQ9e,QAAQ,GAAM,GAEvC6e,EAASp5C,KAAKs5C,EAAO,KAChB,CACL1hD,KAAKuhD,QAAQn5C,KAAKq5C,GAClB,MAAMC,EAAU1hD,KAAK8hD,WAAWL,GAChCD,EAASp5C,KAAKs5C,EAAO,IAGlBC,QAAQx2C,IAAIq2C,EACrB,CAEQM,WAAWL,GACjB,OAAO,IAAIE,QAAiB,CAACC,EAASC,KACpC,MAAM7wC,EAAOhR,KAAKqhD,UAAUrP,cAAc,UAC1ChhC,EAAK1E,KAAO,kBACZ0E,EAAK4U,IAAM67B,EACXzwC,EAAK+wC,OAAS,KACZH,EAAQ,CAAEzG,IAAKsG,EAAQ9e,QAAQ,GAAM,EAEvC3xB,EAAKgxC,QAAU,KACbhxC,EAAKgc,SACLhtB,KAAKuhD,QAAUvhD,KAAKuhD,QAAQ/0C,OAAQrE,GAASA,IAASs5C,GAC/CI,EAAO,CAAE1G,IAAKsG,EAAQ9e,QAAQ,KAEvC3iC,KAAKqhD,UAAUh/C,qBAAqB,QAAQ,GAAGowC,YAAYzhC,EAAI,EAEnE,CAACnO,kDAtCUu+C,IAAaa,MAEJrO,MAAQ,wCAFjBwN,GAAa95C,QAAb85C,GAAa,mBAAbA,EAAa,8ECOnB,IAAMc,EAAgB,MAAvB,MAAOA,GACXC,eAAeC,GACb,MAAM57B,EAAY47B,GAAGC,eACjB77B,IACEA,GAAW87B,MAEb97B,EAAU87B,QACD97B,GAAW+7B,iBAEpB/7B,EAAU+7B,kBAGhB,CAEAF,aACE/1C,EACA81C,EACA57B,EACA4E,GAEA,GACEA,GACA5E,GAC0B,OAA1BA,GAAWg8B,YACS,SAApBh8B,GAAWla,MACe,KAA1Bka,GAAWlM,WAEX,IACE,OAAIhO,IAASnG,oBACXnG,KAAKyiD,aAAaj8B,GAEO,CACzB3e,KAAMyE,EACNoa,OAAQ0E,EACRs3B,UAAWl8B,EACXw1B,mBAAoBh8C,KAAK2iD,sBACvBn8B,EAAUo8B,WAAW,GAAGC,wBACxBr8B,EACA4E,EACA9e,GAEF+c,OAAQ+4B,SAGH5vC,GAEP,YADAswC,QAAQC,KAAKvwC,GAMnB,CAEQiwC,aAAaj8B,GACnB,MAAMw8B,EAAcx8B,EAAUo8B,WAAW,GACzC,IAAIK,EAAc,EAClB,GAAsC,OAAlCD,EAAKE,eAAeC,UACtB,QAAS3a,EAAIwa,EAAKC,YAAaza,GAAK,GAC9B,KAAK2N,KAAK6M,EAAKE,eAAeC,UAAU3a,IADPA,IAEnCya,IAMN,IAAIG,EAAY,EAChB,GAAoC,OAAhCJ,EAAKK,aAAaF,UACpB,QAAS3a,EAAIwa,EAAKI,UAAW5a,EAAIwa,EAAKK,aAAaF,UAAU7gD,QACvD,KAAK6zC,KAAK6M,EAAKK,aAAaF,UAAU3a,IADyBA,IAEjE4a,IAMNH,SAAcD,EAAKC,YAAcA,EACjCA,EAAcA,EAAc,EAAI,EAAsC,MAAlCD,EAAKE,eAAeC,UAAoB,EAAIF,EAChFG,EAAYJ,EAAKI,UAAYA,EACzBJ,EAAKK,aAAaF,WAAW7gD,SAC/B8gD,EACEA,GAAaJ,EAAKK,aAAaF,UAAU7gD,OACL,MAAhC0gD,EAAKK,aAAaF,UAChB,EACAH,EAAKK,aAAaF,UAAU7gD,OAC9B8gD,GAERJ,EAAKM,SAASN,EAAKE,eAAgBD,GACnCD,EAAKO,OAAOP,EAAKK,aAAcD,GAC/B58B,EAAU+7B,kBACV/7B,EAAUg9B,SAASR,GACZx8B,CACT,CAEAi9B,6BAA6BrB,GAC3B,IACIsB,EADAC,EAAgBvB,EAEpB,MAAMwB,EAA4B,GAClC,IAAIC,EAEJ,KAAOF,IAAkBvB,EAAE0B,KAAK,CAC9BJ,EAAsBC,EAAcI,OACpC,UAAWC,KAAS/sC,MAAMgtC,KAAKP,EAAoBQ,QACjD,GAAIF,IAAUL,EAAe,CAC3B,UAAWQ,KAAgBltC,MAAMgtC,KAAKP,EAAoBthD,SAASC,qBAAqB,WAElF8hD,EAAaC,gBAAkBT,IACjCE,EAAOM,EAAaE,wBACpBT,EAAUx7C,KAAK,CAAEk8C,EAAGT,EAAKxjD,EAAGkkD,EAAGV,EAAK9F,KAGxC4F,EAAgBD,EAChB,OAGN,OAAOE,EAAUvrB,OACf,CAACmsB,EAAaC,MAEVH,EAAGE,EAAYF,EAAIG,EAAaH,EAChCC,EAAGC,EAAYD,EAAIE,EAAaF,IAGpC,CAAED,EAAG,EAAGC,EAAG,GAEf,CAEQ5B,sBACN+B,EACAl+B,EACA4E,EACA9e,GAEA,IAAIvK,EAAiB,GACrB,MAAM4iD,EAAgB,GAChBC,EAAuB,KACvBC,GAAY7kD,KAAK8kD,qBAAqBt+B,GACtCu+B,GAAuB,GAC7B,IAAI1kD,GAAI,EACJ09C,GAAI,EA6DR,GA5DA,SAASiH,GAAaC,IACpB,MAAMlB,GAA6BkB,GAAUC,cAC7C,GAAInB,GAAQ,CACV,IAAIoB,IAAU,EASd,GAP0B,OAAxBF,GAAU9B,WACV38B,EAAU4+B,aAAaH,IAAW,KACI,UAArCA,GAAUI,SAAS34C,eAAkE,aAArCu4C,GAAUI,SAAS34C,gBACpEk4C,EAAqBvM,KAAK4M,GAAU9B,aAEpCgC,IAAU,GAGc,OAAxBF,GAAU9B,WACTgC,KACD3+B,EAAU4+B,aAAaH,IAAW,IACX,IAAvBA,GAAUK,UACTvB,GAAOl3B,UAAU04B,SAAS,cAC1BxB,GAAOltB,QAAQ,eACG,WAAnBktB,GAAOzJ,QAkCP,QAAS9R,EAAI,EAAGgd,GAAMP,GAAUQ,WAAWnjD,OAAQkmC,EAAIgd,KAAOhd,EAC5Dwc,GAAaC,GAAUQ,WAAWjd,SAjC/Boc,EAAqBvM,KAAK4M,GAAU9B,YAAcY,GAAOl3B,UAAU04B,SAAS,SAC3Ej5C,IAASnG,oBACX49C,GAAOl3B,UAAUC,IAAI,YAGvB/qB,EAAKqG,KAAK68C,GAAU9B,WAChBY,GAAOl3B,UAAU04B,SAAS,UACxBj5C,IAASnG,oBACX49C,GAAOl3B,UAAUC,IAAI,WAEvBi4B,GAAM38C,KAAK27C,KAEbY,EAAMv8C,KAAK68C,IACS,IAAhBljD,EAAKO,QACHgK,IAASnG,WAGPpE,EAAK,GAFLykB,EAAUg8B,aAAeh8B,EAAUk/B,UACjCb,GACQ9iD,EAAK,GAAG62B,UAAU,EAAGpS,EAAUm/B,cAAc/sB,UAAUpS,EAAUo/B,aAEjE7jD,EAAK,GAAG62B,UAAU,EAAGpS,EAAUo/B,aAAahtB,UAAUpS,EAAUm/B,cAIhE5jD,EAAK,GAAG62B,UADhBisB,GAC0Br+B,EAAUo/B,YAEVp/B,EAAUm/B,eAQV,CAI5C,CACAX,CAAaN,GACT3iD,EAAKO,OAAS,GAAqB,IAAhBP,EAAKO,OAAc,CACxC,IACIujD,GADAC,GAAMt/B,EAAUlM,WAEpBwrC,GAAMA,GAAIltB,UAAUktB,GAAIC,YAAY,KAAO,EAAGD,GAAIxjD,QAC9CkkB,EAAUk/B,YAEVG,GADmC,IAAjCr/B,EAAUk/B,UAAUJ,SAChB9+B,EAAUk/B,UAAUprC,WAEc,OAAlCkM,EAAUk/B,UAAUvC,UAAqB38B,EAAUk/B,UAAUvC,UAAY,GAEjF0C,GAAMA,GAAIjtB,UAAU,EAAGitB,GAAI9f,QAAQ,KAAO,IAGxC8e,KACF9iD,EAAKA,EAAKO,OAAS,GAAKP,EAAKA,EAAKO,OAAS,GAAGs2B,UAAU,EAAGpS,EAAUm/B,cAAY,CAOrF,GAJIv6B,EAAOyB,UAAU04B,SAAS,eAAiBV,KAC7C9iD,EAAOA,EAAKoV,MAAM,GAAG,IAGnB4tC,GAAMziD,OAAQ,CAChB,MAAM0jD,GAAejB,GAAM,GAC3B,GAAIiB,GAAaC,cAAcC,YAAa,CAC1C,MAAMC,GAAcnmD,KAAKyjD,6BAA6BuC,GAAaC,cAAcC,aACjFnI,GAAIoI,GAAY5B,EAAIyB,GAAa3B,wBAAwBP,IACzDzjD,GAAI8lD,GAAY7B,EAAI0B,GAAa3B,wBAAwB+B,KAAOJ,GAAa3B,wBAAwB1rC,MAAQ,GAajH,MAAO,CACL2rC,EAAGjkD,GACHkkD,EAAGxG,GACH9B,KAZel6C,EACdmV,KAAK,KACLlV,QAAQ,kBAAmB,KAC3BA,QAAQ,QAAS,MACjBA,QAAQ,SAAU,KAClBA,QAAQ,MAAO,KACfA,QAAQ,KAAM,KACdo0B,OAOL,CAEQ0uB,qBAAqBt+B,GAC3B,IAAIq+B,GAAY,EAChB,GAAIr+B,GAAaA,EAAUg8B,YAAch8B,EAAUk/B,YAC5Cl/B,EAAU6/B,YAAa,CAC1B,MAAMC,EAAQlkD,SAASmkD,cACvBD,EAAMhD,SAAS98B,EAAUg8B,WAAYh8B,EAAUm/B,cAC/CW,EAAM/C,OAAO/8B,EAAUk/B,UAAWl/B,EAAUo/B,aAC5Cf,EAAYyB,EAAME,UAClBF,EAAMG,QAAM,CAGhB,OAAO5B,CACT,CAEQ6B,YAAYlgC,EAAuBla,GACzC,OAAOka,EAAUE,OAAOigC,uBACtBr6C,IAASnG,mBAAqC,eAAiB,YAEnE,CAEAuiB,cACE5C,EACA0B,EACAgB,EACAlc,EACA0Z,GAEAA,GAAYzc,QAAQ,CAACid,EAAW0V,KAC9B,IAAKpW,EAAMxjB,OACT,OAEF,MAAMskD,GAAY9gC,EAAMtZ,OAAQg8B,GAAMsV,OAAOtV,EAAEtgB,SAASC,OAASX,GAC3Dq/B,GAAeD,GAAUtkD,OAASskD,GAAUA,GAAUtkD,OAAS,GAAKwjB,EAAM,GAChF,IAAK+gC,GAAapJ,MAAMn7C,OACtB,OAEF,MAAMyiD,GAAQ8B,GAAapJ,MAAMjxC,OAAQg8B,GAAMsV,OAAOtV,EAAErgB,OAASX,GAC3Dw+B,GAAejB,GAAMziD,OAASyiD,GAAMA,GAAMziD,OAAS,GAAKukD,GAAapJ,MAAM,GACjF,IAAKuI,GACH,OAEF,IAAIc,GAAW9mD,KAAK0mD,YAAYlgC,EAAWla,GAC3C,IAAKw6C,GAASxkD,OACZ,KACGkkB,EAAUE,OAAOmG,UAAU04B,SAAS,UAAW/+B,EAAUE,OAAOmG,UAAU04B,SAAS,aACpF/+B,EAAUE,OAAOw+B,cAIjB,OAFA4B,GAAWtgC,EAAUE,OAAOw+B,cAAcyB,uBAAuB,eAEjE,CAGJ,UAAWn7C,KAAWyL,MAAMgtC,KAAK6C,IAC/Bt7C,EAAQqhB,UAAUG,OAAO,iBAAkB,cAAe,oBAAqB,kBAEjF,MAAM+5B,GAAYjhC,EAAMkyB,UAAWxP,GAAMA,IAAMqe,IAC/C,IAAkB,IAAdE,GACF,OAEF,IAAIC,GAAY,EAChB,GAAID,GAAY,EACd,QAASve,EAAI,EAAGA,EAAIue,GAAWve,IAE7Bwe,IADalhC,EAAM0iB,GACUiV,MAAMn7C,OAMvC,GAFA0kD,IAD0BH,GAAapJ,MAAMzF,UAAWxP,GAAMA,IAAMwd,IAGhE9pB,EACF,QAASsM,EAAI,EAAGA,EAAItM,EAAOsM,IAGzBwe,IADsBhnD,KAAK0mD,YADJ1gC,EAAWwiB,GACqBl8B,GACjBhK,OAI1BwkD,GAASE,MAIrB16C,IAASnG,SACX2gD,GAASE,IAAWn6B,UAAUC,IAAItE,EAAU,iBAAmB,eACtDlc,IAASnG,oBAClB2gD,GAASE,IAAWn6B,UAAUC,IAAItE,EAAU,oBAAsB,kBAAgB,EAGxF,CAEA/B,eAAejb,EAAsBc,GACjBtM,KAAKinD,eAAez7C,GAC5BjC,QAAS29C,IACjB,MAAMC,EAAWD,EAAS9T,YACtB+T,EAASt6B,UAAU04B,SAAS,SAAW4B,EAASt6B,UAAU04B,SAAS,YACjEj5C,IAASnG,SACXghD,EAASt6B,UAAUG,OAAO,iBAAkB,eACnC1gB,IAASnG,oBAClBghD,EAASt6B,UAAUG,OAAO,UAAW,oBAAqB,kBAAgB,EAIlF,CAEQi6B,eAAevC,GACrB,IAAIv5C,EAAc,GAClB,GAAIu5C,GAAM9jD,WACR,IAAK8jD,EAAOA,EAAK9jD,WAAY8jD,EAAMA,EAAOA,EAAK0C,YAExB,IAAlB1C,EAAKY,UAAoC,OAAlBZ,EAAKW,UACV,IAAlBX,EAAKY,UAAqC,OAAnBZ,EAAKvB,WAAyC,SAAnBuB,EAAKvB,WAAwBuB,EAAKtR,WAErFjoC,EAAI/C,KAAKs8C,GAETv5C,EAAMA,EAAIk8C,OAAOrnD,KAAKinD,eAAevC,IAI3C,OAAOv5C,CACT,CAEAm8C,QAAQ97C,GACN,IAAI+7C,EAAWtwC,MAAMgtC,KAAKz4C,EAAQi6C,YAClC,QAASjd,EAAI,EAAGA,EAAI+e,EAASjlD,OAAQkmC,IAAK,CACxC,IAAIgf,EAAQD,EAAS/e,GACrB,GAAuB,IAAnBgf,EAAMlC,SAERtlD,KAAKsnD,QAAQE,QAAoB,GAEd,IAAnBA,EAAMlC,UACNkC,EAAMrE,WACc,OAApBqE,EAAMrE,WACc,SAApBqE,EAAMrE,WACNqE,EAAMpU,WACN,CAEA,MAAMqU,EAAUrlD,SAAS4vC,cAAc,QAErCyV,EAAQ56B,UAAUC,IADI,MAApB06B,EAAMrE,UACc,QAEA,cAExBsE,EAAQC,UAAYF,EAAMrE,UAC1B33C,EAAQm8C,aAAaF,EAASD,EAAK,EAGzC,CAEAI,oBAAoBp8C,GAClB,GAAIA,EAAQm7C,uBAAuB,QAAQrkD,OACzC,OAUFtC,KAAKsnD,QAAQ97C,GACb,MAAMq8C,EAAYr8C,EAAQm7C,uBAAuB,cACjD,QAASne,EAAIqf,EAAUvlD,OAAS,EAAGkmC,GAAK,EAAGA,IAAK,CAC9C,MAAMrgC,EAAO0/C,EAAUrf,GACvB,IAAI3P,GAAiB,GACjB1wB,EAAKu/C,WACOv/C,EAAKu/C,UAAU34C,MAAM,KAC7BxF,QAAQ,CAACu+C,GAAM5rB,MACf4rB,GAAKxlD,OACM,MAATwlD,IAAyB,WAATA,IAAgBA,GAAK1P,WAAW,KAClDvf,GAAKzwB,KAAK,uBAAuB0/C,aAEjCjvB,GAAKzwB,KAAK,sBAAsB0/C,aAGlCjvB,GAAKzwB,KAAK,+BAA8B,GAI1CD,EAAK4/C,YACP5/C,EAAK4/C,UAAYlvB,GAAK3hB,KAAK,gCAA8B,CAI7D,MAAM8wC,EAAkB/wC,MAAMgtC,KAAKz4C,EAAQy8C,iBAAiB,iDACzDt8C,IAAK68B,IACJ,MAAM0f,EAAS1f,EAAEyf,iBAAiB,SAClC,OAAOC,EAAOA,EAAO5lD,OAAS,EAAC,GAEhCkK,OAAQhB,QACY/J,IAAZ+J,GAGLu5C,EAAQv5C,EAAQm7C,uBAAuB,QAE7C,QAASne,EAAI,EAAGA,EAAIuc,EAAMziD,OAAQkmC,IAAK,CACrC,MAAMsf,EAAO/C,EAAMvc,GACdsf,EAAKjxB,QAAQ,cAChBixB,EAAK5C,eAAer4B,UAAUC,IAAI,YAEhCg7B,EAAKJ,YAAcI,EAAK5C,eAAen8C,OACzCi/C,EAAgB5/C,KAAK0/C,EAAI,CAI7BE,EAAgBz+C,QAASu+C,KAClB,CAAC,IAAK,IAAK,KAAKv8C,KAAM48C,GAASL,EAAKJ,UAAUU,SAASD,MAAWL,EAAKj7B,UAAU04B,SAAS,WAC7FuC,EAAKj7B,UAAUC,IAAI,SACnBg7B,EAAKJ,UAAY,GAAGI,EAAKJ,oDAG/B,CAAC7kD,kDAtcUq/C,GAAgB,wCAAhBA,GAAgB56C,QAAhB46C,GAAgB,qBAFf,gBAEDA,EAAgB,6GCFtB,IAAMnS,EAAU,MAAjB,MAAOA,EACXlwC,YACU45B,EACA1rB,EACAhF,EACAs/C,GAHAroD,WACAA,sBACAA,aACAA,WACP,CAEHsoD,YAAY/I,GACV,OAAOv/C,KAAKy5B,IAAI8V,WACd,8BAA8BgQ,KAAUv/C,KAAK+N,eAAexM,kBAAkBC,WAElF,CAEA+mD,YAAY/nD,GACNA,EAAKgoD,UAELxoD,KAAK+I,MAAM0/C,SADTjoD,EAAKK,WAAaC,cACAN,EAAKqxC,YAAc,GAAGrxC,EAAKqxC,iBAAiBrxC,EAAKgoD,YAAchoD,EAAKgoD,UAC/EhoD,EAAKqxC,YACM,GAAGrxC,EAAKgoD,eAAehoD,EAAKqxC,cAE5BrxC,EAAKgoD,WAElBhoD,EAAKqxC,aACd7xC,KAAK+I,MAAM0/C,SAASjoD,EAAKqxC,aAG3B,IAAI92B,EAAQ,GACRva,EAAKkoD,aACP3tC,EAAQva,EAAKkoD,aACJloD,EAAKmoD,YACd5tC,EAAQva,EAAKmoD,WAGfnoD,EAAKgoD,UAAYhoD,EAAKgoD,WAAa,GACnChoD,EAAKooD,gBAAkBpoD,EAAKooD,iBAAmB,GAE/C5oD,KAAKqoD,KAAKQ,UAAU,CAClB9uC,KAAM,WACNw/B,QAAS/4C,EAAKyX,SAAWzX,EAAKyX,SAASf,KAAK,MAAQ,KAEtDlX,KAAKqoD,KAAKQ,UAAU,CAAE9uC,KAAM,cAAew/B,QAAS/4C,EAAKooD,kBAEzD5oD,KAAKqoD,KAAKQ,UAAU,CAClB9uC,KAAM,eACNw/B,QAAS,wBAEXv5C,KAAKqoD,KAAKQ,UAAU,CAAE9uC,KAAM,gBAAiBw/B,QAAS/4C,EAAKgoD,YAC3DxoD,KAAKqoD,KAAKQ,UAAU,CAClB9uC,KAAM,qBACNw/B,QAAS/4C,EAAKgoD,YAEhBxoD,KAAKqoD,KAAKQ,UAAU,CAClB9uC,KAAM,sBACNw/B,QAAS/4C,EAAKooD,kBAEhB5oD,KAAKqoD,KAAKQ,UAAU,CAAE9uC,KAAM,gBAAiBw/B,QAASx+B,IACtD/a,KAAKqoD,KAAKQ,UAAU,CAAE9uC,KAAM,oBAAqBw/B,QAAS/4C,EAAKgoD,YAE/DxoD,KAAKqoD,KAAKQ,UAAU,CAAEC,SAAU,SAAUvP,QAAShwB,OAAOuF,SAASojB,OACnElyC,KAAKqoD,KAAKQ,UAAU,CAAEC,SAAU,WAAYvP,QAAS/4C,EAAKgoD,YAC1DxoD,KAAKqoD,KAAKQ,UAAU,CAAEC,SAAU,WAAYvP,QAASx+B,IACrD/a,KAAKqoD,KAAKQ,UAAU,CAClBC,SAAU,eACVvP,QAASx+B,EAAQva,EAAKgoD,UAAY,KAEpCxoD,KAAKqoD,KAAKQ,UAAU,CAClBC,SAAU,iBACVvP,QAAS/4C,EAAKooD,kBAGhB5oD,KAAKqoD,KAAKQ,UAAU,CAClB9uC,KAAM,SACNw/B,QAAS/4C,EAAKuoD,yBAA2B,UAAY,OAEzD,CAEA/Y,wBAAwB1nC,GAClBA,GACFtI,KAAKqoD,KAAKQ,UAAU,CAAEC,SAAU,2BAA4BvP,QAASjxC,GAEzE,CAACzF,kDAjFUktC,GAAUjtC,wFAAVitC,EAAUzoC,QAAVyoC,EAAU,qBAFT,gBAEDA,CAAU,sDCRhB,MAAMpuC,EAAc,CACzBqnD,YAAY,EACZC,iBAAkB,KAClBC,iBAAkB,IACT3/B,OAAOuF,SAAS+jB,SAASsW,oBAAoBf,SAAS,cAE/DgB,mBAAoB,IACX7/B,OAAOuF,SAASu6B,OAAS,IAElCC,qBAAqB,EACrBC,iBAAkB,2CAClBC,eAAgB,kDAChBC,qBAAsB,gDACtBC,cAAe,iDACfC,cAAe,yBACfnxC,WCf+C,CAC/C,CACE0f,MAAO,IACPptB,WAAY,CACV,CACE4N,MAAO,KACPH,OAAQ,MAEV,CACEG,MAAO,KACPH,OAAQ,MAEV,CACEG,MAAO,IACPH,OAAQ,KAEV,CACEG,MAAO,IACPH,OAAQ,OAId,CACE2f,MAAO,EACPptB,WAAY,CACV,CACE4N,MAAO,IACPH,OAAQ,KAEV,CACEG,MAAO,IACPH,OAAQ,OAId,CACE2f,MAAO,MACPptB,WAAY,CACV,CACE4N,MAAO,KACPH,OAAQ,MAEV,CACEG,MAAO,KACPH,OAAQ,MAEV,CACEG,MAAO,IACPH,OAAQ,KAEV,CACEG,MAAO,IACPH,OAAQ,OAId,CACE2f,MAAO,IACPptB,WAAY,CACV,CACE4N,MAAO,KACPH,OAAQ,MAEV,CACEG,MAAO,IACPH,OAAQ,MAGV,CACEG,MAAO,IACPH,OAAQ,KAEV,CACEG,MAAO,IACPH,OAAQ,QD1DdqxC,wBAAwB,EACxBC,YAAa,IACyB,2CAA7BtgC,OAAOuF,SAAS+jB,SACnB,6CACA,sCAENiX,cAAe,uIEVX,SAAUC,EAAmBC,GACjC,OAAO,IAAIC,MAEP,OACN,UCEgBC,KACd,cAAe3gC,OAAW,YAAsBA,OAAOnnB,SAAa,GACtE,UAEgB+nD,KAMd,cAAc/hB,QAAY,KAA6C,qBAA9B,GAAG9tB,SAASwuB,KAAKV,QAC5D,CAEM,SAAUgiB,GAAoB3N,GAClC,OAAQA,EAAQn6C,QACd,KAAK,EACH,OAAO,IAAI+nD,KACb,KAAK,EACH,OAAO5N,EAAQ,GACjB,QACE,OAAO,IAAI6N,KAAsB7N,GAEvC,UAEgB8N,GACZC,EAAyBC,EAAsCj/C,EAC/Dk/C,EAAiCC,EAA2B,IAAIC,IAChEC,EAA4B,IAAID,KAClC,MAAME,EAAkB,GAClBC,EAA4C,GAClD,IAAIC,GAAiB,EACjBC,EAAuC,KAiC3C,GAhCAP,EAAUnhD,QAAQ2hD,IAChB,MAAMC,EAASD,EAAGz6B,IAAI,UAChB26B,GAAeD,GAAUH,EACzBK,GAAqCD,IAAgBH,GAAqB,IAAIL,IACpFM,EAAG3hD,QAAQ,CAACiuC,GAAK8T,MACf,IAAIC,GAAiBD,GACjBE,GAAkBhU,GACtB,GAAa,WAAT8T,GAEF,OADAC,GAAiBd,EAAWgB,sBAAsBF,GAAgBT,GAC1DU,IACN,KAAKE,KACHF,GAAkBb,EAAUl6B,IAAI66B,IAChC,MAEF,KAAKK,KACHH,GAAkBX,EAAWp6B,IAAI66B,IACjC,MAEF,QACEE,GACIf,EAAWmB,oBAAoBN,GAAMC,GAAgBC,GAAiBV,GAIhFO,GAAmBQ,IAAIN,GAAgBC,GAAe,GAEnDJ,IACHL,EAAoB3iD,KAAKijD,IAE3BJ,EAAmBI,GACnBL,EAAiBG,IAEfL,EAAOxoD,OACT,MDyFE,SAAUwpD,GAAgBhB,GAC9B,OAAO,IAAIb,MAAY,MAEnB8B,EAGN,CC/FUD,GAGR,OAAOf,CACT,CAEM,SAAUiB,GACZllC,EAAyBmlC,EAAmB5kC,EAC5C6kC,GACF,OAAQD,GACN,IAAK,QACHnlC,EAAOqlC,QAAQ,IAAMD,EAAS7kC,GAAS+kC,GAAmB/kC,EAAO,QAASP,KAC1E,MACF,IAAK,OACHA,EAAOulC,OAAO,IAAMH,EAAS7kC,GAAS+kC,GAAmB/kC,EAAO,OAAQP,KACxE,MACF,IAAK,UACHA,EAAOwlC,UAAU,IAAMJ,EAAS7kC,GAAS+kC,GAAmB/kC,EAAO,UAAWP,KAGpF,UAEgBslC,GACZ55C,EAAmB+5C,EAAmBzlC,GACxC,MAEMO,EAAQmlC,GACVh6C,EAAEhH,QAASgH,EAAEi6C,YAAaj6C,EAAEk6C,UAAWl6C,EAAEm6C,QAASJ,GAAa/5C,EAAE+5C,UAHnDzlC,EAAO8lC,WAIIp6C,EAAEo6C,YAHb9lC,EAAe+lC,UAI3BrsD,EAAQgS,EAAUs6C,MACxB,OAAY,MAARtsD,IACD6mB,EAAcylC,MAAWtsD,GAErB6mB,CACT,UAEgBmlC,GACZhhD,EAAcihD,EAAqBC,EAAmBC,EAAiBJ,EAAoB,GAC3FK,EAAoB,EAAGC,GACzB,MAAO,CAACrhD,UAASihD,cAAaC,YAAWC,UAASJ,YAAWK,YAAWC,WAAYA,EACtF,UAEgBE,GAA2BphD,EAAgBtE,EAAQmxC,GACjE,IAAI/rC,EAAQd,EAAI8kB,IAAIppB,GACpB,OAAKoF,GACHd,EAAIkgD,IAAIxkD,EAAKoF,EAAQ+rC,GAEhB/rC,CACT,CAEM,SAAUugD,GAAqBC,GACnC,MAAMC,EAAeD,EAAQlnB,QAAQ,KAGrC,MAAO,CAFIknB,EAAQr0B,UAAU,EAAGs0B,GACjBD,EAAQ91C,MAAM+1C,EAAe,GAE9C,CAEA,IAAIC,GAA+C,CAACC,EAAWC,KAAc,EACzEC,GACA,CAAC9hD,EAAc+hD,EAAkBC,IACxB,GAETC,GAAiC,KAE/B,SAAUC,GAAiBliD,GAC/B,MAAMu4C,EAASv4C,EAAQ4nC,YAAc5nC,EAAQmiD,KAC7C,OAAI5J,IAAW0J,GACN,KAEF1J,CACT,EAIgBoG,aACMyD,QAAY,OAC3B1D,MAKHuD,GAAoC,KAAMrrD,SAASwqB,gBAAf,GACpCugC,GAAY,CAACC,EAAMC,KACjB,KAAOA,GAAM,CACX,GAAIA,IAASD,EACX,OAAO,EAETC,EAAOK,GAAiBL,EAAI,CAE9B,OAAO,IAZTF,GAAY,CAACC,EAAMC,IAASD,EAAK7H,SAAS8H,GAgB5CC,GAAS,CAAC9hD,EAAc+hD,EAAkBC,KACxC,GAAIA,EACF,OAAOv2C,MAAMgtC,KAAKz4C,EAAQy8C,iBAAiBsF,IAE7C,MAAMv8C,EAAOxF,EAAQqiD,cAAcN,GACnC,OAAOv8C,EAAO,CAACA,GAAQ,KAU3B,IAAI88C,GAAkC,KAClCC,IAAa,EA8BV,MAAMC,GAAkBb,GAClBc,GAAcX,GCrN3B,IAIaY,GAAmB,YAAnBA,EACXC,sBAAsB7C,GACpB,ODiLE,SAAU6C,GAAsB7C,GAC/BwC,KACHA,YAoBYM,KACd,cAAWhsD,SAAY,IACdA,SAAS42B,KAEX,IACT,CAzBmBo1B,IAAiB,GAChCL,KAAaD,GAAcnb,OAAS,qBAAsBmb,GAAcnb,OAG1E,IAAIzqC,GAAS,EACb,OAAI4lD,GAAcnb,QAfpB,SAAS0b,GAAqB/C,GAG5B,MAA+B,SAAxBA,EAAK1yB,UAAU,EAAG,EAC3B,CAW8By1B,CAAqB/C,KAC/CpjD,EAASojD,KAAQwC,GAAcnb,OAC1BzqC,GAAU6lD,KAEb7lD,EADkB,SAAWojD,EAAKgD,OAAO,GAAGC,cAAgBjD,EAAKn0C,MAAM,KACjD22C,GAAcnb,QAIjCzqC,CACT,CCjMWimD,CAAsB7C,GAG/BkD,eAAeC,EAAeC,GAE5B,OAAO,EAGTV,gBAAgBZ,EAAWC,GACzB,OAAOW,GAAgBZ,EAAMC,GAG/BK,iBAAiBliD,GACf,OAAOkiD,GAAiBliD,GAG1B2B,MAAM3B,EAAc+hD,EAAkBC,GACpC,OAAOS,GAAYziD,EAAS+hD,EAAUC,GAGxCmB,aAAanjD,EAAc8/C,EAAc9S,GACvC,OAAOA,GAAgB,GAGzBoW,QACIpjD,EAAck/C,EAA8ChiD,EAAkB4nC,EAC9Eue,EAAgBC,EAAyB,GACzCC,GACF,OAAO,IAAI1E,KAAoB3hD,EAAU4nC,mDA9BhC,qDAAmB,KAqCV0e,GAAe,YAAfA,GACbA,cAAyC,IAAId,GADhCc,CAAe,KCvC9B,MAAMC,GAAa,IAIbC,GAAkB,WAClBC,GAAkB,WAClBC,GAAuB,aACvBC,GAAsB,cACtBC,GAAyB,eACzBC,GAAwB,gBAE/B,SAAUC,GAAmB/iD,GACjC,GAAoB,iBAATA,EAAmB,OAAOA,EAErC,MAAMgoC,EAAUhoC,EAAMy5B,MAAM,qBAC5B,OAAKuO,GAAWA,EAAQnyC,OAAS,EAAU,EAEpCmtD,GAAsB9W,WAAWlE,EAAQ,IAAKA,EAAQ,GAC/D,CAEA,SAASgb,GAAsBhjD,EAAeijD,GAC5C,MACO,MADCA,EAEGjjD,EAAQwiD,GAERxiD,CAEb,UAEgBkjD,GACZC,EAAuC9E,EAAiB+E,GAC1D,OAAOD,EAAQ/mB,eAAe,YACV+mB,EAItB,SAASE,GACL9F,EAAoBc,EAAiB+E,GAEvC,IAAInnD,EACA4nC,EAAgB,EAChBue,EAAiB,GACrB,GAAmB,iBAAR7E,EAAkB,CAC3B,MAAMvV,EAAUuV,EAAI9jB,MALR,4EAMZ,GAAgB,OAAZuO,EACFqW,SAAO1iD,KAAK2hD,KACL,CAACrhD,SAAU,EAAG4nC,MAAO,EAAGue,OAAQ,IAGzCnmD,EAAW+mD,GAAsB9W,WAAWlE,EAAQ,IAAKA,EAAQ,IAEjE,MAAMsb,EAAatb,EAAQ,GACT,MAAdsb,IACFzf,EAAQmf,GAAsB9W,WAAWoX,GAAatb,EAAQ,KAGhE,MAAMub,EAAYvb,EAAQ,GACtBub,IACFnB,EAASmB,QAGXtnD,EAAWshD,EAGb,IAAK6F,EAAqB,CACxB,IAAII,GAAiB,EACjBC,EAAapF,EAAOxoD,OACpBoG,EAAW,IACboiD,EAAO1iD,cH9DG+nD,IACd,OAAO,IAAIlG,MAAY,MAEnB8B,EACN,CG0DkBoE,IACZF,GAAiB,GAEf3f,EAAQ,IACVwa,EAAO1iD,cH5DGgoD,IACd,OAAO,IAAInG,MAAY,MAEnB8B,EACN,CGwDkBqE,IACZH,GAAiB,GAEfA,GACFnF,EAAOuF,OAAOH,EAAY,EAAGnG,IAAuB,CAIxD,MAAO,CAACrhD,WAAU4nC,QAAOue,SAC3B,CAhDMiB,CAAmCF,EAAS9E,EAAQ+E,EAC1D,UAiDgBS,GACZjrB,EAA2BkrB,EAAoC,IACjE3nB,cAAOkP,KAAKzS,GAAK97B,QAAQ+hD,IACvBiF,EAAYjF,GAAQjmB,EAAIimB,EAAI,GAEvBiF,CACT,CAEM,SAAUC,GAAanrB,GAC3B,MAAMorB,EAA0B,IAAI7F,IACpChiB,cAAOkP,KAAKzS,GAAK97B,QAAQ+hD,IAEvBmF,EAAS5E,IAAIP,EADDjmB,EAAIimB,GACM,GAEjBmF,CACT,CAuBM,SAAUC,GACZC,EAAuBJ,EAA6B,IAAI3F,IACxDgG,GACF,GAAIA,EACF,QAAUtF,EAAM9T,KAAQoZ,EACtBL,EAAY1E,IAAIP,EAAM9T,GAG1B,QAAU8T,EAAM9T,KAAQmZ,EACtBJ,EAAY1E,IAAIP,EAAM9T,GAExB,OAAO+Y,CACT,CAEA,SAASM,GAAwBrlD,EAAcnE,EAAaoF,GAG1D,OAAIA,EACKpF,EAAM,IAAMoF,EAAQ,IAEpB,EAEX,CAEA,SAASqkD,GAAoBtlD,GAK3B,IAAIulD,EAAiB,GACrB,QAASvoB,EAAI,EAAGA,EAAIh9B,EAAQmnC,MAAMrwC,OAAQkmC,IAAK,CAC7C,MAAMnhC,EAAMmE,EAAQmnC,MAAMxqC,KAAKqgC,GAC/BuoB,GAAkBF,GAAwBrlD,EAASnE,EAAKmE,EAAQmnC,MAAMqe,iBAAiB3pD,GAAI,CAE7F,UAAWA,KAAOmE,EAAQmnC,MAEnBnnC,EAAQmnC,MAAM9J,eAAexhC,KAAQA,EAAI+wC,WAAW,OAIzD2Y,GAAkBF,GAAwBrlD,EAD1BylD,GAAoB5pD,GACwBmE,EAAQmnC,MAAMtrC,KAE5EmE,EAAQyjC,aAAa,QAAS8hB,EAChC,UAEgBG,GAAU1lD,EAAcmlD,EAAuBQ,GACzD3lD,EAAQmnC,QACVge,EAAOpnD,QAAQ,CAACiuC,EAAK8T,KACnB,MAAM8F,EAAYC,GAAoB/F,GAClC6F,IAAiBA,EAAaG,IAAIhG,IACpC6F,EAAatF,IAAIP,EAAM9/C,EAAQmnC,MAAMye,IAEvC5lD,EAAQmnC,MAAMye,GAAa5Z,IAGzB2S,MACF2G,GAAoBtlD,GAG1B,CAEgB,YAAYA,EAAcmlD,GACpCnlD,EAAQmnC,QACVge,EAAOpnD,QAAQ,CAACyzB,EAAGsuB,KACjB,MAAM8F,EAAYC,GAAoB/F,GACtC9/C,EAAQmnC,MAAMye,GAAa,KAGzBjH,MACF2G,GAAoBtlD,GAG1B,CAEM,SAAU+lD,GAAwBC,GAEtC,OAAIv6C,MAAMw6C,QAAQD,GACI,GAAhBA,EAAMlvD,OAAoBkvD,EAAM,IAAC,EAC9BE,MAASF,GAEXA,CACT,CAeA,MAAMG,GACF,IAAIxrB,OAAO,oBAAmE,KAC5E,SAAUyrB,GAAmBnlD,GACjC,IAAIvF,EAAmB,GACvB,GAAqB,iBAAVuF,EAAoB,CAC7B,IAAIy5B,EACJ,KAAOA,EAAQyrB,GAAYxb,KAAK1pC,IAC9BvF,EAAOkB,KAAK89B,EAAM,IAEpByrB,GAAYE,UAAY,EAE1B,OAAO3qD,CACT,UAEgBC,GACZsF,EAAsBvF,EAA+B4jD,GACvD,MAAMgH,EAAWrlD,EAAM6N,WACjBi+B,EAAMuZ,EAAS9vD,QAAQ2vD,GAAa,CAAC30B,EAAG+0B,KAC5C,IAAIC,EAAW9qD,EAAO6qD,GAEtB,OAAgB,MAAZC,IACFlH,EAAO1iD,KHrNP,SAAU6pD,EAAkBF,GAChC,OAAO,IAAI9H,MAEP,QACN,CGiNkBgI,IACZD,EAAW,IAENA,EAAS13C,UAAQ,GAI1B,OAAOi+B,GAAOuZ,EAAWrlD,EAAQ8rC,CACnC,CAEM,SAAU2Z,GAAgB9sB,GAC9B,MAAMkE,EAAa,GACnB,IAAInhC,EAAOi9B,EAAShd,OACpB,MAAQjgB,EAAKgqD,MACX7oB,EAAIlhC,KAAKD,EAAKsE,OACdtE,EAAOi9B,EAAShd,OAElB,OAAOkhB,CACT,CAEA,MAAM8oB,GAAmB,gBACnB,SAAUf,GAAoBgB,GAClC,OAAOA,EAAMrwD,QAAQowD,GAAkB,IAAIE,IAAaA,EAAE,GAAG/D,cAC/D,CAEM,SAAU0C,GAAoBoB,GAClC,OAAOA,EAAMrwD,QAAQ,kBAAmB,SAAS0K,aACnD,UAgCgB6lD,GAAaC,EAAc9N,EAAW+N,GACpD,OAAQ/N,EAAKp4C,MACX,OACE,OAAOkmD,EAAQE,aAAahO,EAAM+N,GACpC,OACE,OAAOD,EAAQG,WAAWjO,EAAM+N,GAClC,OACE,OAAOD,EAAQI,gBAAgBlO,EAAM+N,GACvC,OACE,OAAOD,EAAQK,cAAcnO,EAAM+N,GACrC,OACE,OAAOD,EAAQM,WAAWpO,EAAM+N,GAClC,OACE,OAAOD,EAAQO,aAAarO,EAAM+N,GACpC,OACE,OAAOD,EAAQQ,eAAetO,EAAM+N,GACtC,OACE,OAAOD,EAAQS,WAAWvO,EAAM+N,GAClC,OACE,OAAOD,EAAQU,eAAexO,EAAM+N,GACtC,OACE,OAAOD,EAAQW,kBAAkBzO,EAAM+N,GACzC,QACE,OAAOD,EAAQY,gBAAgB1O,EAAM+N,GACvC,QACE,OAAOD,EAAQa,WAAW3O,EAAM+N,GAClC,QACE,OAAOD,EAAQc,aAAa5O,EAAM+N,GACpC,QACE,MHvSA,SAAUc,GAAgBjO,GAC9B,OAAO,IAAI2E,MAEP,QACN,CGmSYsJ,GAEZ,CAEgB,YAAa/nD,EAAc8/C,GACzC,OAAa/hC,OAAO9mB,iBAAiB+I,GAAU8/C,EACjD,CChVO,MAAMkI,EAAY,IAIT,YACZC,EAA6C3I,GAC/C,MAAM4I,EAAqC,GAC3C,MAA8B,iBAAnBD,EACTA,EAAgB1kD,MAAM,WAAWxF,QAC7BgvC,GAOR,SAASob,EACLC,EAAkBF,EAAoC5I,GACxD,GAAmB,KAAf8I,EAAS,GAAW,CACtB,MAAM1rD,EAyBV,SAAS2rD,GAAoBC,EAAehJ,GAC1C,OAAQgJ,GACN,IAAK,SACH,MAAO,YACT,IAAK,SACH,MAAO,YACT,IAAK,aACH,MAAO,CAACpH,EAAgBC,IAA0BhU,WAAWgU,GAAWhU,WAAW+T,GACrF,IAAK,aACH,MAAO,CAACA,EAAgBC,IAA0BhU,WAAWgU,GAAWhU,WAAW+T,GACrF,QACE5B,SAAO1iD,KJmFP,SAAU2rD,GAAuBD,GACrC,OAAO,IAAI7J,MAEP,QACN,CIvFkB8J,IACL,SAEb,CAvCmBF,CAAoBD,EAAU9I,GAC7C,GAAqB,mBAAV5iD,EAET,YADAwrD,EAAYtrD,KAAKF,GAGnB0rD,EAAW1rD,EAGb,MAAMg+B,EAAQ0tB,EAAS1tB,MAAM,2CAC7B,GAAa,MAATA,GAAiBA,EAAM5jC,OAAS,EAClCwoD,SAAO1iD,KJuGL,SAAU4rD,GAAkBC,GAChC,OAAO,IAAIhK,MAEP,QACN,CI3GgB+J,IACLN,EAGT,MAAMhH,EAAYxmB,EAAM,GAClBguB,EAAYhuB,EAAM,GAClBymB,EAAUzmB,EAAM,GACtBwtB,EAAYtrD,KAAK+rD,GAAqBzH,EAAWC,IAG7B,KAAhBuH,EAAU,MADaxH,GAAa8G,GAAa7G,GAAW6G,IAE9DE,EAAYtrD,KAAK+rD,GAAqBxH,EAASD,GAEnD,CAjCeiH,CAAwBpb,EAAKmb,EAAa5I,IAErD4I,EAAYtrD,KAA0BqrD,GAEjCC,CACT,CAkDA,MAAMU,GAAsB,IAAIC,IAAY,CAAC,OAAQ,MAC/CC,GAAuB,IAAID,IAAY,CAAC,QAAS,MAEvD,SAASF,GAAqBI,EAAaC,GACzC,MAAMC,EAAoBL,GAAoB9C,IAAIiD,IAAQD,GAAqBhD,IAAIiD,GAC7EG,EAAoBN,GAAoB9C,IAAIkD,IAAQF,GAAqBhD,IAAIkD,GAEnF,MAAO,CAAC9H,EAAgBC,KACtB,IAAIgI,EAAWJ,GAAOf,GAAae,GAAO7H,EACtCkI,EAAWJ,GAAOhB,GAAagB,GAAO7H,EAE1C,OAAKgI,GAAYF,GAA0C,kBAAd/H,IAC3CiI,EAAWjI,EAAY0H,GAAoB9C,IAAIiD,GAAOD,GAAqBhD,IAAIiD,KAE5EK,GAAYF,GAAwC,kBAAZ/H,IAC3CiI,EAAWjI,EAAUyH,GAAoB9C,IAAIkD,GAAOF,GAAqBhD,IAAIkD,IAGxEG,GAAYC,EAEvB,CC3EA,MACMC,GAAmB,IAAI1uB,OAAa,cAAmB,KAsCvD,SAAU2uB,GACZtK,EAAyBuK,EAAiDjK,EAC1EkK,GACF,OAAO,IAAIC,GAA2BzK,GAAQ0K,MAAMH,EAAUjK,EAAQkK,EACxE,OAIaC,GACXp1D,YAAoBs1D,QAAOA,QAAPA,EAEpBD,MAAMH,EAAiDjK,EAAiBkK,GAEtE,MAAMvC,EAAU,IAAI2C,GAA2BtK,GAC/C,YAAKuK,8BAA8B5C,GAEHF,GAAavyD,KAAMuxD,GAAwBwD,GAAWtC,GAchF4C,8BAA8B5C,GACpCA,EAAQ6C,qBAzBU,GA0BlB7C,EAAQ8C,gBAAkB,IAAI3K,IAC9B6H,EAAQ8C,gBAAgB1J,IA3BN,GA2ByB,IAAIjB,KAC/C6H,EAAQjrC,YAAc,EAGxBkrC,aAAaqC,EAAoCtC,GAE/C,IAAI+C,EAAa/C,EAAQ+C,WAAa,EAClCC,EAAWhD,EAAQgD,SAAW,EAClC,MAAMC,EAAqB,GACrBC,EAA+B,GACrC,MAA+B,KAA3BZ,EAASh7C,KAAKu0C,OAAO,IACvBmE,EAAQ3H,OAAO1iD,cL7CLwtD,KACd,OAAO,IAAI3L,MAAY,MAEnB8B,EAEN,CKwC0B6J,IAGtBb,EAASc,YAAYtsD,QAAQusD,IAE3B,GADA91D,KAAKq1D,8BAA8B5C,GACvB,GAARqD,EAAIxpD,KAAqC,CAC3C,MAAMypD,EAAWD,EACX/7C,EAAOg8C,EAASh8C,KACtBA,EAAKO,WAAWvL,MAAM,WAAWxF,QAAQysD,IACvCD,EAASh8C,KAAOi8C,EAChBN,EAAOttD,KAAKpI,KAAK2yD,WAAWoD,EAAUtD,GAAQ,GAEhDsD,EAASh8C,KAAOA,UACC,GAAR+7C,EAAIxpD,KAA0C,CACvD,MAAM2pD,EAAaj2D,KAAK4yD,gBAAgBkD,EAAoCrD,GAC5E+C,GAAcS,EAAWT,WACzBC,GAAYQ,EAAWR,SACvBE,EAAYvtD,KAAK6tD,EAAU,MAE3BxD,EAAQ3H,OAAO1iD,cLzDP8tD,KACd,OAAO,IAAIjM,MAAY,MAEnB8B,EACN,CKqD4BmK,GAAmB,GAIpC,CACL5pD,KAAmC,EACnCyN,KAAMg7C,EAASh7C,KACf27C,SACAC,cACAH,aACAC,WACAU,QAAS,MAIbxD,WAAWoC,EAAkCtC,GAC3C,MAAM2D,EAAWp2D,KAAKizD,WAAW8B,EAASpE,OAAQ8B,GAC5C4D,EAAatB,EAASoB,SAAWpB,EAASoB,QAAQjvD,QAAW,KACnE,GAAIkvD,EAASE,sBAAuB,CAClC,MAAMC,EAAc,IAAIlC,IAClBntD,EAASmvD,GAAa,GAC5BD,EAASzF,OAAOpnD,QAAQopC,IAClBA,aAAiBiY,KACnBjY,EAAMppC,QAAQkD,IACZmlD,GAAmBnlD,GAAOlD,QAAQitD,IAC3BtvD,EAAO2hC,eAAe2tB,IACzBD,EAAYzpC,IAAI0pC,EAAG,EAEtB,EACF,GAGDD,EAAYE,OACSvE,GAAgBqE,EAAYxe,UACnD0a,EAAQ3H,OAAO1iD,KLrFP,YAAasuD,EAAsBH,GACjD,OAAO,IAAItM,MAAY,MAEnB8B,EAIN,CK8E4B4K,IAA2C,CAInE,MAAO,CACLrqD,KAAiC,EACjCyN,KAAMg7C,EAASh7C,KACf44B,MAAOyjB,EACPD,QAASE,EAAY,CAACnvD,OAAQmvD,GAAa,MAI/CzD,gBAAgBmC,EAAuCtC,GAErDA,EAAQ+C,WAAa,EACrB/C,EAAQgD,SAAW,EACnB,MAAMmB,EAAYrE,GAAavyD,KAAMuxD,GAAwBwD,EAAS6B,WAAYnE,GAGlF,MAAO,CACLnmD,KAAsC,EACtCuqD,SAJeC,GAAoB/B,EAASd,KAAMxB,EAAQ3H,QAK1D8L,YACApB,WAAY/C,EAAQ+C,WACpBC,SAAUhD,EAAQgD,SAClBU,QAASY,GAA0BhC,EAASoB,UAIhDtD,cAAckC,EAAqCtC,GAEjD,MAAO,CACLnmD,KAAoC,EACpCklD,MAAOuD,EAASvD,MAAM7lD,IAAIqrD,GAAKzE,GAAavyD,KAAMg3D,EAAGvE,IACrD0D,QAASY,GAA0BhC,EAASoB,UAIhDrD,WAAWiC,EAAkCtC,GAC3C,MAAMjrC,EAAcirC,EAAQjrC,YAC5B,IAAIyvC,EAAe,EACnB,MAAMzF,EAAQuD,EAASvD,MAAM7lD,IAAIurD,IAC/BzE,EAAQjrC,YAAcA,EACtB,MAAM2vC,EAAW5E,GAAavyD,KAAMk3D,EAAMzE,GAC1CwE,SAAe5/C,KAAK+/C,IAAIH,EAAcxE,EAAQjrC,aACvC2vC,IAGT1E,SAAQjrC,YAAcyvC,EACf,CACL3qD,KAAiC,EACjCklD,QACA2E,QAASY,GAA0BhC,EAASoB,UAIhDpD,aAAagC,EAAoCtC,GAE/C,MAAM4E,EA8UV,SAASC,GAAmB7qD,EAAqCq+C,GAC/D,GAAIr+C,EAAMo8B,eAAe,YACvB,OAAOp8B,EAGT,GAAoB,iBAATA,EAET,OAAO8qD,GADU5H,GAAcljD,EAAOq+C,GAAQpiD,SACf,EAAG,IAGpC,MAAM8uD,EAAW/qD,EAEjB,GADkB+qD,EAASzoD,MAAM,OAAOxD,KAAKksD,GAAoB,KAAfA,EAAEnJ,OAAO,IAA4B,KAAfmJ,EAAEnJ,OAAO,IAClE,CACb,MAAMoJ,EAAMH,GAAc,EAAG,EAAG,IAChCG,SAAIC,SAAU,EACdD,EAAIF,SAAWA,EACRE,EAGT,MAAM9H,EAAUD,GAAc6H,EAAU1M,GACxC,OAAOyM,GAAc3H,EAAQlnD,SAAUknD,EAAQtf,MAAOsf,EAAQf,OAChE,CAnWsByI,CAAmBvC,EAASnF,QAAS6C,EAAQ3H,QAC/D2H,EAAQmF,sBAAwBP,EAChC,IAAIjB,EACAyB,EACA9C,EAASpE,OAASoE,EAASpE,UAAShe,MAAM,IAC9C,GAAsB,GAAlBklB,EAAcvrD,KAChB8pD,EAAWp2D,KAAKgzD,eAAe6E,EAAqDpF,OAC/E,CACL,IAAIoF,EAAgB9C,EAASpE,OACzBmH,GAAU,EACd,IAAKD,EAAe,CAClBC,GAAU,EACV,MAAMC,EAAgD,GAClDV,EAAUxI,SACZkJ,EAAalJ,OAAYwI,EAAUxI,QAErCgJ,KAAgBllB,MAAMolB,EAAY,CAEpCtF,EAAQjrC,aAAe6vC,EAAU3uD,SAAW2uD,EAAU/mB,MACtD,MAAM0nB,EAAYh4D,KAAKizD,WAAW4E,EAAepF,GACjDuF,EAAUC,YAAcH,EACxB1B,EAAW4B,EAGbvF,SAAQmF,sBAAwB,KACzB,CACLtrD,KAAmC,EACnCsjD,QAASyH,EACT1kB,MAAOyjB,EACPD,QAAS,MAIblD,WAAW8B,EAAkCtC,GAC3C,MAAMiF,EAAM13D,KAAKk4D,cAAcnD,EAAUtC,GACzC,YAAK0F,kBAAkBT,EAAKjF,GACrBiF,EAGDQ,cAAcnD,EAAkCtC,GAEtD,MAAM9B,EAA0C,GAC1CyH,EAAiBnhD,MAAMw6C,QAAQsD,EAASpE,QAAUoE,EAASpE,OAAS,CAACoE,EAASpE,QAEpF,QAAS0H,KAAcD,EACK,iBAAfC,EACLA,IAAe1M,KACjBgF,EAAOvoD,KAAKiwD,GAEZ5F,EAAQ3H,OAAO1iD,KLtLhB,IAAI6hD,MAEP,UKuLE0G,EAAOvoD,KAAKooD,GAAa6H,IAI7B,IAAI/B,GAAwB,EACxBgC,EAA+B,KACnC3H,SAAOpnD,QAAQgvD,IACb,GAAIA,aAAqB3N,MACnB2N,EAAUjH,IAAI,YAChBgH,EAAkBC,EAAU9nC,IAAI,UAChC8nC,EAAUz9B,OAAO,YAEdw7B,GACH,QAAS7pD,KAAS8rD,EAAUxgB,SAC1B,GAAItrC,EAAO6N,WAAWyrB,QFvQK,OEuQ+B,EAAG,CAC3DuwB,GAAwB,EACxB,SAOH,CACLhqD,KAAiC,EACjCqkD,SACA9B,OAAQyJ,EACRnN,OAAQ4J,EAAS5J,OACjBmL,wBACAH,QAAS,MAILgC,kBAAkBT,EAAejF,GACvC,MAAM7C,EAAU6C,EAAQmF,sBACxB,IAAIY,EAAU/F,EAAQjrC,YAClBixC,EAAYhG,EAAQjrC,YACpBooC,GAAW6I,EAAY,IACzBA,GAAa7I,EAAQlnD,SAAWknD,EAAQtf,OAG1ConB,EAAI/G,OAAOpnD,QAAQmvD,IACI,iBAAVA,GAEXA,EAAMnvD,QAAQ,CAACkD,EAAO6+C,KAWpB,MAAMiK,EAAkB9C,EAAQ8C,gBAAgB9kC,IAAIgiC,EAAQ6C,sBACtDqD,EAAiBpD,EAAgB9kC,IAAI66B,GAC3C,IAAIsN,GAAuB,EACvBD,IACEF,GAAaD,GAAWC,GAAaE,EAAeF,WACpDD,GAAWG,EAAeH,UAC5B/F,EAAQ3H,OAAO1iD,KLzOrB,SAAUywD,GACZvN,EAAcwN,EAAoBC,EAAkBC,EACpDC,GACF,OAAO,IAAIhP,MAAY,MAEnB8B,EAIN,CKgOgC8M,IAEpBD,GAAuB,GAMzBH,EAAYE,EAAeF,WAGzBG,GACFrD,EAAgB1J,IAAIP,EAAM,CAACmN,YAAWD,YAGpC/F,EAAQ0D,kBF3HJ+C,GACZzsD,EAAqC0pD,EAA2BrL,GAClE,MAAM5jD,EAASivD,EAAQjvD,QAAU,GAC3ButC,EAAUmd,GAAmBnlD,GAC/BgoC,EAAQnyC,QACVmyC,EAAQlrC,QAAQwoD,IACT7qD,EAAO2hC,eAAekpB,IACzBjH,EAAO1iD,KHjMT,SAAU+wD,EAAmBpH,GACjC,OAAO,IAAI9H,MAAY,MAEnB8B,EAEN,CG4LoBoN,GAA2B,EAI/C,CEiHUD,CAAoBzsD,EAAOgmD,EAAQ0D,QAAS1D,EAAQ3H,OAAM,EAE7D,GAILkI,eAAe+B,EAA8CtC,GAE3D,MAAMiF,EAAoB,CAACprD,KAAI,EAAmCqkD,OAAQ,GAAIwF,QAAS,MACvF,IAAK1D,EAAQmF,sBACXnF,SAAQ3H,OAAO1iD,cLxPLgxD,KACd,OAAO,IAAInP,MAAY,MAEnB8B,EACN,CKoP0BqN,IACb1B,EAKT,IAAI2B,EAA4B,EAChC,MAAMC,EAAoB,GAC1B,IAAIC,GAAoB,EACpBC,GAAsB,EACtBxO,EAAyB,EAE7B,MAAMN,EAAwBqK,EAASvD,MAAM7lD,IAAIglD,KAC/C,MAAMhe,GAAQ3yC,KAAKk4D,cAAcvH,GAAQ8B,GACzC,IAAIgH,GACgB,MAAhB9mB,GAAMwY,OAAiBxY,GAAMwY,OA+JvC,SAASuO,GAAc/I,GACrB,GAAqB,iBAAVA,EAAoB,OAAO,KAEtC,IAAIxF,EAAsB,KAE1B,GAAIl0C,MAAMw6C,QAAQd,GAChBA,EAAOpnD,QAAQ8uD,IACb,GAAIA,aAAsBzN,KAAOyN,EAAW/G,IAAI,UAAW,CACzD,MAAMjsB,EAAMgzB,EACZlN,EAASxS,WAAWtT,EAAI5U,IAAI,WAC5B4U,EAAIvK,OAAO,SAAQ,SAEtB,GACQ61B,aAAkB/F,KAAO+F,EAAOW,IAAI,UAAW,CACxD,MAAMjsB,EAAMsrB,EACZxF,EAASxS,WAAWtT,EAAI5U,IAAI,WAC5B4U,EAAIvK,OAAO,SAAQ,CAErB,OAAOqwB,CACT,CAlLgDuO,CAAc/mB,GAAMge,QAC1DxF,GAAiB,EACrB,OAAiB,MAAbsO,KACFJ,IACAlO,GAASxY,GAAMwY,OAASsO,IAE1BD,EAAsBA,GAAuBrO,GAAS,GAAKA,GAAS,EACpEoO,EAAoBA,GAAqBpO,GAASH,EAClDA,EAAiBG,GACjBmO,EAAQlxD,KAAK+iD,IACNxY,KAGL6mB,GACF/G,EAAQ3H,OAAO1iD,cL/QLuxD,IACd,OAAO,IAAI1P,MAAY,MAEnB8B,EACN,CK2Q0B4N,IAGlBJ,GACF9G,EAAQ3H,OAAO1iD,cL7QLwxD,KACd,OAAO,IAAI3P,MAAY,MAEnB8B,EACN,CKyQ0B6N,IAGtB,MAAMt3D,EAASyyD,EAASvD,MAAMlvD,OAC9B,IAAIu3D,GAAkB,EAClBR,EAA4B,GAAKA,EAA4B/2D,EAC/DmwD,EAAQ3H,OAAO1iD,cL7QL0xD,KACd,OAAO,IAAI7P,MAAY,MAEnB8B,EACN,CKyQ0B+N,IACkB,GAA7BT,IACTQ,GArC0B,GAqCev3D,EAAS,IAGpD,MAAMk2B,GAAQl2B,EAAS,EACjBklB,GAAcirC,EAAQjrC,YACtBowC,GAAwBnF,EAAQmF,sBAChCmC,GAAkBnC,GAAsBlvD,SAC9CgiD,SAAUnhD,QAAQ,CAAC2hD,GAAI1iB,MACrB,MAAM2iB,GAAS0O,GAAkB,EAAKrxB,IAAKhQ,GAAQ,EAAKqhC,GAAkBrxB,GAAM8wB,EAAQ9wB,IAClFwxB,GAAwB7O,GAAS4O,GACvCtH,EAAQjrC,YAAcA,GAAcowC,GAAsBtnB,MAAQ0pB,GAClEpC,GAAsBlvD,SAAWsxD,GACjCh6D,KAAKm4D,kBAAkBjN,GAAIuH,GAC3BvH,GAAGC,OAASA,GAEZuM,EAAI/G,OAAOvoD,KAAK8iD,GAAE,GAGbwM,EAGTxE,eAAe6B,EAAsCtC,GAEnD,MAAO,CACLnmD,KAAqC,EACrCsqD,UAAWrE,GAAavyD,KAAMuxD,GAAwBwD,EAAS6B,WAAYnE,GAC3E0D,QAASY,GAA0BhC,EAASoB,UAIhDhD,kBAAkB4B,EAAyCtC,GAEzDA,SAAQgD,WACD,CACLnpD,KAAwC,EACxC6pD,QAASY,GAA0BhC,EAASoB,UAIhD/C,gBAAgB2B,EAAuCtC,GAErD,MAAO,CACLnmD,KAAsC,GACtCsqD,UAAW52D,KAAKkzD,eAAe6B,EAAS6B,UAAWnE,GACnD0D,QAASY,GAA0BhC,EAASoB,UAIhD9C,WAAW0B,EAAkCtC,GAC3C,MAAMwH,EAAiBxH,EAAQ6C,qBACzBa,EAAWpB,EAASoB,SAAW,GAErC1D,EAAQ+C,aACR/C,EAAQ78B,aAAem/B,EACvB,MAAOxH,EAAU2M,GAuCrB,SAASC,GAAkB5M,GACzB,MAAM6M,IAAe7M,EAASx+C,MAAM,WAAWT,KAAK+rD,GApdnC,SAod4CA,GAC7D,OAAID,IACF7M,EAAWA,EAASvrD,QAAQ6yD,GAAkB,KAKhDtH,EAAWA,EAASvrD,QAAQ,OAAQqtD,IACpBrtD,QAAQ,QAASkkC,GAASmpB,GAAsB,IAAMnpB,EAAM/uB,MAAM,IAClEnV,QAAQ,cAAeutD,IAEhC,CAAChC,EAAU6M,EACpB,CApDoCD,CAAkBpF,EAASxH,UAC3DkF,EAAQ6C,qBACJ2E,EAAe33D,OAAU23D,EAAiB,IAAM1M,EAAYA,EAChER,GAAqB0F,EAAQ8C,gBAAiB9C,EAAQ6C,qBAAsB,IAAI1K,KAEhF,MAAMgM,EAAYrE,GAAavyD,KAAMuxD,GAAwBwD,EAAS6B,WAAYnE,GAClFA,SAAQ78B,aAAe,KACvB68B,EAAQ6C,qBAAuB2E,EAExB,CACL3tD,KAAiC,GACjCihD,WACA/0B,MAAO29B,EAAQ39B,OAAS,EACxB8hC,WAAYnE,EAAQmE,SACpBJ,cACAtD,YACA2D,iBAAkBxF,EAASxH,SAC3B4I,QAASY,GAA0BhC,EAASoB,UAIhD7C,aAAayB,EAAoCtC,GAE1CA,EAAQ78B,cACX68B,EAAQ3H,OAAO1iD,cLvVLoyD,KACd,OAAO,IAAIvQ,MAAY,MAEnB8B,EACN,CKmV0ByO,IAEtB,MAAM5K,EAA+B,SAArBmF,EAASnF,QACrB,CAAClnD,SAAU,EAAG4nC,MAAO,EAAGue,OAAQ,QAChCc,GAAcoF,EAASnF,QAAS6C,EAAQ3H,QAAQ,GAEpD,MAAO,CACLx+C,KAAmC,GACnCsqD,UAAWrE,GAAavyD,KAAMuxD,GAAwBwD,EAAS6B,WAAYnE,GAC3E7C,UACAuG,QAAS,aA6BFf,GAWXv1D,YAAmBirD,QAAMA,OAANA,EAVZ9qD,KAAUw1D,WAAW,EACrBx1D,KAAQy1D,SAAW,EACnBz1D,KAAiBy6D,kBAAqC,KACtDz6D,KAAY41B,aAAgC,KAC5C51B,KAAoBs1D,qBAAgB,KACpCt1D,KAAqB43D,sBAAmB,KACxC53D,KAAWwnB,YAAW,EACtBxnB,qBAAkB,IAAI4qD,IACtB5qD,KAAOm2D,QAA0B,KACjCn2D,mCAA6C,IAAIq0D,KAkD1D,SAAS0C,GAA0BZ,GACjC,OAAIA,GACFA,EAAU7F,GAAQ6F,IACNjvD,SACVivD,EAAQjvD,OAxEd,SAASwzD,GAAgBr1B,GACvB,OAAOA,EAAMirB,GAAQjrB,GAAO,IAC9B,CAsE0Bq1B,CAAgBvE,EAAQjvD,SAG9CivD,EAAU,GAELA,CACT,CAEA,SAASoB,GAAc7uD,EAAkB4nC,EAAeue,GACtD,MAAO,CAACnmD,WAAU4nC,QAAOue,SAC3B,UChjBgB8L,GACZnvD,EAAck/C,EAAiCkQ,EAC/CC,EAA0BnyD,EAAkB4nC,EAAeue,EAAsB,KACjFiM,GAAuB,GACzB,MAAO,CACLxuD,KAA0D,EAC1Dd,UACAk/C,YACAkQ,gBACAC,iBACAnyD,WACA4nC,QACAsc,UAAWlkD,EAAW4nC,EACtBue,SACAiM,cAEJ,OC/BaC,GAAbl7D,cACUG,UAAO,IAAI4qD,IAEnBn6B,IAAIjlB,GACF,OAAOxL,KAAKg7D,KAAKvqC,IAAIjlB,IAAY,GAGnC2zB,OAAO3zB,EAAcyvD,GACnB,IAAIC,EAAuBl7D,KAAKg7D,KAAKvqC,IAAIjlB,GACpC0vD,GACHl7D,KAAKg7D,KAAKnP,IAAIrgD,EAAS0vD,EAAuB,IAEhDA,EAAqB9yD,QAAQ6yD,GAG/B3J,IAAI9lD,GACF,OAAOxL,KAAKg7D,KAAK1J,IAAI9lD,GAGvB2vD,QACEn7D,KAAKg7D,KAAKG,SCZd,MAEMC,GAAoB,IAAIj1B,OADV,SAC8B,KAE5Ck1B,GAAoB,IAAIl1B,OADV,SAC8B,KAiFlC,YACZqkB,EAAyB8Q,EAAkB5D,EAC3C6D,EAAwBC,EAAwBC,EAAgC,IAAI7Q,IACpF8Q,EAA6B,IAAI9Q,IAAOuL,EACxCwF,EAAyC7Q,EAAkB,IAC7D,OAAO,IAAI8Q,IAAkCC,eACzCrR,EAAQ8Q,EAAa5D,EAAK6D,EAAgBC,EAAgBC,EAAgBC,EAC1EvF,EAASwF,EAAiB7Q,EAChC,OAEa8Q,GACXC,eACIrR,EAAyB8Q,EAAkB5D,EAC3C6D,EAAwBC,EAAwBC,EAChDC,EAA4BvF,EAC5BwF,EACA7Q,EAAkB,IACpB6Q,EAAkBA,GAAmB,IAAIZ,GACzC,MAAMtI,EAAU,IAAIqJ,GAChBtR,EAAQ8Q,EAAaK,EAAiBJ,EAAgBC,EAAgB1Q,EAAQ,IAClF2H,EAAQ0D,QAAUA,EAClB,MAAM7lB,GAAQ6lB,EAAQ7lB,MAAQkf,GAAmB2G,EAAQ7lB,OAAS,EAClEmiB,EAAQsJ,gBAAgBC,cAAc1rB,IACtCmiB,EAAQsJ,gBAAgB7K,UAAU,CAACuK,GAAiB,KAAMhJ,EAAQ3H,OAAQqL,GAE1E5D,GAAavyD,KAAM03D,EAAKjF,GAGxB,MAAMwJ,GAAYxJ,EAAQwJ,UAAUzvD,OAAO0vD,IAAYA,GAASC,qBAMhE,GAAIF,GAAU35D,QAAUo5D,EAAYjF,KAAM,CACxC,IAAI2F,GACJ,QAAS5zB,GAAIyzB,GAAU35D,OAAS,EAAGkmC,IAAK,EAAGA,KAAK,CAC9C,MAAM0zB,GAAWD,GAAUzzB,IAC3B,GAAI0zB,GAAS1wD,UAAY8vD,EAAa,CACpCc,GAAmBF,GACnB,OAGAE,KAAqBA,GAAiBC,2BACxCD,GAAiBlL,UAAU,CAACwK,GAAc,KAAMjJ,EAAQ3H,OAAQqL,EAAO,CAG3E,OAAO8F,GAAU35D,OACb25D,GAAUtwD,IAAIuwD,IAAYA,GAASL,kBACnC,CAAClB,GAA0BW,EAAa,GAAI,GAAI,GAAI,EAAGhrB,GAAO,IAAI,IAGxEoiB,aAAagF,EAAiBjF,IAI9BE,WAAW+E,EAAejF,IAI1BG,gBAAgB8E,EAAoBjF,IAIpCU,kBAAkBuE,EAAsBjF,GACtC,MAAM6J,EAAsB7J,EAAQkJ,gBAAgBlrC,IAAIgiC,EAAQjnD,SAChE,GAAI8wD,EAAqB,CACvB,MAAMC,EAAe9J,EAAQ+J,iBAAiB9E,EAAIvB,SAC5CsC,EAAYhG,EAAQsJ,gBAAgBv0C,YACpCgxC,EAAUx4D,KAAKy8D,sBACjBH,EAAqBC,EAAcA,EAAapG,SAChDsC,GAAaD,GAGf/F,EAAQiK,yBAAyBlE,EAAO,CAG5C/F,EAAQkK,aAAejF,EAGzBtE,gBAAgBsE,EAAoBjF,GAClC,MAAM8J,EAAe9J,EAAQ+J,iBAAiB9E,EAAIvB,SAClDoG,EAAaG,2BACb18D,KAAK48D,yBAAyB,CAAClF,EAAIvB,QAASuB,EAAId,UAAUT,SAAU1D,EAAS8J,GAC7Ev8D,KAAKkzD,eAAewE,EAAId,UAAW2F,GACnC9J,EAAQiK,yBAAyBH,EAAaR,gBAAgBv0C,aAC9DirC,EAAQkK,aAAejF,EAGjBkF,yBACJC,EAAkDpK,EAClD8J,GACF,UAAWO,KAAuBD,EAAuB,CACvD,MAAME,EAAiBD,GAAqBxsB,MAC5C,GAAIysB,EAAgB,CAClB,MAAMC,EAAgD,iBAAnBD,EAC/BA,EACAvN,GAAmBroD,GACf41D,EAAgBD,GAAqB51D,QAAU,GAAIurD,EAAQ3H,SACnEyR,EAAaP,cAAcgB,EAAmB,GAK5CP,sBACJxB,EAA8CxI,EAC9C0D,GAEF,IAAIc,EADcxE,EAAQsJ,gBAAgBv0C,YAK1C,MAAM9e,EAA+B,MAApBytD,EAAQztD,SAAmB8mD,GAAmB2G,EAAQztD,UAAY,KAC7E4nC,EAAyB,MAAjB6lB,EAAQ7lB,MAAgBkf,GAAmB2G,EAAQ7lB,OAAS,KAC1E,OAAiB,IAAb5nC,GACFuyD,EAAa1xD,QAAQ0zD,IACnB,MAAMC,EACFzK,EAAQ0K,4BAA4BF,EAAav0D,EAAU4nC,GAC/D2mB,EACI5/C,KAAK+/C,IAAIH,EAAciG,EAAmBx0D,SAAWw0D,EAAmB5sB,MAAK,GAI9E2mB,EAGT/D,eAAewE,EAAmBjF,GAChCA,EAAQ2K,cAAc1F,EAAIvB,SAAS,GACnC5D,GAAavyD,KAAM03D,EAAId,UAAWnE,GAClCA,EAAQkK,aAAejF,EAGzB7E,cAAc6E,EAAkBjF,GAC9B,MAAM4K,EAAkB5K,EAAQ4K,gBAChC,IAAI1xC,EAAM8mC,EACV,MAAM0D,EAAUuB,EAAIvB,QAEpB,GAAIA,IAAYA,EAAQjvD,QAAUivD,EAAQ7lB,SACxC3kB,EAAM8mC,EAAQ+J,iBAAiBrG,GAC/BxqC,EAAI+wC,2BAEiB,MAAjBvG,EAAQ7lB,OAAe,CACA,GAArB3kB,EAAIgxC,aAAarwD,OACnBqf,EAAIowC,gBAAgBuB,wBACpB3xC,EAAIgxC,aAAeY,IAGrB,MAAMjtB,EAAQkf,GAAmB2G,EAAQ7lB,OACzC3kB,EAAIqwC,cAAc1rB,EAAK,CAIvBonB,EAAIlG,MAAMlvD,SACZo1D,EAAIlG,MAAMjoD,QAAQytD,GAAKzE,GAAavyD,KAAMg3D,EAAGrrC,IAG7CA,EAAIowC,gBAAgByB,wBAKhB7xC,EAAI0xC,gBAAkBA,GACxB1xC,EAAI+wC,4BAIRjK,EAAQkK,aAAejF,EAGzB5E,WAAW4E,EAAejF,GACxB,MAAMgL,EAAoC,GAC1C,IAAIxG,EAAexE,EAAQsJ,gBAAgBv0C,YAC3C,MAAM8oB,EAAQonB,EAAIvB,SAAWuB,EAAIvB,QAAQ7lB,MAAQkf,GAAmBkI,EAAIvB,QAAQ7lB,OAAS,EAEzFonB,EAAIlG,MAAMjoD,QAAQytD,IAChB,MAAMuF,EAAe9J,EAAQ+J,iBAAiB9E,EAAIvB,SAC9C7lB,GACFisB,EAAaP,cAAc1rB,GAG7BiiB,GAAavyD,KAAMg3D,EAAGuF,GACtBtF,EAAe5/C,KAAK+/C,IAAIH,EAAcsF,EAAaR,gBAAgBv0C,aACnEi2C,EAAer1D,KAAKm0D,EAAaR,gBAAe,GAMlD0B,EAAel0D,QACX2yD,GAAYzJ,EAAQsJ,gBAAgB2B,6BAA6BxB,IACrEzJ,EAAQiK,yBAAyBzF,GACjCxE,EAAQkK,aAAejF,EAGjBiG,aAAajG,EAAgBjF,GACnC,GAAKiF,EAAyBC,QAAS,CACrC,MAAMH,EAAYE,EAAyBF,SAG3C,OAAO7H,GADH8C,EAAQvrD,OAASC,GAAkBqwD,EAAU/E,EAAQvrD,OAAQurD,EAAQ3H,QAAU0M,EACjD/E,EAAQ3H,OAAM,CAEhD,MAAO,CAACpiD,SAAUgvD,EAAIhvD,SAAU4nC,MAAOonB,EAAIpnB,MAAOue,OAAQ6I,EAAI7I,QAIlEkE,aAAa2E,EAAiBjF,GAC5B,MAAM7C,EAAU6C,EAAQmF,sBAAwB53D,KAAK29D,aAAajG,EAAI9H,QAAS6C,GACzEyJ,EAAWzJ,EAAQsJ,gBACrBnM,EAAQtf,QACVmiB,EAAQmL,cAAchO,EAAQtf,OAC9B4rB,EAASoB,yBAGX,MAAM3qB,EAAQ+kB,EAAI/kB,MACJ,GAAVA,EAAMrmC,KACRtM,KAAKgzD,eAAergB,EAAO8f,IAE3BA,EAAQmL,cAAchO,EAAQlnD,UAC9B1I,KAAKizD,WAAWtgB,EAAmB8f,GACnCyJ,EAASsB,yBAGX/K,EAAQmF,sBAAwB,KAChCnF,EAAQkK,aAAejF,EAGzBzE,WAAWyE,EAAejF,GACxB,MAAMyJ,EAAWzJ,EAAQsJ,gBACnBnM,EAAU6C,EAAQmF,uBAInBhI,GAAWsM,EAAS2B,6BACvB3B,EAAS4B,eAGX,MAAMjP,EAAUe,GAAWA,EAAQf,QAAW6I,EAAI7I,OAC9C6I,EAAIO,YACNiE,EAAS6B,eAAelP,GAExBqN,EAAShL,UAAUwG,EAAI/G,OAAQ9B,EAAQ4D,EAAQ3H,OAAQ2H,EAAQ0D,SAGjE1D,EAAQkK,aAAejF,EAGzB1E,eAAe0E,EAAmBjF,GAChC,MAAMmF,EAAwBnF,EAAQmF,sBAChCa,EAAahG,EAAQsJ,gBAAkBrzD,SACvCA,EAAWkvD,EAAsBlvD,SAEjCs1D,EADevL,EAAQ+J,mBACMT,gBACnCiC,EAAcnP,OAAS+I,EAAsB/I,OAE7C6I,EAAI/G,OAAOpnD,QAAQ2tD,IAEjB8G,EAAcC,aADS/G,EAAK/L,QAAU,GACHziD,GACnCs1D,EAAc9M,UAAUgG,EAAKvG,OAAQuG,EAAKrI,OAAQ4D,EAAQ3H,OAAQ2H,EAAQ0D,SAC1E6H,EAAcR,uBAAqB,GAKrC/K,EAAQsJ,gBAAgB2B,6BAA6BM,GAIrDvL,EAAQiK,yBAAyBjE,EAAY/vD,GAC7C+pD,EAAQkK,aAAejF,EAGzBrE,WAAWqE,EAAejF,GAGxB,MAAMgG,EAAYhG,EAAQsJ,gBAAgBv0C,YACpC2uC,EAAWuB,EAAIvB,SAAW,GAC1B7lB,EAAQ6lB,EAAQ7lB,MAAQkf,GAAmB2G,EAAQ7lB,OAAS,EAE9DA,IAC0D,IAAzDmiB,EAAQkK,aAAarwD,MACP,GAAbmsD,GAAkBhG,EAAQsJ,gBAAgB8B,+BAC9CpL,EAAQsJ,gBAAgBuB,wBACxB7K,EAAQkK,aAAeY,IAGzB,IAAItG,EAAewB,EACnB,MAAMyF,EAAOzL,EAAQxE,YACjByJ,EAAInK,SAAUmK,EAAI6C,iBAAkB7C,EAAIl/B,MAAOk/B,EAAIwC,cACnD/D,EAAQmE,SAAyB7H,EAAQ3H,QAE7C2H,EAAQ0L,kBAAoBD,EAAK57D,OACjC,IAAI87D,EAA4C,KAChDF,EAAK30D,QAAQ,CAACiC,EAASg9B,KACrBiqB,EAAQ4L,kBAAoB71B,EAC5B,MAAM+zB,EAAe9J,EAAQ+J,iBAAiB9E,EAAIvB,QAAS3qD,GACvD8kC,GACFisB,EAAaP,cAAc1rB,GAGzB9kC,IAAYinD,EAAQjnD,UACtB4yD,EAAsB7B,EAAaR,iBAGrCxJ,GAAavyD,KAAM03D,EAAId,UAAW2F,GAKlCA,EAAaR,gBAAgByB,wBAG7BvG,EAAe5/C,KAAK+/C,IAAIH,EADRsF,EAAaR,gBAAgBv0C,YACA,GAG/CirC,EAAQ4L,kBAAoB,EAC5B5L,EAAQ0L,kBAAoB,EAC5B1L,EAAQiK,yBAAyBzF,GAE7BmH,IACF3L,EAAQsJ,gBAAgB2B,6BAA6BU,GACrD3L,EAAQsJ,gBAAgBuB,yBAG1B7K,EAAQkK,aAAejF,EAGzBpE,aAAaoE,EAAiBjF,GAC5B,MAAM6L,EAAgB7L,EAAQ6L,cACxBC,EAAK9L,EAAQsJ,gBACbnM,EAAU8H,EAAI9H,QACdlnD,EAAW2O,KAAK4gB,IAAI23B,EAAQlnD,UAC5B81D,EAAU91D,GAAY+pD,EAAQ0L,kBAAoB,GACxD,IAAI7tB,EAAQ5nC,EAAW+pD,EAAQ4L,kBAG/B,OADyBzO,EAAQlnD,SAAW,EAAI,UAAYknD,EAAQf,QAElE,IAAK,UACHve,EAAQkuB,EAAUluB,EAClB,MACF,IAAK,OACHA,EAAQguB,EAAcG,mBAI1B,MAAMvC,EAAWzJ,EAAQsJ,gBACrBzrB,GACF4rB,EAASF,cAAc1rB,GAGzB,MAAMouB,EAAexC,EAAS10C,YAC9B+qC,GAAavyD,KAAM03D,EAAId,UAAWnE,GAClCA,EAAQkK,aAAejF,EAMvB4G,EAAcG,mBACTF,EAAG/2C,YAAck3C,GAAiBH,EAAG9F,UAAY6F,EAAcvC,gBAAgBtD,YAQxF,MAAM8E,GAAyD,SAClDzB,GAWXj8D,YACYs1D,EAAiC3pD,EAClCmwD,EAAgDgD,EAC/CC,EAAgC9T,EAAwBmR,EAChE4C,GAHQ7+D,KAAOm1D,QAAPA,EAAiCn1D,KAAOwL,QAAPA,EAClCxL,KAAe27D,gBAAfA,EAAgD37D,KAAe2+D,gBAAfA,EAC/C3+D,KAAe4+D,gBAAfA,EAAgC5+D,KAAM8qD,OAANA,EAAwB9qD,KAASi8D,UAATA,EAb7Dj8D,KAAas+D,cAAkC,KAE/Ct+D,KAAqB43D,sBAAwB,KAC7C53D,KAAY28D,aAA+BY,GAC3Cv9D,KAAeq9D,gBAAG,EAClBr9D,KAAOm2D,QAAqB,GAC5Bn2D,KAAiBq+D,kBAAW,EAC5Br+D,KAAiBm+D,kBAAW,EAC5Bn+D,KAAkBy+D,mBAAW,EAOlCz+D,KAAK+7D,gBAAkB8C,GAAmB,IAAIC,GAAgB9+D,KAAKm1D,QAAS3pD,EAAS,GACrFywD,EAAU7zD,KAAKpI,KAAK+7D,iBAGlB70D,aACF,OAAOlH,KAAKm2D,QAAQjvD,OAGtBk2D,cAAcjH,EAAgC4I,GAC5C,IAAK5I,EAAS,OAEd,MAAM6I,EAAa7I,EACnB,IAAI8I,EAAkBj/D,KAAKm2D,QAGA,MAAvB6I,EAAWt2D,WACZu2D,EAAwBv2D,SAAW8mD,GAAmBwP,EAAWt2D,WAG5C,MAApBs2D,EAAW1uB,QACb2uB,EAAgB3uB,MAAQkf,GAAmBwP,EAAW1uB,QAGxD,MAAM4uB,EAAYF,EAAW93D,OAC7B,GAAIg4D,EAAW,CACb,IAAIC,EAAwCF,EAAgB/3D,OACvDi4D,IACHA,EAAiBn/D,KAAKm2D,QAAQjvD,OAAS,IAGzC0hC,OAAOkP,KAAKonB,GAAW31D,QAAQwQ,MACxBglD,IAAiBI,EAAet2B,eAAe9uB,MAClDolD,EAAeplD,GAAQ5S,GAAkB+3D,EAAUnlD,GAAOolD,EAAgBn/D,KAAK8qD,QAAM,EAExF,EAIGsU,eACN,MAAMjJ,EAA4B,GAClC,GAAIn2D,KAAKm2D,QAAS,CAChB,MAAMkJ,EAAYr/D,KAAKm2D,QAAQjvD,OAC/B,GAAIm4D,EAAW,CACb,MAAMn4D,EAAgCivD,EAAQjvD,OAAY,GAC1D0hC,OAAOkP,KAAKunB,GAAW91D,QAAQwQ,IAC7B7S,EAAO6S,GAAQslD,EAAUtlD,EAAI,EAC9B,EAGL,OAAOo8C,EAGTqG,iBAAiBrG,EAAiC,KAAM3qD,EAAe8zD,GAErE,MAAMl0C,EAAS5f,GAAWxL,KAAKwL,QACzBinD,EAAU,IAAIqJ,GAChB97D,KAAKm1D,QAAS/pC,EAAQprB,KAAK27D,gBAAiB37D,KAAK2+D,gBAAiB3+D,KAAK4+D,gBACvE5+D,KAAK8qD,OAAQ9qD,KAAKi8D,UAAWj8D,KAAK+7D,gBAAgBwD,KAAKn0C,EAAQk0C,GAAW,IAC9E7M,SAAQkK,aAAe38D,KAAK28D,aAC5BlK,EAAQmF,sBAAwB53D,KAAK43D,sBAErCnF,EAAQ0D,QAAUn2D,KAAKo/D,eACvB3M,EAAQ2K,cAAcjH,GAEtB1D,EAAQ4L,kBAAoBr+D,KAAKq+D,kBACjC5L,EAAQ0L,kBAAoBn+D,KAAKm+D,kBACjC1L,EAAQ6L,cAAgBt+D,KACxBA,KAAKq9D,kBACE5K,EAGTiK,yBAAyB4C,GACvB,YAAK3C,aAAeY,GACpBv9D,KAAK+7D,gBAAkB/7D,KAAK+7D,gBAAgBwD,KAAKv/D,KAAKwL,QAAS8zD,GAC/Dt/D,KAAKi8D,UAAU7zD,KAAKpI,KAAK+7D,iBAClB/7D,KAAK+7D,gBAGdoB,4BACIF,EAA2Cv0D,EAC3C4nC,GACF,MAAMkvB,EAAiC,CACrC92D,SAAUA,GAA8Bu0D,EAAYv0D,SACpD4nC,MAAOtwC,KAAK+7D,gBAAgBv0C,aAAe8oB,GAAwB,GAAK2sB,EAAY3sB,MACpFue,OAAQ,IAEJ4Q,EAAU,IAAIC,GAChB1/D,KAAKm1D,QAAS8H,EAAYzxD,QAASyxD,EAAYvS,UAAWuS,EAAYrC,cACtEqC,EAAYpC,eAAgB2E,EAAgBvC,EAAY0C,yBAC5D,YAAK1D,UAAU7zD,KAAKq3D,GACbD,EAGT5B,cAAcz1C,GACZnoB,KAAK+7D,gBAAgBkC,YAAYj+D,KAAK+7D,gBAAgBrzD,SAAWyf,GAGnE6zC,cAAc1rB,GAERA,EAAQ,GACVtwC,KAAK+7D,gBAAgBC,cAAc1rB,GAIvC2d,YACIV,EAAkBgN,EAA0B/hC,EAAe0hC,EAC3DI,EAAmBxP,GACrB,IAAIpsB,EAAiB,GAIrB,GAHIw7B,GACFx7B,EAAQt2B,KAAKpI,KAAKwL,SAEhB+hD,EAASjrD,OAAS,EAAG,CAEvBirD,GADAA,EAAWA,EAASvrD,QAAQo5D,GAAmB,IAAMp7D,KAAK2+D,kBACtC38D,QAAQq5D,GAAmB,IAAMr7D,KAAK4+D,iBAE1D,IAAIgB,EAAW5/D,KAAKm1D,QAAQhoD,MAAMnN,KAAKwL,QAAS+hD,EADzB,GAAT/0B,GAEA,IAAVA,IACFonC,EAAWpnC,EAAQ,EAAIonC,EAASzoD,MAAMyoD,EAASt9D,OAASk2B,EAAOonC,EAASt9D,QACjDs9D,EAASzoD,MAAM,EAAGqhB,IAE3CkG,EAAQt2B,QAAQw3D,EAAQ,CAG1B,OAAKtF,GAA8B,GAAlB57B,EAAQp8B,QACvBwoD,EAAO1iD,KR3dP,SAAUy3D,GAAatS,GAC3B,OAAO,IAAItD,MAAY,MAEnB8B,EAGN,CQqdkB8T,IAEPnhC,SAIEogC,GAaXj/D,YACYs1D,EAAiC3pD,EAAqBitD,EACtDqH,GADA9/D,KAAOm1D,QAAPA,EAAiCn1D,KAAOwL,QAAPA,EAAqBxL,KAASy4D,UAATA,EACtDz4D,KAA4B8/D,6BAA5BA,EAdL9/D,KAAQ0I,SAAW,EACnB1I,KAAM6uD,OAAgB,KACrB7uD,uBAAmC,IAAI4qD,IACvC5qD,sBAAkC,IAAI4qD,IACtC5qD,gBAAa,IAAI4qD,IACjB5qD,mBAAgB,IAAI4qD,IACpB5qD,0BAAsC,IAAI4qD,IAE1C5qD,oBAAgC,IAAI4qD,IACpC5qD,eAA2B,IAAI4qD,IAC/B5qD,KAAyB+/D,0BAAuB,KAKjD//D,KAAK8/D,+BACR9/D,KAAK8/D,6BAA+B,IAAIlV,KAG1C5qD,KAAKggE,sBAAwBhgE,KAAK8/D,6BAA6BrvC,IAAIjlB,GAC9DxL,KAAKggE,wBACRhgE,KAAKggE,sBAAwBhgE,KAAKigE,qBAClCjgE,KAAK8/D,6BAA6BjU,IAAIrgD,EAASxL,KAAKigE,uBAEtDjgE,KAAKkgE,gBAGP/D,oBACE,OAAQn8D,KAAKmgE,WAAW1J,MACtB,KAAK,EACH,OAAO,EACT,KAAK,EACH,OAAOz2D,KAAK69D,4BACd,QACE,OAAO,GAIbA,4BACE,OAAO79D,KAAKogE,iBAAiB3J,KAAO,EAGlCjvC,kBACF,OAAOxnB,KAAKy4D,UAAYz4D,KAAK0I,SAG/BszD,cAAc1rB,GAKZ,MAAM+vB,EAA2C,IAAzBrgE,KAAKmgE,WAAW1J,MAAcz2D,KAAKsgE,eAAe7J,KAEtEz2D,KAAK0I,UAAY23D,GACnBrgE,KAAKi+D,YAAYj+D,KAAKwnB,YAAc8oB,GAChC+vB,GACFrgE,KAAKs9D,yBAGPt9D,KAAKy4D,WAAanoB,EAItBivB,KAAK/zD,EAAcgc,GACjB,YAAKg2C,wBACE,IAAIsB,GACP9+D,KAAKm1D,QAAS3pD,EAASgc,GAAexnB,KAAKwnB,YAAaxnB,KAAK8/D,8BAG3DI,gBACFlgE,KAAKogE,mBACPpgE,KAAKugE,kBAAoBvgE,KAAKogE,kBAEhCpgE,KAAKogE,iBAAmBpgE,KAAKmgE,WAAW1vC,IAAIzwB,KAAK0I,UAC5C1I,KAAKogE,mBACRpgE,KAAKogE,iBAAmB,IAAIxV,IAC5B5qD,KAAKmgE,WAAWtU,IAAI7rD,KAAK0I,SAAU1I,KAAKogE,mBAI5CtC,eACE99D,KAAK0I,UAxqByB,EAyqB9B1I,KAAKkgE,gBAGPjC,YAAY91C,GACVnoB,KAAKw9D,wBACLx9D,KAAK0I,SAAWyf,EAChBnoB,KAAKkgE,gBAGCM,aAAalV,EAAc7+C,GACjCzM,KAAKigE,qBAAqBpU,IAAIP,EAAM7+C,GACpCzM,KAAKggE,sBAAsBnU,IAAIP,EAAM7+C,GACrCzM,KAAKygE,cAAc5U,IAAIP,EAAM,CAACnjC,KAAMnoB,KAAKwnB,YAAa/a,UAGxD4vD,0BACE,OAAOr8D,KAAK+/D,4BAA8B//D,KAAKogE,iBAGjDrC,eAAelP,GACTA,GACF7uD,KAAKugE,kBAAkB1U,IAAI,SAAUgD,GASvC,QAAUvD,EAAM7+C,KAAUzM,KAAKggE,sBAC7BhgE,KAAK0gE,UAAU7U,IAAIP,EAAM7+C,GAASk/C,MAClC3rD,KAAKogE,iBAAiBvU,IAAIP,EAAMK,MAElC3rD,KAAK+/D,0BAA4B//D,KAAKogE,iBAGxClP,UACImB,EAAwCxD,EAAqB/D,EAC7DqL,GACEtH,GACF7uD,KAAKugE,kBAAkB1U,IAAI,SAAUgD,GAEvC,MAAM3nD,EAAUivD,GAAWA,EAAQjvD,QAAW,GACxCypD,EA0KV,SAASgQ,GAActO,EAAwCuO,GAC7D,MAAMjQ,EAAwB,IAAI/F,IAClC,IAAIiW,EACJxO,SAAM9oD,QAAQ8wD,IACZ,GAAc,MAAVA,EAAe,CACjBwG,EAAgBA,GAAiBD,EAAU9oB,OAC3C,QAASwT,KAAQuV,EACflQ,EAAO9E,IAAIP,EAAMK,KAAU,MAG7B+E,GAAW2J,EAAwB1J,EAAM,GAGtCA,CACT,CAxLmBgQ,CAActO,EAAOryD,KAAKggE,uBACzC,QAAU1U,EAAM7+C,KAAUkkD,EAAQ,CAChC,MAAMnZ,EAAMrwC,GAAkBsF,EAAOvF,EAAQ4jD,GAC7C9qD,KAAKsgE,eAAezU,IAAIP,EAAM9T,GACzBx3C,KAAKigE,qBAAqB3O,IAAIhG,IACjCtrD,KAAK0gE,UAAU7U,IAAIP,EAAMtrD,KAAKggE,sBAAsBvvC,IAAI66B,IAASK,MAEnE3rD,KAAKwgE,aAAalV,EAAM9T,EAAG,EAI/BgmB,wBACkC,GAA5Bx9D,KAAKsgE,eAAe7J,OAExBz2D,KAAKsgE,eAAe/2D,QAAQ,CAACiuC,EAAK8T,KAChCtrD,KAAKogE,iBAAiBvU,IAAIP,EAAM9T,EAAG,GAErCx3C,KAAKsgE,eAAenF,QAEpBn7D,KAAKigE,qBAAqB12D,QAAQ,CAACiuC,EAAK8T,KACjCtrD,KAAKogE,iBAAiB9O,IAAIhG,IAC7BtrD,KAAKogE,iBAAiBvU,IAAIP,EAAM9T,EAAG,IAKzC8lB,wBACE,QAAUhS,EAAM9T,KAAQx3C,KAAKigE,qBAC3BjgE,KAAKsgE,eAAezU,IAAIP,EAAM9T,GAC9Bx3C,KAAKwgE,aAAalV,EAAM9T,GAI5BspB,mBACE,OAAO9gE,KAAKmgE,WAAW1vC,IAAIzwB,KAAK0I,UAG9Bq4D,iBACF,MAAMA,EAAuB,GAC7B,QAASzV,KAAQtrD,KAAKogE,iBACpBW,EAAW34D,KAAKkjD,GAElB,OAAOyV,EAGTrD,6BAA6BxB,GAC3BA,EAASuE,cAAcl3D,QAAQ,CAACy3D,EAAU1V,KACxC,MAAM2V,EAAWjhE,KAAKygE,cAAchwC,IAAI66B,KACnC2V,GAAYD,EAAS74C,KAAO84C,EAAS94C,OACxCnoB,KAAKwgE,aAAalV,EAAM0V,EAASv0D,MAAK,GAK5CovD,iBACE77D,KAAKw9D,wBACL,MAAM5C,EAAgB,IAAIvG,IACpBwG,EAAiB,IAAIxG,IACrByD,EAAmC,IAAzB93D,KAAKmgE,WAAW1J,MAAgC,IAAlBz2D,KAAK0I,SAEnD,IAAIw4D,EAAuC,GAC3ClhE,KAAKmgE,WAAW52D,QAAQ,CAAC43D,EAAUh5C,KACjC,MAAMi5C,EAAgB1Q,GAAWyQ,EAAU,IAAIvW,IAAO5qD,KAAK0gE,WAC3DU,EAAc73D,QAAQ,CAACkD,EAAO6+C,KACxB7+C,IAAUi/C,KACZkP,EAAc9tC,IAAIw+B,GACT7+C,IAAUk/C,MACnBkP,EAAe/tC,IAAIw+B,EAAI,GAGtBwM,GACHsJ,EAAcvV,IAAI,SAAU1jC,EAAOnoB,KAAK0I,UAE1Cw4D,EAAe94D,KAAKg5D,EAAa,GAGnC,MAAMC,EAAqBzG,EAAcnE,KAAOvE,GAAgB0I,EAAc7iB,UAAY,GACpFupB,EAAsBzG,EAAepE,KAAOvE,GAAgB2I,EAAe9iB,UAAY,GAG7F,GAAI+f,EAAS,CACX,MAAMyJ,EAAML,EAAe,GACrBM,EAAM,IAAI5W,IAAI2W,GACpBA,EAAI1V,IAAI,SAAU,GAClB2V,EAAI3V,IAAI,SAAU,GAClBqV,EAAiB,CAACK,EAAKC,EAAG,CAG5B,OAAO7G,GACH36D,KAAKwL,QAAS01D,EAAgBG,EAAUC,EAAWthE,KAAK0I,SAAU1I,KAAKy4D,UACvEz4D,KAAK6uD,QAAQ,IAIrB,MAAM6Q,WAA2BZ,GAG/Bj/D,YACI2qD,EAAyBh/C,EAAqBk/C,EACvCkQ,EAAgCC,EAA0BjL,EACzD6R,GAAoC,GAC9CvsB,MAAMsV,EAAQh/C,EAASokD,EAAQtf,OAHiBtwC,KAAS0qD,UAATA,EACvC1qD,KAAa46D,cAAbA,EAAgC56D,KAAc66D,eAAdA,EAC/B76D,KAAwByhE,yBAAxBA,EAEVzhE,KAAK4vD,QAAU,CAAClnD,SAAUknD,EAAQlnD,SAAU4nC,MAAOsf,EAAQtf,MAAOue,OAAQe,EAAQf,QAG3EsN,oBACP,OAAOn8D,KAAK0qD,UAAUpoD,OAAS,EAGxBu5D,iBACP,IAAInR,EAAY1qD,KAAK0qD,WAChBpa,QAAO5nC,WAAUmmD,UAAU7uD,KAAK4vD,QACrC,GAAI5vD,KAAKyhE,0BAA4BnxB,EAAO,CAC1C,MAAMoxB,EAAqC,GACrC9U,EAAYlkD,EAAW4nC,EACvBqxB,EAAcrxB,EAAQsc,EAGtBgV,EAAmBlR,GAAWhG,EAAU,IAC9CkX,EAAiB/V,IAAI,SAAU,GAC/B6V,EAAat5D,KAAKw5D,GAElB,MAAMC,EAAmBnR,GAAWhG,EAAU,IAC9CmX,EAAiBhW,IAAI,SAAUiW,GAAYH,IAC3CD,EAAat5D,KAAKy5D,GAkBlB,MAAMrpC,EAAQkyB,EAAUpoD,OAAS,EACjC,QAASkmC,EAAI,EAAGA,GAAKhQ,EAAOgQ,IAAK,CAC/B,IAAI0iB,GAAKwF,GAAWhG,EAAUliB,IAC9B,MAAMu5B,GAAY7W,GAAGz6B,IAAI,UAEzBy6B,GAAGW,IAAI,SAAUiW,IADMxxB,EAAQyxB,GAAYr5D,GACGkkD,IAC9C8U,EAAat5D,KAAK8iD,GAAE,CAItBxiD,EAAWkkD,EACXtc,EAAQ,EACRue,EAAS,GAETnE,EAAYgX,EAGd,OAAO/G,GACH36D,KAAKwL,QAASk/C,EAAW1qD,KAAK46D,cAAe56D,KAAK66D,eAAgBnyD,EAAU4nC,EAAOue,GACnF,IAIR,SAASiT,GAAY3W,EAAgB6W,EAAgB,GACnD,MAAMC,EAAO5qD,KAAK6qD,IAAI,GAAIF,EAAgB,GAC1C,OAAO3qD,KAAKkR,MAAM4iC,EAAS8W,GAAQA,CACrC,OCn4BsBE,ICCtB,MAAMC,GAAuB,IAAI/N,IAAI,CACnC,QACA,SACA,WACA,YACA,WACA,YACA,OACA,MACA,SACA,QACA,WACA,eACA,gBACA,aACA,cACA,gBACA,eACA,YACA,aACA,eACA,cACA,eACA,cACA,iBACA,kBACA,mBACA,oBACA,aACA,gBAGI,MAAOgO,WAAqCF,GACvC1W,sBAAsB6W,EAAsBxX,GACnD,OAAOuG,GAAoBiR,GAGpB1W,oBACL2W,EAA8BC,EAA4B/1D,EAC1Dq+C,GACF,IAAI4E,EAAe,GACnB,MAAM+S,EAASh2D,EAAM6N,WAAW8b,OAEhC,GAAIgsC,GAAqB9Q,IAAIkR,IAAiC,IAAV/1D,GAAyB,MAAVA,EACjE,GAAqB,iBAAVA,EACTijD,EAAO,SACF,CACL,MAAMgT,EAAoBj2D,EAAMy5B,MAAM,0BAClCw8B,GAAoD,GAA/BA,EAAkB,GAAGpgE,QAC5CwoD,EAAO1iD,KVVD,YAAoBm6D,EAA8B91D,GAChE,OAAO,IAAIw9C,MAAY,MAEnB8B,EACN,CUMsB4W,GAAgD,CAIlE,OAAOF,EAAS/S,GCnCd,SAAUkT,GACZp3D,EAAcihD,EAAqBC,EAAmBC,EACtDkW,EAA8BC,EAA2BC,EACzD9G,EAA2C+G,EAC3CpI,EAAsCC,EAAuCjO,EAC7E9B,IACF,MAAO,CACLx+C,KAA4D,EAC5Dd,UACAihD,cACAoW,sBACAnW,YACAoW,aACAnW,UACAoW,WACA9G,YACA+G,kBACApI,gBACAC,iBACAjO,YACA9B,UAEJ,CC/BA,MAAMmY,GAAe,SAERC,GACXrjE,YACYsjE,EAA6BzL,EAC7B0L,GADApjE,KAAYmjE,aAAZA,EAA6BnjE,KAAG03D,IAAHA,EAC7B13D,KAAYojE,aAAZA,EAEZl9B,MAAMm9B,EAAmBC,EAAgB93D,EAActE,GACrD,OAsIJ,SAASq8D,GACLC,EAAiCH,EAAmBC,EAAgB93D,EACpEtE,GACF,OAAOs8D,EAASj4D,KAAKk4D,GAAMA,EAAGJ,EAAcC,EAAW93D,EAAStE,GAClE,CA1IWq8D,CAA0BvjE,KAAK03D,IAAIb,SAAUwM,EAAcC,EAAW93D,EAAStE,GAGxFw8D,YAAYC,EAAqCz8D,EAA8B4jD,GAE7E,IAAI8Y,EAAS5jE,KAAKojE,aAAa3yC,IAAI,KACnC,YAAkBhvB,IAAdkiE,IACFC,EAAS5jE,KAAKojE,aAAa3yC,IAAIkzC,GAAWrpD,aAAespD,GAEpDA,EAASA,EAAOF,YAAYx8D,EAAQ4jD,GAAU,IAAIF,IAG3DsK,MACI1K,EAAyBh/C,EAAc63D,EAAmBC,EAC1D/H,EAAwBC,EAAwBqI,EAChDC,EAAgCnI,EAChCoI,GACF,MAAMjZ,EAAkB,GAElBkZ,GAA4BhkE,KAAK03D,IAAIvB,SAAWn2D,KAAK03D,IAAIvB,QAAQjvD,QAAU+7D,GAE3EgB,GAAqBjkE,KAAK0jE,YAAYL,EADbQ,GAAkBA,EAAe38D,QAAU+7D,GACQnY,GAC5EoZ,GAAsBJ,GAAeA,EAAY58D,QAAU+7D,GAC3DkB,GAAkBnkE,KAAK0jE,YAAYJ,EAAWY,GAAqBpZ,GAEnEkY,GAAkB,IAAI3O,IACtB+P,GAAc,IAAIxZ,IAClByZ,GAAe,IAAIzZ,IACnB0Z,GAA0B,SAAdhB,EAEZiB,GAAqC,CACzCr9D,OAAQs9D,GAAmBN,GAAqBF,IAChD1zB,MAAOtwC,KAAK03D,IAAIvB,SAAS7lB,OAGrB2rB,GAAY8H,EACd,GACAU,GACIja,EAAQh/C,EAASxL,KAAK03D,IAAId,UAAW2E,EAAgBC,EAAgByI,GACrEE,GAAiBI,GAAkB5I,EAAiB7Q,GAE5D,IAAI8B,GAAY,EAKhB,GAJAqP,GAAU1yD,QAAQg1D,KAChB3R,GAAYv1C,KAAK+/C,IAAImH,GAAG71D,SAAW61D,GAAGjuB,MAAOsc,GAAS,GAGpD9B,EAAOxoD,OACT,OAAOsgE,GACHp3D,EAASxL,KAAKmjE,aAAcE,EAAcC,EAAWgB,GAAWL,GAChEE,GAAiB,GAAI,GAAIC,GAAaC,GAAczX,GAAW9B,GAGrEmR,GAAU1yD,QAAQg1D,KAChB,MAAMmG,GAAMnG,GAAG/yD,QACT61D,GAAWtU,GAAqBqX,GAAaM,GAAK,IAAIrQ,KAC5DkK,GAAG3D,cAAcrxD,QAAQ+hD,IAAQ+V,GAASv0C,IAAIw+B,KAE9C,MAAMgW,GAAYvU,GAAqBsX,GAAcK,GAAK,IAAIrQ,KAC9DkK,GAAG1D,eAAetxD,QAAQ+hD,IAAQgW,GAAUx0C,IAAIw+B,KAE5CoZ,KAAQl5D,GACVw3D,GAAgBl2C,IAAI43C,GAAG,GAQ3B,MAAMC,GAAsBzS,GAAgB8Q,GAAgBjrB,UAC5D,OAAO6qB,GACHp3D,EAASxL,KAAKmjE,aAAcE,EAAcC,EAAWgB,GAAWL,GAChEE,GAAiBlI,GAAW0I,GAAqBP,GAAaC,GAAczX,KAoEpF,SAAS4X,GAAmBI,EAAiCC,GAC3D,MAAM38D,EAA8BooD,GAAQuU,GAE5C,UAAWx9D,KAAOu9D,EACZA,EAAW/7B,eAAexhC,IAA2B,MAAnBu9D,EAAWv9D,KAC/Ca,EAAOb,GAAOu9D,EAAWv9D,IAI7B,OAAOa,CACT,OAEa48D,GACXjlE,YACY8wD,EAA0BoU,EAC1Bta,GADAzqD,KAAM2wD,OAANA,EAA0B3wD,KAAa+kE,cAAbA,EAC1B/kE,KAAUyqD,WAAVA,EAEZiZ,YAAYx8D,EAA8B4jD,GACxC,MAAM4Q,EAA6B,IAAI9Q,IACjCoa,EAAiB1U,GAAQtwD,KAAK+kE,eACpCn8B,cAAOkP,KAAK5wC,GAAQqC,QAAQlC,IAC1B,MAAMoF,EAAQvF,EAAOG,GACP,OAAVoF,IACFu4D,EAAe39D,GAAOoF,KAG1BzM,KAAK2wD,OAAOA,OAAOpnD,QAAQkD,IACJ,iBAAVA,GACTA,EAAMlD,QAAQ,CAACiuC,EAAK8T,KACd9T,IACFA,EAAMrwC,GAAkBqwC,EAAKwtB,EAAgBla,IAE/C,MAAMS,EAAiBvrD,KAAKyqD,WAAWgB,sBAAsBH,EAAMR,GACnEtT,EAAMx3C,KAAKyqD,WAAWmB,oBAAoBN,EAAMC,EAAgB/T,EAAKsT,GACrE4Q,EAAY7P,IAAIP,EAAM9T,EAAG,EAC1B,GAGEkkB,SC3LEuJ,GAKXplE,YACWka,EAAqB29C,EAAyBwN,GAA9CllE,KAAI+Z,KAAJA,EAAqB/Z,KAAG03D,IAAHA,EAAyB13D,KAAWklE,YAAXA,EALlDllE,KAAmBmlE,oBAAiC,GAEpDnlE,YAAS,IAAI4qD,IAIlB8M,EAAIhC,OAAOnsD,QAAQmuD,IAEjB13D,KAAK01D,OAAO7J,IAAI6L,EAAI39C,KAAM,IAAI+qD,GAAqBpN,EAAI/kB,MADhC+kB,EAAIvB,SAAWuB,EAAIvB,QAAQjvD,QAAW,GACgBg+D,GAAY,GAG3FE,GAAkBplE,KAAK01D,OAAQ,OAAQ,KACvC0P,GAAkBplE,KAAK01D,OAAQ,QAAS,KAExCgC,EAAI/B,YAAYpsD,QAAQmuD,IACtB13D,KAAKmlE,oBAAoB/8D,KAAK,IAAI86D,GAA2BnpD,EAAM29C,EAAK13D,KAAK01D,QAAO,GAEtF11D,KAAKqlE,mBAmBT,SAASC,GACL7Y,EAAqBiJ,EACrBjL,GAWF,OAAO,IAAIyY,GAA2BzW,EARJ,CAChCngD,KAAsC,EACtCsqD,UAH6B,CAACtqD,KAAI,EAAkCklD,MAAO,GAAI2E,QAAS,MAIxFU,SALe,CAAC,CAACnK,EAAgBC,KAAiB,GAMlDwJ,QAAS,KACTX,WAAY,EACZC,SAAU,GAEmDC,EACjE,CAjC8B4P,CAAyBvrD,EAAM/Z,KAAK01D,QAG5D6P,sBACF,OAAOvlE,KAAK03D,IAAIlC,WAAa,EAG/BgQ,gBAAgBnC,EAAmBC,EAAgB93D,EAActE,GAI/D,OADIlH,KAAKmlE,oBAAoB72D,KAAKm3D,GAAKA,EAAEv/B,MAAMm9B,EAAcC,EAAW93D,EAAStE,KACjE,KAGlBw+D,YAAYrC,EAAmBn8D,EAA8B4jD,GAC3D,OAAO9qD,KAAKqlE,mBAAmB3B,YAAYL,EAAcn8D,EAAQ4jD,IAoBrE,SAASsa,GACLO,EAA6CC,EAAcC,GACzDF,EAASrU,IAAIsU,GACVD,EAASrU,IAAIuU,IAChBF,EAAS9Z,IAAIga,EAAMF,EAASl1C,IAAIm1C,IAEzBD,EAASrU,IAAIuU,IACtBF,EAAS9Z,IAAI+Z,EAAMD,EAASl1C,IAAIo1C,GAEpC,CC5DA,MAAMC,GAAwB,IAAI/K,SAErBgL,GAKXlmE,YACWmmE,EAAuB7Q,EACtB+P,GADDllE,KAAQgmE,SAARA,EAAuBhmE,KAAOm1D,QAAPA,EACtBn1D,KAAWklE,YAAXA,EANJllE,iBAAc,IAAI4qD,IAClB5qD,kBAAe,IAAI4qD,IACpB5qD,KAAOy8C,QAAsB,GAMpCwpB,SAAS39D,EAAYysD,GACnB,MAAMjK,EAAkB,GAClBkK,EAAqB,GACrB0C,EAAM5C,GAAkB90D,KAAKm1D,QAASJ,EAAUjK,EAAQkK,GAC9D,GAAIlK,EAAOxoD,OACT,MdgJA,SAAU4jE,GAAepb,GAC7B,OAAO,IAAIb,MAAY,MAEnB8B,EAGN,CctJYma,GAKNlmE,KAAKmmE,YAAYta,IAAIvjD,EAAIovD,GAIrB0O,aACJ59B,EAAiCmiB,EACjCE,GACF,MAAMr/C,EAAUg9B,EAAEh9B,QACZk/C,EAAYH,GACdvqD,EAAcA,KAAKklE,YAAa15D,EAASg9B,EAAEkiB,UAAWC,EAAWE,GACrE,OAAO7qD,KAAKm1D,QAAQvG,QAAQpjD,EAASk/C,EAAWliB,EAAE9/B,SAAU8/B,EAAE8H,MAAO9H,EAAEqmB,OAAQ,IAAI,GAGrFl0B,OAAOryB,EAAYkD,EAAc2qD,EAA4B,IAC3D,MAAMrL,EAAkB,GAClB4M,EAAM13D,KAAKmmE,YAAY11C,IAAInoB,GACjC,IAAI2yD,EAEJ,MAAMoL,EAAgB,IAAIzb,IAgB1B,GAdI8M,GACFuD,EAAewJ,GACXzkE,KAAKm1D,QAAS3pD,EAASksD,EAAKxI,GAAiBC,GAAiB,IAAIvE,IAAO,IAAIA,IAC7EuL,EAAS2P,GAAuBhb,GACpCmQ,EAAa1xD,QAAQ+8D,IACnB,MAAM3V,EAAS5D,GACXsZ,EAAeC,EAAK96D,QAAS,IAAIo/C,KACrC0b,EAAKzL,eAAetxD,QAAQ+hD,IAAQqF,EAAO9E,IAAIP,GAAM,MAAK,KAG5DR,EAAO1iD,cdqHGm+D,KACd,OAAO,IAAItc,MAAY,MAEnB8B,EACN,CczHkBwa,IACZtL,EAAe,IAGbnQ,EAAOxoD,OACT,MdsHA,SAAUkkE,GAAsB1b,GACpC,OAAO,IAAIb,MAAY,MAEnB8B,EAGN,Cc5HYya,GAGRH,EAAc98D,QAAQ,CAAConD,EAAQnlD,KAC7BmlD,EAAOpnD,QAAQ,CAACyzB,GAAGsuB,MACjBqF,EAAO9E,IAAIP,GAAMtrD,KAAKm1D,QAAQxG,aAAanjD,EAAS8/C,GAAMK,MAAW,EACtE,GAGH,MAIM7kC,EAASsjC,GAJC6Q,EAAatvD,IAAI68B,IAC/B,MAAMmoB,EAAS0V,EAAc51C,IAAI+X,EAAEh9B,SACnC,OAAOxL,KAAKomE,aAAa59B,EAAG,IAAIoiB,IAAO+F,EAAM,IAG/C,YAAK8V,aAAa5a,IAAIvjD,EAAIwe,GAC1BA,EAAOwlC,UAAU,IAAMtsD,KAAK0mE,QAAQp+D,IAEpCtI,KAAKy8C,QAAQr0C,KAAK0e,GACXA,EAGT4/C,QAAQp+D,GACN,MAAMwe,EAAS9mB,KAAK2mE,WAAWr+D,GAC/Bwe,EAAO4/C,UACP1mE,KAAKymE,aAAa3rC,OAAOxyB,GACzB,MAAM4zB,EAAQl8B,KAAKy8C,QAAQ1W,QAAQjf,GAC/BoV,GAAS,GACXl8B,KAAKy8C,QAAQ4T,OAAOn0B,EAAO,GAIvByqC,WAAWr+D,GACjB,MAAMwe,EAAS9mB,KAAKymE,aAAah2C,IAAInoB,GACrC,IAAKwe,EACH,Md4FA,SAAU8/C,GAAct+D,GAC5B,OAAO,IAAI2hD,MAEP,QACN,CchGY2c,GAER,OAAO9/C,EAGT+/C,OAAOv+D,EAAYkD,EAAiBygD,EAAmBC,GAGrD,MAAM4a,EAAYta,GAAmBhhD,EAAS,GAAI,GAAI,IACtDwgD,UAAehsD,KAAK2mE,WAAWr+D,GAAK2jD,EAAW6a,EAAW5a,GACnD,OAGTe,QAAQ3kD,EAAYkD,EAAcyhD,EAAiB8Z,GACjD,GAAe,YAAX9Z,EAEF,YADAjtD,KAAKimE,SAAS39D,EAAIy+D,EAAK,IAIzB,GAAe,UAAX9Z,EAGF,YADAjtD,KAAK26B,OAAOryB,EAAIkD,EADCu7D,EAAK,IAAM,IAK9B,MAAMjgD,EAAS9mB,KAAK2mE,WAAWr+D,GAC/B,OAAQ2kD,GACN,IAAK,OACHnmC,EAAO2B,OACP,MACF,IAAK,QACH3B,EAAOw0B,QACP,MACF,IAAK,QACHx0B,EAAO2Y,QACP,MACF,IAAK,UACH3Y,EAAOkgD,UACP,MACF,IAAK,SACHlgD,EAAOmgD,SACP,MACF,IAAK,OACHngD,EAAOogD,OACP,MACF,IAAK,cACHpgD,EAAOqgD,YAAYxuB,WAAWouB,EAAK,KACnC,MACF,IAAK,UACH/mE,KAAK0mE,QAAQp+D,KC5IrB,MAAM8+D,GAAmB,oBAEnBC,GAAqB,sBAKrBC,GAAkD,GAClDC,GAA4C,CAChDC,YAAa,GACbC,eAAe,EACfC,YAAY,EACZC,cAAc,EACdC,sBAAsB,GAElBC,GAAoD,CACxDL,YAAa,GACbE,YAAY,EACZD,eAAe,EACfE,cAAc,EACdC,sBAAsB,GAmBXE,GAAe,qBAWfC,GAIP7gE,aACF,OAAOlH,KAAKm2D,QAAQjvD,OAGtBrH,YAAYwyD,EAAmBmV,EAAsB,IAAtBxnE,KAAWwnE,YAAXA,EAC7B,MAAMQ,EAAQ3V,GAASA,EAAMxpB,eAAe,SAG5C,GADA7oC,KAAKyM,MA+gDT,SAASw7D,GAAsBx7D,GAI7B,OAAOA,GAAwB,IACjC,CAphDiBw7D,CADCD,EAAQ3V,EAAM5lD,MAAW4lD,GAEnC2V,EAAO,CACT,MAAM7R,EAAU7F,GAAQ+B,UACjB8D,EAAQ1pD,MACfzM,KAAKm2D,QAAUA,OAEfn2D,KAAKm2D,QAAU,GAEZn2D,KAAKm2D,QAAQjvD,SAChBlH,KAAKm2D,QAAQjvD,OAAS,IAI1BghE,cAAc/R,GACZ,MAAM+I,EAAY/I,EAAQjvD,OAC1B,GAAIg4D,EAAW,CACb,MAAMG,EAAYr/D,KAAKm2D,QAAQjvD,OAC/B0hC,OAAOkP,KAAKonB,GAAW31D,QAAQ+hD,IACN,MAAnB+T,EAAU/T,KACZ+T,EAAU/T,GAAQ4T,EAAU5T,GAAI,EAEnC,GAKA,MAAM6c,GAAa,OACbC,GAAsB,IAAIL,GAAWI,UAErCE,GAUXxoE,YACWyI,EAAmBggE,EAA0BC,GAA7CvoE,KAAEsI,GAAFA,EAAmBtI,KAAWsoE,YAAXA,EAA0BtoE,KAAOuoE,QAAPA,EAVjDvoE,KAAOy8C,QAAgC,GAEtCz8C,eAAY,IAAI4qD,IAChB5qD,KAAMwoE,OAAuB,GAE7BxoE,uBAAoB,IAAI4qD,IAM9B5qD,KAAKyoE,eAAiB,UAAYngE,EAClC89B,GAASkiC,EAAatoE,KAAKyoE,gBAG7B5B,OAAOr7D,EAAcuO,EAAc2uD,EAAexc,GAChD,IAAKlsD,KAAK2oE,UAAUrX,IAAIv3C,GACtB,MfiFU,YAAe2uD,EAAe3uD,GAC5C,OAAO,IAAIkwC,MAAY,MAEnB8B,EAGN,CevFY6c,GAGR,GAAa,MAATF,GAAiC,GAAhBA,EAAMpmE,OACzB,MfqFA,SAAUumE,GAAa9uD,GAC3B,OAAO,IAAIkwC,MAAY,MAEnB8B,EAGN,Ce3FY8c,GAGR,IAo+CJ,SAASC,GAAoB7c,GAC3B,MAAoB,SAAbA,GAAqC,QAAbA,CACjC,CAt+CS6c,CAAoBJ,GACvB,MfyFU,YAAwBA,EAAe3uD,GACrD,OAAO,IAAIkwC,MAAY,MAEnB8B,EAGN,Ce/FYgd,GAGR,MAAMC,EAAYjc,GAAqB/sD,KAAKipE,kBAAmBz9D,EAAS,IAClEhL,EAAO,CAACuZ,OAAM2uD,QAAOxc,YAC3B8c,EAAU5gE,KAAK5H,GAEf,MAAM0oE,EACFnc,GAAqB/sD,KAAKuoE,QAAQY,gBAAiB39D,EAAS,IAAIo/C,KACpE,OAAKse,EAAmB5X,IAAIv3C,KAC1BqsB,GAAS56B,EAAS4jD,IAClBhpB,GAAS56B,EAAS4jD,GAAuB,IAAMr1C,GAC/CmvD,EAAmBrd,IAAI9xC,EAAMquD,KAGxB,KAILpoE,KAAKuoE,QAAQa,WAAW,KACtB,MAAMltC,EAAQ8sC,EAAUjjC,QAAQvlC,GAC5B07B,GAAS,GACX8sC,EAAU3Y,OAAOn0B,EAAO,GAGrBl8B,KAAK2oE,UAAUrX,IAAIv3C,IACtBmvD,EAAmBpuC,OAAO/gB,EAAI,EAEjC,EAILksD,SAASlsD,EAAc29C,GACrB,OAAI13D,KAAK2oE,UAAUrX,IAAIv3C,KAIrB/Z,KAAK2oE,UAAU9c,IAAI9xC,EAAM29C,IAClB,GAIH2R,YAAYtvD,GAClB,MAAMuvD,EAAUtpE,KAAK2oE,UAAUl4C,IAAI1W,GACnC,IAAKuvD,EACH,MfoDA,SAAUC,GAAoBxvD,GAClC,OAAO,IAAIkwC,MAEP,QACN,CexDYsf,GAER,OAAOD,EAGTA,QAAQ99D,EAAcihD,EAAqBhgD,EAAY+8D,GAA6B,GAElF,MAAMF,EAAUtpE,KAAKqpE,YAAY5c,GAC3B3lC,EAAS,IAAI2iD,GAA0BzpE,KAAKsI,GAAImkD,EAAajhD,GAEnE,IAAI09D,EAAqBlpE,KAAKuoE,QAAQY,gBAAgB14C,IAAIjlB,GACrD09D,IACH9iC,GAAS56B,EAAS4jD,IAClBhpB,GAAS56B,EAAS4jD,GAAuB,IAAM3C,GAC/CzsD,KAAKuoE,QAAQY,gBAAgBtd,IAAIrgD,EAAS09D,EAAqB,IAAIte,MAGrE,IAAI8B,EAAYwc,EAAmBz4C,IAAIg8B,GACvC,MAAME,EAAU,IAAIob,GAAWt7D,EAAOzM,KAAKsI,IAoB3C,KAnBcmE,GAASA,EAAMo8B,eAAe,WAC9B6jB,GACZC,EAAQub,cAAcxb,EAAUyJ,SAGlC+S,EAAmBrd,IAAIY,EAAaE,GAE/BD,IACHA,EAAY0b,IAGIzb,EAAQlgD,QAAU07D,IAQlBzb,EAAUjgD,QAAUkgD,EAAQlgD,MAAO,CAGnD,IAsgDN,SAASi9D,GAAUv7D,EAAyBE,GAC1C,MAAMs7D,EAAK/gC,OAAOkP,KAAK3pC,GACjBy7D,EAAKhhC,OAAOkP,KAAKzpC,GACvB,GAAIs7D,EAAGrnE,QAAUsnE,EAAGtnE,OAAQ,OAAO,EACnC,QAASkmC,EAAI,EAAGA,EAAImhC,EAAGrnE,OAAQkmC,IAAK,CAClC,MAAM8iB,EAAOqe,EAAGnhC,GAChB,IAAKn6B,EAAEw6B,eAAeyiB,IAASn9C,EAAEm9C,KAAUj9C,EAAEi9C,GAAO,OAAO,EAE7D,OAAO,CACT,CA/gDWoe,CAAUhd,EAAUxlD,OAAQylD,EAAQzlD,QAAS,CAChD,MAAM4jD,GAAkB,GAClBgY,GAAawG,EAAQ5D,YAAYhZ,EAAUjgD,MAAOigD,EAAUxlD,OAAQ4jD,IACpEiY,GAAWuG,EAAQ5D,YAAY/Y,EAAQlgD,MAAOkgD,EAAQzlD,OAAQ4jD,IAChEA,GAAOxoD,OACTtC,KAAKuoE,QAAQsB,YAAY/e,IAEzB9qD,KAAKuoE,QAAQa,WAAW,KACtBU,GAAYt+D,EAASs3D,IACrB5R,GAAU1lD,EAASu3D,GAAQ,EAC5B,CAGL,OAGF,MAAMgH,GACFhd,GAAqB/sD,KAAKuoE,QAAQyB,iBAAkBx+D,EAAS,IACjEu+D,GAAiBxgE,QAAQud,KAKnBA,GAAO0gD,aAAexnE,KAAKsI,IAAMwe,GAAO2lC,aAAeA,GAAe3lC,GAAOmjD,QAC/EnjD,GAAO4/C,SAAO,GAIlB,IAAIzQ,GACAqT,EAAQ9D,gBAAgB9Y,EAAUjgD,MAAOkgD,EAAQlgD,MAAOjB,EAASmhD,EAAQzlD,QACzEgjE,IAAuB,EAC3B,IAAKjU,GAAY,CACf,IAAKuT,EAAmB,OACxBvT,GAAaqT,EAAQjE,mBACrB6E,IAAuB,EAGzB,YAAK3B,QAAQ4B,qBACbnqE,KAAKwoE,OAAOpgE,KACR,CAACoD,UAASihD,cAAawJ,cAAYvJ,YAAWC,UAAS7lC,SAAQojD,0BAE9DA,KACH9jC,GAAS56B,EAAS47D,IAClBtgD,EAAOqlC,QAAQ,KACb7lB,GAAY96B,EAAS47D,GAAgB,IAIzCtgD,EAAOulC,OAAO,KACZ,IAAInwB,GAAQl8B,KAAKy8C,QAAQ1W,QAAQjf,GAC7BoV,IAAS,GACXl8B,KAAKy8C,QAAQ4T,OAAOn0B,GAAO,GAG7B,MAAMugB,GAAUz8C,KAAKuoE,QAAQyB,iBAAiBv5C,IAAIjlB,GAClD,GAAIixC,GAAS,CACX,IAAIvgB,GAAQugB,GAAQ1W,QAAQjf,GACxBoV,IAAS,GACXugB,GAAQ4T,OAAOn0B,GAAO,EAAC,IAK7Bl8B,KAAKy8C,QAAQr0C,KAAK0e,GAClBijD,GAAiB3hE,KAAK0e,GAEfA,EAGTsjD,WAAWrwD,GACT/Z,KAAK2oE,UAAU7tC,OAAO/gB,GAEtB/Z,KAAKuoE,QAAQY,gBAAgB5/D,QAAQo8D,GAAYA,EAAS7qC,OAAO/gB,IAEjE/Z,KAAKipE,kBAAkB1/D,QAAQ,CAACy/D,EAAWx9D,KACzCxL,KAAKipE,kBAAkBpd,IAAIrgD,EAASw9D,EAAUx8D,OAAO69D,GAC5CA,EAAMtwD,MAAQA,GACrB,GAINuwD,kBAAkB9+D,GAChBxL,KAAKuoE,QAAQY,gBAAgBruC,OAAOtvB,GACpCxL,KAAKipE,kBAAkBnuC,OAAOtvB,GAC9B,MAAM++D,EAAiBvqE,KAAKuoE,QAAQyB,iBAAiBv5C,IAAIjlB,GACrD++D,IACFA,EAAehhE,QAAQud,GAAUA,EAAO4/C,WACxC1mE,KAAKuoE,QAAQyB,iBAAiBlvC,OAAOtvB,IAIjCg/D,+BAA+BlP,EAAkB7I,GACvD,MAAMmN,EAAW5/D,KAAKuoE,QAAQ/d,OAAOr9C,MAAMmuD,EAAajM,IAAqB,GAK7EuQ,EAASr2D,QAAQm7D,IAGf,GAAIA,EAAIoD,IAAe,OAEvB,MAAM2C,EAAazqE,KAAKuoE,QAAQmC,yBAAyBhG,GACrD+F,EAAWhU,KACbgU,EAAWlhE,QAAQohE,GAAMA,EAAGC,sBAAsBlG,EAAKjS,GAAS,GAAO,IAEvEzyD,KAAKsqE,kBAAkB5F,EAAG,GAM9B1kE,KAAKuoE,QAAQsC,yBACT,IAAMjL,EAASr2D,QAAQm7D,GAAO1kE,KAAKsqE,kBAAkB5F,KAG3DkG,sBACIp/D,EAAcinD,EAAcqY,EAC5BtB,GACF,MAAMuB,EAAgB/qE,KAAKuoE,QAAQY,gBAAgB14C,IAAIjlB,GACjDw/D,EAAyB,IAAIpgB,IACnC,GAAImgB,EAAe,CACjB,MAAMtuB,EAAuC,GAa7C,GAZAsuB,EAAcxhE,QAAQ,CAAC7I,EAAO+rD,KAI5B,GAHAue,EAAuBnf,IAAIY,EAAa/rD,EAAM+L,OAG1CzM,KAAK2oE,UAAUrX,IAAI7E,GAAc,CACnC,MAAM3lC,EAAS9mB,KAAKspE,QAAQ99D,EAASihD,EAAa0b,GAAYqB,GAC1D1iD,GACF21B,EAAQr0C,KAAK0e,EAAM,IAKrB21B,EAAQn6C,OACV,YAAKimE,QAAQ0C,qBAAqBjrE,KAAKsI,GAAIkD,GAAS,EAAMinD,EAASuY,GAC/DF,GACF1gB,GAAoB3N,GAAS4P,OAAO,IAAMrsD,KAAKuoE,QAAQ2C,iBAAiB1/D,KAEnE,EAGX,OAAO,EAGT2/D,+BAA+B3/D,GAC7B,MAAMw9D,EAAYhpE,KAAKipE,kBAAkBx4C,IAAIjlB,GACvC4/D,EAAgBprE,KAAKuoE,QAAQY,gBAAgB14C,IAAIjlB,GAIvD,GAAIw9D,GAAaoC,EAAe,CAC9B,MAAMC,EAAkB,IAAIhX,IAC5B2U,EAAUz/D,QAAQ+hE,IAChB,MAAM7e,EAAc6e,EAASvxD,KAC7B,GAAIsxD,EAAgB/Z,IAAI7E,GAAc,OACtC4e,EAAgBv+C,IAAI2/B,GAGpB,MAAMwJ,EADUj2D,KAAK2oE,UAAUl4C,IAAIg8B,GACR4Y,mBACrB3Y,EAAY0e,EAAc36C,IAAIg8B,IAAgB2b,GAC9Czb,EAAU,IAAIob,GAAWI,IACzBrhD,EAAS,IAAI2iD,GAA0BzpE,KAAKsI,GAAImkD,EAAajhD,GAEnExL,KAAKuoE,QAAQ4B,qBACbnqE,KAAKwoE,OAAOpgE,KAAK,CACfoD,UACAihD,cACAwJ,aACAvJ,YACAC,UACA7lC,SACAojD,sBAAsB,GACvB,EACF,EAILqB,WAAW//D,EAAcinD,GACvB,MAAM+Y,EAASxrE,KAAKuoE,QAMpB,GALI/8D,EAAQigE,mBACVzrE,KAAKwqE,+BAA+Bh/D,EAASinD,GAI3CzyD,KAAK4qE,sBAAsBp/D,EAASinD,GAAS,GAAO,OAIxD,IAAIiZ,GAAoC,EACxC,GAAIF,EAAOG,gBAAiB,CAC1B,MAAMC,EACFJ,EAAO/uB,QAAQn6C,OAASkpE,EAAOK,wBAAwBp7C,IAAIjlB,GAAW,GAM1E,GAAIogE,GAAkBA,EAAetpE,OACnCopE,GAAoC,MAC/B,CACL,IAAI3nB,EAASv4C,EACb,KAAOu4C,EAASA,EAAO3Q,YAErB,GADiBo4B,EAAOrC,gBAAgB14C,IAAIszB,GAC9B,CACZ2nB,GAAoC,EACpC,QAcR,GAJA1rE,KAAKmrE,+BAA+B3/D,GAIhCkgE,EACFF,EAAOP,qBAAqBjrE,KAAKsI,GAAIkD,GAAS,EAAOinD,OAChD,CACL,MAAMqZ,EAActgE,EAAQs8D,MACvBgE,GAAeA,IAAgBvE,MAGlCiE,EAAOpC,WAAW,IAAMppE,KAAKsqE,kBAAkB9+D,IAC/CggE,EAAOO,uBAAuBvgE,GAC9BggE,EAAOQ,mBAAmBxgE,EAASinD,GAAO,EAKhDwZ,WAAWzgE,EAAcu4C,GACvB3d,GAAS56B,EAASxL,KAAKyoE,gBAGzByD,uBAAuBC,GACrB,MAAMlR,EAAmC,GACzC,YAAKuN,OAAOj/D,QAAQ8gE,IAClB,MAAMvjD,EAASujD,EAAMvjD,OACrB,GAAIA,EAAOs0B,UAAW,OAEtB,MAAM5vC,EAAU6+D,EAAM7+D,QAChBw9D,EAAYhpE,KAAKipE,kBAAkBx4C,IAAIjlB,GACzCw9D,GACFA,EAAUz/D,QAAS+hE,IACjB,GAAIA,EAASvxD,MAAQswD,EAAM5d,YAAa,CACtC,MAAMqa,EAAYta,GACdhhD,EAAS6+D,EAAM5d,YAAa4d,EAAM3d,UAAUjgD,MAAO49D,EAAM1d,QAAQlgD,OACpEq6D,EAAkBha,MAAWqf,EAC9BngB,GAAeqe,EAAMvjD,OAAQwkD,EAAS5C,MAAO5B,EAAWwE,EAASpf,SAAQ,IAK3EplC,EAAOslD,iBACTpsE,KAAKuoE,QAAQa,WAAW,KAGtBtiD,EAAO4/C,SAAO,GAGhBzL,EAAa7yD,KAAKiiE,EAAK,GAI3BrqE,KAAKwoE,OAAS,GAEPvN,EAAax3C,KAAK,CAACtV,EAAGE,KAG3B,MAAMg+D,EAAKl+D,EAAE8nD,WAAWyB,IAAIjC,SACtB6W,EAAKj+D,EAAE4nD,WAAWyB,IAAIjC,SAC5B,OAAU,GAAN4W,GAAiB,GAANC,EACND,EAAKC,EAEPtsE,KAAKuoE,QAAQ/d,OAAOwD,gBAAgB7/C,EAAE3C,QAAS6C,EAAE7C,SAAW,GAAI,IAI3Ek7D,QAAQjU,GACNzyD,KAAKy8C,QAAQlzC,QAAQgjE,GAAKA,EAAE7F,WAC5B1mE,KAAKwqE,+BAA+BxqE,KAAKsoE,YAAa7V,GAGxD+Z,oBAAoBhhE,GAClB,IAAIihE,GAAe,EACnB,OAAIzsE,KAAKipE,kBAAkB3X,IAAI9lD,KAAUihE,GAAe,GACxDA,IACKzsE,KAAKwoE,OAAOl6D,KAAK+7D,GAASA,EAAM7+D,UAAYA,IAA4BihE,EACtEA,SAUEC,GAwBXV,mBAAmBxgE,EAAcinD,GAC/BzyD,KAAK2sE,kBAAkBnhE,EAASinD,GAGlC5yD,YACWmmE,EAAsBxb,EACrB0a,GADDllE,KAAQgmE,SAARA,EAAsBhmE,KAAMwqD,OAANA,EACrBxqD,KAAWklE,YAAXA,EA7BLllE,KAAOy8C,QAAgC,GACvCz8C,qBAAkB,IAAI4qD,IACtB5qD,sBAAmB,IAAI4qD,IACvB5qD,6BAA0B,IAAI4qD,IAC9B5qD,qBAAkB,IAAI4qD,IACtB5qD,mBAAgB,IAAIq0D,IAEpBr0D,KAAe2rE,gBAAG,EAClB3rE,KAAkBmqE,mBAAG,EAEpBnqE,KAAgB4sE,iBAAiD,GACjE5sE,KAAc6sE,eAAmC,GACjD7sE,KAAS8sE,UAAkB,GAC3B9sE,KAAa+sE,cAAkB,GAEhC/sE,6BAA0B,IAAI4qD,IAC9B5qD,KAAsBgtE,uBAAU,GAChChtE,KAAsBitE,uBAAU,GAGhCjtE,KAAiB2sE,kBAAG,CAACnhE,EAAcinD,KAAf,EAWvBya,oBACF,MAAMzwB,EAAuC,GAC7C,YAAKowB,eAAetjE,QAAQohE,IAC1BA,EAAGluB,QAAQlzC,QAAQud,IACbA,EAAOmjD,QACTxtB,EAAQr0C,KAAK0e,EAAM,EAEtB,GAEI21B,EAGT0wB,gBAAgB3F,EAAqBc,GACnC,MAAMqC,EAAK,IAAItC,GAA6Bb,EAAac,EAAatoE,MACtE,OAAIA,KAAKgmE,UAAYhmE,KAAKwqD,OAAOwD,gBAAgBhuD,KAAKgmE,SAAUsC,GAC9DtoE,KAAKotE,sBAAsBzC,EAAIrC,IAK/BtoE,KAAKqtE,gBAAgBxhB,IAAIyc,EAAaqC,GAOtC3qE,KAAKstE,oBAAoBhF,IAEpBtoE,KAAK4sE,iBAAiBpF,GAAemD,EAGtCyC,sBAAsBzC,EAAkCrC,GAC9D,MAAMiF,EAAgBvtE,KAAK6sE,eACrBW,EAA0BxtE,KAAKwtE,wBAErC,GADcD,EAAcjrE,OAAS,GACxB,EAAG,CACd,IAAI0mB,GAAQ,EAGRykD,EAAWztE,KAAKwqD,OAAOkD,iBAAiB4a,GAC5C,KAAOmF,GAAU,CACf,MAAMC,EAAaF,EAAwB/8C,IAAIg9C,GAC/C,GAAIC,EAAY,CAGd,MAAMxxC,EAAQqxC,EAAcxnC,QAAQ2nC,GACpCH,EAAcld,OAAOn0B,EAAQ,EAAG,EAAGyuC,GACnC3hD,GAAQ,EACR,MAEFykD,EAAWztE,KAAKwqD,OAAOkD,iBAAiB+f,EAAQ,CAE7CzkD,GAIHukD,EAAcI,QAAQhD,EAAE,MAG1B4C,EAAcnlE,KAAKuiE,GAGrB6C,SAAwB3hB,IAAIyc,EAAaqC,GAClCA,EAGT1E,SAASuB,EAAqBc,GAC5B,IAAIqC,EAAK3qE,KAAK4sE,iBAAiBpF,GAC/B,OAAKmD,IACHA,EAAK3qE,KAAKmtE,gBAAgB3F,EAAac,IAElCqC,EAGTiD,gBAAgBpG,EAAqBztD,EAAcuvD,GACjD,IAAIqB,EAAK3qE,KAAK4sE,iBAAiBpF,GAC3BmD,GAAMA,EAAG1E,SAASlsD,EAAMuvD,IAC1BtpE,KAAK2rE,kBAITjF,QAAQc,EAAqB/U,GAC3B,IAAK+U,EAAa,OAElB,MAAMmD,EAAK3qE,KAAK6tE,gBAAgBrG,GAEhCxnE,KAAKopE,WAAW,KACdppE,KAAKwtE,wBAAwB1yC,OAAO6vC,EAAGrC,oBAChCtoE,KAAK4sE,iBAAiBpF,GAC7B,MAAMtrC,EAAQl8B,KAAK6sE,eAAe9mC,QAAQ4kC,GACtCzuC,GAAS,GACXl8B,KAAK6sE,eAAexc,OAAOn0B,EAAO,EAAC,GAIvCl8B,KAAK6qE,yBAAyB,IAAMF,EAAGjE,QAAQjU,IAGzCob,gBAAgBvlE,GACtB,OAAOtI,KAAK4sE,iBAAiBtkE,GAG/BoiE,yBAAyBl/D,GAMvB,MAAMi/D,EAAa,IAAIpW,IACjB+W,EAAgBprE,KAAKmpE,gBAAgB14C,IAAIjlB,GAC/C,GAAI4/D,EACF,QAAS0C,KAAc1C,EAAcrzB,SACnC,GAAI+1B,EAAWtG,YAAa,CAC1B,MAAMmD,EAAK3qE,KAAK6tE,gBAAgBC,EAAWtG,aACvCmD,GACFF,EAAW39C,IAAI69C,EAAE,CAKzB,OAAOF,EAGTnB,QAAQ9B,EAAqBh8D,EAAcuO,EAActN,GACvD,GAAIshE,GAAcviE,GAAU,CAC1B,MAAMm/D,EAAK3qE,KAAK6tE,gBAAgBrG,GAChC,GAAImD,EACFA,SAAGrB,QAAQ99D,EAASuO,EAAMtN,IACnB,EAGX,OAAO,EAGTw/D,WAAWzE,EAAqBh8D,EAAcu4C,EAAaiqB,GACzD,IAAKD,GAAcviE,GAAU,OAI7B,MAAMyiE,EAAUziE,EAAQs8D,IACxB,GAAImG,GAAWA,EAAQxG,cAAe,CACpCwG,EAAQxG,eAAgB,EACxBwG,EAAQvG,YAAa,EACrB,MAAMxrC,EAAQl8B,KAAKitE,uBAAuBlnC,QAAQv6B,GAC9C0wB,GAAS,GACXl8B,KAAKitE,uBAAuB5c,OAAOn0B,EAAO,EAAC,CAO/C,GAAIsrC,EAAa,CACf,MAAMmD,EAAK3qE,KAAK6tE,gBAAgBrG,GAO5BmD,GACFA,EAAGsB,WAAWzgE,EAASu4C,EAAM,CAK7BiqB,GACFhuE,KAAKstE,oBAAoB9hE,GAI7B8hE,oBAAoB9hE,GAClBxL,KAAKgtE,uBAAuB5kE,KAAKoD,GAGnC0iE,sBAAsB1iE,EAAciB,GAC9BA,EACGzM,KAAKmuE,cAAc7c,IAAI9lD,KAC1BxL,KAAKmuE,cAAcrhD,IAAIthB,GACvB46B,GAAS56B,EAAS67D,KAEXrnE,KAAKmuE,cAAc7c,IAAI9lD,KAChCxL,KAAKmuE,cAAcrzC,OAAOtvB,GAC1B86B,GAAY96B,EAAS67D,KAIzBkE,WAAW/D,EAAqBh8D,EAAc4iE,EAAwB3b,GACpE,GAAIsb,GAAcviE,GAAU,CAC1B,MAAMm/D,EAAKnD,EAAcxnE,KAAK6tE,gBAAgBrG,GAAe,KAO7D,GANImD,EACFA,EAAGY,WAAW//D,EAASinD,GAEvBzyD,KAAKirE,qBAAqBzD,EAAah8D,GAAS,EAAOinD,GAGrD2b,EAAe,CACjB,MAAMC,EAASruE,KAAKwtE,wBAAwB/8C,IAAIjlB,GAC5C6iE,GAAUA,EAAO/lE,KAAOk/D,GAC1B6G,EAAO9C,WAAW//D,EAASinD,EAAO,OAItCzyD,KAAKgsE,mBAAmBxgE,EAASinD,GAIrCwY,qBACIzD,EAAqBh8D,EAAcm8D,EAAwBlV,EAC3DuY,GACFhrE,KAAKitE,uBAAuB7kE,KAAKoD,GACjCA,EAAQs8D,IAAgB,CACtBN,cACAC,cAAehV,EACfkV,eACAC,sBAAsB,EACtBoD,0BAIJnE,OACIW,EAAqBh8D,EAAcuO,EAAc2uD,EACjDxc,GACF,OAAI6hB,GAAcviE,GACTxL,KAAK6tE,gBAAgBrG,GAAaX,OAAOr7D,EAASuO,EAAM2uD,EAAOxc,GAEjE,OAGDoiB,kBACJjE,EAAyBkE,EAAqChT,EAC9DC,EAAwBgT,GAC1B,OAAOnE,EAAMpU,WAAWf,MACpBl1D,KAAKwqD,OAAQ6f,EAAM7+D,QAAS6+D,EAAM3d,UAAUjgD,MAAO49D,EAAM1d,QAAQlgD,MAAO8uD,EACxEC,EAAgB6O,EAAM3d,UAAUyJ,QAASkU,EAAM1d,QAAQwJ,QAASoY,EAAcC,GAGpFzC,uBAAuB0C,GACrB,IAAI7O,EAAW5/D,KAAKwqD,OAAOr9C,MAAMshE,EAAkBpf,IAAqB,GACxEuQ,EAASr2D,QAAQiC,GAAWxL,KAAK0uE,kCAAkCljE,IAE1B,GAArCxL,KAAK6rE,wBAAwBpV,OAEjCmJ,EAAW5/D,KAAKwqD,OAAOr9C,MAAMshE,EAAkBlf,IAAuB,GACtEqQ,EAASr2D,QAAQiC,GAAWxL,KAAK2uE,sCAAsCnjE,KAGzEkjE,kCAAkCljE,GAChC,MAAMixC,EAAUz8C,KAAKgqE,iBAAiBv5C,IAAIjlB,GACtCixC,GACFA,EAAQlzC,QAAQud,IAIVA,EAAOmjD,OACTnjD,EAAOslD,kBAAmB,EAE1BtlD,EAAO4/C,SAAO,GAMtBiI,sCAAsCnjE,GACpC,MAAMixC,EAAUz8C,KAAK6rE,wBAAwBp7C,IAAIjlB,GAC7CixC,GACFA,EAAQlzC,QAAQud,GAAUA,EAAOmgD,UAIrC2H,oBACE,OAAO,IAAIjtB,QAAcC,IACvB,GAAI5hD,KAAKy8C,QAAQn6C,OACf,OAAO8nD,GAAoBpqD,KAAKy8C,SAAS4P,OAAO,IAAMzK,KAEtDA,GAAO,GAKbspB,iBAAiB1/D,GACf,MAAMyiE,EAAUziE,EAAQs8D,IACxB,GAAImG,GAAWA,EAAQxG,cAAe,CAGpC,GADAj8D,EAAQs8D,IAAgBP,GACpB0G,EAAQzG,YAAa,CACvBxnE,KAAK+rE,uBAAuBvgE,GAC5B,MAAMm/D,EAAK3qE,KAAK6tE,gBAAgBI,EAAQzG,aACpCmD,GACFA,EAAGL,kBAAkB9+D,EAAO,CAGhCxL,KAAKgsE,mBAAmBxgE,EAASyiE,EAAQxG,cAAa,CAGpDj8D,EAAQqhB,WAAW04B,SAAS8hB,KAC9BrnE,KAAKkuE,sBAAsB1iE,GAAS,GAGtCxL,KAAKwqD,OAAOr9C,MAAM3B,EAl0BI,wBAk0BwB,GAAMjC,QAAQm7C,IAC1D1kD,KAAKkuE,sBAAsBxpB,GAAM,EAAK,GAI1CmqB,MAAM1C,GAAsB,GAC1B,IAAI1vB,EAA6B,GAMjC,GALIz8C,KAAKqtE,gBAAgB5W,OACvBz2D,KAAKqtE,gBAAgB9jE,QAAQ,CAACohE,EAAIn/D,IAAYxL,KAAKotE,sBAAsBzC,EAAIn/D,IAC7ExL,KAAKqtE,gBAAgBlS,SAGnBn7D,KAAK2rE,iBAAmB3rE,KAAKgtE,uBAAuB1qE,OACtD,QAASkmC,EAAI,EAAGA,EAAIxoC,KAAKgtE,uBAAuB1qE,OAAQkmC,IAEtDpC,GADYpmC,KAAKgtE,uBAAuBxkC,GA/0BzB,oBAo1BnB,GAAIxoC,KAAK6sE,eAAevqE,SACnBtC,KAAKmqE,oBAAsBnqE,KAAKitE,uBAAuB3qE,QAAS,CACnE,MAAMwsE,EAAyB,GAC/B,IACEryB,EAAUz8C,KAAK+uE,iBAAiBD,EAAY3C,EAK7C,CAJA,QACC,QAAS3jC,EAAI,EAAGA,EAAIsmC,EAAWxsE,OAAQkmC,IACrCsmC,EAAWtmC,IAEd,OAED,QAASA,EAAI,EAAGA,EAAIxoC,KAAKitE,uBAAuB3qE,OAAQkmC,IAEtDxoC,KAAKkrE,iBADWlrE,KAAKitE,uBAAuBzkC,IAWhD,GANAxoC,KAAKmqE,mBAAqB,EAC1BnqE,KAAKgtE,uBAAuB1qE,OAAS,EACrCtC,KAAKitE,uBAAuB3qE,OAAS,EACrCtC,KAAK8sE,UAAUvjE,QAAQk6D,GAAMA,KAC7BzjE,KAAK8sE,UAAY,GAEb9sE,KAAK+sE,cAAczqE,OAAQ,CAI7B,MAAM0sE,EAAWhvE,KAAK+sE,cACtB/sE,KAAK+sE,cAAgB,GAEjBtwB,EAAQn6C,OACV8nD,GAAoB3N,GAAS4P,OAAO,KAClC2iB,EAASzlE,QAAQk6D,GAAMA,IAAI,GAG7BuL,EAASzlE,QAAQk6D,GAAMA,IAAI,EAKjCoG,YAAY/e,GACV,MftqBE,SAAUmkB,GAAyBnkB,GACvC,OAAO,IAAIb,MAAY,MAEnB8B,EAGN,CegqBUkjB,GAGAF,iBAAiBD,EAAwB3C,GAE/C,MAAMoC,EAAe,IAAIxT,GACnBmU,EAA8C,GAC9CC,EAAoB,IAAIvkB,IACxBwkB,EAAyC,GACzCpM,EAAkB,IAAIpY,IACtBykB,EAAsB,IAAIzkB,IAC1B0kB,EAAuB,IAAI1kB,IAE3B2kB,EAAsB,IAAIlb,IAChCr0D,KAAKmuE,cAAc5kE,QAAQm7C,KACzB6qB,EAAoBziD,IAAI43B,IACxB,MAAM8qB,GAAuBxvE,KAAKwqD,OAAOr9C,MAAMu3C,GAh5B7B,sBAg5BoD,GACtE,QAASlc,GAAI,EAAGA,GAAIgnC,GAAqBltE,OAAQkmC,KAC/C+mC,EAAoBziD,IAAI0iD,GAAqBhnC,IAAE,GAInD,MAAMw9B,EAAWhmE,KAAKgmE,SAChByJ,GAAqBx4D,MAAMgtC,KAAKjkD,KAAKmpE,gBAAgBrxB,QACrD43B,GAAeC,GAAaF,GAAoBzvE,KAAKgtE,wBAKrD4C,GAAkB,IAAIhlB,IAC5B,IAAIpiB,GAAI,EACRknC,GAAanmE,QAAQ,CAACo7C,GAAOhkD,MAC3B,MAAMslC,GAAYipB,GAAkB1mB,KACpConC,GAAgB/jB,IAAIlrD,GAAMslC,IAC1B0e,GAAMp7C,QAAQm7C,IAAQte,GAASse,GAAMze,IAAU,GAGjD,MAAM4pC,GAAuB,GACvBC,GAAmB,IAAIzb,IACvB0b,GAA8B,IAAI1b,IACxC,QAAS7rB,GAAI,EAAGA,GAAIxoC,KAAKitE,uBAAuB3qE,OAAQkmC,KAAK,CAC3D,MAAMh9B,GAAUxL,KAAKitE,uBAAuBzkC,IACtCylC,GAAUziE,GAAQs8D,IACpBmG,IAAWA,GAAQxG,gBACrBoI,GAAcznE,KAAKoD,IACnBskE,GAAiBhjD,IAAIthB,IACjByiE,GAAQtG,aACV3nE,KAAKwqD,OAAOr9C,MAAM3B,GA36BN,qBA26B8B,GAAMjC,QAAQm7D,IAAOoL,GAAiBhjD,IAAI43C,KAEpFqL,GAA4BjjD,IAAIthB,IAAO,CAK7C,MAAMwkE,GAAkB,IAAIplB,IACtBqlB,GAAeN,GAAaF,GAAoBx4D,MAAMgtC,KAAK6rB,KACjEG,GAAa1mE,QAAQ,CAACo7C,GAAOhkD,MAC3B,MAAMslC,GAAYkpB,GAAkB3mB,KACpCwnC,GAAgBnkB,IAAIlrD,GAAMslC,IAC1B0e,GAAMp7C,QAAQm7C,IAAQte,GAASse,GAAMze,IAAU,GAGjD6oC,EAAW1mE,KAAK,KACdsnE,GAAanmE,QAAQ,CAACo7C,GAAOhkD,MAC3B,MAAMslC,GAAY2pC,GAAgBn/C,IAAI9vB,IACtCgkD,GAAMp7C,QAAQm7C,IAAQpe,GAAYoe,GAAMze,IAAU,GAGpDgqC,GAAa1mE,QAAQ,CAACo7C,GAAOhkD,MAC3B,MAAMslC,GAAY+pC,GAAgBv/C,IAAI9vB,IACtCgkD,GAAMp7C,QAAQm7C,IAAQpe,GAAYoe,GAAMze,IAAU,GAGpD4pC,GAActmE,QAAQiC,KACpBxL,KAAKkrE,iBAAiB1/D,GAAO,EAC9B,GAGH,MAAM0kE,GAA0C,GAC1CC,GAAyD,GAC/D,QAAS3nC,GAAIxoC,KAAK6sE,eAAevqE,OAAS,EAAGkmC,IAAK,EAAGA,KACxCxoC,KAAK6sE,eAAerkC,IAC5B0jC,uBAAuBC,GAAa5iE,QAAQ8gE,KAC7C,MAAMvjD,GAASujD,GAAMvjD,OACftb,GAAU6+D,GAAM7+D,QAGtB,GAFA0kE,GAAW9nE,KAAK0e,IAEZ9mB,KAAKgtE,uBAAuB1qE,OAAQ,CACtC,MAAM2rE,GAAUziE,GAAQs8D,IAGxB,GAAImG,IAAWA,GAAQvG,WAAY,CACjC,GAAIuG,GAAQjD,wBACRiD,GAAQjD,uBAAuB1Z,IAAI+Y,GAAM5d,aAAc,CACzD,MAAM2jB,GAAgBnC,GAAQjD,uBAAuBv6C,IAAI45C,GAAM5d,aAIzDyc,GAAqBlpE,KAAKmpE,gBAAgB14C,IAAI45C,GAAM7+D,SAC1D,GAAI09D,IAAsBA,GAAmB5X,IAAI+Y,GAAM5d,aAAc,CACnE,MAAM/rD,GAAQwoE,GAAmBz4C,IAAI45C,GAAM5d,aAC3C/rD,GAAM+L,MAAQ2jE,GACdlH,GAAmBrd,IAAIwe,GAAM5d,YAAa/rD,GAAK,EAKnD,YADAomB,GAAO4/C,SACP,EAIJ,MAAM2J,IAAkBrK,IAAahmE,KAAKwqD,OAAOwD,gBAAgBgY,EAAUx6D,IACrEgwD,GAAiBwU,GAAgBv/C,IAAIjlB,IACrC+vD,GAAiBqU,GAAgBn/C,IAAIjlB,IACrCyxD,GAAcj9D,KAAKsuE,kBACrBjE,GAAOkE,EAAchT,GAAgBC,GAAgB6U,IACzD,GAAIpT,GAAYnS,QAAUmS,GAAYnS,OAAOxoD,OAE3C,YADA6tE,GAAqB/nE,KAAK60D,IAQ5B,GAAIoT,GAIF,OAHAvpD,GAAOqlC,QAAQ,IAAM2d,GAAYt+D,GAASyxD,GAAY6F,aACtDh8C,GAAOwlC,UAAU,IAAM4E,GAAU1lD,GAASyxD,GAAY8F,gBACtDmM,EAAe9mE,KAAK0e,IAOtB,GAAIujD,GAAMH,qBAIR,OAHApjD,GAAOqlC,QAAQ,IAAM2d,GAAYt+D,GAASyxD,GAAY6F,aACtDh8C,GAAOwlC,UAAU,IAAM4E,GAAU1lD,GAASyxD,GAAY8F,gBACtDmM,EAAe9mE,KAAK0e,IAStB,MAAMm1C,GAA4C,GAClDgB,GAAYhB,UAAU1yD,QAAQg1D,KAC5BA,GAAGoB,yBAA0B,EACxB3/D,KAAKmuE,cAAc7c,IAAIiN,GAAG/yD,UAC7BywD,GAAU7zD,KAAKm2D,GAAE,GAGrBtB,GAAYhB,UAAYA,GAExBsS,EAAapvC,OAAO3zB,GAASyxD,GAAYhB,WAIzCmT,EAAmBhnE,KAFL,CAAC60D,eAAan2C,UAAQtb,aAIpCyxD,GAAY+F,gBAAgBz5D,QACxBiC,IAAWuhD,GAAqBiW,EAAiBx3D,GAAS,IAAIpD,KAAK0e,KAEvEm2C,GAAYrC,cAAcrxD,QAAQ,CAAC+mE,GAAW9kE,MAC5C,GAAI8kE,GAAU7Z,KAAM,CAClB,IAAI8Z,GAAsBlB,EAAoB5+C,IAAIjlB,IAC7C+kE,IACHlB,EAAoBxjB,IAAIrgD,GAAS+kE,GAAS,IAAIlc,KAEhDic,GAAU/mE,QAAQ,CAACyzB,GAAGsuB,KAASilB,GAAOzjD,IAAIw+B,IAAK,IAInD2R,GAAYpC,eAAetxD,QAAQ,CAAC+mE,GAAW9kE,MAC7C,IAAI+kE,GAAsBjB,EAAqB7+C,IAAIjlB,IAC9C+kE,IACHjB,EAAqBzjB,IAAIrgD,GAAS+kE,GAAS,IAAIlc,KAEjDic,GAAU/mE,QAAQ,CAACyzB,GAAGsuB,KAASilB,GAAOzjD,IAAIw+B,IAAK,EAChD,GAIL,GAAI6kB,GAAqB7tE,OAAQ,CAC/B,MAAMwoD,GAAkB,GACxBqlB,GAAqB5mE,QAAQ0zD,KAC3BnS,GAAO1iD,Kfl1BC,YAAiB2R,EAAc+wC,GAC7C,OAAO,IAAIb,MAAY,MAEnB8B,EACN,Ce80BoBykB,GAA8D,GAG5EN,GAAW3mE,QAAQud,IAAUA,GAAO4/C,WACpC1mE,KAAK6pE,YAAY/e,GAAM,CAGzB,MAAM2lB,GAAwB,IAAI7lB,IAK5B8lB,GAAsB,IAAI9lB,IAChCwkB,EAAmB7lE,QAAQ8gE,KACzB,MAAM7+D,GAAU6+D,GAAM7+D,QAClB+iE,EAAajd,IAAI9lD,MACnBklE,GAAoB7kB,IAAIrgD,GAASA,IACjCxL,KAAK2wE,sBACDtG,GAAMvjD,OAAO0gD,YAAa6C,GAAMpN,YAAawT,IAAqB,GAI1EvB,EAAe3lE,QAAQud,KACrB,MAAMtb,GAAUsb,GAAOtb,QAEnBxL,KAAK4wE,oBAAoBplE,IAAS,EAAOsb,GAAO0gD,YAAa1gD,GAAO2lC,YAAa,MACrEljD,QAAQsnE,KACtB9jB,GAAqB0jB,GAAuBjlE,GAAS,IAAIpD,KAAKyoE,IAC9DA,GAAWnK,SAAO,EACnB,GAUH,MAAMoK,GAAejB,GAAcrjE,OAAOk4C,IACjCqsB,GAAuBrsB,GAAM2qB,EAAqBC,IAIrD0B,GAAgB,IAAIpmB,IACGqmB,GACzBD,GAAehxE,KAAKwqD,OAAQulB,GAA6BT,EAAsB3jB,MAE9DpiD,QAAQm7C,KACvBqsB,GAAuBrsB,GAAM2qB,EAAqBC,IACpDwB,GAAa1oE,KAAKs8C,GAAI,GAK1B,MAAMwsB,GAAe,IAAItmB,IACzB8kB,GAAanmE,QAAQ,CAACo7C,GAAOhkD,MAC3BswE,GACIC,GAAclxE,KAAKwqD,OAAQ,IAAI6J,IAAI1P,IAAQ0qB,EAAqB3jB,KAAS,GAG/EolB,GAAavnE,QAAQm7C,KACnB,MAAMnhB,GAAOytC,GAAcvgD,IAAIi0B,IACzBysB,GAAMD,GAAazgD,IAAIi0B,IAC7BssB,GAAcnlB,IACVnH,GACA,IAAIkG,IAAI,IAAI3zC,MAAMgtC,KAAK1gB,IAAMgU,WAAa,OAAQtgC,MAAMgtC,KAAKktB,IAAK55B,WAAa,MAAK,GAG1F,MAAM65B,GAA2C,GAC3CC,GAA0C,GAC1CC,GAAuC,GAC7ClC,EAAmB7lE,QAAQ8gE,KACzB,MAAO7+D,WAASsb,UAAQm2C,gBAAeoN,GAGvC,GAAIkE,EAAajd,IAAI9lD,IAAU,CAC7B,GAAI+jE,EAAoBje,IAAI9lD,IAK1B,OAJAsb,GAAOwlC,UAAU,IAAM4E,GAAU1lD,GAASyxD,GAAY8F,WACtDj8C,GAAO+lC,UAAW,EAClB/lC,GAAOyqD,kBAAkBtU,GAAYrQ,gBACrCsiB,EAAe9mE,KAAK0e,IAUtB,IAAI0qD,GAA2BF,GAC/B,GAAIZ,GAAoBja,KAAO,EAAG,CAChC,IAAIiO,GAAMl5D,GACV,MAAMimE,GAAsB,GAC5B,KAAO/M,GAAMA,GAAItxB,YAAY,CAC3B,MAAMs+B,GAAiBhB,GAAoBjgD,IAAIi0C,IAC/C,GAAIgN,GAAgB,CAClBF,GAAsBE,GACtB,MAEFD,GAAarpE,KAAKs8D,GAAG,CAEvB+M,GAAaloE,QAAQw6C,IAAU2sB,GAAoB7kB,IAAI9H,GAAQytB,IAAoB,CAGrF,MAAMG,GAAc3xE,KAAK4xE,gBACrB9qD,GAAO0gD,YAAavK,GAAawT,GAAuBtB,EAAmB+B,GAC3EF,IAIJ,GAFAlqD,GAAO+qD,cAAcF,IAEjBH,KAAwBF,GAC1BF,GAAYhpE,KAAK0e,QACZ,CACL,MAAMgrD,GAAgB9xE,KAAKgqE,iBAAiBv5C,IAAI+gD,IAC5CM,IAAiBA,GAAcxvE,SACjCwkB,GAAOirD,aAAe3nB,GAAoB0nB,KAE5C5C,EAAe9mE,KAAK0e,GAAM,OAG5BgjD,GAAYt+D,GAASyxD,GAAY6F,YACjCh8C,GAAOwlC,UAAU,IAAM4E,GAAU1lD,GAASyxD,GAAY8F,WAItDsO,GAAWjpE,KAAK0e,IACZyoD,EAAoBje,IAAI9lD,KAC1B0jE,EAAe9mE,KAAK0e,GAAM,GAMhCuqD,GAAW9nE,QAAQud,KAGjB,MAAMkrD,GAAoB7C,EAAkB1+C,IAAI3J,GAAOtb,SACvD,GAAIwmE,IAAqBA,GAAkB1vE,OAAQ,CACjD,MAAMqvE,GAAcvnB,GAAoB4nB,IACxClrD,GAAO+qD,cAAcF,GAAW,IAOpCzC,EAAe3lE,QAAQud,KACjBA,GAAOirD,aACTjrD,GAAOmrD,iBAAiBnrD,GAAOirD,cAE/BjrD,GAAO4/C,SAAO,GAOlB,QAASl+B,GAAI,EAAGA,GAAIqnC,GAAcvtE,OAAQkmC,KAAK,CAC7C,MAAMh9B,GAAUqkE,GAAcrnC,IACxBylC,GAAUziE,GAAQs8D,IAMxB,GALAxhC,GAAY96B,GAAS2jD,IAKjB8e,IAAWA,GAAQtG,aAAc,SAErC,IAAIlrB,GAAuC,GAK3C,GAAIumB,EAAgBvM,KAAM,CACxB,IAAIyb,GAAuBlP,EAAgBvyC,IAAIjlB,IAC3C0mE,IAAwBA,GAAqB5vE,QAC/Cm6C,GAAQr0C,QAAQ8pE,IAGlB,IAAIC,GAAuBnyE,KAAKwqD,OAAOr9C,MAAM3B,GAAS+jD,IAAuB,GAC7E,QAAS6iB,GAAI,EAAGA,GAAID,GAAqB7vE,OAAQ8vE,KAAK,CACpD,IAAIC,GAAiBrP,EAAgBvyC,IAAI0hD,GAAqBC,KAC1DC,IAAkBA,GAAe/vE,QACnCm6C,GAAQr0C,QAAQiqE,GAAc,EAKpC,MAAMC,GAAgB71B,GAAQjwC,OAAO+/D,KAAMA,GAAEnxB,WACzCk3B,GAAchwE,OAChBiwE,GAA8BvyE,KAAMwL,GAAS8mE,IAE7CtyE,KAAKkrE,iBAAiB1/D,GAAO,CAKjCqkE,UAAcvtE,OAAS,EAEvB8uE,GAAY7nE,QAAQud,KAClB9mB,KAAKy8C,QAAQr0C,KAAK0e,IAClBA,GAAOulC,OAAO,KACZvlC,GAAO4/C,UAEP,MAAMxqC,GAAQl8B,KAAKy8C,QAAQ1W,QAAQjf,IACnC9mB,KAAKy8C,QAAQ4T,OAAOn0B,GAAO,EAAC,GAE9BpV,GAAO2B,MAAI,GAGN2oD,GAGT5E,oBAAoBhF,EAAqBh8D,GACvC,IAAIihE,GAAe,EACnB,MAAMwB,EAAUziE,EAAQs8D,IACxB,OAAImG,GAAWA,EAAQxG,gBAAegF,GAAe,GACjDzsE,KAAKgqE,iBAAiB1Y,IAAI9lD,KAAUihE,GAAe,GACnDzsE,KAAK6rE,wBAAwBva,IAAI9lD,KAAUihE,GAAe,GAC1DzsE,KAAKmpE,gBAAgB7X,IAAI9lD,KAAUihE,GAAe,GAC/CzsE,KAAK6tE,gBAAgBrG,GAAagF,oBAAoBhhE,IAAYihE,EAG3ErD,WAAWld,GACTlsD,KAAK8sE,UAAU1kE,KAAK8jD,GAGtB2e,yBAAyB3e,GACvBlsD,KAAK+sE,cAAc3kE,KAAK8jD,GAGlB0kB,oBACJplE,EAAiBgnE,EAA2BhL,EAAsB/a,EAClEgmB,GACF,IAAIh2B,EAAuC,GAC3C,GAAI+1B,EAAkB,CACpB,MAAME,EAAwB1yE,KAAK6rE,wBAAwBp7C,IAAIjlB,GAC3DknE,IACFj2B,EAAUi2B,OAEP,CACL,MAAMnI,EAAiBvqE,KAAKgqE,iBAAiBv5C,IAAIjlB,GACjD,GAAI++D,EAAgB,CAClB,MAAMoI,GAAsBF,GAAgBA,GAAgBtK,GAC5DoC,EAAehhE,QAAQud,IACjBA,EAAOmjD,SACN0I,GAAsB7rD,EAAO2lC,aAAeA,GACjDhQ,EAAQr0C,KAAK0e,EAAM,EACpB,EAGL,OAAI0gD,GAAe/a,KACjBhQ,EAAUA,EAAQjwC,OAAOsa,KACnB0gD,GAAeA,GAAe1gD,EAAO0gD,aACrC/a,GAAeA,GAAe3lC,EAAO2lC,eAItChQ,EAGDk0B,sBACJnJ,EAAqBvK,EACrBwT,GACF,MACMnV,EAAc2B,EAAYzxD,QAI1BonE,EACF3V,EAAY4F,yBAAsBphE,EAAY+lE,EAC5CqL,EACF5V,EAAY4F,yBAAsBphE,EARlBw7D,EAAYxQ,YAUhC,UAAWqmB,KAAuB7V,EAAYhB,UAAW,CACvD,MAAMzwD,EAAUsnE,EAAoBtnE,QAC9BgnE,EAAmBhnE,IAAY8vD,EAC/B7e,EAAUsQ,GAAqB0jB,EAAuBjlE,EAAS,IAC7CxL,KAAK4wE,oBACzBplE,EAASgnE,EAAkBI,EAAmBC,EAAmB5V,EAAYtQ,SACjEpjD,QAAQud,KACtB,MAAMisD,GAAcjsD,GAAqCksD,gBACrDD,GAAWE,eACbF,GAAWE,gBAEbnsD,GAAO4/C,UACPjqB,EAAQr0C,KAAK0e,GAAM,EACpB,CAKHgjD,GAAYxO,EAAa2B,EAAY6F,YAG/B8O,gBACJpK,EAAqBvK,EACrBwT,EACAtB,EAAgD+B,EAChDF,GACF,MAAMvkB,EAAcwQ,EAAYxQ,YAC1B6O,EAAc2B,EAAYzxD,QAI1B0nE,EAAiD,GACjDC,EAAsB,IAAI9e,IAC1B+e,EAAiB,IAAI/e,IACrBgf,GAAgBpW,EAAYhB,UAAUtwD,IAAImnE,KAC9C,MAAMtnE,GAAUsnE,GAAoBtnE,QACpC2nE,EAAoBrmD,IAAIthB,IAGxB,MAAMyiE,GAAUziE,GAAQs8D,IACxB,GAAImG,IAAWA,GAAQrG,qBACrB,OAAO,IAAIvd,KAAoByoB,GAAoBpqE,SAAUoqE,GAAoBxiC,OACnF,MAAMkiC,GAAmBhnE,KAAY8vD,EAC/BxM,GAoUZ,SAASwkB,GAAoB72B,GAC3B,MAAM82B,EAAkC,GACxCC,UAA0B/2B,EAAS82B,GAC5BA,CACT,CAvUUD,EAAqB7C,EAAsBhgD,IAAIjlB,KAAY87D,IAClC37D,IAAI4gE,IAAKA,GAAEyG,kBAC/BxmE,OAAO+/D,MAKKA,GACD/gE,SADC+gE,GACY/gE,UAAYA,IAGvCm/C,GAAYumB,EAAazgD,IAAIjlB,IAC7Bq/C,GAAammB,EAAcvgD,IAAIjlB,IAE/Bk/C,GAAYH,GACdvqD,EAAaA,KAAKklE,YAAa15D,EAASsnE,GAAoBpoB,UAAWC,GACvEE,IACE/jC,GAAS9mB,KAAKomE,aAAa0M,GAAqBpoB,GAAWoE,IAQjE,GAJIgkB,GAAoBhY,aAAeqU,GACrCiE,EAAetmD,IAAIthB,IAGjBgnE,GAAkB,CACpB,MAAMiB,GAAgB,IAAIhK,GAA0BjC,EAAa/a,EAAajhD,IAC9EioE,GAAc5B,cAAc/qD,IAC5BosD,EAAkB9qE,KAAKqrE,GAAa,CAGtC,OAAO3sD,KAGTosD,EAAkB3pE,QAAQud,KACxBimC,GAAqB/sD,KAAK6rE,wBAAyB/kD,GAAOtb,QAAS,IAAIpD,KAAK0e,IAC5EA,GAAOulC,OAAO,IA8JpB,SAASqnB,GAAyB/nE,EAAkBtE,EAAQoF,GAC1D,IAAIknE,EAAgBhoE,EAAI8kB,IAAIppB,GAC5B,GAAIssE,EAAe,CACjB,GAAIA,EAAcrxE,OAAQ,CACxB,MAAM45B,EAAQy3C,EAAc5tC,QAAQt5B,GACpCknE,EAActjB,OAAOn0B,EAAO,EAAC,CAEH,GAAxBy3C,EAAcrxE,QAChBqJ,EAAImvB,OAAOzzB,EAAG,CAGlB,OAAOssE,CACT,CA1K0BD,CAAmB1zE,KAAK6rE,wBAAyB/kD,GAAOtb,QAASsb,IAAO,GAG9FqsD,EAAoB5pE,QAAQiC,IAAW46B,GAAS56B,GAAS8jD,KACzD,MAAMxoC,GAASsjC,GAAoBipB,IACnCvsD,UAAOwlC,UAAU,KACf6mB,EAAoB5pE,QAAQiC,IAAW86B,GAAY96B,GAAS8jD,KAC5D4B,GAAUoK,EAAa2B,EAAY8F,SAAQ,GAK7CqQ,EAAe7pE,QAAQiC,KACrBuhD,GAAqBoiB,EAAmB3jE,GAAS,IAAIpD,KAAK0e,GAAM,GAG3DA,GAGDs/C,aACJnJ,EAA2CvS,EAC3CoE,GACF,OAAIpE,EAAUpoD,OAAS,EACdtC,KAAKwqD,OAAOoE,QACfqO,EAAYzxD,QAASk/C,EAAWuS,EAAYv0D,SAAUu0D,EAAY3sB,MAClE2sB,EAAYpO,OAAQC,GAKnB,IAAIzE,KAAoB4S,EAAYv0D,SAAUu0D,EAAY3sB,cAIxDm5B,GAcX5pE,YAAmB2nE,EAA4B/a,EAA4BjhD,GAAxDxL,KAAWwnE,YAAXA,EAA4BxnE,KAAWysD,YAAXA,EAA4BzsD,KAAOwL,QAAPA,EAbnExL,aAA2B,IAAIqqD,KAC/BrqD,KAAmB4zE,qBAAG,EAEtB5zE,sBAAmB,IAAI4qD,IACf5qD,KAASo7C,WAAG,EACrBp7C,KAAY+xE,aAAyB,KAErC/xE,KAAgBosE,kBAAY,EAC5BpsE,KAAQ6sD,UAAG,EAET7sD,KAAMiqE,QAAY,EACXjqE,KAAS4sD,UAAW,EAIpCilB,cAAc/qD,GACR9mB,KAAK4zE,sBAET5zE,KAAK6zE,QAAU/sD,EACf9mB,KAAK8zE,iBAAiBvqE,QAAQ,CAACwqE,EAAWrL,KACxCqL,EAAUxqE,QAAQ2iD,GAAYF,GAAellC,EAAQ4hD,OAAOjnE,EAAWyqD,GAAS,GAGlFlsD,KAAK8zE,iBAAiB3Y,QACtBn7D,KAAK4zE,qBAAsB,EAC3B5zE,KAAKuxE,kBAAkBzqD,EAAO8lC,WAC7B5sD,KAA2BiqE,QAAS,GAGvC+I,gBACE,OAAOhzE,KAAK6zE,QAGdtC,kBAAkB3kB,GACf5sD,KAAa4sD,UAAYA,EAG5BqlB,iBAAiBnrD,GACf,MAAMylD,EAAIvsE,KAAK6zE,QACXtH,EAAEyH,iBACJltD,EAAOqlC,QAAQ,IAAMogB,EAAEyH,gBAAiB,UAE1CltD,EAAOulC,OAAO,IAAMrsD,KAAKinE,UACzBngD,EAAOwlC,UAAU,IAAMtsD,KAAK0mE,WAGtBuN,YAAYl6D,EAAcmyC,GAChCa,GAAqB/sD,KAAK8zE,iBAAkB/5D,EAAM,IAAI3R,KAAK8jD,GAG7DG,OAAOoX,GACDzjE,KAAKiqE,QACPjqE,KAAKi0E,YAAY,OAAQxQ,GAE3BzjE,KAAK6zE,QAAQxnB,OAAOoX,GAGtBtX,QAAQsX,GACFzjE,KAAKiqE,QACPjqE,KAAKi0E,YAAY,QAASxQ,GAE5BzjE,KAAK6zE,QAAQ1nB,QAAQsX,GAGvBnX,UAAUmX,GACJzjE,KAAKiqE,QACPjqE,KAAKi0E,YAAY,UAAWxQ,GAE9BzjE,KAAK6zE,QAAQvnB,UAAUmX,GAGzByD,OACElnE,KAAK6zE,QAAQ3M,OAGfgN,aACE,OAAOl0E,KAAKiqE,QAAiBjqE,KAAK6zE,QAAQK,aAG5CzrD,QACGzoB,KAAKiqE,QAAUjqE,KAAK6zE,QAAQprD,OAG/B6yB,SACGt7C,KAAKiqE,QAAUjqE,KAAK6zE,QAAQv4B,QAG/B0rB,WACGhnE,KAAKiqE,QAAUjqE,KAAK6zE,QAAQ7M,UAG/BC,SACEjnE,KAAK6zE,QAAQ5M,SAGfP,UACG1mE,KAA8Bo7C,WAAY,EAC3Cp7C,KAAK6zE,QAAQnN,UAGfjnC,SACGz/B,KAAKiqE,QAAUjqE,KAAK6zE,QAAQp0C,QAG/B0nC,YAAYoF,GACLvsE,KAAKiqE,QACRjqE,KAAK6zE,QAAQ1M,YAAYoF,GAI7B4H,cACE,OAAOn0E,KAAKiqE,OAAS,EAAIjqE,KAAK6zE,QAAQM,cAIxCH,gBAAgBznB,GACd,MAAMggB,EAAIvsE,KAAK6zE,QACXtH,EAAEyH,iBACJzH,EAAEyH,gBAAgBznB,IA0BxB,SAASwhB,GAAcrpB,GACrB,OAAOA,GAA6B,IAArBA,EAAKY,QACtB,CAMA,SAAS8uB,GAAa5oE,EAAciB,GAClC,MAAM4nE,EAAW7oE,EAAQmnC,MAAMjwC,QAC/B8I,SAAQmnC,MAAMjwC,QAAU+J,GAAwB,OACzC4nE,CACT,CAEA,SAASpD,GACLqD,EAAoC9pB,EAAyBoV,EAC7D2U,EAAwCC,GAC1C,MAAMC,EAAsB,GAC5B7U,EAASr2D,QAAQiC,GAAWipE,EAAUrsE,KAAKgsE,GAAa5oE,KAExD,MAAMkpE,EAAwB,GAE9BH,EAAgBhrE,QAAQ,CAAC4U,EAAoB3S,KAC3C,MAAMmlD,EAAwB,IAAI/F,IAClCzsC,EAAM5U,QAAQ+hD,IACZ,MAAM7+C,GAAQ+9C,EAAOmE,aAAanjD,EAAS8/C,EAAMkpB,GACjD7jB,EAAO9E,IAAIP,EAAM7+C,MAIZA,IAAyB,GAAhBA,GAAMnK,UAClBkJ,EAAQs8D,IAAgBD,GACxB6M,EAAetsE,KAAKoD,GAAO,GAG/B8oE,EAAUzoB,IAAIrgD,EAASmlD,EAAM,GAK/B,IAAInoB,EAAI,EACRo3B,SAASr2D,QAAQiC,GAAW4oE,GAAa5oE,EAASipE,EAAUjsC,OAErDksC,CACT,CAYA,SAAS/E,GAAagF,EAAchwB,GAClC,MAAMiwB,EAAU,IAAIhqB,IAGpB,GAFA+pB,EAAMprE,QAAQ5I,GAAQi0E,EAAQ/oB,IAAIlrD,EAAM,KAEpB,GAAhBgkD,EAAMriD,OAAa,OAAOsyE,EAE9B,MAAMC,EAAY,EACZC,EAAU,IAAIzgB,IAAI1P,GAClBowB,EAAe,IAAInqB,IAEzB,SAASoqB,EAAQtwB,GACf,IAAKA,EAAM,OAAOmwB,EAElB,IAAIl0E,EAAOo0E,EAAatkD,IAAIi0B,GAC5B,GAAI/jD,EAAM,OAAOA,EAEjB,MAAMojD,EAASW,EAAKtR,WACpB,OACEzyC,EADEi0E,EAAQtjB,IAAIvN,GACPA,EACE+wB,EAAQxjB,IAAIvN,GACd8wB,EAEAG,EAAQjxB,GAGjBgxB,EAAalpB,IAAInH,EAAM/jD,GAChBA,EAGTgkD,SAAMp7C,QAAQm7C,IACZ,MAAM/jD,EAAOq0E,EAAQtwB,GACjB/jD,IAASk0E,GACXD,EAAQnkD,IAAI9vB,GAAOyH,KAAKs8C,EAAI,GAIzBkwB,CACT,CAEA,SAASxuC,GAAS56B,EAAcy6B,GAC9Bz6B,EAAQqhB,WAAWC,IAAImZ,EACzB,CAEA,SAASK,GAAY96B,EAAcy6B,GACjCz6B,EAAQqhB,WAAWG,OAAOiZ,EAC5B,CAEA,SAASssC,GACL/G,EAAmChgE,EAAcixC,GACnD2N,GAAoB3N,GAAS4P,OAAO,IAAMmf,EAAON,iBAAiB1/D,GACpE,CAQA,SAASgoE,GAA0B/2B,EAA4B82B,GAC7D,QAAS/qC,EAAI,EAAGA,EAAIiU,EAAQn6C,OAAQkmC,IAAK,CACvC,MAAM1hB,EAAS21B,EAAQjU,GACnB1hB,aAAkBmuD,KACpBzB,GAA0B1sD,EAAO21B,QAAS82B,GAE1CA,EAAanrE,KAAK0e,EAAM,CAG9B,CAaA,SAASiqD,GACLvlE,EAAc6jE,EACdC,GACF,MAAM4F,EAAY5F,EAAqB7+C,IAAIjlB,GAC3C,IAAK0pE,EAAW,OAAO,EAEvB,IAAIC,EAAW9F,EAAoB5+C,IAAIjlB,GACvC,OAAI2pE,EACFD,EAAU3rE,QAAQ/I,GAAQ20E,EAAUroD,IAAItsB,IAExC6uE,EAAoBxjB,IAAIrgD,EAAS0pE,GAGnC5F,EAAqBx0C,OAAOtvB,IACrB,CACT,OC1uDa4pE,GASXv1E,YACYmmE,EAAuB7Q,EACvB+P,GADAllE,KAAQgmE,SAARA,EAAuBhmE,KAAOm1D,QAAPA,EACvBn1D,KAAWklE,YAAXA,EAPJllE,KAAaq1E,cAAsC,GAGpDr1E,KAAiB2sE,kBAAG,CAACnhE,EAAcinD,KAAf,EAKzBzyD,KAAKs1E,kBAAoB,IAAI5I,GAA0B1G,EAAU7Q,EAAS+P,GAC1EllE,KAAKu1E,gBAAkB,IAAIxP,GAAwBC,EAAU7Q,EAAS+P,GAEtEllE,KAAKs1E,kBAAkB3I,kBAAoB,CAACnhE,EAAcinD,IACtDzyD,KAAK2sE,kBAAkBnhE,EAASinD,GAGtCmb,gBACI4H,EAAqBhO,EAAqBc,EAAkBvuD,EAC5Dg7C,GACF,MAAM0gB,EAAWD,EAAc,IAAMz7D,EACrC,IAAIuvD,EAAUtpE,KAAKq1E,cAAcI,GACjC,IAAKnM,EAAS,CACZ,MAAMxe,EAAkB,GAClBkK,EAAqB,GACrB0C,EAAM5C,GACI90D,KAAKm1D,QAASJ,EAA+BjK,EAAQkK,GACrE,GAAIlK,EAAOxoD,OACT,MhBmHQ,YAAmByX,EAAc+wC,GAC/C,OAAO,IAAIb,MAAY,MAEnB8B,EAGN,CgBzHc2pB,GAKRpM,WHzCUqM,GACZ57D,EAAc29C,EAAiBjN,GACjC,OAAO,IAAIwa,GAAiBlrD,EAAM29C,EAAKjN,EACzC,CGsCgBkrB,CAAa57D,EAAM29C,EAAK13D,KAAKklE,aACvCllE,KAAKq1E,cAAcI,GAAYnM,EAEjCtpE,KAAKs1E,kBAAkB1H,gBAAgBpG,EAAaztD,EAAMuvD,GAG5DrD,SAASuB,EAAqBc,GAC5BtoE,KAAKs1E,kBAAkBrP,SAASuB,EAAac,GAG/C5B,QAAQc,EAAqB/U,GAC3BzyD,KAAKs1E,kBAAkB5O,QAAQc,EAAa/U,GAG9CmjB,SAASpO,EAAqBh8D,EAAcu4C,EAAaiqB,GACvDhuE,KAAKs1E,kBAAkBrJ,WAAWzE,EAAah8D,EAASu4C,EAAQiqB,GAGlE6H,SAASrO,EAAqBh8D,EAAcinD,EAAc2b,GACxDpuE,KAAKs1E,kBAAkB/J,WAAW/D,EAAah8D,EAAS4iE,IAAiB,EAAO3b,GAGlFqjB,kBAAkBtqE,EAAcuqE,GAC9B/1E,KAAKs1E,kBAAkBpH,sBAAsB1iE,EAASuqE,GAGxD3tC,QAAQo/B,EAAqBh8D,EAAcs9C,EAAkBr8C,GAC3D,GAA0B,KAAtBq8C,EAASwF,OAAO,GAAW,CAC7B,MAAOhmD,EAAIib,GAAUypC,GAAqBlE,GAE1C9oD,KAAKu1E,gBAAgBtoB,QAAQ3kD,EAAIkD,EAAS+X,EAD7B9W,EACyC,MAEtDzM,KAAKs1E,kBAAkBhM,QAAQ9B,EAAah8D,EAASs9C,EAAUr8C,GAInEo6D,OACIW,EAAqBh8D,EAAcygD,EAAmB+pB,EACtD9pB,GAEF,GAA2B,KAAvBD,EAAUqC,OAAO,GAAW,CAC9B,MAAOhmD,EAAIib,GAAUypC,GAAqBf,GAC1C,OAAOjsD,KAAKu1E,gBAAgB1O,OAAOv+D,EAAIkD,EAAS+X,EAAQ2oC,EAAQ,CAElE,OAAOlsD,KAAKs1E,kBAAkBzO,OAAOW,EAAah8D,EAASygD,EAAW+pB,EAAY9pB,GAGpF2iB,MAAM1C,GAAsB,GAC1BnsE,KAAKs1E,kBAAkBzG,MAAM1C,GAG3B1vB,cACF,OAAQz8C,KAAKs1E,kBAAkB74B,QAC1B4K,OAAOrnD,KAAKu1E,gBAAgB94B,SAGnCmyB,oBACE,OAAO5uE,KAAKs1E,kBAAkB1G,qBC1ElC,IAQaqH,GAAkB,YAAlBA,EAMXp2E,YACY4uD,EAAuBynB,EACvBC,GADAn2E,KAAQyuD,SAARA,EAAuBzuD,KAAYk2E,aAAZA,EACvBl2E,KAAUm2E,WAAVA,EALJn2E,YAAyC,EAM/C,IAAIo2E,EAAgBH,EAAmBI,uBAAuB5lD,IAAIg+B,GAC7D2nB,GACHH,EAAmBI,uBAAuBxqB,IAAI4C,EAAU2nB,EAAgB,IAAIxrB,KAE9E5qD,KAAKs2E,eAAiBF,EAGxB51D,QACMxgB,KAAKu2E,OAAM,IACTv2E,KAAKk2E,cACPhlB,GAAUlxD,KAAKyuD,SAAUzuD,KAAKk2E,aAAcl2E,KAAKs2E,gBAEnDt2E,KAAKu2E,OAAM,GAIftP,SACEjnE,KAAKwgB,QACDxgB,KAAKu2E,OAAM,IACbrlB,GAAUlxD,KAAKyuD,SAAUzuD,KAAKs2E,gBAC1Bt2E,KAAKm2E,aACPjlB,GAAUlxD,KAAKyuD,SAAUzuD,KAAKm2E,YAC9Bn2E,KAAKm2E,WAAa,MAEpBn2E,KAAKu2E,OAAM,GAIf7P,UACE1mE,KAAKinE,SACDjnE,KAAKu2E,OAAM,IACbN,EAAmBI,uBAAuBv7C,OAAO96B,KAAKyuD,UAClDzuD,KAAKk2E,eACPpM,GAAY9pE,KAAKyuD,SAAUzuD,KAAKk2E,cAChCl2E,KAAKm2E,WAAa,MAEhBn2E,KAAKm2E,aACPrM,GAAY9pE,KAAKyuD,SAAUzuD,KAAKm2E,YAChCn2E,KAAKm2E,WAAa,MAEpBjlB,GAAUlxD,KAAKyuD,SAAUzuD,KAAKs2E,gBAC9Bt2E,KAAKu2E,OAAM,IAjDRN,gCAA0C,IAAIO,QAD1CP,CAAkB,KAwE/B,SAASQ,GAA0B9lB,GACjC,IAAIzoD,EAA6B,KACjCyoD,SAAOpnD,QAAQ,CAACiuC,EAAK8T,MASvB,SAASorB,GAAqBprB,GAC5B,MAAgB,YAATA,GAA+B,aAATA,CAC/B,EAVQorB,CAAqBprB,KACvBpjD,EAASA,GAAU,IAAI0iD,IACvB1iD,EAAO2jD,IAAIP,EAAM9T,GAAG,GAGjBtvC,CACT,OClHayuE,GAyBX92E,YACW2L,EAAqBk/C,EACrByL,EACCygB,GAFD52E,KAAOwL,QAAPA,EAAqBxL,KAAS0qD,UAATA,EACrB1qD,KAAOm2D,QAAPA,EACCn2D,KAAc42E,eAAdA,EA3BJ52E,KAAU62E,WAAe,GACzB72E,KAAW82E,YAAe,GAC1B92E,KAAa+2E,cAAe,GAG5B/2E,KAAYg3E,cAAG,EACfh3E,KAASi3E,WAAG,EACZj3E,KAAQk3E,UAAG,EACXl3E,KAAUm3E,YAAG,EAMbn3E,KAAkBo3E,mBAAe,GACjCp3E,KAAmBq3E,oBAAe,GAInCr3E,KAAImoB,KAAG,EAEPnoB,KAAY+xE,aAAyB,KACrC/xE,qBAAiC,IAAI4qD,IAM1C5qD,KAAKs3E,UAAoBnhB,EAAQztD,SACjC1I,KAAKu3E,OAAiBphB,EAAQ7lB,OAAY,EAC1CtwC,KAAKmoB,KAAOnoB,KAAKs3E,UAAYt3E,KAAKu3E,OAG5BC,YACDx3E,KAAKi3E,YACRj3E,KAAKi3E,WAAY,EACjBj3E,KAAK62E,WAAWttE,QAAQk6D,GAAMA,KAC9BzjE,KAAK62E,WAAa,IAItB3P,OACElnE,KAAKomE,eACLpmE,KAAKy3E,4BAGCrR,eACN,GAAIpmE,KAAKg3E,aAAc,OACvBh3E,KAAKg3E,cAAe,EAEpB,MAAMtsB,EAAY1qD,KAAK0qD,UAEvB1qD,KAAK03E,UAAY13E,KAAK23E,qBAAqB33E,KAAKwL,QAASk/C,EAAW1qD,KAAKm2D,SACzEn2D,KAAK43E,eAAiBltB,EAAUpoD,OAASooD,EAAUA,EAAUpoD,OAAS,GAAK,IAAIsoD,IAC/E5qD,KAAK03E,UAAUnuC,iBAAiB,SAAU,IAAMvpC,KAAKw3E,aAG/CC,4BAEFz3E,KAAKu3E,OACPv3E,KAAK63E,uBAEL73E,KAAK03E,UAAUp8B,QAIXw8B,0BAA0BptB,GAChC,MAAMqtB,EAAa,GACnBrtB,SAAUnhD,QAAQy6C,IAChB+zB,EAAI3vE,KAAKwgC,OAAOovC,YAAYh0B,GAAM,GAE7B+zB,EAITJ,qBAAqBnsE,EAAck/C,EAAiCyL,GAGlE,OAAO3qD,EAAQojD,QAAW5uD,KAAK83E,0BAA0BptB,GAAYyL,GAGvEhK,QAAQsX,GACNzjE,KAAKq3E,oBAAoBjvE,KAAKq7D,GAC9BzjE,KAAK82E,YAAY1uE,KAAKq7D,GAGxBpX,OAAOoX,GACLzjE,KAAKo3E,mBAAmBhvE,KAAKq7D,GAC7BzjE,KAAK62E,WAAWzuE,KAAKq7D,GAGvBnX,UAAUmX,GACRzjE,KAAK+2E,cAAc3uE,KAAKq7D,GAG1Bh7C,OACEzoB,KAAKomE,eACApmE,KAAKk0E,eACRl0E,KAAK82E,YAAYvtE,QAAQk6D,GAAMA,KAC/BzjE,KAAK82E,YAAc,GACnB92E,KAAKk3E,UAAW,EACZl3E,KAAK42E,gBACP52E,KAAK42E,eAAep2D,SAGxBxgB,KAAK03E,UAAUjvD,OAGjB6yB,QACEt7C,KAAKknE,OACLlnE,KAAK03E,UAAUp8B,QAGjB2rB,SACEjnE,KAAKknE,OACDlnE,KAAK42E,gBACP52E,KAAK42E,eAAe3P,SAEtBjnE,KAAKw3E,YACLx3E,KAAK03E,UAAUzQ,SAGjBxnC,QACEz/B,KAAK63E,uBACL73E,KAAKm3E,YAAa,EAClBn3E,KAAKi3E,WAAY,EACjBj3E,KAAKk3E,UAAW,EAChBl3E,KAAK82E,YAAc92E,KAAKq3E,oBACxBr3E,KAAK62E,WAAa72E,KAAKo3E,mBAGjBS,uBACF73E,KAAK03E,WACP13E,KAAK03E,UAAUO,SAInBjR,UACEhnE,KAAKy/B,QACLz/B,KAAKyoB,OAGPyrD,aACE,OAAOl0E,KAAKk3E,SAGdxQ,UACO1mE,KAAKm3E,aACRn3E,KAAKm3E,YAAa,EAClBn3E,KAAK63E,uBACL73E,KAAKw3E,YACDx3E,KAAK42E,gBACP52E,KAAK42E,eAAelQ,UAEtB1mE,KAAK+2E,cAAcxtE,QAAQk6D,GAAMA,KACjCzjE,KAAK+2E,cAAgB,IAIzB5P,YAAYoF,QACa9qE,IAAnBzB,KAAK03E,WACP13E,KAAKknE,OAEPlnE,KAAK03E,UAAUlwD,YAAc+kD,EAAIvsE,KAAKmoB,KAGxCgsD,cACE,OAAOn0E,KAAK03E,UAAUlwD,YAAcxnB,KAAKmoB,KAGvCykC,gBACF,OAAO5sD,KAAKu3E,OAASv3E,KAAKs3E,UAG5BrE,gBACE,MAAMtiB,EAAwB,IAAI/F,IAC9B5qD,KAAKk0E,cAIel0E,KAAK43E,eACbruE,QAAQ,CAACiuC,EAAK8T,KACb,WAATA,GACFqF,EAAO9E,IAAIP,EAAMtrD,KAAKi3E,UAAYz/B,EAAMmX,GAAa3uD,KAAKwL,QAAS8/C,GAAK,GAK9EtrD,KAAKk4E,gBAAkBvnB,EAIzBqjB,gBAAgBznB,GACd,MAAM4rB,EAAwB,UAAd5rB,EAAwBvsD,KAAK82E,YAAc92E,KAAK62E,WAChEsB,EAAQ5uE,QAAQk6D,GAAMA,KACtB0U,EAAQ71E,OAAS,SClMR81E,GACXjqB,sBAAsB7C,GAKpB,OAAO,EAGT+sB,gCAAgC/sB,GAM9B,OAAO,EAGTkD,eAAeC,EAAeC,GAE5B,OAAO,EAGTV,gBAAgBZ,EAAWC,GACzB,OAAOW,GAAgBZ,EAAMC,GAG/BK,iBAAiBliD,GACf,OAAOkiD,GAAiBliD,GAG1B2B,MAAM3B,EAAc+hD,EAAkBC,GACpC,OAAOS,GAAYziD,EAAS+hD,EAAUC,GAGxCmB,aAAanjD,EAAc8/C,EAAc9S,GACvC,OAAQjvB,OAAO9mB,iBAAiB+I,GAAiB8/C,GAGnDsD,QACIpjD,EAAck/C,EAA8ChiD,EAAkB4nC,EAC9Eue,EAAgBC,EAAqC,IACvD,MACMwpB,EAAgD,CAAC5vE,WAAU4nC,QAAOioC,KADlD,GAATjoC,EAAa,OAAS,YAI/Bue,IACFypB,EAAczpB,OAAYA,GAG5B,MAAM2pB,EAAgC,IAAI5tB,IACpC6tB,EAAqD3pB,EAAgBtiD,OACvEsa,IAAUA,cAAkB6vD,KhBqNpB,YAA+BjuE,EAAkB4nC,GAC/D,OAAoB,IAAb5nC,GAA4B,IAAV4nC,CAC3B,EgBtNQooC,CAA+BhwE,EAAU4nC,IAC3CmoC,EAA4BlvE,QAAQud,KAClCA,GAAOoxD,gBAAgB3uE,QAAQ,CAACiuC,GAAK8T,KAASktB,EAAe3sB,IAAIP,GAAM9T,IAAI,GAI/E,IAAI2oB,EhBuCF,SAAU5V,GAAmBG,GAEjC,OAAKA,EAAUpoD,OAGXooD,EAAU,aAAcE,IACnBF,EAEFA,EAAU/+C,IAAIu/C,GAAMsF,GAAatF,IAL/B,EAMX,CgBhDqBX,CAAmBG,GAAW/+C,IAAIglD,IAAUD,GAAWC,KACxEwP,WhBiNYwY,GACZntE,EAAck/C,EAAiC8tB,GACjD,GAAIA,EAAe/hB,MAAQ/L,EAAUpoD,OAAQ,CAC3C,IAAIs2E,EAAmBluB,EAAU,GAC7BmuB,EAA8B,GAQlC,GAPAL,EAAejvE,QAAQ,CAACiuC,EAAK8T,KACtBstB,EAAiBtnB,IAAIhG,IACxButB,EAAkBzwE,KAAKkjD,GAEzBstB,EAAiB/sB,IAAIP,EAAM9T,EAAG,GAG5BqhC,EAAkBv2E,OACpB,QAASkmC,EAAI,EAAGA,EAAIkiB,EAAUpoD,OAAQkmC,IAAK,CACzC,IAAI0iB,EAAKR,EAAUliB,GACnBqwC,EAAkBtvE,QAAQ+hD,GAAQJ,EAAGW,IAAIP,EAAMqD,GAAanjD,EAAS8/C,IAAM,EAIjF,OAAOZ,CACT,CgBrOiBiuB,CAAmCntE,EAAS20D,EAAYqY,GACrE,MAAMM,GFvDM,YACZttE,EAAcmlD,GAChB,IAAIooB,EAAkC,KAClCC,EAAgC,KACpC,OAAI/hE,MAAMw6C,QAAQd,IAAWA,EAAOruD,QAClCy2E,EAActC,GAA0B9lB,EAAO,IAC3CA,EAAOruD,OAAS,IAClB02E,EAAYvC,GAA0B9lB,EAAOA,EAAOruD,OAAS,MAEtDquD,aAAkB/F,MAC3BmuB,EAActC,GAA0B9lB,IAGlCooB,GAAeC,EAAa,IAAI/C,GAAmBzqE,EAASutE,EAAaC,GAC7C,IACtC,CEwC0BC,CAA2BztE,EAAS20D,GAC1D,OAAO,IAAIwW,GAAoBnrE,EAAS20D,EAAYmY,EAAeQ,wBChE1DI,GAAwB,MAA/B,MAAOA,UAAgCC,KAI3Ct5E,YAAYu5E,EAAkDC,GAC5DnkC,QAJMl1C,KAAgBs5E,iBAAG,EAQzBt5E,KAAKu5E,UAAYH,EAAaI,eAAeH,EAAIrgD,KAF7C,CAAC1wB,GAAI,IAAKmxE,cAAeC,WAAwB/oB,OAAQ,GAAInwD,KAAM,CAACo2D,UAAW,MAK5E1B,MAAM0B,GACb,MAAMtuD,EAAKtI,KAAKs5E,iBAAiBh/D,WACjCta,KAAKs5E,mBACL,MAAMjP,EAAQpzD,MAAMw6C,QAAQmF,IAAS,EAAIlF,MAASkF,GAAaA,EAC/D+iB,UAAsB35E,KAAKu5E,UAAW,KAAMjxE,EAAI,WAAY,CAAC+hE,IACtD,IAAIuP,GAAwBtxE,EAAItI,KAAKu5E,YAjBnCL,sDAAuBv5E,OAAvBA,MAAuBi0C,sBAAvBj0C,sCAAwB,KAqB/B,MAAOi6E,WAAgCC,KAC3Ch6E,YAAoBi6E,EAAqBP,GACvCrkC,QADkBl1C,KAAG85E,IAAHA,EAAqB95E,KAASu5E,UAATA,EAIhC5+C,OAAOnvB,EAAc2qD,GAC5B,OAAO,IAAI4jB,GAAwB/5E,KAAK85E,IAAKtuE,EAAS2qD,GAAW,GAAIn2D,KAAKu5E,kBAIjEQ,GAIXl6E,YACWyI,EAAmBkD,EAAc2qD,EAChCojB,GADDv5E,KAAEsI,GAAFA,EAAmBtI,KAAOwL,QAAPA,EAClBxL,KAASu5E,UAATA,EALLv5E,KAAY+xE,aAAyB,KACpC/xE,KAAQk3E,UAAG,EAsEZl3E,KAAS4sD,UAAG,EAjEjB5sD,KAAKg6E,SAAS,SAAU7jB,GAGlB8jB,QAAQhuB,EAAmBC,GACjC,OAAOlsD,KAAKu5E,UAAU1S,OAAO7mE,KAAKwL,QAAS,KAAKxL,KAAKsI,MAAM2jD,IAAaC,GAGlE8tB,SAAS/sB,KAAoB8Z,GACnC,OAAO4S,GAAsB35E,KAAKu5E,UAAWv5E,KAAKwL,QAASxL,KAAKsI,GAAI2kD,EAAS8Z,GAG/E1a,OAAOoX,GACLzjE,KAAKi6E,QAAQ,OAAQxW,GAGvBtX,QAAQsX,GACNzjE,KAAKi6E,QAAQ,QAASxW,GAGxBnX,UAAUmX,GACRzjE,KAAKi6E,QAAQ,UAAWxW,GAG1ByD,OACElnE,KAAKg6E,SAAS,QAGhB9F,aACE,OAAOl0E,KAAKk3E,SAGdzuD,OACEzoB,KAAKg6E,SAAS,QACdh6E,KAAKk3E,UAAW,EAGlB57B,QACEt7C,KAAKg6E,SAAS,SAGhBhT,UACEhnE,KAAKg6E,SAAS,WAGhB/S,SACEjnE,KAAKg6E,SAAS,UAGhBtT,UACE1mE,KAAKg6E,SAAS,WAGhBv6C,QACEz/B,KAAKg6E,SAAS,SACdh6E,KAAKk3E,UAAW,EAGlB/P,YAAYoF,GACVvsE,KAAKg6E,SAAS,cAAezN,GAG/B4H,cACE,OAAOn0E,KAAKu5E,UAAU/N,OAAO/uB,SAASz8C,KAAKsI,KAAK6rE,eAAiB,GAMrE,SAASwF,GACLO,EAA6B1uE,EAAclD,EAAY2kD,EAAiB8Z,GAC1E,OAAOmT,EAAStnC,YAAYpnC,EAAS,KAAKlD,KAAM2kD,IAAW8Z,EAC7D,CChHA,MACMoT,GAA0B,aAAa,IAShCC,GAAwB,YAAxBA,EAQXv6E,YACYw6E,EAAoC7O,EAAiC8O,GAArEt6E,KAAQq6E,SAARA,EAAoCr6E,KAAMwrE,OAANA,EAAiCxrE,KAAKs6E,MAALA,EARzEt6E,KAAUu6E,WAAW,EACrBv6E,KAAYw6E,aAAW,EACvBx6E,KAAyBy6E,0BAA6B,GACtDz6E,oBAAiB,IAAI4qD,IACrB5qD,KAAa06E,cAAG,EAChB16E,aAAwB2hD,QAAQC,QAAQ,GAI9C4pB,EAAOmB,kBAAoB,CAACnhE,EAAc6uE,KAKxC,MAAMjnC,EAAainC,GAAUjnC,WAAW5nC,GACpC4nC,GACFinC,EAAShnC,YAAYD,EAAY5nC,EAAO,EAK9CguE,eAAelR,EAAkBh8D,GAC/B,MAIM+tE,EAAWr6E,KAAKq6E,SAASb,eAAelR,EAAah8D,GAC3D,KAAKg8D,GAAgBh8D,GAASA,EAAK9L,MAAS8L,EAAK9L,KAAKo2D,WAAc,CAClE,IAAIsjB,EAA4Cl6E,KAAK26E,eAAelqD,IAAI4pD,GAUxE,OATKH,IAIHA,EACI,IAAIU,GAZe,GAY2BP,EAAUr6E,KAAKwrE,OAFvC,IAAMxrE,KAAK26E,eAAe7/C,OAAOu/C,IAI3Dr6E,KAAK26E,eAAe9uB,IAAIwuB,EAAUH,IAE7BA,EAGT,MAAM1E,EAAclpE,EAAKhE,GACnBk/D,EAAcl7D,EAAKhE,GAAK,IAAMtI,KAAKu6E,WACzCv6E,KAAKu6E,aAELv6E,KAAKwrE,OAAOvF,SAASuB,EAAac,GAElC,MAAMsF,EAAmBtE,IACnBryD,MAAMw6C,QAAQ6X,GAChBA,EAAQ//D,QAAQqkE,GAEhB5tE,KAAKwrE,OAAOoC,gBAAgB4H,EAAahO,EAAac,EAAagB,EAAQvvD,KAAMuvD,EAAO,EAI5FuR,OAD0BvuE,EAAK9L,KAAKo2D,UAClBrtD,QAAQqkE,GAEnB,IAAIkN,GAAkB96E,KAAMwnE,EAAa6S,EAAUr6E,KAAKwrE,QAGjEuP,QACE/6E,KAAK06E,gBACD16E,KAAKq6E,SAASU,OAChB/6E,KAAKq6E,SAASU,QAIVC,qBAENh7E,KAAK0hD,QAAQ7/C,KAAK,KAChB7B,KAAKw6E,iBAKTS,yBAAyBjuE,EAAey2D,EAAqBjjE,GACvDwM,GAAS,GAAKA,EAAQhN,KAAKw6E,aAC7Bx6E,KAAKs6E,MAAMY,IAAI,IAAMzX,EAAGjjE,KAImB,GAAzCR,KAAKy6E,0BAA0Bn4E,QACjCq/C,QAAQC,QAAQ,MAAM//C,KAAK,KACzB7B,KAAKs6E,MAAMY,IAAI,KACbl7E,KAAKy6E,0BAA0BlxE,QAAQmvD,IACrC,MAAO+K,EAAIjjE,GAAQk4D,EACnB+K,EAAGjjE,EAAI,GAETR,KAAKy6E,0BAA4B,IAClC,GAILz6E,KAAKy6E,0BAA0BryE,KAAK,CAACq7D,EAAIjjE,KAG3C26E,MACEn7E,KAAK06E,gBAIqB,GAAtB16E,KAAK06E,eACP16E,KAAKs6E,MAAMc,kBAAkB,KAC3Bp7E,KAAKg7E,qBACLh7E,KAAKwrE,OAAOqD,MAAM7uE,KAAKw6E,aAAY,GAGnCx6E,KAAKq6E,SAASc,KAChBn7E,KAAKq6E,SAASc,MAIlBvM,oBACE,OAAO5uE,KAAKwrE,OAAOoD,qEDzHVjvE,MCOwBA,ODPxBA,MCOwB07E,IDPxB17E,MCOwBA,sBDPxBA,eCOA2H,uBAAwB,WAsHxBszE,GACX/6E,YACc2nE,EAA4B6S,EAA4B7O,EAC1D8P,GADEt7E,KAAWwnE,YAAXA,EAA4BxnE,KAAQq6E,SAARA,EAA4Br6E,KAAMwrE,OAANA,EAC1DxrE,KAAUs7E,WAAVA,EACVt7E,KAAKu7E,YAAcv7E,KAAKq6E,SAASkB,YAAevlB,GAAMqkB,EAASkB,YAAavlB,GAAK,KAG/Ex1D,WACF,OAAOR,KAAKq6E,SAAS75E,KAKvBkmE,UACE1mE,KAAKwrE,OAAO9E,QAAQ1mE,KAAKwnE,YAAaxnE,KAAKq6E,UAC3Cr6E,KAAKq6E,SAAS3T,UACd1mE,KAAKs7E,eAGPtpC,cAAcj4B,EAAcyhE,GAC1B,OAAOx7E,KAAKq6E,SAASroC,cAAcj4B,EAAMyhE,GAG3CC,cAAchvE,GACZ,OAAOzM,KAAKq6E,SAASoB,cAAchvE,GAGrCivE,WAAWjvE,GACT,OAAOzM,KAAKq6E,SAASqB,WAAWjvE,GAGlCgmC,YAAYsR,EAAa43B,GACvB37E,KAAKq6E,SAAS5nC,YAAYsR,EAAQ43B,GAClC37E,KAAKwrE,OAAOoK,SAAS51E,KAAKwnE,YAAamU,EAAU53B,GAAQ,GAG3DiqB,aAAajqB,EAAa43B,EAAeC,EAAeC,GAAkB,GACxE77E,KAAKq6E,SAASrM,aAAajqB,EAAQ43B,EAAUC,GAE7C57E,KAAKwrE,OAAOoK,SAAS51E,KAAKwnE,YAAamU,EAAU53B,EAAQ83B,GAG3DxoC,YAAY0Q,EAAa+3B,EAAe1N,GACtCpuE,KAAKwrE,OAAOqK,SAAS71E,KAAKwnE,YAAasU,EAAU97E,KAAKq6E,SAAUjM,GAGlE2N,kBAAkBC,EAAqBC,GACrC,OAAOj8E,KAAKq6E,SAAS0B,kBAAkBC,EAAgBC,GAGzD7oC,WAAWsR,GACT,OAAO1kD,KAAKq6E,SAASjnC,WAAWsR,GAGlC0C,YAAY1C,GACV,OAAO1kD,KAAKq6E,SAASjzB,YAAY1C,GAGnCzV,aAAaitC,EAASniE,EAActN,EAAe+uE,GACjDx7E,KAAKq6E,SAASprC,aAAaitC,EAAIniE,EAAMtN,EAAO+uE,GAG9CW,gBAAgBD,EAASniE,EAAcyhE,GACrCx7E,KAAKq6E,SAAS8B,gBAAgBD,EAAIniE,EAAMyhE,GAG1Cp1C,SAAS81C,EAASniE,GAChB/Z,KAAKq6E,SAASj0C,SAAS81C,EAAIniE,GAG7BusB,YAAY41C,EAASniE,GACnB/Z,KAAKq6E,SAAS/zC,YAAY41C,EAAIniE,GAGhCqiE,SAASF,EAASvpC,EAAelmC,EAAY4vE,GAC3Cr8E,KAAKq6E,SAAS+B,SAASF,EAAIvpC,EAAOlmC,EAAO4vE,GAG3CC,YAAYJ,EAASvpC,EAAe0pC,GAClCr8E,KAAKq6E,SAASiC,YAAYJ,EAAIvpC,EAAO0pC,GAGvCzpC,YAAYspC,EAASniE,EAActN,GAlNZ,KAmNjBsN,EAAKu0C,OAAO,IAA0Bv0C,GAAQogE,GAChDn6E,KAAK81E,kBAAkBoG,IAAMzvE,GAE7BzM,KAAKq6E,SAASznC,YAAYspC,EAAIniE,EAAMtN,GAIxC8vE,SAAS73B,EAAWj4C,GAClBzM,KAAKq6E,SAASkC,SAAS73B,EAAMj4C,GAG/Bo6D,OAAOz7C,EAAa6gC,EAAmBC,GACrC,OAAOlsD,KAAKq6E,SAASxT,OAAOz7C,EAAQ6gC,EAAWC,GAGvC4pB,kBAAkBtqE,EAAciB,GACxCzM,KAAKwrE,OAAOsK,kBAAkBtqE,EAASiB,IAIrC,MAAOquE,WAA0BF,GACrC/6E,YACWyH,EAAmCkgE,EAAqB6S,EAC/D7O,EAAyBlf,GAC3BpX,MAAMsyB,EAAa6S,EAAU7O,EAAQlf,GAF5BtsD,KAAOsH,QAAPA,EAGTtH,KAAKwnE,YAAcA,EAGZ50B,YAAYspC,EAASniE,EAActN,GA/OrB,KAgPjBsN,EAAKu0C,OAAO,GACQ,KAAlBv0C,EAAKu0C,OAAO,IAAav0C,GAAQogE,GAEnCn6E,KAAK81E,kBAAkBoG,EADvBzvE,OAAkBhL,IAAVgL,KAA+BA,GAGvCzM,KAAKwrE,OAAOpjC,QAAQpoC,KAAKwnE,YAAa0U,EAAIniE,EAAK5C,MAAM,GAAI1K,GAG3DzM,KAAKq6E,SAASznC,YAAYspC,EAAIniE,EAAMtN,GAI/Bo6D,OACLz7C,EAAwC6gC,EACxCC,GACF,GA/PqB,KA+PjBD,EAAUqC,OAAO,GAAwB,CAC3C,MAAM9iD,EAiBZ,SAASgxE,GAAyBpxD,GAChC,OAAQA,GACN,IAAK,OACH,OAAOhpB,SAAS42B,KAClB,IAAK,WACH,OAAO52B,SACT,IAAK,SACH,OAAOmnB,OACT,QACE,OAAO6B,EAEb,CA5BsBoxD,CAAyBpxD,GACzC,IAAIrR,EAAOkyC,EAAU90C,MAAM,GACvBuxD,EAAQ,GAGZ,MArQmB,KAqQf3uD,EAAKu0C,OAAO,MACbv0C,EAAM2uD,GAwBf,SAAS+T,GAAyBhwB,GAChC,MAAMiwB,EAAWjwB,EAAY1mB,QAAQ,KAGrC,MAAO,CAFS0mB,EAAY7zB,UAAU,EAAG8jD,GAC3BjwB,EAAYt1C,MAAMulE,EAAW,GAE7C,CA7BwBD,CAAyB1iE,IAEpC/Z,KAAKwrE,OAAO3E,OAAO7mE,KAAKwnE,YAAah8D,EAASuO,EAAM2uD,EAAOrhD,IAEhErnB,KAAKsH,QAAQ2zE,yBADI5zD,EAAcylC,QAAY,EACIZ,EAAU7kC,EAAK,EAC/D,CAEH,OAAOrnB,KAAKq6E,SAASxT,OAAOz7C,EAAQ6gC,EAAWC,IAsBnD,IC5RaywB,GAA0B,MAAjC,MAAOA,UAAkCvH,GAI7Cv1E,YACsBw5E,EAAU7uB,EAAyBC,EACrDmyB,GACF1nC,MAAMmkC,EAAIrgD,KAAMwxB,EAAQC,GAG1B7jC,cACE5mB,KAAK6uE,SAXI8N,gDFJAh9E,MEIyBi0C,OFJzBj0C,MESS07E,IFTT17E,MESS07E,IFTT17E,MESSA,sBFTTA,eEIA2H,uBAA0B,KAwBvC,MAAMu1E,GAAyC,CAC7C,CAACzzD,QAAS+vD,KAAkB1vD,SAAUyvD,IACtC,CAAC9vD,QAAS+4C,GAA0B2a,oBAXtBC,KACd,OAAO,IAAI1a,EACb,GAUE,CAACj5C,QAASgsD,GAAiB3rD,SAAUkzD,IAA4B,CAC/DvzD,QAAS4zD,MACTF,oBAVYG,GACZ/C,EAA+B1O,EAAyB0R,GAC1D,OAAO,IAAI9C,GAAyBF,EAAU1O,EAAQ0R,EACxD,EAQIC,KAAM,CAACC,KAAqBhI,GAAiBiI,SAQpCC,GAA2C,CACtD,CAACl0D,QAAS4lC,GAAiB8tB,WAAY,IAAM,IAAI1E,IACjD,CAAChvD,QAASm0D,MAAuBj0D,SAAU,wBAAyBuzD,IAOzDW,GAAgD,CAC3D,CAACp0D,QAAS4lC,GAAiBvlC,SAAUykC,IACrC,CAAC9kC,QAASm0D,MAAuBj0D,SAAU,qBAAsBuzD,IC3CnE,IASaY,GAAuB,YAAvBA,EAiBX56E,kBAAkB6sC,GAEhB,MAAO,CACLguC,SAAUD,EACVE,UAAWjuC,EAAOomC,kBAAoB0H,GACAF,oDAtB/B,cHnBA39E,YGmBA89E,gBHnBA99E,iBGmBuB29E,GAFvB5zD,SAA4Bk0D,QAE5BH,CAAuB,KA+DvBI,GAAoB,YAApBA,gEHlFAl+E,YGkFAk+E,gBHlFAl+E,iBGkFoB69E,GAFpB9zD,SAAiCk0D,QAEjCC,CAAoB,2EChGjC,MAAMC,GACFj+E,YAAYk+E,EAAM3rC,EAAS,gBAAiBgH,EAAS,SACjDp5C,KAAK+9E,KAAOA,EACZ/9E,KAAKoyC,OAASA,EACdpyC,KAAKo5C,OAASA,CAClB,CAIA4kC,eAAejvC,GACX,OAAO/uC,KAAK+9E,KAAKttD,IAAK,GAAEzwB,KAAKoyC,SAASrD,IAAO/uC,KAAKo5C,SACtD,8FCGG,IAAM6kC,GAAY,MAAnB,MAAOA,EACXp+E,YACU09B,EACA2gD,EACAztE,EACAgyB,EACA1iC,EACAgO,EACAmgC,GANAluC,mBACAA,kBACAA,mBACAA,qBACAA,cACAA,sBACAA,8BACP,CAEGm+E,YAAYC,GAA6B,qCAC7C,MAAMj/B,QAAY,EAASx0B,MAAe5pB,EAAKw8B,YAAY6hB,eAE3D,GAAID,EAAc,CAChB,MAAMk/B,QAAQ,EAAS1zD,MAAe5pB,EAAKm9E,WAAW51B,YAAYnJ,EAAaI,SAG/E,GAFAx+C,EAAKm9E,WAAW31B,YAAY81B,GAG1Bt9E,EAAKgN,eAAeyjC,qBACpBzwC,EAAKgN,eAAexM,kBAAkBoqC,oBACtCwT,EAAaO,QACb,CACA3+C,EAAKmtC,wBAAwBuD,MAAM1wC,EAAKgN,eAAexM,kBAAkBoqC,oBAEzE,MAAM2yC,EAAS,CACbj3D,MAAO/gB,UACPi4E,SAAUC,UAAUr/B,EAAaO,SACjC++B,YAAa19E,EAAK0P,YAAYg/B,UAEhC1uC,EAAKmtC,wBAAwBwwC,QAAQJ,EAAM,CAG7C,OAAO,EAGP,GAAIF,EAAM59E,KAAKK,WAAaC,cAC1B,OAAO,EACF,GACLs9E,EAAM59E,KAAKK,WAAaC,kBACxBs9E,EAAM59E,KAAKK,WAAaC,oBACxBs9E,EAAM59E,KAAKK,WAAaC,0BACxBs9E,EAAM59E,KAAKK,WAAaC,+BACxB,CACA,MAAMstB,QAAU,EAASzD,MAAe5pB,EAAK0hC,cAAc4d,aAC3Dt/C,EAAKhB,OAAOouB,SAAS,CAACC,GAAa,CAAEuwD,YAAaP,EAAMO,aAAa,SAC5DP,EAAM59E,KAAKK,WAAaC,0BACjC,IAAIyoB,OAAOuF,SAASC,SAAS/sB,QAAQ,IAAK,MAAQlB,0BAIhD,OAAO,EAJ4E,CACnF,MAAMw9C,QAAuB,EAAS3zB,MAAe5pB,EAAK0hC,cAAc0d,0BACxEp/C,EAAKhB,OAAOouB,SAAS,CAACmwB,GAA0B,CAAEqgC,YAAaP,EAAMO,aAAa,CAE3E,SAGTP,EAAM59E,KAAKK,WAAaC,sBACxBs9E,EAAM59E,KAAKK,WAAaC,mBACxB,CACA,MAAMu9C,QAAY,EAAS1zB,MAAe5pB,EAAK0hC,cAAc2d,eAC7Dr/C,EAAKhB,OAAOouB,SAAS,CAACkwB,GAAe,CAAEsgC,YAAaP,EAAMO,aAAa,SAC9DP,EAAM59E,KAAKK,WAAaC,sBAA+B,CAChE,MAAMy9C,QAAmB,EAAS5zB,MAAe5pB,EAAK0hC,cAAcwd,sBACpEl/C,EAAKhB,OAAOouB,SAAS,CAACowB,GAAsB,CAAEogC,YAAaP,EAAMO,aAAa,MAE9E59E,EAAKw8B,YAAYiB,UAAUjV,OAAOuF,SAASC,SAAU,KAEvD,OAAO,CACR,EAvD4C,EAwD/C,CAAClsB,kDAnEUo7E,GAAYhvE,+HAAZgvE,EAAY32E,QAAZ22E,EAAY,qBAFX,gBAEDA,CAAY,KCJZW,GAAc,MAArB,MAAOA,EACX/+E,YACU4Q,EACA1C,EACAmgC,GAFAluC,mBACAA,sBACAA,8BACP,CAEHm+E,YAAYC,EAA+B19E,GACzC,GAAIV,KAAK+N,eAAeyjC,qBAAuBxxC,KAAK+N,eAAexM,kBAAkBoqC,mBAAoB,CACvG3rC,KAAKkuC,wBAAwBuD,MAAMzxC,KAAK+N,eAAexM,kBAAkBoqC,oBACzE,MAAM2yC,EAAiB,CACrBj3D,MAAO/gB,UACPi4E,SAAUC,UAAU99E,EAAMgB,KAC1B+8E,YAAaz+E,KAAKyQ,YAAYg/B,UAEhCzvC,KAAKkuC,wBAAwBwwC,QAAQJ,EAAM,CAE7C,OAAO,CACT,CAACz7E,kDAlBU+7E,GAAc3vE,8EAAd2vE,EAAct3E,QAAds3E,EAAc,qBAFb,gBAEDA,CAAc,KCDdC,GAAe,MAAtB,MAAOA,EACXh/E,YAAoB09B,EAAkCxvB,EAAwChO,GAA1EC,mBAAkCA,sBAAwCA,aAAiB,CAE/Gm+E,YAAYC,EAA+B19E,GACzC,GAAIV,KAAK+N,eAAexM,kBAAmB,CACzC,MAAMG,EAAMhB,EAAMgB,IAAIqN,MAAM,KAC5B,IAAIzG,EAAK5G,EAAIA,EAAIY,OAAS,GAAGyM,MAAM,KAAK,GACxC,MAAM+vE,EAAoBnwC,aAAaowC,QAAQ,kBAEzCC,EAAiBF,EAAqBG,KAAKC,MAAMJ,GAAsC,GAE7F,GAAI9+E,KAAK+N,eAAeugB,aAAe0wD,IAAmB12E,GAAM02E,EAAeh2E,MAAQV,EACrF,YAAKvI,OAAOouB,SAAS,CAAC6wD,EAAeh2E,OAC9B,EAGJV,IACCtI,KAAK+N,eAAexM,kBAAkBsqC,YACxCvjC,EAAKtI,KAAK+N,eAAexM,kBAAkBsqC,YAAYvxB,WAEvDta,KAAKu9B,YAAYiB,UAAUl2B,EAAI,MAInCtI,KAAKu9B,YAAY+hB,gBAAgB,CAC/BC,OAAQj3C,EACRo3C,QAASp3C,EACTm3C,WAAW,GACZ,CAEH,OAAO,CACT,CAAC58C,kDA/BUg8E,GAAe5vE,6EAAf4vE,EAAev3E,QAAfu3E,EAAe,qBAFd,gBAEDA,CAAe,KCH5B,MAAMM,GAAiB,CAErB,CACEznE,KAAM5W,eACNs+E,aAAc,IACZz9B,wEAAkE9/C,KAAMw9E,GAAWA,EAAOC,iBAC5F9+E,KAAM,CAAEK,SAAUC,gBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,kBACNs+E,aAAc,IACZz9B,sDAAwE9/C,KACrEw9E,GAAWA,EAAOE,oBAEvB/+E,KAAM,CAAEK,SAAUC,mBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,wBACNs+E,aAAc,IACZz9B,sDAAoF9/C,KACjFw9E,GAAWA,EAAOG,0BAEvBh/E,KAAM,CAAEK,SAAUC,yBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,sBACNs+E,aAAc,IACZz9B,iFAAkE9/C,KAAMw9E,GAAWA,EAAOI,iBAC5Fj/E,KAAM,CAAEK,SAAUC,uBAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,yBACNs+E,aAAc,IACZz9B,iFAAkE9/C,KAAMw9E,GAAWA,EAAOI,iBAC5Fj/E,KAAM,CAAEK,SAAUC,0BAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,oBACNs+E,aAAc,IACZz9B,iFAAkE9/C,KAAMw9E,GAAWA,EAAOI,iBAC5Fj/E,KAAM,CAAEK,SAAUC,qBAClBq9E,YAAa,CAACF,KAGhB,CACEvmE,KAAM5W,+BACNs+E,aAAc,IACZz9B,+DAA8E9/C,KAC3Ew9E,GAAWA,EAAOK,uBAEvBl/E,KAAM,CAAEK,SAAUC,gCAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,oBACNs+E,aAAc,IACZz9B,iFAAkE9/C,KAAMw9E,GAAWA,EAAOI,iBAC5Fj/E,KAAM,CAAEK,SAAUC,qBAClBq9E,YAAa,CAACF,KAGhB,CACEvmE,KAAM5W,cAAwB,OAC9Bs+E,aAAc,IACZz9B,sDAAgE9/C,KAAMw9E,GAAWA,EAAOM,gBAC1Fn/E,KAAM,CAAEK,SAAUC,eAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,aAAuB,YAC7Bs+E,aAAc,IACZz9B,iFAA8D9/C,KAAMw9E,GAAWA,EAAOO,eACxFp/E,KAAM,CAAEK,SAAUC,cAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,aAAuB,mBAC7Bs+E,aAAc,IACZz9B,iFAA8D9/C,KAAMw9E,GAAWA,EAAOO,eACxFp/E,KAAM,CAAEK,SAAUC,cAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,UAAoB,OAC1Bs+E,aAAc,IAAMz9B,+DAAsD9/C,KAAMw9E,GAAWA,EAAOQ,YAClGr/E,KAAM,CAAEK,SAAUC,WAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,oBACNs+E,aAAc,IACZz9B,iFAA4E9/C,KACzEw9E,GAAWA,EAAOS,sBAEvBt/E,KAAM,CAAEK,SAAUC,qBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,mBACNs+E,aAAc,IACZz9B,wEAA0E9/C,KACvEw9E,GAAWA,EAAOU,qBAEvBv/E,KAAM,CAAEK,SAAUC,oBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,iBACNs+E,aAAc,IACZz9B,0FAAsE9/C,KAAMw9E,GAAWA,EAAOW,mBAChGx/E,KAAM,CAAEK,SAAUC,kBAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,0BACNs+E,aAAc,IACZz9B,0FAA0F9/C,KACvFw9E,GAAWA,EAAOY,4BAEvBz/E,KAAM,CAAEK,SAAUC,2BAClBq9E,YAAa,CAACF,KAGhB,CACEvmE,KAAM5W,qBACNs+E,aAAc,IACZz9B,gFAA8E9/C,KAC3Ew9E,GAAWA,EAAOa,uBAEvB1/E,KAAM,CAAEK,SAAUC,sBAClBq9E,YAAa,CAACS,KAEhB,CACElnE,KAAM5W,mBACNs+E,aAAc,IACZz9B,4GAA0E9/C,KACvEw9E,GAAWA,EAAOc,qBAEvB3/E,KAAM,CAAEK,SAAUC,oBAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,0BACNs+E,aAAc,IACZz9B,iFAA0F9/C,KACvFw9E,GAAWA,EAAOe,4BAEvB5/E,KAAM,CAAEK,SAAUC,2BAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,sBACNs+E,aAAc,IACZz9B,wEAAkF9/C,KAC/Ew9E,GAAWA,EAAOgB,wBAEvB7/E,KAAM,CAAEK,SAAUC,uBAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,qBAA+B,OACrCs+E,aAAc,IACZkB,8BAA8Ez+E,KAC3Ew9E,GAAWA,EAAOkB,uBAEvB//E,KAAM,CAAEK,SAAUC,sBAClBq9E,YAAa,CAACS,KAGhB,CACElnE,KAAM5W,qBACNs+E,aAAc,IACZz9B,+DAAsE9/C,KAAMw9E,GAAWA,EAAOmB,mBAChGhgF,KAAM,CAAEK,SAAUC,sBAClBq9E,YAAa,CAACF,KAGhB,CACEvmE,KAAM5W,iBACNs+E,aAAc,IAAMz9B,iFAAsD9/C,KAAMw9E,GAAWA,EAAOoB,YAClGjgF,KAAM,CAAEK,SAAUC,kBAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM5W,cACNs+E,aAAc,IAAMz9B,iFAAsD9/C,KAAMw9E,GAAWA,EAAOoB,YAClGjgF,KAAM,CAAEK,SAAUC,eAClBq9E,YAAa,CAACF,KAEhB,CACEvmE,KAAM,KACN0nE,aAAc,IAAMkB,8BAAwDz+E,KAAMw9E,GAAWA,EAAOqB,aACpGvC,YAAa,CAACU,MAcX,IAAM8B,GAAgB,MAAvB,MAAOA,EAAgB99E,kDAAhB89E,EAAgB,sCAAhBA,IAAgB99E,yCAHhB,CAACg8E,GAAiBZ,GAAcW,IAAel1D,SALxDC,cAAqBw1D,GAAQ,CAC3ByB,0BAA2B,MAC3BC,eAAe,IAITl3D,gBAECg3D,CAAgB,KCzNtB,IAAKG,GAIX,aAJWA,UAAc,KACxBA,kBACAA,cACAA,kBAHUA,GAAZ,IAAYA,GAIX,0DCQM,IAAMC,GAAuB,MAA9B,MAAOA,EAgBXlhF,YACU2tB,EACAwzD,EACA97D,EACA+7D,EACA7gE,GAJApgB,uBACAA,6BACAA,0BACAA,4BACAA,sBApBVA,aAAS,EAIDA,gBAAY,EAEZA,mBAAgB,sEAEhBA,yBAAsBA,KAAKogB,eAChC8gE,SAAS36E,WACThG,UAAWC,GAAUR,KAAKmhF,UAAY3gF,GACjCR,0BAAuBA,KAAKwtB,gBAAgBK,MAAMttB,UAAWC,IACnER,KAAK8tB,aAAettB,GASnB,CAEH0mE,OACElnE,KAAKy1C,OAASrzC,SAASg/E,eAAe,gBAAa3/E,EACnDzB,KAAKiB,QAAS,CAChB,CAEA61B,YAAYtkB,GACV,IAAI4Y,EAAS5Y,EAAE4Y,OACXA,GAAoB,QAAV5Y,EAAEnL,MACdrH,KAAKihF,qBAAqBI,eAEvBj2D,EAAOyL,QAAQ,UACfzL,EAAOyL,QAAQ,cAAcvuB,KAAOtI,KAAK8tB,cAAczlB,KAAO+iB,EAAOyL,QAAQ,eAE9E72B,KAAKwtB,gBAAgBQ,gBAGpB5C,EAAOyL,QAAQ,4BAA8Bz0B,SAAS42B,KAAK60B,cAAc,cAC1EziC,EAAOyL,QAAQ,aAEfzL,EAAShpB,SAASyrD,cAA2B,gCAE7C7tD,KAAKshF,aAAal2D,GAEhBA,GACFprB,KAAKihF,qBAAqBM,SAASn2D,GAGzC,CAEAo2D,cAAchvE,GACZ,MAAM4Y,EAAS5Y,EAAE4Y,OAEjB,GAAIprB,KAAKmhF,WACO,QAAV3uE,EAAEnL,KAAkBmL,EAAEivE,SAAqB,MAAVjvE,EAAEnL,MACrCmL,EAAEkvE,iBAEJ1hF,KAAKihF,qBAAqBI,kBACrB,CACL,MAAMM,EAAQv2D,EAAOyL,QAAQ,UAAY72B,KAAK4hF,OAAO/qD,QAAQ,SACvDuL,EAAchX,EAAOyL,QAAQ,gBAAkB72B,KAAK4hF,OAAO/qD,QAAQ,eAE3D,UAAVrkB,EAAEnL,IACArH,KAAK4hF,OACPpvE,EAAEkvE,iBACF1hF,KAAK4hF,MAAMC,SACF7hF,KAAK2nB,QACTyD,EAAOyL,QAAQ,OAASzL,EAAOyL,QAAQ,WAC1C72B,KAAK2nB,MAAMk6D,QAEb7hF,KAAKihF,qBAAqBM,SAASn2D,KAE/BA,EAAOyB,UAAU04B,SAAS,aAAen6B,EAAOyB,UAAU04B,SAAS,YACrEn6B,EAAOy2D,QAGF7hF,KAAK8tB,cAAgB1C,EAAOyL,QAAQ,yBAC7C72B,KAAK8hF,eAAetvE,EAAG4Y,GACdu2D,EACT3hF,KAAK+hF,YAAYvvE,EAAGmvE,GACXv/C,EACTpiC,KAAK+hF,YAAYvvE,EAAG4vB,GACD,QAAV5vB,EAAEnL,MAER+jB,EAAOyL,QAAQ,4BAA8Bz0B,SAAS42B,KAAK60B,cAAc,cAC1EziC,EAAOyL,QAAQ,eAEfrkB,EAAEkvE,gBAAc,CAIxB,CAEA9qD,cAAcxL,GACZprB,KAAKihF,qBAAqBe,cAC1BhiF,KAAKihF,qBAAqBI,cACtBj2D,EAAOyB,UAAU04B,SAAS,yBAC5BvlD,KAAKghF,sBAAsBiB,WAClBjiF,KAAK8tB,eAEX1C,EAAOyL,QAAQ,UACfzL,EAAOyL,QAAQ,cAAcvuB,KAAOtI,KAAK8tB,cAAczlB,KAAO+iB,EAAOyL,QAAQ,eAE9E72B,KAAKwtB,gBAAgBQ,gBAGzBhuB,KAAKklB,mBAAmByQ,MAAMx1B,QAAKsqB,MAAK,IAAIlqB,UAAWC,IACjDA,EAAKg7C,MAAMI,UAAYxwB,EAAOyL,QAAQ,wBACxC72B,KAAKklB,mBAAmB8B,YAEtBxmB,EAAKk7C,UAAYtwB,EAAOyL,QAAQ,2BAClC72B,KAAKklB,mBAAmB03B,eAAa,EAG3C,CAEQklC,eAAetvE,EAAkB4Y,GACvC,GAAc,WAAV5Y,EAAEnL,IACJmL,EAAE0vE,kBACFliF,KAAKwtB,gBAAgBQ,qBAAa,IAElChuB,KAAKmiF,YAAY3vE,EAAEnL,MACnBrH,KAAKoiF,YAAY5vE,EAAEnL,MACnBrH,KAAKqiF,aAAa7vE,EAAEnL,MACpBrH,KAAKsiF,UAAU9vE,EAAEnL,SAEb+jB,EAAOyL,QAAQ,wBAA0B72B,KAAKoiF,YAAY5vE,EAAEnL,OAAQrH,KAAKqiF,aAAa7vE,EAAEnL,MAErF,CACLmL,EAAEkvE,iBACsC,UAAlCt2D,EAAOi6B,SAAS34C,eAA6D,SAAhC0e,EAAOm3D,aAAa,SACrEviF,KAAKihF,qBAAqBe,cAE5B,MACMQ,GADWxiF,KAAK8tB,cAAczlB,GAAKjG,SAASg/E,eAAephF,KAAK8tB,aAAazlB,SAAM5G,IACjD2pB,EAAOyL,QAAQ,yBACvD,GAAI2rD,EAAW,CACb,MAAMj2E,EAAQi2E,EAAU30B,cAAc,sBAAsB5F,iBAAiBjoD,KAAKyiF,eAElF,GAAIl2E,EACF,GAAIvM,KAAKmiF,YAAY3vE,EAAEnL,MAAQrH,KAAKqiF,aAAa7vE,EAAEnL,KACjD,QACiB5F,IAAfzB,KAAK4hF,OACJ5hF,KAAK4hF,OAAS5hF,KAAK4hF,MAAM/qD,QAAQ,qBACjCzL,EAAOyL,QAAQ,uBACZ72B,KAAK4hF,OAAU5hF,KAAK4hF,OAAS5hF,KAAK4hF,MAAM/qD,QAAQ,qBAEhDtqB,GAAOjK,QAETtC,KAAKihF,qBAAqByB,SADVn2E,EAAM,IACsB,OAEzC,CACL,MAAMf,EAAUxL,KAAKihF,qBAAqB0B,WAAW1rE,MAAMgtC,KAAK13C,IAAyB,GAErFf,GACFxL,KAAKihF,qBAAqByB,SAASl3E,GAAS,EAAI,SAG3CxL,KAAKsiF,UAAU9vE,EAAEnL,MAAQrH,KAAKoiF,YAAY5vE,EAAEnL,KAAM,CAC3D,MAAMmE,EAAUxL,KAAKihF,qBAAqB2B,WAAW3rE,MAAMgtC,KAAK13C,IAAyB,GAEzF,GAAIf,EACFxL,KAAKihF,qBAAqByB,SAASl3E,GAAS,OACvC,CACL,MAAMq3E,EAASL,EAAU30B,cAA2B,oBAChDg1B,GACF7iF,KAAKihF,qBAAqByB,SAASG,GAAQ,EAAI,IAQ/D,CAEQd,YAAYvvE,EAAkBgwE,GACpC,GAAIxiF,KAAKmiF,YAAY3vE,EAAEnL,MAAQrH,KAAKoiF,YAAY5vE,EAAEnL,MAAQrH,KAAKqiF,aAAa7vE,EAAEnL,MAAQrH,KAAKsiF,UAAU9vE,EAAEnL,KAAM,CAK3G,IAAImE,EAJJgH,EAAEkvE,iBAEF1hF,KAAKihF,qBAAqBe,cAG1B,MAAMz1E,EAAQi2E,EAAUv6B,iBAAiBjoD,KAAKyiF,eAC1Cl2E,IACEvM,KAAKmiF,YAAY3vE,EAAEnL,MAAQrH,KAAKqiF,aAAa7vE,EAAEnL,KACjDmE,EAAUxL,KAAKihF,qBAAqB0B,WAAW1rE,MAAMgtC,KAAK13C,IAAyB,IAC1EvM,KAAKsiF,UAAU9vE,EAAEnL,MAAQrH,KAAKoiF,YAAY5vE,EAAEnL,QACrDmE,EAAUxL,KAAKihF,qBAAqB2B,WAAW3rE,MAAMgtC,KAAK13C,IAAyB,KAInFf,GACFxL,KAAKihF,qBAAqByB,SAASl3E,EAAO,CAGhD,CAEAob,cACE5mB,KAAK8iF,qBAAqBrtD,cAC1Bz1B,KAAK+iF,sBAAsBttD,aAC7B,CAEQ6rD,aAAal2D,GACnB,GAAIprB,KAAKy1C,OAAQ,CACf,MAAMutC,EAAyBhjF,KAAKy1C,OAAOwtC,aAAe,GACpDn/B,EAAM14B,EAAOi5B,wBAAwBP,IAAMk/B,EAAyB,GACtEl/B,EAAM,GACRv6B,OAAO25D,SAAS,EAAGp/B,EAAG,CAG5B,CAEQq+B,YAAY96E,GAClB,MAAe,cAARA,CACT,CAEQi7E,UAAUj7E,GAChB,MAAe,YAARA,CACT,CAEQ+6E,YAAY/6E,GAClB,MAAe,cAARA,CACT,CAEQg7E,aAAah7E,GACnB,MAAe,eAARA,CACT,CAACxE,kDArOUk+E,GAAuB9xE,sGAAvB8xE,EAAuBz5E,QAAvBy5E,EAAuB,qBAFtB,gBAEDA,CAAuB,kFCN7B,IAAMoC,GAAmB,MAA1B,MAAOA,EACXtjF,YAAsCuC,EAAiDghF,GAAjDpjF,gBAAiDA,iBAAqB,CAE5GqjF,aACE,SAAIC,OAAkBtjF,KAAKojF,aAAU,EAC5BG,MAAUh6D,OAAQ,UAAUppB,QACjCqjF,MAAU,IAAC,EACX73E,MAAK0b,GACIkC,OAAOk6D,SAAWzjF,KAAKoC,SAASwqB,gBAAgB82D,YACxD,EACDC,QAIK5yE,IAEX,CAAClO,kDAhBUsgF,GAAmBl0E,MACV2kC,OAAQ3kC,MAAsC20E,OAAW,wCADlET,EAAmB77E,QAAnB67E,EAAmB,mBAAnBA,CAAmB,gECNpBU,GAKX,aALWA,UAAY,KACtBA,yBACAA,0BACAA,2BACAA,sBAJUA,GAAZ,IAAYA,GAKX,cCMM,IAAMC,GAAY,MAAnB,MAAOA,EACXjkF,YAAoB4iC,EAAsCz2B,GAAtChM,qBAAsCA,oBAA+B,CAEzF+jF,gBAAgB57E,EAAsBoE,EAAsBsqC,EAAsBmtC,GAChF,IAAK77E,EAAKgiC,SAER,OAGF,MAAMzoC,EAAM1B,KAAKgM,cAAcsP,aAAanT,EAAKkT,WAAalT,EAAKzG,KAE/DyG,EAAKtH,WAAaC,oBAA8BqH,EAAKtH,WAAaC,iBACpEd,KAAKyiC,cAAcmc,WAAWl9C,GACrByG,EAAKtH,WAAaC,sBAAgCqH,EAAKtH,WAAaC,mBAC7Ed,KAAKyiC,cAAcrB,aAAa1/B,GACvByG,EAAKtH,WAAaC,0BAC3Bd,KAAKyiC,cAAcoc,wBAAwBn9C,GAClCyG,EAAKtH,WAAaC,sBAC3Bd,KAAKyiC,cAAcqc,oBAAoBp9C,GAC9ByG,EAAKtH,WAAaC,sBAC3Bd,KAAKyiC,cAAcsc,oBAAoBr9C,IAEvCyG,EAAKtH,WAAaC,0BAClBqH,EAAKtH,WAAaC,iCAElBd,KAAKyiC,cAAcuc,uBAAuBt9C,IAGxCyG,EAAK87E,WAIL97E,EAAKmE,OAASu3E,YAChB17E,EAAKzG,IAAMyG,EAAKzG,IACPyG,EAAK+7E,mBAAqBpjF,eACnCqH,EAAKzG,IAAM,IACFyG,EAAKkT,YACdlT,EAAKzG,IAAMA,GAGbm1C,EAAMzuC,KAAK,CACTC,GAAIF,EAAKmE,OAASu3E,aAA2C,OAAlBG,EAAyBA,EAAgB77E,EAAKG,GACzFP,MAAOwE,EACPzD,MAAOX,EAAK4R,KACZlS,KAAMM,EAAKmE,KACXoa,OAAQve,EAAKijB,OACbpiB,IAAKb,EAAKzG,MAEd,CAEAyiF,iBAAiBC,GACf,MAAMl8E,EAAwB,GAE9B,UAAWm8E,KAAOD,EAAOE,KACvB,UAAWC,KAAUF,EAAIvjC,QACvB,GAAIyjC,EAAO93E,MAAO,CAChB,MAAMF,EAA0B,GAChCg4E,EAAO93E,MAAMF,MAAMhD,QAASpB,IAC1BoE,EAAMnE,KAAKD,EAAI,GAEjBoE,EAAMhD,QAAQ,CAACpB,EAAM+zB,KACnB,MAAMsoD,EAA6B,GACnC,GAAIr8E,EAAKmE,OAASu3E,YAChB,UAAWr8B,KAASr/C,EAAKoE,MACvBvM,KAAK+jF,gBAAgBv8B,EAAO,GAAIg9B,GAGpCxkF,KAAK+jF,gBAAgB57E,EAAMq8E,EAAat8E,EAAQg0B,EAAK,EACtD,CAKP,OAAOh0B,CACT,CAEAu8E,aAAa/iF,GACX,OAAOA,IAAQ6nB,OAAOuF,SAASC,QACjC,CAEA21D,iBAAiBC,GACf,QAAOA,EAAKr2E,KAAM0C,GAASA,IAASuY,OAAOuF,SAASC,SACtD,CAAClsB,kDAlFUihF,GAAY70E,gEAAZ60E,EAAYx8E,QAAZw8E,EAAY,qBAFX,gBAEDA,CAAY,+BCQPnkF,eAMC,UACOA,SAAiBA,qDAHvBA,uCADAA,0BAIMA,mDAERA,eAOC,UACOA,SAAiBA,0CALvBA,yBAEAA,0BAGMA,mDAlBVA,cACEA,sBASAA,sBAUFA,6CAlBKA,wFASAA,yIA1BfA,SACEA,cAAI,4CASAA,WACEA,gBAAMA,SAAgBA,QACxBA,QACAA,WACEA,cACEA,uBAqBFA,QACFA,QACFA,UAEJA,mDArCMA,wEAGE,gEAHFA,CAGE,yDAKMA,wBAIkBA,6DA4B5BA,gBAOEA,SACFA,oDAJEA,uCADAA,0BAIAA,2DAEFA,gBAOGA,SAAgBA,yCAJjBA,yBAEAA,0BAECA,mDAlBPA,SACEA,cACEA,sBASAA,uBASFA,QACFA,mDAlBOA,wFASAA,mFAtDTA,SACEA,kCAyCAA,iCAsBFA,6CA/DiBA,wDAyCAA,mFA5CrBA,SACEA,cACEA,iCAiEFA,QACFA,8BAlEmCA,oCCc5B,IAAMilF,GAAe,MAAtB,MAAOA,EAKX/kF,YACUkO,EACA00B,EACAoiD,EACAp3D,EACA8P,GAJAv9B,sBACAA,qBACAA,oBACAA,0BACAA,mBATVA,gBAAY,CAUT,CAEHC,WACED,KAAKytB,mBAAmBM,OAAOxtB,UAAWC,IACxCR,KAAK8kF,iBAAmBtkF,IAG1B,MAAMm+C,EAAS3+C,KAAK+N,eAAexM,kBAAkB0oC,SACjD0U,GACF3+C,KAAKyiC,cACFic,UAAUC,GACVx+C,QAAKsqB,MAAK,IACVlqB,UACE6jF,IACCpkF,KAAKokF,OAASpkF,KAAK6kF,aAAaV,iBAAiBC,GACjDpkF,KAAKmhF,WAAY,GAElBtgE,IACC7gB,KAAKu9B,YAAYiB,UAAUjV,OAAOuF,SAASC,SAAUlO,EAAMtO,OAAM,EAI3E,CAEIsxE,mBACF,OAAOA,EACT,CAEAY,aAAat8E,GACX,OAAOA,EAAKa,MAAQugB,OAAOuF,SAASC,QACtC,CAEA21D,iBAAiBn4E,GACf,QAAOA,EAAMZ,IAAKqF,GAASA,EAAKhI,KAAKsF,KAAM0C,GAASA,IAASuY,OAAOuF,SAASC,SAC/E,CAAClsB,kDA7CU+hF,GAAe31E,gGAAf21E,EAAe7hF,ivBDhB5BpD,sCAAeA,k9ICgBFilF,CAAe,KCTfG,GAAe,MAAtB,MAAOA,EACXllF,YAAoB45B,aAAkB,CAEtCurD,YAAYrmC,GACV,OAAO3+C,KAAKy5B,IAAI8V,WAAuB,2BAA2BoP,IACpE,CAAC97C,kDALUkiF,GAAe91E,qDAAf81E,EAAez9E,QAAfy9E,EAAe,qBAFd,gBAEDA,CAAe,oBCErB,IAAME,GAAc,MAArB,MAAOA,EACXplF,YAAoB2H,qBAA2B,CAE/C09E,mBAAmBd,GACjB,MAAMl8E,EAAoB,CACxB2L,KAAM,IAGFsxE,EAAgB,GA8CtB,GA5CAf,EAAOE,KAAK/6E,QAAQ,CAAC86E,EAAK77C,KACxB67C,EAAIvjC,QAAQv3C,QAAQ,CAACg7E,EAAQnS,KACvBmS,EAAO93E,OAAOF,OAChBg4E,EAAO93E,OAAOF,MAAMhD,QAAQ,CAACpB,EAAMi9E,KACjC,GAAIj9E,EAAKmE,OAASu3E,YAAuB,CACvC,MAAMwB,EAAyB,CAC7Bv8E,MAAOX,EAAK4R,KACZrQ,MAAOvB,EAAKwB,MACZ5B,MAAO,IAETI,EAAKoE,MAAMhD,QAAQ,CAACi+C,GAAO89B,MACzB,MAAMr/C,GAAY,SAASuC,KAAK4pC,KAAKgT,KAAKE,KACtC99B,GAAM+9B,YACRJ,EAAI/8E,KACF,qBAAqB69B,gCAAuCuhB,GAAM+9B,4BAItEF,EAASt9E,MAAMK,KAAK,CAClB2C,KAAMy8C,GAAM3a,QACZ/jC,MAAO0+C,GAAMztC,KACbrQ,MAAO89C,GAAM79C,MACbX,IAAKw+C,GAAM9lD,IAAM,GAAG8lD,GAAM9lD,2BAA6B,GACvDglB,OAAQ8gC,GAAMp8B,QAAU,SACxBziB,YAAa3I,KAAKwH,YAAYoB,QAAQ4+C,GAAM3+C,aAC5C28E,MAAOh+B,GAAM+9B,WACT,CACEE,UAAWx/C,GACXy/C,MAAOl+B,GAAM+9B,iBAEf9jF,GACL,GAEHyG,EAAO2L,KAAKzL,KAAKi9E,EAAQ,MAChBl9E,EAAKmE,OAASu3E,cACvB37E,EAAOlD,KAAO,CACZ8D,MAAOX,EAAK4R,KACZ/Q,IAAKb,EAAKzG,IAAM,GAAGyG,EAAKzG,2BAA6B,MAG1D,EAEJ,GAECwG,EAAQ,CACV,GAAIi9E,EAAK,CACP,MAAMxyC,EAAQvwC,SAAS4vC,cAAc,SACrCW,EAAMF,YAAYrwC,SAASujF,eAAeR,EAAIjuE,KAAK,MACnD9U,SAASC,qBAAqB,QAAQ,GAAGowC,YAAYE,EAAK,CAE5DzqC,EAAOy4B,WAAaz4B,EAAO2L,KAAK,EAAC,CAEnC,OAAO3L,CACT,CAACrF,kDA/DUoiF,GAAch2E,oDAAdg2E,EAAc39E,QAAd29E,EAAc,qBAFb,gBAEDA,CAAc,wJCNrBtlF,cAAsC,cAIlCA,sEAASA,qBAAc,GAGvBA,WAOAA,gBACFA,QACAA,WACFA,qEAdIA,qDAA8C,yCAK5CA,qCAA0B,uDAMJA,kDAEZA,qCAA4B,2EAG9CA,gBAAyG,UACjGA,SAAyBA,QAC/BA,gBACFA,+BAH2CA,wCACnCA,sCACkBA,0EAKxBA,SACEA,WACFA,kEADgBA,qCAA4B,0EAF9CA,SACEA,iCAGFA,6CAHiBA,4EA7BrBA,SACEA,iBAA4C,UAExCA,wBAkBFA,QACAA,sBAIFA,QACAA,iBACEA,iCAKFA,QACFA,8BA/B0BA,0CAmBAA,uCAMQA,qEAW5BA,gBAQEA,WAOFA,kEATEA,oCAHAA,0BACAA,yBAKEA,qCAA0B,iFAkB1BA,kDAAuDA,qIAX3DA,kBAAyC,6DACkEA,QACzGA,gBACEA,WAQAA,yBACFA,oEAXgBA,6EACbA,mCAECA,qCAA0B,wDAOGA,gEA5BrCA,SACEA,uBAgBAA,0BAcFA,kCA7BKA,+BAeGA,yDAlBVA,kBACEA,iCAgCFA,8BAhCiCA,uDAuC7BA,mBAA8C,cACvBA,SAAWA,sCAAXA,6CAJ3BA,mBAAgD,WACnBA,SAAWA,QACtCA,gBACEA,0BAGFA,oDALOA,kBAAoBA,kBAEQA,0BClEhC,IAAMimF,GAAiB,MAAxB,MAAOA,EAGX/lF,YACUgmF,EACAC,EACA/3E,GAFA/N,uBACAA,sBACAA,qBACP,CAEHC,WACE,MAAM0+C,EAAS3+C,KAAK+N,eAAexM,kBAAkB6oC,WACjDuU,GACF3+C,KAAK6lF,gBAAgBb,YAAYrmC,GAAQp+C,UAAWwlF,IAClD/lF,KAAK+lF,SAAW/lF,KAAK8lF,eAAeZ,mBAAmBa,EAAQ,EAGrE,CAEA1kD,UAAUvoB,GACJ9Y,KAAK+lF,WACP/lF,KAAK+lF,SAASplD,WAAa7nB,EAGzB9Y,KAAK+lF,SAASC,kBADZhmF,KAAK+lF,SAASC,oBAAsBltE,OACJrX,EAEAqX,EAGxC,CAACjW,kDA5BU+iF,GAAiB32E,sEAAjB22E,EAAiB7iF,+6BDX9BpD,iCAoCAA,2CAqCAA,iDAzEeA,i9JCWFimF,CAAiB,KCFjBK,GAAa,MAApB,MAAOA,EAGXpmF,YAAoB4Q,qBAA2B,CAE/CxQ,WACED,KAAKkmF,KAAOlmF,KAAKyQ,YAAYy1E,IAC/B,CAEAC,WACEnmF,KAAKyQ,YAAY21E,QACnB,CAACvjF,kDAXUojF,GAAah3E,mDAAbg3E,EAAaljF,yPCT1BpD,kDAKEA,WACEA,gBAAMA,SAAoBA,QAC5BA,QACAA,WACEA,cAAI,OAAJA,CAAI,cAEQA,gCAASgsB,YAAU,GACzBhsB,eACAA,iBAAMA,gCAAkCA,cAIhDA,QACFA,eAjBEA,oCAA8B,0CAA9BA,CAA8B,mDAKtBA,kDAMwBA,yCAClBA,6qEDJHsmF,CAAa,oDEEpBtmF,qBAAqEA,oDACrEA,qBAAqEA,sDACrEA,qBAAoEA,4DACpEA,qBAAoEA,0DAGpEA,mDAfJA,kDAQEA,WACEA,uBACAA,uBACAA,uBACAA,uBACFA,QACAA,YACEA,kCACAA,4BACFA,QACFA,8BAhBEA,kBAAY,kCAAZA,CAAY,iBAAZA,CAAY,aAAZA,CAAY,wDAONA,uFACAA,uFACAA,sFACAA,sFAGYA,0DAOdA,wCAA4DA,qCAAvDA,2DACLA,wCAA+DA,qCAA1DA,6DAEPA,SACEA,mBACAA,cAAIA,SAAcA,QACpBA,+BAFwBA,oDAClBA,sDARVA,SACEA,qBAA2C,aAEvCA,yBACAA,yBACFA,QACAA,iCAIFA,QACFA,8BARgCA,qCACCA,sCAEdA,kGAYnBA,6FAYEA,WACEA,gBACFA,QACAA,YACEA,oCAIFA,QACFA,8BAnBEA,qBAAe,6BAAfA,CAAe,oBAAfA,CAAe,iBAAfA,CAAe,0BAAfA,CAAe,aAAfA,CAAe,sBAAfA,CAAe,wBAAfA,CAAe,6GAWWA,yCAItBA,6FAA4E,sDAKlFA,oFAOEA,gBACFA,8BALEA,kCAEAA,8GAEwBA,+DAGxBA,gEACAA,qBAA0DA,0DAASA,kBAAS,GAC1EA,8BACFA,cADEA,8EAHJA,eACEA,gCACAA,4BAGFA,8BAJgBA,oCACLA,sCCvDN,IAAM0mF,GAAsB,MAA7B,MAAOA,EAgBXxmF,YACUymF,EACAv4E,EACA0C,EACAgyB,EACAhV,EACAD,GALAxtB,2BACAA,sBACAA,mBACAA,qBACAA,0BACAA,uBARVA,gBAAqB,CASlB,CAEHC,WACED,KAAKksC,KAAOlsC,KAAK+N,eAAexM,kBAAkB2qC,KAClDlsC,KAAKumF,UAAYvmF,KAAK+N,eAAexM,kBAAkBg0B,cAAgB5uB,WAEvE3G,KAAK2Q,WAAa3Q,KAAKyQ,YAAYE,WACnC3Q,KAAKwmF,cAAcxmF,KAAK+N,eAAexM,kBAAkB6oC,WACzDpqC,KAAKsuB,YAActuB,KAAK+N,eAAeugB,YACvCtuB,KAAKymF,mBAAqBzmF,KAAK+N,eAAeK,YAAcpO,KAAK+N,eAAeS,cAEhFxO,KAAKwtB,gBAAgBK,MAAMttB,UAAWkM,IACpCzM,KAAK8tB,aAAerhB,IAGtBzM,KAAKyiC,cAAc2d,cAAc7/C,UAAWmB,IAC1C1B,KAAK0mF,YAAchlF,IAGrB1B,KAAKytB,mBAAmBM,OAAOxtB,UAAWC,IACxCR,KAAKiuB,MAAQztB,IAGfR,KAAKyiC,cAAc4d,YAAY9/C,UAAWmB,IACxC1B,KAAKouB,WAAa1sB,IAGpB1B,KAAK2mF,SAAW3mF,KAAK+N,eAAexM,kBAAkBuH,MAEtD9I,KAAKsmF,oBAAoBjD,aAAa9iF,UAAWqmF,IAC1Cr9D,OAAOilB,cACVxuC,KAAK6mF,YAAYD,EAAG,EAG1B,CAEAE,UACE9mF,KAAKyQ,YAAYs2E,OACnB,CAEIjmF,mBACF,OAAOA,IACT,CAEQ+lF,YAAYG,GAGlBhnF,KAAKinF,SAAWD,GAAkBE,CACpC,CAACrkF,kDAvEUwjF,GAAsBp3E,6GAAtBo3E,EAAsBtjF,2uCDjBnCpD,iBACAA,iBACEA,sCAmBAA,iCAaAA,iBACAA,iBACEA,yBACFA,QAEAA,qCAsBAA,4BASAA,wBAMFA,eAzEKA,+CAkBYA,8BAmBZA,oCAsBAA,mDAQGA,89OCrDK0mF,CAAsB,0CCd7B1mF,oBAAoDA,oDACpDA,oBAAoDA,wDASlDA,SACEA,gBAA0DA,SAAgBA,QAC5EA,wCAD8BA,uCAA8BA,mDAE5DA,SACEA,iBAAOA,SAAgBA,QACzBA,wCADSA,mDATbA,SACEA,cACEA,eACFA,QACAA,cACEA,iCAGAA,iCAGFA,QACFA,kCAV2CA,gDAGxBA,6BAGAA,yDATrBA,SACEA,iCAaFA,+BAbiCA,6DARnCA,gBAAuD,OAAvDA,CAAuD,SAGjDA,sBACAA,sBACFA,UAEFA,iCAeFA,8BApBOA,4CACwBA,6CACAA,6CAGdA,8CCGV,IAAMwnF,GAAoB,MAA3B,MAAOA,EAKXtnF,YAAoBunF,EAAgD35D,GAAhDztB,0BAAgDA,0BAJpEA,aAAS,EACTA,WAAiB,GACRA,eAAW,CAEyF,CAE7GC,WACED,KAAKonF,mBAAmBzxD,MAAMp1B,UAAWC,IACvCR,KAAKuM,MAAQ/L,IAEfR,KAAKytB,mBAAmB45D,QAAQ9mF,UAAWC,IACzCR,KAAKo0C,OAAS5zC,GAElB,CAEA8mF,aACE,IAAKtnF,KAAKo0C,QAAUp0C,KAAKuM,MAAMjK,OAAQ,CACrC,MAAM6F,EAAOnI,KAAKuM,MAAMvM,KAAKuM,MAAMjK,OAAS,GAC5C,GAAI6F,EAAKa,IACP,OAAOb,EAAKa,IAGhB,MAAO,GACT,CAACnG,kDAxBUskF,GAAoBl4E,8DAApBk4E,EAAoBpkF,ohBDVjCpD,4BAAKA,g0DCUQwnF,CAAoB,6HCP3BI,EAEAC,EACAC,EACAC,EAEAC,kBANAJ,EACF,iIACEC,EAAsB,2BACtBC,EAAkB,oBAClBC,EAAsB,2CA+JxBrI,QA7JEsI,EAAa,CAOfC,iBAAkB,SAAUC,EAASC,EAAaC,GAKhD,GAJAA,EAAOA,GAAQ,GAEfF,EAAUA,EAAQzxD,SAClB0xD,EAAcA,EAAY1xD,QACR,CAIhB,IAAK2xD,EAAKC,gBACR,OAAOH,EAET,IAAII,EAAwBN,EAAWO,SAASL,GAChD,IAAKI,EACH,MAAM,IAAIE,MAAM,mCAElBF,SAAsBvwE,KAAOiwE,EAAWS,cACtCH,EAAsBvwE,MAEjBiwE,EAAWU,kBAAkBJ,EAAqB,CAE3D,IAAIK,GAAgBX,EAAWO,SAASJ,GACxC,IAAKQ,GACH,MAAM,IAAIH,MAAM,uCAElB,GAAIG,GAAcC,OAGhB,OAAKR,EAAKC,iBAGVM,GAAc5wE,KAAOiwE,EAAWS,cAAcE,GAAc5wE,MACrDiwE,EAAWU,kBAAkBC,KAH3BR,EAKX,IAAIU,GAAYb,EAAWO,SAASL,GACpC,IAAKW,GACH,MAAM,IAAIL,MAAM,mCAElB,IAAKK,GAAUC,QAAUD,GAAU9wE,MAA8B,MAAtB8wE,GAAU9wE,KAAK,GAAY,CAGpE,IAAIgxE,GAAYlB,EAAoBrxC,KAAKqyC,GAAU9wE,MACnD8wE,GAAUC,OAASC,GAAU,GAC7BF,GAAU9wE,KAAOgxE,GAAU,EAAC,CAE1BF,GAAUC,SAAWD,GAAU9wE,OACjC8wE,GAAU9wE,KAAO,KAEnB,IAAIixE,GAAa,CAGfJ,OAAQC,GAAUD,OAClBE,OAAQH,GAAcG,OACtB/wE,KAAM,KACNxQ,OAAQohF,GAAcphF,OACtBiG,MAAOm7E,GAAcn7E,MACrBotC,SAAU+tC,GAAc/tC,UAE1B,IAAK+tC,GAAcG,SAIjBE,GAAWF,OAASD,GAAUC,OAGA,MAA1BH,GAAc5wE,KAAK,IACrB,GAAK4wE,GAAc5wE,KAgBZ,CAKL,IAAIkxE,GAAcJ,GAAU9wE,KACxBmxE,GACFD,GAAYhwD,UAAU,EAAGgwD,GAAY7iC,YAAY,KAAO,GACxDuiC,GAAc5wE,KAChBixE,GAAWjxE,KAAOiwE,EAAWS,cAAcS,GAAO,MAtBlDF,GAAWjxE,KAAO8wE,GAAU9wE,KAIvB4wE,GAAcphF,SACjByhF,GAAWzhF,OAASshF,GAAUthF,OAIzBohF,GAAcn7E,QACjBw7E,GAAWx7E,MAAQq7E,GAAUr7E,QAgBvC,OAAwB,OAApBw7E,GAAWjxE,OACbixE,GAAWjxE,KAAOqwE,EAAKC,gBACnBL,EAAWS,cAAcE,GAAc5wE,MACvC4wE,GAAc5wE,MAEbiwE,EAAWU,kBAAkBM,KAEtCT,SAAU,SAAUxmF,GAClB,IAAIonF,EAAQvB,EAAUpxC,KAAKz0C,GAC3B,OAAKonF,EAGE,CACLP,OAAQO,EAAM,IAAM,GACpBL,OAAQK,EAAM,IAAM,GACpBpxE,KAAMoxE,EAAM,IAAM,GAClB5hF,OAAQ4hF,EAAM,IAAM,GACpB37E,MAAO27E,EAAM,IAAM,GACnBvuC,SAAUuuC,EAAM,IAAM,IARf,MAWXV,cAAe,SAAU1wE,GAgBvB,IATAA,EAAOA,EAAK3I,MAAM,IAAI4rC,UAAUzjC,KAAK,IAAIlV,QAAQylF,EAAiB,IAUhE/vE,EAAKpV,UAAYoV,EAAOA,EAAK1V,QAAQ0lF,EAAqB,KAAKplF,SAEjE,OAAOoV,EAAK3I,MAAM,IAAI4rC,UAAUzjC,KAAK,KAEvCmxE,kBAAmB,SAAUS,GAC3B,OACEA,EAAMP,OACNO,EAAML,OACNK,EAAMpxE,KACNoxE,EAAM5hF,OACN4hF,EAAM37E,MACN27E,EAAMvuC,ixCChKP,MAAMwuC,EACXjrC,OAAOkrC,UACP,SAAUv8E,GACR,MAAwB,iBAAVA,GAAsBu8E,SAASv8E,EAC/C,EC+CUw8E,MAAM,SAANA,YAAMC,oCAAND,EAAME,kCAANF,EAAMG,oCAANH,EAAMI,kCAANJ,EAAMK,8BAANL,EAAMM,gCAANN,EAAMO,kCAANP,EAAMQ,sCAANR,EAAMS,oCAANT,EAAMU,0BAANV,EAAMW,oCAANX,EAAMY,kCAANZ,EAAMa,sCAANb,EAAMc,oCAANd,EAAMe,oCAANf,EAAMgB,oCAANhB,EAAMiB,kCAANjB,EAAMkB,gCAANlB,EAAMmB,8BAANnB,EAAMoB,gCAANpB,EAAMqB,uCAANrB,EAAMsB,kCAANtB,EAAMuB,6CAANvB,EAAMwB,+CAANxB,EAAMyB,6CAANzB,EAAM0B,2CAAN1B,EAAM2B,yCAAN3B,EAAM4B,mDAAN5B,EAAM6B,mDAAN7B,EAAM8B,+CAAN9B,EAAM+B,iDAAN/B,EAAMgC,+CAANhC,EAAMiC,mDAANjC,EAAMkC,4BAANlC,EAAMmC,2DAANnC,EAAMoC,iCAANpC,EAAMqC,8BAANrC,EAAMsC,0DAANtC,EAAMuC,4BAANvC,EAAMwC,kCAANxC,EAAMyC,sDAANzC,EAAM0C,+CAAN1C,EAAM2C,+CAAN3C,EAAM4C,4BAAN5C,EAAM6C,gCAAN7C,EAAM8C,8BAAN9C,EAAM+C,sBAAN/C,EAAMgD,gDAANhD,EAAMiD,iBAANjD,EAAMkD,2BAANlD,EAAMmD,4BAANnD,EAAMoD,0BAANpD,EAAMqD,oDAANrD,EAAMsD,2CAANtD,CAAM,MCnDNuD,GAAU,SAAVA,YAAUC,6BAAVD,EAAUE,yBAAVF,EAAUG,kCAAVH,EAAUI,qBAAVJ,EAAUK,yBAAVL,CAAU,MAaVM,GAAY,SAAZA,YAAYC,qCAAZD,EAAYE,yCAAZF,EAAYG,2CAAZH,EAAYI,gEAAZJ,EAAYK,kEAAZL,EAAYM,uFAAZN,EAAYO,qFAAZP,EAAYQ,gEAAZR,EAAYS,sEAAZT,EAAYU,gEAAZV,EAAYW,wCAAZX,EAAYY,4CAAZZ,EAAYa,8CAAZb,EAAYc,qEAAZd,EAAYe,oCAAZf,EAAYgB,kCAAZhB,EAAYiB,sCAAZjB,EAAYkB,wCAAZlB,EAAYmB,sCAAZnB,EAAYoB,6CAAZpB,EAAYqB,iDAAZrB,EAAYsB,6CAAZtB,EAAYuB,uDAAZvB,EAAYwB,gCAAZxB,EAAYyB,oCAAZzB,EAAY0B,sCAAZ1B,EAAY2B,sCAAZ3B,EAAY4B,mBAAZ5B,EAAY6B,oCAAZ7B,EAAY8B,8BAAZ9B,EAAY+B,kCAAZ/B,EAAYgC,6CAAZhC,EAAYiC,iEAAZjC,EAAYkC,wCAAZlC,EAAYmC,8CAAZnC,EAAYoC,0CAAZpC,EAAYqC,oCAAZrC,EAAYsC,2CAAZtC,EAAYuC,2CAAZvC,EAAYwC,uCAAZxC,EAAYyC,2BAAZzC,EAAY0C,kBAAZ1C,CAAY,MCAxB,MAAM2C,GAAqB,WAAY,EAEjCC,GAAsB,CAC1BC,MAAOF,GACPG,MAAOH,GACPI,IAAKJ,GACL1sC,KAAM0sC,GACN/7D,KAAM+7D,GACN5uE,MAAO4uE,IAGT,IAAIK,GAA0BJ,GA4DvB,MAAMK,GAAkBD,GCpFzBE,GAA2B,gBAC3BC,GAAkB,4BAGjB,MAAMC,GAGXrwF,YAAYswF,GACW,iBAAVA,IACTA,EAAQD,GAASE,cAAcD,IAGjC,UAAWE,KAAQF,EACbA,EAAMtnD,eAAewnD,KACM,OAAzBA,EAAKz3D,UAAU,EAAG,KACpB54B,KAAKswF,YAActwF,KAAKswF,aAAe,GACvCtwF,KAAKswF,YAAYloF,KAAKioF,IAExBrwF,KAAKqwF,GAAQF,EAAME,GAGzB,CAEAE,eAAeC,GACb,MAAMC,EAAWxoE,SAASjoB,KAAKwwF,GAAW,IAC1C,OAAIC,EAAW3yC,OAAO4yC,iBACbrgD,IAGFogD,CACT,CAEAE,mBAAmBH,GACjB,GAAIxwF,KAAKwwF,GAAW,CAClB,IAAII,GAAe5wF,KAAKwwF,IAAa,MAAMr5E,MAAM,GACjDy5E,GAAoC,EAArBA,EAAYtuF,OAAa,IAAM,IAAMsuF,EAEpD,MAAMnkF,EAAQ,IAAIokF,WAAWD,EAAYtuF,OAAS,GAClD,QAASkmC,EAAI,EAAGA,EAAIooD,EAAYtuF,OAAS,EAAGkmC,IAC1C/7B,EAAM+7B,GAAKvgB,SAAS2oE,EAAYz5E,MAAU,EAAJqxB,EAAW,EAAJA,EAAQ,GAAI,IAG3D,OAAO/7B,EAEP,OAAO,IAEX,CAEAqkF,2BAA2BN,GACzB,MAAMC,EAAWxoE,SAASjoB,KAAKwwF,GAAW,IAC1C,OAAIC,EAAW3yC,OAAO4yC,iBACbrgD,IAGFogD,CACT,CAEAM,qBAAqBP,GACnB,OAAO73C,WAAW34C,KAAKwwF,GACzB,CAEAQ,cAAcR,EAAkBh4C,GAC9B,MAAM/rC,EAAQzM,KAAKwwF,GACnB,OAAO/jF,EAAQksC,WAAWlsC,GAAS+rC,CACrC,CAEAy4C,iBAAiBT,GACf,OAAOxwF,KAAKwwF,EACd,CAEAU,KAAKV,GACH,MAA0B,QAAnBxwF,KAAKwwF,EACd,CAEAW,kBAAkBX,GAMhB,MAAMY,EAAMpB,GAAyB75C,KAAKn2C,KAAKwwF,IAC/C,GAAY,OAARY,EAIJ,MAAO,CACLz4E,MAAOsP,SAASmpE,EAAI,GAAI,IACxB34E,OAAQwP,SAASmpE,EAAI,GAAI,IAE7B,CAEAvuF,qBAAqBwvD,GACnB,IAAInsB,EACJ,MAAMiqD,EAAQ,GAGd,IADAF,GAAgBp+B,UAAY,EACqB,QAAzC3rB,EAAQ+pD,GAAgB95C,KAAKkc,KAAkB,CACrD,IAAI5lD,EAAQy5B,EAAM,GAGS,IAAzBz5B,EAAMs5B,QANI,MAOVt5B,EAAMs5C,YAPI,OAOmBt5C,EAAMnK,OAAS,IAE5CmK,EAAQA,EAAM0K,MAAM,GAAG,IAGzBg5E,EADajqD,EAAM,GAAG9P,QACR3pB,EAEhB,OAAO0jF,CACT,EClFK,SAASkB,GAAkBb,GAChC,MACU,eAARA,GACyC,cAAzCA,CAEJ,CAEO,MAAMc,GAMXzxF,YAAY0xF,EAAyBC,GACnC,GADoExxF,KAL/DqwF,UAAI,OACHoB,gBAAU,OACVC,cAAQ,OACRC,wBAAkB,EAGpBH,EAAqB,CACvB,MAAMI,EAAeJ,EAAoBnB,KACzC,UAAWhpF,KAAOuqF,EAChB,GACEhpD,OAAOtD,UAAUuD,eAAeC,KAAKyoD,EAAelqF,IACpDkqF,EAAclqF,KAASuqF,EAAavqF,GACpC,CACA0oF,GAAOhtC,KACwB17C,qEAA0CkqF,EAAcM,OAEvF7xF,KAAK2xF,mBAAqBtqF,EAC1B,MAIJkqF,EAAgBO,GACd,IAAI5B,GAAS,IACb0B,EACAL,EACF,CAIF,GAFAvxF,KAAKqwF,KAAOkB,EACZvxF,KAAKyxF,WAAa,IAAI52E,KAAK02E,EAAa,eACpC,aAA+BvxF,KAAKqwF,KAAM,CAC5C,MAAM0B,EAAU,IAAIl3E,KAAK7a,KAAKqwF,KAAI,aAC9B2B,EAAgBD,EAAQpyE,aAC1B3f,KAAK0xF,SAAWK,GAGtB,CAEIzpF,SACF,OAAOtI,KAAKqwF,KAAKwB,EACnB,CAEII,YACF,OAAOjyF,KAAKqwF,KAAK6B,KACnB,CAEIC,gBACF,OAAOnyF,KAAKyxF,UACd,CAEIM,cACF,GAAI/xF,KAAK0xF,SACP,OAAO1xF,KAAK0xF,SAEd,MAAMhpF,EAAW1I,KAAK0I,SACtB,OAAiB,OAAbA,EACK,IAAImS,KAAK7a,KAAKyxF,WAAW9xE,UAAuB,IAAXjX,GAEvC,IACT,CAEIA,eACF,GAAI,aAA+B1I,KAAKqwF,KAAM,CAC5C,MAAM3nF,EAAW1I,KAAKqwF,KAAKU,qBAAoB,YAG/C,GAAIqB,EAAgB1pF,GAClB,OAAOA,UAEA1I,KAAK0xF,SACd,OAAQ1xF,KAAK0xF,SAAS/xE,UAAY3f,KAAKyxF,WAAW9xE,WAAa,IAEjE,OAAO,IACT,CAEI0yE,sBACF,MAAI,qBAAuCryF,KAAKqwF,KACvCrwF,KAAKqwF,KAAKU,qBAAoB,oBAIhC,IACT,CAEIuB,gBACF,OAAOtyF,KAAKqwF,KAAKa,KAAI,cACvB,CAEIqB,cACF,QACIvyF,KAAKsI,KACNtI,KAAK2xF,oBACNa,EAAgBxyF,KAAKmyF,UAAUxyE,aACZ,OAAlB3f,KAAK0I,UAAqB1I,KAAK0I,UAAY,MAC1C1I,KAAKsyF,aAAetyF,KAAKiyF,MAE/B,EC5HK,MAAMQ,GAAiC5yF,mBAC5C6yF,SAAmB,EAAK1yF,KACxBiB,OAAiB,EAACjB,KAClBmwC,MAAgB,EAACnwC,KACjBirB,MAAgB,EAACjrB,KACjB2yF,WAAqB,EAAC3yF,KACtB4yF,WAAqB,EAAC5yF,KACtBkB,QAA2C,CAAEsf,MAAO,EAAGqyE,MAAO,EAAG1X,IAAK,GAAGn7E,KACzE8yF,QAAgC,CAAEtyE,MAAO,EAAG26D,IAAK,GAAGn7E,KACpD+yF,UAA6C,CAAEvyE,MAAO,EAAGqyE,MAAO,EAAG1X,IAAK,EAAG,ECH7E,IAAkB6X,GAAqB,sDAmBhC,MAAMC,GAeXpzF,YAAYqzF,GAAiBlzF,KAdrBmzF,WAA8B,KAAInzF,KAClCozF,KAAsB,KAAIpzF,KAGlBkzF,aAAO,OAEhBG,YAAM,OAENC,kBAAuC,CAC5C,CAACN,GAAsBO,OAAQ,KAC/B,CAACP,GAAsBQ,OAAQ,KAC/B,CAACR,GAAsBS,YAAa,MAIpCzzF,KAAKkzF,QAAUA,CACjB,CAGAQ,aAAajnF,EAAeub,GAC1B,MAAM9gB,EAASuF,EAAMsC,MAAM,IAAK,GAC1B4kF,EAAsB,GAE1BA,EAAU,GADU,IAAlBzsF,EAAO5E,OACM0lB,EAAWA,EAAS4rE,mBAAqB,EAEzC3rE,SAAS/gB,EAAO,IAEjCysF,EAAU,GAAK1rE,SAAS/gB,EAAO,IAAMysF,EAAU,GAC/C3zF,KAAKmzF,WAAaQ,CACpB,CAEIA,gBACF,OAAK3zF,KAAKmzF,WAIHnzF,KAAKmzF,WAHH,EAIX,CAEIU,2BACF,OAAO7zF,KAAK2zF,UAAU,EACxB,CAEIC,yBACF,OAAO5zF,KAAK2zF,UAAU,EACxB,CAEIjyF,UACF,OAAK1B,KAAKozF,MAAQpzF,KAAKkzF,SAAWlzF,KAAKqzF,SACrCrzF,KAAKozF,KAAOxL,oBAAiB5nF,KAAKkzF,QAASlzF,KAAKqzF,OAAQ,CACtDrL,iBAAiB,KAGdhoF,KAAKozF,MAAQ,EACtB,CAEI1xF,QAAI+K,GACNzM,KAAKozF,KAAO3mF,CACd,EAMK,MAAMqnF,WAAiBb,GAwD5BpzF,YAAYyM,EAAyB4mF,GACnCh+C,MAAMg+C,GAASlzF,KAxDT+zF,aAAgC,KAAI/zF,KAErCg0F,mBAAoC,KAAIh0F,KACxCi0F,gBAAiC,KAAIj0F,KACrCk0F,QAA2B,GAAEl0F,KAG7B0I,SAAmB,EAAC1I,KAEpBm0F,GAA6B,EAACn0F,KAI9Bo0F,eAAS,OAEA9nF,UAAI,OAEb+nF,OAA+C,KAAIr0F,KAEnDs0F,UAA6C,KAAIt0F,KAEjD49C,OAAgB,EAAE59C,KAElBu0F,GAAa,EAACv0F,KAEdw0F,cAAQ,OAERC,YAAM,OAENC,cAAQ,OAERC,YAAM,OAENn0E,MAAgB,EAACxgB,KAEjB40F,cAAQ,OAERC,iBAAW,OAEXC,eAAS,OAETC,MAAmB,IAAItC,GAAWzyF,KAClCg1F,MAAgB,EAACh1F,KACjBQ,UAAI,OAEJy0F,aAAuB,EAAKj1F,KAE5B+I,MAAuB,KAAI/I,KAE3Bk1F,YAA+B,KAAIl1F,KAEnCm1F,aAAO,OAEPC,SAAG,EAIRp1F,KAAKsM,KAAOA,CACd,CAEI+oF,kBACF,MAAQjB,aAAcp0F,KACtB,IAAKo0F,IAAcp0F,KAAK+zF,aACtB,OAAO,KAGT,IAAK/zF,KAAK+zF,cAAgB/zF,KAAKo0F,YAAcp0F,KAAKo0F,UAAUkB,KAAM,CAChE,MAAMjuF,EAAMrH,KAAKo0F,UAAU5jD,SAC3B,GAAInpC,EACFrH,KAAK+zF,aAAe1sF,EAAIkuF,eAAev1F,KAAKm0F,QACvC,CACL,MAAMqB,EAAa5sD,OAAOkP,KAAK93C,KAAKo0F,WACpC,GAA0B,IAAtBoB,EAAWlzF,OACb,OAAQtC,KAAK+zF,aAAe/zF,KAAKo0F,UAC/BoB,EAAW,IACXD,eAAev1F,KAAKm0F,GAAE,EAO9B,OAAOn0F,KAAK+zF,YACd,CAEI5Y,UACF,OAAOn7E,KAAKwgB,MAAQxgB,KAAK0I,QAC3B,CAEI+sF,yBAKF,GAJ6B,OAAzBz1F,KAAKi0F,kBAIJjC,EAAgBhyF,KAAKi0F,iBACxB,OAAO,KAGT,MAAMvrF,EAAY0pF,EAAgBpyF,KAAK0I,UAAgB1I,KAAK0I,SAAT,EAEnD,OAAO1I,KAAKi0F,gBAA6B,IAAXvrF,CAChC,CAEIgtF,gBAAY,MAId,GAAIC,OAAJA,EAAI31F,KAAK+zF,eAAL4B,EAAmBD,UACrB,OAAO,EACF,GAAI11F,KAAKo0F,UAAW,CACzB,MAAMoB,EAAa5sD,OAAOkP,KAAK93C,KAAKo0F,WAC9B5uC,EAAMgwC,EAAWlzF,OACvB,GAAIkjD,EAAM,GAAc,IAARA,GAAaxlD,KAAKo0F,UAAUoB,EAAW,IAAIE,UACzD,OAAO,EAIX,OAAO,CACT,CAEAE,aAAaC,GACX,GAAI71F,KAAKo0F,UAAW,CAClB,MAAM/sF,EAAMrH,KAAKo0F,UAAUyB,GACvBxuF,IAAQrH,KAAK+zF,eACf/zF,KAAK+zF,aAAe1sF,EAAIkuF,eAAev1F,KAAKm0F,IAAE,CAGpD,CAEA2B,gBAAsB,QACT,OAAXC,OAAK1B,SAAL0B,EAAaC,QACC,OAAdC,OAAK3B,YAAL2B,EAAgBD,OAClB,CAEAE,wBACE5pF,EACAkoF,EACAC,EACAC,EACAC,EACAwB,GAAmB,GAEnB,MAAQ7C,qBAAsBtzF,KACxB0zB,EAAO4/D,EAAkBhnF,GAC1BonB,GAWLA,EAAK8gE,SAAWn9E,KAAK++E,IAAI1iE,EAAK8gE,SAAUA,GACxC9gE,EAAK+gE,OAASp9E,KAAK+/C,IAAI1jC,EAAK+gE,OAAQA,GACpC/gE,EAAKghE,SAAWr9E,KAAK++E,IAAI1iE,EAAKghE,SAAUA,GACxChhE,EAAKihE,OAASt9E,KAAK+/C,IAAI1jC,EAAKihE,OAAQA,IAblCrB,EAAkBhnF,GAAQ,CACxBkoF,WACAC,SACAC,WACAC,SACAwB,UASN,CAEAE,4BACE,MAAQ/C,qBAAsBtzF,KAC9BszF,EAAkBN,GAAsBO,OAAS,KACjDD,EAAkBN,GAAsBQ,OAAS,KACjDF,EAAkBN,GAAsBS,YAAc,IACxD,EAMK,MAAM6C,WAAarD,GAUxBpzF,YACE02F,EACAC,EACAtD,EACAh3D,EACAlU,GAEAktB,MAAMg+C,GAASlzF,KAhBDy2F,WAAqB,EAACz2F,KACtB0I,SAAmB,EAAC1I,KACpBo1F,KAAe,EAAKp1F,KACpB02F,aAAuB,EAAK12F,KAC5BqzF,YAAM,OACN94C,cAAQ,OACRre,WAAK,OACd64D,MAAmB,IAAItC,GAU5BzyF,KAAK0I,SAAW6tF,EAAUxF,qBAAqB,YAC/C/wF,KAAKo1F,IAAMmB,EAAUrF,KAAK,OAC1BlxF,KAAK02F,YAAcH,EAAUrF,KAAK,eAClClxF,KAAKqzF,OAASkD,EAAUtF,iBAAiB,OACzCjxF,KAAKu6C,SAAWi8C,EAChBx2F,KAAKk8B,MAAQA,EACb,MAAMy3D,EAAY4C,EAAUtF,iBAAiB,aACzC0C,GACF3zF,KAAK0zF,aAAaC,EAAW3rE,GAE3BA,IACFhoB,KAAKy2F,WAAazuE,EAASyuE,WAAazuE,EAAStf,SAErD,CAEI8X,YACF,OAAOxgB,KAAKu6C,SAAS/5B,MAAQxgB,KAAKy2F,UACpC,CAEItb,UACF,OAAOn7E,KAAKwgB,MAAQxgB,KAAK0I,QAC3B,CAEIzH,aACF,MAAQqyF,qBAAsBtzF,KAC9B,SACEszF,EAAkBqD,OAClBrD,EAAkBsD,OAClBtD,EAAkBuD,WAEtB,EClTK,MAAMC,GA+CXj3F,YAAYkqB,GAAS/pB,KA9Cd+2F,UAAoB,EAAK/2F,KACzBg3F,gBAA0B,EAAKh3F,KAC/Bi3F,2BAAqB,OACrBC,MAAgB,EAACl3F,KACjBm3F,MAAgB,EAACn3F,KACjBo3F,eAAS,OACTC,kBAAY,OACZC,SAA0B,KAAIt3F,KAC9Bu3F,gBAAU,OACVC,MAAgB,EAAIx3F,KACpBy3F,UAAoB,EAACz3F,KACrB03F,sBAAgB,OAChBC,SAAmB,EAAI33F,KACvB43F,UAAoB,EAAI53F,KACxB63F,uBAAiB,OACjBC,OAAiB,EAAC93F,KAClB+3F,QAAkB,EAAC/3F,KACnBg4F,QAAkB,EAACh4F,KACnBi4F,gBAAiC,KAAIj4F,KACrCk4F,eAAyB,EAACl4F,KAC1Bm4F,cAAwB,EAACn4F,KACzBsM,KAAsB,KAAItM,KAC1B0B,SAAG,OACH02F,KAAe,GAAEp4F,KACjBq4F,QAAyB,KAAIr4F,KAC7Bs4F,gBAA0B,EAAKt4F,KAC/Bu4F,aAAuB,EAACv4F,KACxBw4F,mBAA6B,EAAKx4F,KAClCy4F,gBAA0B,EAACz4F,KAC3B04F,+BAAyB,OACzBC,aAAuB,EAAC34F,KACxB44F,SAAmB,EAAC54F,KACpB64F,WAAqB,EAAC74F,KACtB84F,iBAAW,OACXC,sBAAgB,OAChBC,WAAqB,EAACh5F,KACtBi5F,uBAAiB,OACjBC,eAAyB,EAACl5F,KAC1Bm5F,aAAuB,EAACn5F,KACxBo5F,WAAqB,EAACp5F,KACtBq5F,SAAmB,EAACr5F,KACpBs5F,wBAAkB,OAClBC,qBAAqC,KAAIv5F,KACzCw5F,aAAmC,KAAIx5F,KACvCy5F,iBAAkB,EAGvBz5F,KAAKo3F,UAAY,GACjBp3F,KAAKs5F,mBAAqB,GAC1Bt5F,KAAKu3F,WAAa,GAClBv3F,KAAK0B,IAAMqoB,CACb,CAEA2vE,SAAS1xE,GACP,IAAKA,EAGH,OAFAhoB,KAAK43F,UAAW,OAChB53F,KAAK23F,SAAU,GAGjB,MAAMgC,EAAa35F,KAAK45F,WAAa5xE,EAAS4xE,WACxCC,EAAgB75F,KAAK85F,cAAgB9xE,EAAS8xE,cACpD95F,KAAK23F,QACH33F,KAAKm3F,QAAUnvE,EAASmvE,SAAW0C,KAAmBF,EACxD35F,KAAK43F,SACH53F,KAAKm3F,MAAQnvE,EAASmvE,OACtBwC,EAAa,GACG,IAAfA,GAAoBE,EAAgB,EAErC75F,KAAK83F,OADH93F,KAAK23F,SAAW33F,KAAK43F,SACTvgF,KAAKC,MAAwB,GAAlB0Q,EAAS8vE,QAEpB9vE,EAAS8vE,OAAS,EAElC93F,KAAK63F,kBAAoB7vE,EAAS6vE,iBACpC,CAEIkC,yBACF,QAAI/5F,KAAKo3F,UAAU90F,QACV0vF,EACLhyF,KAAKo3F,UAAUp3F,KAAKo3F,UAAU90F,OAAS,GAAG2xF,gBAIhD,CAEI+F,0BACF,OACEh6F,KAAKi3F,uBACLj3F,KAAKk4F,gBA7FqB,EAgG9B,CAEI+B,YACF,MAAMC,EAAUl6F,KAAKm5F,aAAen5F,KAAKk5F,eACzC,OAAIgB,EAAU,EAEU,KADFl6F,KAAKq5F,SAAWr5F,KAAKo5F,YACXc,EAEzB,CACT,CAEIC,WACF,OAAOn6F,KAAKo6F,SAAWp6F,KAAKq6F,WAC9B,CAEID,cAAkB,MACpB,OAAIE,OAAJA,EAAIt6F,KAAKs3F,WAALgD,EAAeh4F,OACVtC,KAAKs3F,SAASt3F,KAAKs3F,SAASh1F,OAAS,GAAG64E,IAE1Cn7E,KAAKq6F,WACd,CAEIA,kBAAsB,MACxB,OAAIE,OAAJA,EAAIv6F,KAAKo3F,YAALmD,EAAgBj4F,OACXtC,KAAKo3F,UAAUp3F,KAAKo3F,UAAU90F,OAAS,GAAG64E,IAE5C,CACT,CAEIqf,UACF,OAAIx6F,KAAK03F,iBACArgF,KAAK+/C,IAAIv8C,KAAKwU,MAAQrvB,KAAK03F,iBAAkB,GAAK,IAEpD,CACT,CAEIoC,oBAAwB,MAC1B,OAAIW,OAAJA,EAAIz6F,KAAKs3F,WAALmD,EAAen4F,OACVtC,KAAKs3F,SAASt3F,KAAKs3F,SAASh1F,OAAS,GAAG45B,OAE1C,CACT,CAEI09D,iBAAqB,MACvB,OAAIc,OAAJA,EAAI16F,KAAKs3F,WAALoD,EAAep4F,OACVtC,KAAKs3F,SAASt3F,KAAKs3F,SAASh1F,OAAS,GAAGi4C,SAAS45C,GAEnDn0F,KAAKm3F,KACd,EC/HK,SAASwD,GAAaC,GAC3B,OAAO/J,WAAW5sC,KAAK42C,KAAKD,GAAoBtrE,GAAMA,EAAEwrE,WAAW,GACrE,CCkBO,SAASC,GAAexiD,GAC7B,OAAOs4C,WAAW5sC,KAAK+2C,SAASlkD,mBAAmByB,IAAQjpB,GACzDA,EAAEwrE,WAAW,GAEjB,CC1CA,IAAkBG,GAAU,wHAQVC,GAAgB,oKAO3B,SAASC,GACdC,GAEA,OAAQA,GACN,KAAKF,GAAiBG,SACpB,OAAOJ,GAAWI,SACpB,KAAKH,GAAiBI,UACpB,OAAOL,GAAWK,UACpB,KAAKJ,GAAiBK,SACpB,OAAON,GAAWM,SACpB,KAAKL,GAAiBM,SACpB,OAAOP,GAAWO,SAExB,CAGA,IAAkBC,YAAYF,mCAoBvB,SAASG,GACdC,GAEA,OAAQA,GACN,KAAKV,GAAWI,SACd,OAAOH,GAAiBG,SAC1B,KAAKJ,GAAWK,UACd,OAAOJ,GAAiBI,UAC1B,KAAKL,GAAWM,SACd,OAAOL,GAAiBK,SAC1B,KAAKN,GAAWO,SACd,OAAON,GAAiBM,SAE9B,CAEO,SAASI,GACdlsD,GAEA,MAAQmsD,aAAYC,sBAAuBpsD,EACrCqsD,EAAoCF,EACtC,CACEZ,GAAWI,SACXJ,GAAWM,SACXN,GAAWK,UACXL,GAAWO,UACXhvF,OAAQmvF,KAAgBE,EAAWF,IACrC,GACJ,OAAKI,EAAoBd,GAAWM,WAAaO,GAC/CC,EAAoB3zF,KAAK6yF,GAAWM,UAE/BQ,CACT,CAOO,MAAMC,UAEFC,KAAS,KAChBA,KAAKt2D,WACLs2D,KAAKt2D,UAAUq2D,4BAERC,KAAKt2D,UAAUq2D,4BAA4BE,KAAKD,KAAKt2D,WAErD,KCtGJ,SAASw2D,GACdtlD,EACAr2B,EACA26D,GAIA,OAAO0V,WAAWvrD,UAAUnuB,MACxB0/B,EAAM1/B,MAAMqJ,EAAO26D,GACnB,IAAI0V,WAAW55E,MAAMquB,UAAUnuB,MAAM2xB,KAAK+N,EAAOr2B,EAAO26D,GAC9D,CCCO,MAAMihB,GAAWA,CAAC57F,EAAkB2qD,IAcrCA,EAAS,IAAM3qD,EAAK8B,QAGH,KAAjB9B,EAAK2qD,IACgB,KAArB3qD,EAAK2qD,EAAS,IACO,KAArB3qD,EAAK2qD,EAAS,IAGV3qD,EAAK2qD,EAAS,GAAK,KAAQ3qD,EAAK2qD,EAAS,GAAK,KAG9C3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,IAgBhBkxC,GAAWA,CAAC77F,EAAkB2qD,IAIrCA,EAAS,IAAM3qD,EAAK8B,QAGH,KAAjB9B,EAAK2qD,IACgB,KAArB3qD,EAAK2qD,EAAS,IACO,KAArB3qD,EAAK2qD,EAAS,IAGV3qD,EAAK2qD,EAAS,GAAK,KAAQ3qD,EAAK2qD,EAAS,GAAK,KAG9C3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,KACnB3qD,EAAK2qD,EAAS,GAAK,IAkBhBmxC,GAAaA,CACxB97F,EACA2qD,KAEA,MAAMoxC,EAAQpxC,EACd,IAAI7oD,EAAS,EAEb,KAAO85F,GAAS57F,EAAM2qD,IAEpB7oD,GAAU,GAGVA,GADak6F,GAASh8F,EAAM2qD,EAAS,GAGjCkxC,GAAS77F,EAAM2qD,EAAS,MAE1B7oD,GAAU,IAGZ6oD,GAAU7oD,EAGZ,GAAIA,EAAS,EACX,OAAO9B,EAAKi8F,SAASF,EAAOA,EAAQj6F,EAAM,EAMxCk6F,GAAWA,CAACh8F,EAAkB2qD,KAClC,IAAIsL,EAAO,EACXA,UAAuB,IAAfj2D,EAAK2qD,KAAmB,GAChCsL,IAA4B,IAAnBj2D,EAAK2qD,EAAS,KAAc,GACrCsL,IAA4B,IAAnBj2D,EAAK2qD,EAAS,KAAc,EACrCsL,GAA2B,IAAnBj2D,EAAK2qD,EAAS,GACfsL,GAGIimC,GAAWA,CAACl8F,EAAkB2qD,IAEvCixC,GAAS57F,EAAM2qD,IACfqxC,GAASh8F,EAAM2qD,EAAS,GAAK,IAAM3qD,EAAK8B,OAAS6oD,EAyBxCwxC,GAAoB34C,GAE7BA,GACc,SAAdA,EAAM38C,KACS,iDAAf28C,EAAMtwB,KAIJkpE,GAAgBp8F,IAMpB,MAAM8L,EAAemuC,OAAOC,aAAal6C,EAAK,GAAIA,EAAK,GAAIA,EAAK,GAAIA,EAAK,IACnEi2D,EAAe+lC,GAASh8F,EAAM,GAKpC,MAAO,CAAE8L,OAAMmqD,OAAMj2D,KAAMA,EAAKi8F,SAFjB,MAE2ChmC,KAO/ComC,GAAgBC,IAC3B,IAAI3xC,EAAS,EACb,MAAMjH,EAAkB,GAExB,KAAOk4C,GAASU,EAAS3xC,IAAS,CAChC,MAAMsL,EAAO+lC,GAASM,EAAS3xC,EAAS,GAExCA,GAAU,GACV,MAAMgwB,EAAMhwB,EAASsL,EAErB,KAAOtL,EAAS,EAAIgwB,GAAK,CACvB,MAAM4hB,EAAsBH,GAAaE,EAAQL,SAAStxC,IACpDnH,EAA2Bg5C,GAAYD,GACzC/4C,GACFE,EAAO97C,KAAK47C,GAIdmH,GAAU4xC,EAAUtmC,KAAO,GAGzB4lC,GAASS,EAAS3xC,KACpBA,GAAU,IAId,OAAOjH,GAGI84C,GAAeh5C,GACP,SAAfA,EAAM13C,KACD2wF,GAAgBj5C,GACI,MAAlBA,EAAM13C,KAAK,GACb4wF,GAAel5C,GAGjBm5C,GAAgBn5C,GAGnBi5C,GACJj5C,IAKA,GAAIA,EAAMyS,KAAO,EACf,OAGF,MAAM2mC,EAAQC,GAAer5C,EAAMxjD,MAAM,GACnC88F,EAAc,IAAIzM,WAAW7sC,EAAMxjD,KAAKi8F,SAASW,EAAM96F,OAAS,IAEtE,MAAO,CAAE+E,IAAK28C,EAAM13C,KAAMonB,KAAM0pE,EAAO58F,KAAM88F,EAAYC,SAGrDJ,GAAmBn5C,IACvB,GAAIA,EAAMyS,KAAO,EACf,OAGF,GAAmB,SAAfzS,EAAM13C,KAAiB,CAMzB,IAAI4vB,EAAQ,EACZ,MAAMrzB,EAAcw0F,GAAer5C,EAAMxjD,KAAKi8F,SAASvgE,IAAQ,GAE/DA,GAASrzB,EAAYvG,OAAS,EAC9B,MAAMmK,EAAQ4wF,GAAer5C,EAAMxjD,KAAKi8F,SAASvgE,IAEjD,MAAO,CAAE70B,IAAK28C,EAAM13C,KAAMonB,KAAM7qB,EAAarI,KAAMiM,GAOrD,MAAM1K,EAAOs7F,GAAer5C,EAAMxjD,KAAKi8F,SAAS,IAChD,MAAO,CAAEp1F,IAAK28C,EAAM13C,KAAM9L,KAAMuB,IAG5Bm7F,GAAkBl5C,IACtB,GAAmB,SAAfA,EAAM13C,KAAiB,CAMzB,GAAI03C,EAAMyS,KAAO,EACf,OAGF,IAAIv6B,EAAQ,EACZ,MAAMrzB,EAAsBw0F,GAC1Br5C,EAAMxjD,KAAKi8F,SAASvgE,IACpB,GAGFA,GAASrzB,EAAYvG,OAAS,EAC9B,MAAMmK,EAAgB4wF,GAAer5C,EAAMxjD,KAAKi8F,SAASvgE,IAEzD,MAAO,CAAE70B,IAAK28C,EAAM13C,KAAMonB,KAAM7qB,EAAarI,KAAMiM,GAMrD,MAAM/K,EAAc27F,GAAer5C,EAAMxjD,MACzC,MAAO,CAAE6G,IAAK28C,EAAM13C,KAAM9L,KAAMkB,IAG5B87F,GACJC,IAEA,GAAuC,IAAnCA,EAAej9F,KAAKk9F,WAAkB,CACxC,MAAMl9F,EAAO,IAAIqwF,WAAW4M,EAAej9F,MAI3C,IAAIm9F,GACDn9F,EAAK,IAAM,KAAOA,EAAK,IAAM,KAAOA,EAAK,IAAM,GAAKA,EAAK,GAC5Dm9F,UAAa,GAHc,EAAVn9F,EAAK,KAMpBm9F,GAAa,aAGRtmF,KAAKkR,MAAMo1E,EAAS,GAelBN,GAAiBA,CAC5BxmD,EACA+mD,GAAsB,KAEtB,MAAMC,EAkER,SAASC,KACP,OAAKD,WAAkB5B,KAAK8B,YAAgB,MAC1CF,GAAU,IAAI5B,KAAK8B,YAAY,UAG1BF,EACT,CAxEkBC,GAChB,GAAID,EAAS,CACX,MAAMG,EAAUH,EAAQI,OAAOpnD,GAE/B,GAAI+mD,EAAY,CAEd,MAAMM,EAAMF,EAAQj4D,QAAQ,MAC5B,OAAe,IAARm4D,EAAaF,EAAQplE,UAAU,EAAGslE,GAAOF,EAIlD,OAAOA,EAAQh8F,QAAQ,MAAO,GAAE,CAGlC,MAAMwjD,EAAM3O,EAAMv0C,OAClB,IAAIgtB,EACA6uE,EACAC,EACAC,EAAM,GACN71D,EAAI,EACR,KAAOA,EAAIgd,GAAK,CAEd,GADAl2B,EAAIunB,EAAMrO,KACA,IAANlZ,GAAcsuE,EAChB,OAAOS,EACF,GAAU,IAAN/uE,GAAoB,IAANA,EAIzB,OAAQA,GAAK,GACX,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EAEH+uE,GAAO5jD,OAAOC,aAAaprB,GAC3B,MACF,KAAK,GACL,KAAK,GAEH6uE,EAAQtnD,EAAMrO,KACd61D,GAAO5jD,OAAOC,cAAmB,GAAJprB,IAAa,EAAc,GAAR6uE,GAChD,MACF,KAAK,GAEHA,EAAQtnD,EAAMrO,KACd41D,EAAQvnD,EAAMrO,KACd61D,GAAO5jD,OAAOC,cACN,GAAJprB,IAAa,IAAgB,GAAR6uE,IAAiB,GAAe,GAARC,IAAiB,GAElE,CAIN,OAAOC,GAOT,IAAIR,GCxYJ,MAAMS,WACK,SAAUznD,GACjB,IAAI0B,EAAM,GACV,QAAS/P,EAAI,EAAGA,EAAIqO,EAAMv0C,OAAQkmC,IAAK,CACrC,IAAI+1D,EAAI1nD,EAAMrO,GAAGluB,SAAS,IACtBikF,EAAEj8F,OAAS,IACbi8F,EAAI,IAAMA,GAGZhmD,GAAOgmD,EAET,OAAOhmD,CACT,ECRIimD,GAAannF,KAAK6qD,IAAI,EAAG,IAAM,EAC/B95D,GAAO,GAAGA,KAUHq2F,GAAuB,CAClC7H,MAAO,EACPD,MAAO,EACP+H,IAAK,EACL38F,KAAM,GAGD,SAAS48F,GAAQn+F,GACtB,OAAOi6C,OAAOC,aAAakkD,MAAM,KAAMp+F,EACzC,CAEO,SAASq+F,GAAWtB,EAAoBpyC,GAC7C,MAAM3T,EAAO+lD,EAAOpyC,IAAW,EAAKoyC,EAAOpyC,EAAS,GACpD,OAAO3T,EAAM,EAAI,MAAQA,EAAMA,CACjC,CAEO,SAASsnD,GAAWvB,EAAoBpyC,GAC7C,MAAM3T,EAAMunD,GAAWxB,EAAQpyC,GAC/B,OAAO3T,EAAM,EAAI,WAAaA,EAAMA,CACtC,CAEO,SAASunD,GAAWxB,EAAoBpyC,GAC7C,OACGoyC,EAAOpyC,IAAW,GAClBoyC,EAAOpyC,EAAS,IAAM,GACtBoyC,EAAOpyC,EAAS,IAAM,EACvBoyC,EAAOpyC,EAAS,EAEpB,CAEO,SAAS6zC,GAAYzB,EAAoBpyC,EAAgB1+C,GAC9D8wF,EAAOpyC,GAAU1+C,GAAS,GAC1B8wF,EAAOpyC,EAAS,GAAM1+C,GAAS,GAAM,IACrC8wF,EAAOpyC,EAAS,GAAM1+C,GAAS,EAAK,IACpC8wF,EAAOpyC,EAAS,GAAa,IAAR1+C,CACvB,CAGO,SAASwyF,GAAQz+F,EAAkBkX,GACxC,MAAMgnB,EAAU,GAChB,IAAKhnB,EAAKpV,OAER,OAAOo8B,EAET,MAAMy8C,EAAM36E,EAAKk9F,WAEjB,QAASl1D,EAAI,EAAGA,EAAI2yC,GAAO,CACzB,MAAM1kB,EAAOqoC,GAAWt+F,EAAMgoC,GAExB02D,EAASzoC,EAAO,EAAIjuB,EAAIiuB,EAAO0kB,EAErC,GAHawjB,GAAQn+F,EAAKi8F,SAASj0D,EAAI,EAAGA,EAAI,MAGjC9wB,EAAK,GAChB,GAAoB,IAAhBA,EAAKpV,OAGPo8B,EAAQt2B,KAAK5H,EAAKi8F,SAASj0D,EAAI,EAAG02D,QAC7B,CAEL,MAAMC,EAAaF,GAAQz+F,EAAKi8F,SAASj0D,EAAI,EAAG02D,GAASxnF,EAAKP,MAAM,IAChEgoF,EAAW78F,QACb8F,GAAKw2F,MAAMlgE,EAASygE,EAAU,CAIpC32D,EAAI02D,EAIN,OAAOxgE,CACT,CAUO,SAAS0gE,GAAkBC,GAChC,MAAMC,EAAoB,GAEpBjH,EAAUgH,EAAK,GAGrB,IAAInjE,EAAQ,EAEZ,MAAMqjE,EAAYT,GAAWO,EAAMnjE,GACnCA,GAAS,EAQPA,GADc,IAAZm8D,EACO,EAEA,GAIXn8D,GAAS,EAET,IAAIsjE,EAAYH,EAAK/8F,OAXD,EAapB,MAAMm9F,EAAkBZ,GAAWQ,EAAMnjE,GACzCA,GAAS,EAET,QAASsM,EAAI,EAAGA,EAAIi3D,EAAiBj3D,IAAK,CACxC,IAAIk3D,EAAiBxjE,EAErB,MAAMyjE,EAAgBb,GAAWO,EAAMK,GACvCA,GAAkB,EAElB,MAAME,GAAgC,WAAhBD,EAGtB,IAFuC,WAAhBA,KAAgC,IAEjC,EACpB5P,UAAOhtC,KAAK,oDACL,KAGT,MAAM88C,GAAqBf,GAAWO,EAAMK,GAC5CA,GAAkB,EAElBJ,EAAWl3F,KAAK,CACdw3F,iBACAC,sBACAnsE,KAAM,CACJhrB,SAAUm3F,GAAqBN,EAC/B/+E,MAAOg/E,EACPrkB,IAAKqkB,EAAYI,GAAgB,KAIrCJ,GAAaI,GAIbF,GAAkB,EAGlBxjE,EAAQwjE,EAGV,MAAO,CACLI,yBAvD+B,EAwD/BP,YACAlH,UACAoH,kBACAH,aAEJ,CA8CO,SAASS,GAAiB7K,GAC/B,MAAMhtF,EAAmB,GACnB83F,EAAQf,GAAQ/J,EAAa,CAAC,OAAQ,SAC5C,QAAS1sD,EAAI,EAAGA,EAAIw3D,EAAM19F,OAAQkmC,IAAK,CACrC,MAAMy3D,EAAOD,EAAMx3D,GACb03D,EAAOjB,GAAQgB,EAAM,CAAC,SAAS,GACrC,GAAIC,EAAM,CACR,IAAI7H,EAAU6H,EAAK,GACfhkE,EAAoB,IAAZm8D,EAAgB,GAAK,GACjC,MAAM8H,EAAUrB,GAAWoB,EAAMhkE,GAC3BkkE,EAAOnB,GAAQgB,EAAM,CAAC,OAAQ,SAAS,GAC7C,GAAIG,EAAM,CACR/H,EAAU+H,EAAK,GACflkE,EAAoB,IAAZm8D,EAAgB,GAAK,GAC7B,MAAMkH,EAAYT,GAAWsB,EAAMlkE,GAC7BmkE,GAAOpB,GAAQgB,EAAM,CAAC,OAAQ,SAAS,GAC7C,GAAII,GAAM,CACR,MAAMC,GAAW3B,GAAQ0B,GAAK5D,SAAS,EAAG,KACpCnwF,GAA6B,CACjCi0F,KAAMvN,GAAsBO,MAC5BiN,KAAMxN,GAAsBQ,OAC5B8M,IACF,GAAIh0F,GAAM,CAER,MAAMm0F,GAAOxB,GAAQgB,EAAM,CAAC,OAAQ,OAAQ,OAAQ,SAAS,GAC7D,IAAIS,GACAD,KACFC,GAAQ/B,GAAQ8B,GAAKhE,SAAS,GAAI,MAQpCv0F,EAAOi4F,GAAW,CAAEZ,YAAWjzF,SAC/BpE,EAAOoE,IAAQ,CAAEizF,YAAWj3F,GAAI63F,EAASO,cAQnDC,OADa1B,GAAQ/J,EAAa,CAAC,OAAQ,OAAQ,SAC9C3rF,QAASo3F,IACZ,MAAMR,EAAUrB,GAAW6B,EAAM,GAC3BC,EAAQ14F,EAAOi4F,GACjBS,IACFA,EAAM5xF,QAAU,CACdtG,SAAUo2F,GAAW6B,EAAM,IAC3BtkB,MAAOyiB,GAAW6B,EAAM,QAKvBz4F,CACT,CAiDO,SAAS24F,GAAUC,GACxB,MAAMC,EAAO9B,GAAQ6B,EAAM,CAAC,SAAS,GACrC,GAAIC,EAAM,CACR,MAAMxY,EAASoW,GAAQoC,EAAKtE,SAAS,EAAG,IACxC,GAAe,SAAXlU,GAAgC,SAAXA,EACvB,OAAO0W,GAAQ6B,EAAM,CAAC,OAAQ,SAAS,EAAC,CAG5C/Q,UAAOlvE,MAAO,4BACP,IACT,CAmLO,SAASmgF,GAA8BC,GAC5C,MAAM5kB,EAAQyiB,GAAWmC,EAAM,GAG/B,IAAI91C,EAAS,EAED,EAARkxB,IACFlxB,GAAU,GAGA,EAARkxB,IACFlxB,GAAU,GAGZ,IAAIziD,EAAW,EACf,MAAMw4F,EAAcpC,GAAWmC,EAAM,GACrC,QAASz4D,EAAI,EAAGA,EAAI04D,EAAa14D,IAEnB,IAAR6zC,IAEF3zE,GADuBo2F,GAAWmC,EAAM91C,GAExCA,GAAU,GAGA,IAARkxB,IACFlxB,GAAU,GAGA,KAARkxB,IACFlxB,GAAU,GAGA,KAARkxB,IACFlxB,GAAU,GAGd,OAAOziD,CACT,CAmEO,SAASy4F,GACdC,EACAC,GAEA,MAAMC,EAAO,IAAIzQ,WAAWuQ,EAAM9+F,OAAS++F,EAAM/+F,QACjDg/F,SAAKz1C,IAAIu1C,GACTE,EAAKz1C,IAAIw1C,EAAOD,EAAM9+F,QAEfg/F,CACT,CAaO,SAASC,GACdC,EACAZ,GAEA,MAAMa,EAAa,GACbC,EAAYd,EAAMe,QAClBpC,EAAYqB,EAAMrB,UAClBY,EAAUS,EAAMt4F,GACtB,IAAIs5F,GAAe,EAGnBC,OADc5C,GAAQyC,EAAW,CAAC,SAC5B/1F,IAAKm2F,IACT,MAAMC,EAAaD,EAAKE,WAAa,EACvB/C,GAAQ6C,EAAM,CAAC,SACvBn2F,IAAKs2F,IAET,MAAMC,GAAWjD,GAAQgD,EAAM,CAAC,SAASt2F,IAAKw2F,KAC5C,MAAM9J,GAAU8J,GAAK,GACrB,IAAIj6F,GAAS42F,GAAWqD,GAAM,GAC9B,OAAgB,IAAZ9J,KACFnwF,IAAUmP,KAAK6qD,IAAI,EAAG,IACtBh6D,IAAU42F,GAAWqD,GAAM,IAEtBj6F,GAASq3F,IACf,GAEH,YAAiB99F,IAAbygG,KACFV,EAAaU,IAGRjD,GAAQgD,EAAM,CAAC,SAASt2F,IAAKy2F,KAClC,MAAM95F,GAAKw2F,GAAWsD,GAAM,GACtBC,GAAkC,SAAtBvD,GAAWsD,GAAM,GAInC,IAAIE,GAAwB,EAC5B,MAAMC,GAAsD,IAAd,GAAZF,IAClC,IAAIG,GAAoB,EACxB,MAAMC,GAAuD,IAAd,GAAZJ,IACnC,IAAIK,GAAa,EAEbp6F,KAAO63F,IAT8C,IAAd,EAAZkC,MAW3BK,IAAc,GAV+C,IAAd,EAAZL,MAanCK,IAAc,GAZ8C,IAAd,EAAZL,MAelCC,GAAwBxD,GAAWsD,GAAMM,IACzCA,IAAc,GAEZH,KACFC,GAAoB1D,GAAWsD,GAAMM,IACrCA,IAAc,GAEZD,KACFC,IAAc,GAEG,UAAf9B,EAAMt0F,OACRs1F,EAqFZ,SAASe,GAAOjC,GACd,IAAKA,EACH,OAAO,EAET,MAAMkC,EAAUlC,EAAM36D,QAAQ,KACxB88D,EAAYD,EAAU,EAAIlC,EAAQA,EAAM9nE,UAAU,EAAGgqE,GAC3D,MACgB,SAAdC,GACc,SAAdA,GAEc,SAAdA,GACc,SAAdA,CAEJ,CAlG2BF,CAAO/B,EAAMF,QAG9BzB,GAAQgD,EAAM,CAAC,SAASt2F,IAAKs1F,KAC3B,MAAM5I,GAAU4I,GAAK,GACf5kB,GAA8B,SAAtByiB,GAAWmC,GAAM,GACzB6B,GAA2C,IAAd,EAARzmB,IAC3B,IAAI0mB,GAAa,EACjB,MAAMC,GAAiD,IAAd,EAAR3mB,IAC3B4mB,GAA+C,IAAd,IAAR5mB,IAC/B,IAAI6mB,GAAiB,EACrB,MAAMC,GAA2C,IAAd,IAAR9mB,IAC3B,IAAI+mB,GAAa,EACjB,MAAMC,GAA4C,IAAd,KAARhnB,IACtBinB,GAAyD,IAAd,KAARjnB,IACzC,IAAIknB,GAAoB,EACxB,MAAMrC,GAAcpC,GAAWmC,GAAM,GACrC,IAAIuC,GAAa,EAEbV,KACFC,GAAajE,GAAWmC,GAAMuC,IAC9BA,IAAc,GAEZR,KACFQ,IAAc,GAGhB,IAAIC,GAAeV,GAAahB,EAEhC,QAAS2B,GAAK,EAAGA,GAAKxC,GAAawC,KAAM,CAwBvC,GAvBIT,IACFC,GAAiBpE,GAAWmC,GAAMuC,IAClCA,IAAc,GAEdN,GAAiBZ,GAEfa,IACFC,GAAatE,GAAWmC,GAAMuC,IAC9BA,IAAc,GAEdJ,GAAaZ,GAEXa,KACFG,IAAc,GAEZF,KAEAC,GADc,IAAZlL,GACkByG,GAAWmC,GAAMuC,IAEjBzE,GAAWkC,GAAMuC,IAEvCA,IAAc,GAEZ5C,EAAMt0F,OAAS0mF,GAAsBQ,MAAO,CAC9C,IAAImQ,GAAgB,EACpB,KAAOA,GAAgBP,IAAY,CACjC,MAAMQ,GAAW9E,GAAW4C,EAAW+B,IACvCA,IAAgB,EACZI,GAAajC,EAAcF,EAAU+B,MAKvCK,GAJapC,EAAUjF,SACrBgH,GACAA,GAAeG,IAIfhC,EAAe,EAAI,EACnBJ,EAAa+B,GAAoBhE,EACjCkC,GAGJgC,IAAgBG,GAChBD,IAAiBC,GAAW,GAIhCpC,GAAc0B,GAAiB3D,KAElC,EAEJ,EACF,GAEIkC,CACT,CAiBA,SAASoC,GAAajC,EAAuBmC,GAC3C,GAAInC,EAAc,CAChB,MAAMoC,EAAYD,GAAc,EAAK,GACrC,OAAoB,KAAbC,GAAgC,KAAbA,CAAa,CAGvC,OAAoB,IADU,GAAbD,EAGrB,CAEO,SAASD,GACdG,EACAC,EACAC,EACAxC,GAEA,MAAMnhG,EAAO4jG,GAAWH,GACxB,IAAII,EAAS,EAEbA,GAAUH,EACV,IAAII,EAAc,EACdC,EAAc,EACdC,GAAgB,EAChBn2F,EAAI,EAER,KAAOg2F,EAAS7jG,EAAK8B,QAAQ,CAC3BgiG,EAAc,EACd,EAAG,CACD,GAAID,GAAU7jG,EAAK8B,OACjB,MAEF+L,EAAI7N,EAAK6jG,KACTC,GAAej2F,QACF,MAANA,GAGTk2F,EAAc,EACd,EAAG,CACD,GAAIF,GAAU7jG,EAAK8B,OACjB,MAEF+L,EAAI7N,EAAK6jG,KACTE,GAAel2F,QACF,MAANA,GAET,MAAMo2F,EAAWjkG,EAAK8B,OAAS+hG,EAE/B,IAAKG,GAAiC,IAAhBF,GAAqBD,EAAS7jG,EAAK8B,QAIvD,GAHAkiG,GAAgB,EAGI,MADAhkG,EAAK6jG,KACA,CACvB,MAAMK,GAAe7F,GAAWr+F,EAAM6jG,GAGtC,GAFAA,GAAU,EAEW,KAAjBK,GAAqB,CACvB,MAAMC,GAAgB7F,GAAWt+F,EAAM6jG,GAGvC,GAFAA,GAAU,EAEY,aAAlBM,GAA8B,CAChC,MAAMC,GAAepkG,EAAK6jG,KAG1B,GAAqB,IAAjBO,GAAoB,CACtB,MAAMC,GAAYrkG,EAAK6jG,KAEjBrjG,GAAU,GAAO6jG,GACjBC,GAAa9jG,GAAU,EAAe,GAF3B,GAAO6jG,IAEwB,EAC1CE,GAAY,IAAIlU,WAAWiU,IACjC,GAAI9jG,GAAS,CACX+jG,GAAU,GAAKF,GACf,QAASr8D,GAAI,EAAGA,GAAIs8D,GAAYt8D,KAC9Bu8D,GAAUv8D,IAAKhoC,EAAK6jG,IAAQ,CAIhC1C,EAAQv5F,KAAK,CACXkE,KAAMs4F,GACNN,cACAH,MACAa,MAAOD,IACR,aAKgB,IAAhBT,GAAqBC,EAAcE,GAG5C,GAFAD,GAAgB,EAEZD,EAAc,GAAI,CACpB,MAAMU,EAA8B,GACpC,QAASz8D,GAAI,EAAGA,GAAI,GAAIA,KAAK,CAC3B,MAAMn6B,GAAI7N,EAAK6jG,KAAU/pF,SAAS,IAClC2qF,EAAa78F,KAAiB,GAAZiG,GAAE/L,OAAc,IAAM+L,GAAIA,KAElC,IAANm6B,IAAiB,IAANA,IAAiB,IAANA,IAAiB,IAANA,KACnCy8D,EAAa78F,KAAK,IAAG,CAGzB,MAAM9F,GAASiiG,EAAc,GACvBW,GAAgB,IAAIrU,WAAWvuF,IACrC,QAASkmC,GAAI,EAAGA,GAAIlmC,GAAQkmC,KAC1B08D,GAAc18D,IAAKhoC,EAAK6jG,KAG1B1C,EAAQv5F,KAAK,CACXk8F,cACAH,MACAgB,KAAMF,EAAa/tF,KAAK,IACxBkuF,SAAU/H,GAAe6H,IACzBA,kBACD,UAEMX,EAAcE,EACvBJ,GAAUE,UACDA,EAAcE,EACvB,MAGN,CAKO,SAASL,GAAW5jG,GACzB,MAAM8B,EAAS9B,EAAKk9F,WACd2H,EAAe,GACrB,IAAI78D,EAAI,EAGR,KAAOA,EAAIlmC,EAAS,GACF,IAAZ9B,EAAKgoC,IAA4B,IAAhBhoC,EAAKgoC,EAAI,IAA4B,IAAhBhoC,EAAKgoC,EAAI,IACjD68D,EAAaj9F,KAAKogC,EAAI,GACtBA,GAAK,GAELA,IAMJ,GAA4B,IAAxB68D,EAAa/iG,OACf,OAAO9B,EAIT,MAAM8kG,EAAYhjG,EAAS+iG,EAAa/iG,OAClCijG,EAAU,IAAI1U,WAAWyU,GAC/B,IAAIE,EAAc,EAElB,IAAKh9D,EAAI,EAAGA,EAAI88D,EAAWE,IAAeh9D,IACpCg9D,IAAgBH,EAAa,KAE/BG,IAEAH,EAAaI,SAEfF,EAAQ/8D,GAAKhoC,EAAKglG,GAEpB,OAAOD,CACT,CCt7BA,IAAIG,GAAkD,GAe/C,MAAMC,GAYX9iG,+BACE6iG,GAAmB,EACrB,CAEA7lG,YACE+lG,EACAC,EACAzK,EACA0K,EAA2B,CAAC,GAC5BC,EAAwB,MACxB/lG,KArBc6lG,SAAG,OACHD,YAAM,OACN/P,eAAS,OACTmQ,uBAAiB,OACjBtQ,eAAS,OACTuQ,wBAAkB,OAC3BF,GAAwB,KAAI/lG,KAC5BqH,IAAyB,KAAIrH,KAC7BkmG,MAA2B,KAAIlmG,KAC/BmmG,KAA0B,KAa/BnmG,KAAK4lG,OAASA,EACd5lG,KAAK6lG,IAAMA,EACX7lG,KAAK61F,UAAYuF,EACjBp7F,KAAKgmG,kBAAoBF,EACzB9lG,KAAK+lG,GAAKA,EACV/lG,KAAK01F,YAAYkQ,GAAoB,SAAXA,EAC1B5lG,KAAKimG,mBAAqBjmG,KAAK01F,WAAwB,YAAXkQ,CAC9C,CAEOQ,cAEL,GAAIpmG,KAAK4lG,OAAQ,CACf,GAAoB,YAAhB5lG,KAAK4lG,QAAwC,SAAhB5lG,KAAK4lG,OACpC,OAAO,EAET,GAAuB,aAAnB5lG,KAAK61F,UAEP,MAAuB,eAAhB71F,KAAK4lG,OAEZ,OAAQ5lG,KAAK61F,WACX,KAAKqF,GAAiBG,SACtB,KAAKH,GAAiBK,SACtB,KAAKL,GAAiBI,UACtB,KAAKJ,GAAiBM,SACpB,OAM6B,IAL3B,CACE,cACA,aACA,kBACA,kBACAz1D,QAAQ/lC,KAAK4lG,QAAc,CAKvC,OAAO,CACT,CAEOrQ,eAAepB,GACpB,IAAKn0F,KAAK01F,YAAc11F,KAAK6lG,IAC3B,OAAO,KAGT,GAAoB,YAAhB7lG,KAAK4lG,QAAwB5lG,KAAK6lG,MAAQ7lG,KAAK+lG,GAAI,CACnC,iBAAP5R,IAIW,YAAhBn0F,KAAK4lG,SAAyB5lG,KAAK+lG,IACrChW,GAAOhtC,KACJ,sDAAqD/iD,KAAK4lG,8BAI/DzR,EAAK,GAEP,MAAM4R,EAoGZ,SAASM,GAA2BC,GAClC,MAAMC,EAAY,IAAI1V,WAAW,IACjC,QAASroD,EAAI,GAAIA,EAAI,GAAIA,IACvB+9D,EAAU/9D,GAAM89D,GAAkB,GAAK,GAAK99D,GAAO,IAErD,OAAO+9D,CACT,CA1GiBF,CAA2BlS,GAQtC,OAPoB,IAAIwR,GACtB3lG,KAAK4lG,OACL5lG,KAAK6lG,IACL,WACA7lG,KAAKgmG,kBACLD,EACF,CASF,MAAMS,ENjGH,SAASC,GAA2BZ,GAEzC,MAAMa,EAAab,EAAI92F,MAAM,KAC7B,IAAI43F,EAA6B,KACjC,GAAsB,SAAlBD,EAAW,IAAuC,IAAtBA,EAAWpkG,OAAc,CACvD,MAAMskG,EAAiBF,EAAW,GAAG33F,MAAM,KACrC83F,EAAaD,EAAeA,EAAetkG,OAAS,GAAGyM,MAAM,KACnE,GAA0B,IAAtB83F,EAAWvkG,OAAc,CAC3B,MACM9B,EAAOqmG,EAAW,GADW,WAAlBA,EAAW,IAG1BD,EAAev2C,QAAO,EAAI,GAC1Bs2C,EAAUhM,GAAan6F,IAEvBmmG,EAlCR,SAASG,GAAcvuD,GACrB,MAAMwuD,EAAahM,GAAexiD,GAAKkkD,SAAS,EAAG,IAC7CuK,EAAmB,IAAInW,WAAW,IACxCmW,SAAiBn7C,IAAIk7C,EAAY,GAAKA,EAAWzkG,QAC1C0kG,CACT,CA6BkBF,CAActmG,EAAI,EAIlC,OAAOmmG,CACT,CM8EqBF,CAA2BzmG,KAAK6lG,KACjD,GAAIW,EACF,OAAQxmG,KAAK61F,WACX,KAAKqF,GAAiBK,SACpBv7F,KAAKmmG,KAAOK,EAERA,EAASlkG,QAAU,KACrBtC,KAAKkmG,MAAQM,EAAS/J,SACpB+J,EAASlkG,OAAS,GAClBkkG,EAASlkG,OAAS,IAGtB,MACF,KAAK44F,GAAiBI,UAAW,CAC/B,MAAM2L,EAAyB,IAAIpW,WAAW,CAC5C,IAAM,EAAM,IAAM,IAAM,IAAM,GAAM,GAAM,IAAM,IAAM,IAAM,IAC5D,GAAM,IAAM,IAAM,GAAM,MAG1B7wF,KAAKmmG,KD+5BR,SAASe,GACdC,EACAC,EACA5mG,GAEA,GAA4B,KAAxB2mG,EAASzJ,WACX,MAAM,IAAI2J,WAAW,qBAEvB,IAAIhP,EACAiP,EAeAC,EAdJ,GAAIH,EAAQ,CACV/O,EAAU,EACViP,EAAO,IAAIzW,WAA2B,GAAhBuW,EAAO9kG,QAC7B,QAASohG,EAAK,EAAGA,EAAK0D,EAAO9kG,OAAQohG,IAAM,CACzC,MAAMte,EAAIgiB,EAAO1D,GACjB,GAAqB,KAAjBte,EAAEsY,WACJ,MAAM,IAAI2J,WAAW,eAEvBC,EAAKz7C,IAAIu5B,EAAQ,GAALse,EAAO,OAGrBrL,EAAU,EACViP,EAAO,IAAIzW,WAGTwH,EAAU,GACZkP,EAAW,IAAI1W,WAAW,GACtBuW,EAAQ9kG,OAAS,GACnB,IAAIklG,SAASD,EAAShK,QAAQkK,UAAU,EAAGL,EAAQ9kG,QAAQ,IAG7DilG,EAAW,IAAI1W,WAEjB,MAAM6W,EAAW,IAAI7W,WAAW,GAChC,OAAIrwF,GAAQA,EAAKk9F,WAAa,GAC5B,IAAI8J,SAASE,EAASnK,QAAQkK,UAAU,EAAGjnG,EAAKk9F,YAAY,GAvDzD,SAASiK,GAAOr7F,KAA4Bs7F,GACjD,MAAMpiD,EAAMoiD,EAAQtlG,OACpB,IAAIm0D,EAAO,EACPjuB,EAAIgd,EACR,KAAOhd,KACLiuB,GAAQmxC,EAAQp/D,GAAGk1D,WAErB,MAAMx1F,EAAS,IAAI2oF,WAAWp6B,GAM9B,IALAvuD,EAAO,GAAMuuD,GAAQ,GAAM,IAC3BvuD,EAAO,GAAMuuD,GAAQ,GAAM,IAC3BvuD,EAAO,GAAMuuD,GAAQ,EAAK,IAC1BvuD,EAAO,GAAY,IAAPuuD,EACZvuD,EAAO2jD,IAAIv/C,EAAM,GACZk8B,EAAI,EAAGiuB,EAAO,EAAGjuB,EAAIgd,EAAKhd,IAC7BtgC,EAAO2jD,IAAI+7C,EAAQp/D,GAAIiuB,GACvBA,GAAQmxC,EAAQp/D,GAAGk1D,WAErB,OAAOx1F,CACT,CAuCSy/F,CACL,CAAC,IAAK,IAAK,IAAK,KAChB,IAAI9W,WAAW,CACbwH,EACA,EACA,EACA,IAEF8O,EACAI,EACAD,EACAI,EACAlnG,GAAQ,IAAIqwF,WAEhB,CCl9BsBqW,CAAQD,EAAwB,KAAMT,GAElD,MAAMqB,EAAgB,IAAIC,YACxBtB,EAASjJ,OACTiJ,EAASxE,WACTwE,EAAS9I,WAAa,GAElBqK,EAAattD,OAAOC,aAAakkD,MACrC,KACA3nF,MAAMgtC,KAAK4jD,IAIPG,EAAcD,EAAWnvE,UAC7BmvE,EAAWhiE,QAAQ,KACnBgiE,EAAWzlG,QAIP2lG,GAFS,IAAInvE,WACGC,gBAAgBivE,EAAa,YAC5B3lG,qBAAqB,OAAO,GACnD,GAAI4lG,EAAS,CACX,MAAM/B,EAAQ+B,EAAQxiD,WAAW,GAC7BwiD,EAAQxiD,WAAW,GAAGtC,UACtB8kD,EAAQ1lB,aAAa,SACzB,GAAI2jB,EAAO,CACT,MAAMgC,EAAavN,GAAauL,GAAOzJ,SAAS,EAAG,KN1J1D,SAAS0L,GAAiBjC,GAC/B,MAAMkC,EAAO,SAAUvxD,EAAmBoN,EAAcokD,GACtD,MAAMC,EAAMzxD,EAAMoN,GAClBpN,EAAMoN,GAAQpN,EAAMwxD,GACpBxxD,EAAMwxD,GAAMC,GAGdF,EAAKlC,EAAO,EAAG,GACfkC,EAAKlC,EAAO,EAAG,GACfkC,EAAKlC,EAAO,EAAG,GACfkC,EAAKlC,EAAO,EAAG,EACjB,EMkJciC,CAAiBD,GACjBloG,KAAKkmG,MAAQgC,GAGjB,KACF,CACA,QAAS,CACP,IAAIvB,EAAUH,EAAS/J,SAAS,EAAG,IACnC,GAAuB,KAAnBkK,EAAQrkG,OAAe,CACzB,MAAMimG,EAAS,IAAI1X,WAAW,IAC9B0X,EAAO18C,IAAI86C,EAAS,GAAKA,EAAQrkG,QACjCqkG,EAAU4B,EAEZvoG,KAAKkmG,MAAQS,EACb,KACF,EAKJ,IAAK3mG,KAAKkmG,OAAmC,KAA1BlmG,KAAKkmG,MAAMxI,WAAmB,CAC/C,IAAIwI,EAAQR,GAAiB1lG,KAAK6lG,KAClC,IAAKK,EAAO,CACV,MAAM1uD,EACJ5O,OAAOkP,KAAK4tD,IAAkBpjG,OAASw7C,OAAO4yC,iBAChDwV,EAAQ,IAAIrV,WAAW,IACZ,IAAI2W,SAAStB,EAAM3I,OAAQ,GAAI,GACvCkK,UAAU,EAAGjwD,GAChBkuD,GAAiB1lG,KAAK6lG,KAAOK,EAE/BlmG,KAAKkmG,MAAQA,EAGf,OAAOlmG,IACT,ECnMF,MAAMwoG,GAA6B,0BAE5B,SAASC,GAAsBlwD,GACpC,OAAOiwD,GAA2BnwD,KAAKE,EACzC,CAEO,SAASmwD,GACdC,EAIAtY,EACAuY,GAEA,GAA4B,OAAxBD,EAAOnP,cAAyBmP,EAAOlP,gBACzC,QAASjxD,EAAIogE,EAAetmG,OAAQkmC,KAAO,CACzC,MAAMzuB,EAAO6uF,EAAepgE,GACtB/7B,EAAQ4jF,EAAKt2E,GACftN,IACF4jF,EAAKt2E,GAAQ8uF,GAAoBF,EAAQl8F,GAAK,CAItD,CAEO,SAASo8F,GACdF,EAIAl8F,GAEA,GAA4B,OAAxBk8F,EAAOnP,cAAyBmP,EAAOlP,gBAAiB,CAC1D,MAAMD,EAAemP,EAAOnP,aAC5B,OAAO/sF,EAAMzK,QACXwmG,GACCM,IACC,MAAMC,EAAeD,EAAkBlwE,UACrC,EACAkwE,EAAkBxmG,OAAS,GAEvB0mG,EAAgBxP,IAAeuP,GACrC,YAAsBtnG,IAAlBunG,GACFL,EAAOpP,uBAAPoP,EAAOpP,qBAAyB,IAAIpR,MAC6B4gB,sEAE1DD,GAEFE,GAEX,CAEF,OAAOv8F,CACT,CAEO,SAASw8F,GACdN,EAIAtY,EACA6Y,GAEA,IAIIC,EACAC,EALA5P,EAAemP,EAAOnP,aAM1B,GALKA,IACHmP,EAAOnP,aAAeA,EAAe,IAInC,eAAgBnJ,EAAM,CACxB8Y,EAAO9Y,EAAKgZ,WACZ,IACE,MAAMC,EAAe,IAAIrN,KAAKsN,IAAIL,GAAWI,aAC7C,IAAIA,EAAah4C,IAAI63C,GAGnB,MAAM,IAAIhhB,MACP,IAAGghB,kDAAqDD,MAH3DE,EAAQE,EAAa74E,IAAI04E,EAU7B,OAJStoF,GACP8nF,EAAOpP,uBAAPoP,EAAOpP,qBAAyB,IAAIpR,MACNtnE,8BAAM2oF,WAEtC,OAEAL,EAAO9Y,EAAK8Y,KACZC,EAAQ/Y,EAAK+Y,MAEXD,KAAQ3P,EACVmP,EAAOpP,uBAAPoP,EAAOpP,qBAAyB,IAAIpR,MACqBghB,8DAGzD3P,EAAa2P,GAAQC,GAAS,EAElC,CAEO,SAASK,GACdd,EAIAtY,EACAqZ,GAEA,MAAMC,EAAStZ,EAAKsZ,OACpB,GAAID,GAAsBC,KAAUD,EAAoB,CACtD,IAAIlQ,EAAemP,EAAOnP,aACrBA,IACHmP,EAAOnP,aAAeA,EAAe,IAEvCA,EAAamQ,GAAUD,EAAmBC,EAAM,MAEhDhB,EAAOpP,uBAAPoP,EAAOpP,qBAAyB,IAAIpR,MACoCwhB,4EAG5E,CCvHO,SAASC,KACd,YAAW3N,KAAS,KACpB,OAAOA,KAAK4N,aAAiB5N,KAAa6N,iBAC5C,CCJA,MAAMC,GAAsB,CAC1BpT,MAAO,CACLqT,MAAM,EACN,QAAQ,EACR,QAAQ,EACRC,MAAM,EACNC,MAAM,EACNC,MAAM,EACN,QAAQ,EACR,QAAQ,EACRC,MAAM,EACNC,MAAM,EACNC,MAAM,EACN,QAAQ,EACRC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACN,QAAQ,EACRC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,GAER9U,MAAO,CACL+U,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACNC,MAAM,EACN,QAAQ,EACRC,MAAM,EACNC,MAAM,GAERtrG,KAAM,CACJurG,MAAM,EACNC,MAAM,IAIJ1D,GAAcD,KASb,SAAS4D,GAAsB9M,EAAep0F,GAA0B,MAC7E,OAC0E,OAD1EmhG,EACE5D,IAAa6D,gBAAiB,GAAEphG,GAAQ,uBAAuBo0F,QAAS+M,CAG5E,CC5CA,MAAME,GACJ,qJACIC,GAA8B,qBAE9BC,GAAoB,mCAEpBC,GAA4B,IAAI3nE,OACpC,CACE,0CAA0CxgB,OAC1C,oBAAoBA,OACpB,yBAAyBA,OACzB,gCAAgCA,OAChC,MAAMA,QACNzO,KAAK,KACP,KAGI62F,GAA4B,IAAI5nE,OACpC,CACE,YAAYxgB,OACZ,6HACGA,OACH,wFACGA,OACH,qCAAqCA,OACrC,kBAAkBA,OAClB,sBAAsBA,QACtBzO,KAAK,MAGM,MAAM82F,GACnBnrG,iBACEorG,EACAC,GAEA,QAAS1lE,EAAI,EAAGA,EAAIylE,EAAO3rG,OAAQkmC,IAAK,CACtC,MAAM/G,EAAQwsE,EAAOzlE,GACrB,GAAI/G,EAAMn5B,KAAO4lG,EACf,OAAOzsE,EAGb,CAEA5+B,2BAA2B69F,GAEzB,MAAMyN,EAAUzN,EAAM3xF,MAAM,KAC5B,GAAIo/F,EAAQ7rG,OAAS,EAAG,CACtB,IAAI4F,EAASimG,EAAQ1I,QAAU,IAC/Bv9F,UAAU+f,SAASkmF,EAAQ1I,SAASnrF,SAAS,IAC7CpS,IAAW,MAAQ+f,SAASkmF,EAAQ1I,SAASnrF,SAAS,KAAKnD,OAAM,GAC1DjP,EAET,OAAOw4F,CACT,CAEA79F,eAAenB,EAAKqoB,GAClB,OAAO69D,oBAAiB79D,EAASroB,EAAK,CAAEsmF,iBAAiB,GAC3D,CAEAnlF,uBAAuB01C,GACrB,OAAOs1D,GAAkBx1D,KAAKE,EAChC,CAEA11C,2BACEurG,EACAlb,GAEA,MAGMyV,EAAqC,CACzC0F,gBAAiB,KACjBvkG,OAAQ,GACRyvF,qBAAsB,KACtB+U,YAAa,KACbC,YAAa,KACbtW,gBAAiB,KACjBuB,aAAc,KACdC,gBAVEgP,GAAsB2F,IAYpBI,EAAuC,GAI7C,IAAItmG,EACJ,IAHAylG,GAAsB97C,UAAY,EAGsB,OAAhD3pD,EAASylG,GAAsBx3D,KAAKi4D,KAC1C,GAAIlmG,EAAO,GAAI,OAEb,MAAMioF,EAAQ,IAAID,GAAShoF,EAAO,IAEhCwgG,GAAgCC,EAAQxY,EAAO,CAC7C,SACA,sBACA,cACA,aACA,oBACA,QACA,QACA,YACA,kBACA,SAGJ,MAAM0V,EACFgD,GAAoBF,EAAQzgG,EAAO,IAEjC01C,EAAqB,CACzBuyC,QACAse,QACEte,EAAMI,eAAe,sBACrBJ,EAAMI,eAAe,aACvBx2E,KAAMo2E,EAAMgZ,KACZznG,IAAKssG,GAAWpsD,QAAQikD,EAAK3S,IAGzBwb,GAAave,EAAMgB,kBAAkB,cACvCud,KACF9wD,EAAMjlC,MAAQ+1F,GAAW/1F,MACzBilC,EAAMnlC,OAASi2F,GAAWj2F,QAG5Bk2F,IACIxe,EAAMye,QAAqB,IAAI7/F,MAAM,SAASvC,OAAQ8iB,IAAMA,IAC9DsuB,GAGEA,EAAMixD,aAAmD,IAArCjxD,EAAMixD,WAAW9oE,QAAQ,UAC/C6X,EAAMixD,WAAab,GAAWc,oBAAoBlxD,EAAMixD,aAGrDE,OAADA,EAACnxD,EAAMoxD,gBAAND,EAAqBzsG,QACxBksG,EAAsBpmG,KAAKw1C,GAG7B+qD,EAAO7+F,OAAO1B,KAAKw1C,EAAK,SACf11C,EAAO,GAAI,CACpB,MACM+mG,EAAa/mG,EAAO,GAC1B,OAFYA,EAAO,IAGjB,IAAK,eAAgB,CAEnB,MAAMgnG,EAAe,IAAIhf,GAAS+e,GAEhCvG,GAAgCC,EAAQuG,EAAc,CACpD,UACA,WACA,QACA,QAGJ,MAAMC,GAASD,EAAa,WACxBC,KACyB,OAAvBxG,EAAO2F,cACT3F,EAAO2F,YAAc,IAEvB3F,EAAO2F,YAAYa,IAAUD,GAE/B,KACF,CACA,IAAK,cAAe,CAElB,MAAME,EAAaC,GAASJ,EAAY/b,EAASyV,GAC7CyG,EAAW1Z,WAAa0Z,EAAWhJ,eACV,OAAvBuC,EAAO4F,cACT5F,EAAO4F,YAAc,IAEvB5F,EAAO4F,YAAYnmG,KAAKgnG,IAExBrf,GAAOhtC,KAC8CksD,yDAGvD,KACF,CACA,IAAK,SAEgC,CACjC,MAAMK,EAAqB,IAAIpf,GAAS+e,GACxCvG,GAAgCC,EAAQ2G,EAAoB,CAC1D,OACA,QACA,eAEFrG,GAAsBN,EAAQ2G,EAAoBpc,EACpD,CACA,MAEF,IAAK,mBAAoB,CAEvB,MAAMqc,EAA4B,IAAIrf,GAAS+e,GAE7CvG,GACEC,EACA4G,EACA,CAAC,aAAc,eAGnB5G,EAAO0F,gBAAkB,CACvBxI,IAAKmI,GAAWpsD,QACd2tD,EAA0B,cAC1Brc,GAEFsc,UAAWD,EAA0B,eAAiB,KAExD,KACF,CACA,IAAK,QAEH5G,EAAO1Q,gBAAkBwX,GAAqBR,GAEhD,CAWNtG,SAAO7+F,OAHL0kG,EAAsBlsG,OAAS,GAC/BksG,EAAsBlsG,OAASqmG,EAAO7+F,OAAOxH,OAG3CksG,EACA7F,EAAO7+F,OACkB,IAAzB6+F,EAAO7+F,OAAOxH,SAChBqmG,EAAOpP,qBAAuB,IAAIpR,MAAM,gCAGnCwgB,CACT,CAEA9lG,gCACEurG,EACAlb,EACAyV,GAEA,IAAIzgG,EACJ,MAAMw2B,EAA0C,GAC1C50B,EAAS6+F,EAAO7+F,OAChB4lG,EAAe,CACnBnc,MAAOzpF,EAAO6B,IAAKiyC,KACjBt1C,GAAIs1C,EAAMuyC,MAAMoD,MAChBoc,WAAY/xD,EAAM+xD,cAEpBC,UAAW9lG,EAAO6B,IAAKiyC,KACrBt1C,GAAIs1C,EAAMuyC,MAAMyf,UAChBC,UAAWjyD,EAAMiyD,aAEnB,kBAAmB,IAErB,IAAIvnG,EAAK,EAET,IADAslG,GAA4B/7C,UAAY,EACuB,QAAvD3pD,EAAS0lG,GAA4Bz3D,KAAKi4D,KAAmB,CACnE,MAAMje,EAAQ,IAAID,GAAShoF,EAAO,IAC5BoE,EAAsC6jF,EAAM2f,KAGlD,GAAIxjG,EAAM,CACR,MAAM2hG,EAASyB,EAAapjG,GACtBkK,GAA0BkoB,EAAQpyB,IAAS,GACjDoyB,EAAQpyB,GAAQkK,GAEdkyF,GAAgCC,EAAQxY,EAAO,CAC7C,MACA,WACA,WACA,iBACA,sBACA,OACA,cACA,kBACA,aAGJ,MAAMx5E,GAAuB,CAC3Bw5E,QACAse,QAAS,EACTnmG,GAAIA,IACJynG,QAAS5f,EAAM,aAAe,GAC9B6f,WAAY7f,EAAM,eAClBp2E,KAAMo2E,EAAMgZ,MAAQhZ,EAAM8f,UAAY,GACtC3jG,OACA0C,QAASmhF,EAAMe,KAAK,WACpBgf,WAAY/f,EAAMe,KAAK,cACvBif,OAAQhgB,EAAMe,KAAK,UACnBniD,KAAMohD,EAAM8f,SACZvuG,IAAKyuF,EAAMigB,IAAMpC,GAAWpsD,QAAQuuC,EAAMigB,IAAKld,GAAW,IAG5D,GAAU,MAAN+a,KAAQ3rG,OAAQ,CAIlB,MAAM+tG,GACJrC,GAAWsC,UAAUrC,EAAQt3F,GAAMo5F,UAAsB9B,EAAO,GAClEsC,GAAY55F,GAAO05F,GAAY,cAC/BE,GAAY55F,GAAO05F,GAAY,YAAW,CAG5C75F,GAAOpO,KAAKuO,GAAK,EAGrB,OAAO+nB,CACT,CAEA77B,0BACEurG,EACAlb,EACA5qF,EACAgE,EACAkkG,EACAC,GAEA,MAAM7yD,EAAQ,IAAIk5C,GAAa5D,GACzBkE,EAAiCx5C,EAAMw5C,UAE7C,IAOIlvF,GACAsgC,GACA4rD,GATAsc,EAAsC,KACtCC,EAAY,EACZC,EAAc,EACdzY,GAAgB,EAChB0Y,GAAuB,EACvBC,GAA4B,KAC5Bta,GAAiB,IAAI1C,GAASxnF,EAAM4mF,GAIpC6d,IAAgB,EAChBC,IAAiB,EAQrB,IANAlD,GAA0Bj8C,UAAY,EACtCjU,EAAMw6C,KAAOgW,EACbxwD,EAAM67C,gBACFgP,GAAsB2F,GAGmC,QAArDlmG,GAAS4lG,GAA0B33D,KAAKi4D,KAAmB,CAC7D4C,KACFA,IAAiB,EACjBxa,GAAO,IAAI1C,GAASxnF,EAAM4mF,GAE1BsD,GAAKh2E,MAAQ23E,GACb3B,GAAKrC,GAAKwc,EACVna,GAAKjC,GAAKsc,GACVra,GAAK54C,MAAQt1C,EACTooG,IACFla,GAAKtB,YAAcwb,EACnBla,GAAKxC,mBAAqB0c,EAAmB1c,mBAC7C0c,EAAmB1c,mBAAqB,OAI5C,MAAMtrF,GAAWR,GAAO,GACxB,GAAIQ,GAAU,CAEZ8tF,GAAK9tF,SAAWiwC,WAAWjwC,IAE3B,MAAMK,IAAS,IAAMb,GAAO,IAAIiP,MAAM,GACtCq/E,GAAKztF,MAAQA,IAAS,KACtBytF,GAAKtC,QAAQ9rF,KAAKW,GAAQ,CAAC,MAAOL,GAAUK,IAAS,CAAC,MAAOL,IAAS,SAC7DR,GAAO,IAEhB,GAAI8pF,EAAgBwE,GAAK9tF,UAAW,CAClC8tF,GAAKh2E,MAAQ23E,GACT/D,IACF6c,GAAiBza,GAAMpC,GAAWx2C,GAEpC44C,GAAKrC,GAAKwc,EACVna,GAAK54C,MAAQt1C,EACbkuF,GAAKjC,GAAKsc,GACVra,GAAKxB,MAAQwb,EACbpZ,EAAUhvF,KAAKouF,IAEf,MAAMqP,IAAO,IAAM39F,GAAO,IAAIiP,MAAM,GACpCq/E,GAAKnD,OACDwV,GAAoBjrD,EAAOioD,IAE/BqL,GAAsB1a,GAAMsa,IAC5BA,GAAWta,GACX2B,IAAiB3B,GAAK9tF,SACtBioG,IACAC,EAAc,EACdI,IAAiB,WAEV9oG,GAAO,GAAI,CAEpB,MAAM1H,IAAQ,IAAM0H,GAAO,IAAIiP,MAAM,GACjC25F,GACFta,GAAK9C,aAAalzF,GAAMswG,IAExBta,GAAK9C,aAAalzF,GAAI,SAEf0H,GAAO,GAGhBsuF,GAAKxC,oBAAsB,IAAM9rF,GAAO,IAAIiP,MAAM,GAClDq/E,GAAKtC,QAAQ9rF,KAAK,CAAC,oBAAqBouF,GAAKxC,sBACvB,IAAlB+c,KACFA,GAAgB3Z,EAAU90F,YAEvB,CAEL,GADA4F,GAASA,GAAO,GAAGg+B,MAAM6nE,KACpB7lG,GAAQ,CACX6nF,GAAOhtC,KAAK,sDACZ,SAEF,IAAKva,GAAI,EAAGA,GAAItgC,GAAO5F,iBACV4F,GAAOsgC,IAAO,KADIA,MAO/B,MAAMjd,IAAO,IAAMrjB,GAAOsgC,KAAIrxB,MAAM,GAC9Bg6F,IAAU,IAAMjpG,GAAOsgC,GAAI,IAAIrxB,MAAM,GACrCi6F,GAASlpG,GAAOsgC,GAAI,IAAM,IAAMtgC,GAAOsgC,GAAI,IAAIrxB,MAAM,GAAK,GAEhE,OAAQoU,IACN,IAAK,gBACHqyB,EAAMtxC,KAAO6kG,GAAO5iD,cACpB,MACF,IAAK,iBACHoiD,EAAY/yD,EAAMo6C,QAAU/vE,SAASkpF,IACrC,MACF,IAAK,OAAQ,CACX,MAAME,GAAY,IAAInhB,GAASihB,IAE7BzI,GAAgC9qD,EAAOyzD,GAAW,CAChD,gCAGJ,MAAM5Y,GACJ4Y,GAAU9gB,eAAe,oBAC3B,GAAI6B,EAAgBqG,IAAkB,CACpC76C,EAAM66C,gBAAkBA,GAExB,QAASjwD,GAAIiwD,GAAiBjwD,MAC5B4uD,EAAUzpB,QAAQ,MAEpBgjC,GAAalY,GAEf,MAAMC,GAA4B2Y,GAAUpgB,iBAC1C,+BAEEyH,KACF96C,EAAM86C,0BACJA,GAA0B3pF,MAAM,OAEpC,KACF,CACA,IAAK,iBACH6uC,EAAMs6C,eAAiB7gF,KAAK+/C,IAAInvC,SAASkpF,IAAS,GAClD,MACF,IAAK,UACHvzD,EAAMy6C,QAAUpwE,SAASkpF,IACzB,MACF,IAAK,SACH,MACF,IAAK,UACHvzD,EAAM45C,MAAO,EACb,MACF,IAAK,KACC2Z,IAAUC,KACZ5a,GAAKtC,QAAQ9rF,KAAKgpG,GAAS,CAACD,GAAQC,IAAU,CAACD,KAEjD,MACF,IAAK,gBACHN,KACAra,GAAKtC,QAAQ9rF,KAAK,CAAC,QACnB,MACF,IAAK,MACHouF,GAAKpB,KAAM,EACXoB,GAAKtC,QAAQ9rF,KAAK,CAACmjB,KACnB,MACF,IAAK,UACHirE,GAAKtC,QAAQ9rF,KAAK,CAACmjB,GAAK4lF,KACxB,MACF,IAAK,YAAa,CAChB,MAAM5f,GAAgB,IAAIrB,GAASihB,IAEjCzI,GAAgC9qD,EAAO2zC,GAAe,CACpD,KACA,QACA,aACA,WACA,aACA,aACA,cAEFmX,GACE9qD,EACA2zC,GACAA,GAAcjB,aAGlB,MAAMghB,GAAY,IAAIhgB,GACpBC,GACA3zC,EAAM25C,WAAWhG,GAAcM,KAE7Byf,GAAU/e,SAAW30C,EAAM66C,gBAC7B76C,EAAM25C,WAAW+Z,GAAUhpG,IAAMgpG,GAEjCvhB,GAAOhtC,KAAyCouD,2CAGlD3a,GAAKtC,QAAQ9rF,KAAK,CAAC,kBAAmB+oG,KACtC,KACF,CACA,IAAK,SACgC,CACjC,MAAM7B,GAAqB,IAAIpf,GAASihB,IACxCzI,GAAgC9qD,EAAO0xD,GAAoB,CACzD,OACA,QACA,SACA,eAEE,WAAYA,GACd7F,GACE7rD,EACA0xD,GACAmB,GAGFxH,GAAsBrrD,EAAO0xD,GAAoBpc,EAErD,CACA,MAGF,IAAK,yBACH2d,GAAuB5oF,SAASkpF,IAChC,MACF,IAAK,MAAO,CACV,MAAMI,GAAWlC,GAAS8B,GAAQje,EAASt1C,GAC3C,GAAI2zD,GAASnL,cAAe,CAC1B,GAAwB,SAApBmL,GAAS3L,OAAmB,CAC9BxR,QAAY3yF,EACZ,MAEG2yF,KACHA,GAAY,IAEVA,GAAUmd,GAAS1b,aACrBzB,GAAYtC,GAAc,GAAIsC,KAEhCA,GAAUmd,GAAS1b,WAAa0b,QAEhCxhB,GAAOhtC,KAAgDouD,kDAEzD,KACF,CACA,IAAK,QACHvzD,EAAMq6C,gBAAkBwX,GAAqB0B,IAC7C,MACF,IAAK,MAAO,CACV,MAAMK,GAAW,IAAIthB,GAASihB,IAO9B,GALEzI,GAAgC9qD,EAAO4zD,GAAU,CAC/C,YACA,QAGAhb,GAAK9tF,SAAU,CAIjB,MAAMw+D,GAAO,IAAI4sB,GAASxnF,EAAM4mF,GAChCue,GAAevqC,GAAMsqC,GAAUlpG,EAAI8rF,IACnCsc,EAAqBxpC,GACrBsvB,GAAKtB,YAAcwb,EAEjBA,EAAmB1c,qBAClBwC,GAAKxC,qBAENwC,GAAKxC,mBAAqB0c,EAAmB1c,yBAI/Cyd,GAAejb,GAAMgb,GAAUlpG,EAAI8rF,IACnCsc,EAAqBla,GACrBwa,IAAiB,EAEnB,KACF,CACA,IAAK,iBAAkB,CACrB,MAAMU,GAAqB,IAAIxhB,GAASihB,IACxCvzD,EAAM06C,eAAiBoZ,GAAmBxgB,KAAK,oBAC/CtzC,EAAM26C,aAAemZ,GAAmB1gB,cACtC,iBACA,GAEFpzC,EAAM46C,kBACJ56C,EAAM26C,aAAe,GACrBmZ,GAAmBxgB,KAAK,uBAC1BtzC,EAAM+6C,aAAe+Y,GAAmB1gB,cACtC,iBACA,GAEFpzC,EAAMg7C,SAAW8Y,GAAmB1gB,cAAc,YAAa,GAC/D,KACF,CACA,IAAK,WAAY,CACf,MAAM2gB,GAAe,IAAIzhB,GAASihB,IAClCvzD,EAAMi7C,WAAa8Y,GAAa5gB,qBAAqB,eACrD,KACF,CACA,IAAK,OAAQ,CACX,IAAIuG,GAAW15C,EAAM05C,SAChBA,KACHA,GAAW15C,EAAM05C,SAAW,IAE9B,MAAMsa,GACJhB,EAAc,EAAItZ,GAASA,GAASh1F,OAAS,QAAKb,EAC9Cy6B,GAAQ00E,IACRra,GAAY,IAAIrG,GAASihB,IAE7BzI,GAAgC9qD,EAAO24C,GAAW,CAChD,YACA,QAGJ,MAAMsb,GAAO,IAAIvb,GACfC,GACAC,GACAtD,EACAh3D,GACA01E,IAEFta,GAASlvF,KAAKypG,IACdrb,GAAK9tF,UAAYmpG,GAAKnpG,SACtB,KACF,CACA,IAAK,eAAgB,CACnB,MAAMopG,GAAmB,IAAI5hB,GAASihB,IAEpCzI,GAAgC9qD,EAAOk0D,GAAkB,CAAC,QAE5Dl0D,EAAMk7C,YAAcgZ,GACpB,KACF,CACA,IAAK,mBAAoB,CACvB,MAAMC,GAAuB,IAAI7hB,GAASihB,IAExCzI,GAAgC9qD,EAAOm0D,GAAsB,CAC3D,QAGJn0D,EAAMm7C,iBAAmBn7C,EAAMm7C,kBAAoB,GACnDn7C,EAAMm7C,iBAAiB3wF,KAAK2pG,IAC5B,KACF,CACA,QACEhiB,GAAOhtC,KAAqC76C,sCAC5C,EAIJ4oG,KAAaA,GAASzd,QACxB+D,EAAU4a,MACV7Z,IAAiB2Y,GAASpoG,SACtBk1C,EAAM05C,WACR15C,EAAMy5C,aAAeyZ,KAEdlzD,EAAM05C,WACf4Z,GAAsB1a,GAAMsa,IAC5Bta,GAAKjC,GAAKsc,GACVjzD,EAAMy5C,aAAeb,GACjBpC,IACF6c,GAAiBza,GAAMpC,GAAWx2C,IAGtC,MAAMq0D,GAAiB7a,EAAU90F,OAC3B4vG,GAAgB9a,EAAU,GAC1B+a,GAAe/a,EAAU6a,GAAiB,GAEhD,GADA9Z,IAAiBv6C,EAAM66C,gBAAkB76C,EAAMs6C,eAC3CC,GAAgB,GAAK8Z,IAAkBE,GAAc,CACvDv0D,EAAMq5C,sBAAwBkB,GAAgB8Z,GAC9C,MAAMG,GAASD,GAAahe,GAC5Bv2C,EAAMu5C,MAAmB,gBAAXib,GAA2BA,GAAS,EAC7Cx0D,EAAM45C,OACT2a,GAAahd,SAAU,GAErB+c,KACFt0D,EAAMm6C,QAAUma,GAAc3d,SAGhC32C,EAAMu5C,MAAQ,EACdv5C,EAAMm6C,QAAU,EAElB,OAAIn6C,EAAMy5C,eACRc,IAAiBv6C,EAAMy5C,aAAa3uF,UAEtCk1C,EAAMu6C,cAAgBA,GACtBv6C,EAAMs5C,MAAQ2Z,GAWVE,GAAgB,GAyFxB,SAASsB,GACPjb,EACA2Z,GAEA,IAAIuB,EAAWlb,EAAU2Z,GACzB,QAASvoE,EAAIuoE,EAAevoE,KAAO,CACjC,MAAMguD,EAAOY,EAAU5uD,GAEvB,IAAKguD,EACH,OAEFA,EAAKvC,gBACFqe,EAASre,gBAA6C,IAAhBuC,EAAK9tF,SAC9C4pG,EAAW9b,EAEf,CAvGM6b,CAAyBjb,EAAW2Z,IAG/BnzD,CACT,EAGF,SAASyxD,GACPkD,EACArf,EACAyV,GACU,QAEV,MAAM6J,EAAW,IAAItiB,GAASqiB,GAE5B7J,GAAgCC,EAAQ6J,EAAU,CAChD,YACA,oBACA,MACA,KACA,QAGJ,MAAMC,EAA+B,OAAlBC,EAAGF,EAASG,QAAMD,EAAI,GACnCE,EAAaJ,EAASpC,IACtByC,EAAYL,EAAS7hB,mBAAmB,MACxCmiB,EAA2BN,EAASO,kBAEpCC,EAAqC,OAArBC,EAAGT,EAASU,WAASD,EAAI,WAE3CL,GAAcJ,EAASW,KAAON,GAChC9iB,GAAOlvE,MAAO,eAAc2xF,EAASW,MAIvC,MAAMC,EAAcR,EAAa5E,GAAWpsD,QAAQgxD,EAAY1f,GAAW,GACrE8S,IACJ8M,GAAsD,KAErD/jG,MAAM,KACNpD,IAAImyC,QACJtxC,OAAOsxC,OAAOkrC,UAEjB,OAAO,IAAI2c,GACT8M,EACAW,EACAJ,EACAhN,GACA6M,EAEJ,CAEA,SAASpD,GAAqB4D,GAE5B,MAAMpb,EADa,IAAI/H,GAASmjB,GACGtiB,qBAAqB,eACxD,OAAIyB,EAAgByF,GACXA,EAEF,IACT,CAEA,SAAS0W,GAAU2E,EAAuB11D,GACxC,CAAC,QAAS,QAAS,QAAQr0C,QAAS+C,IAClC,MAAMinG,EAAWD,EAAO9mG,OAAQk0F,GD9tB7B,SAAS8S,GAAY9S,EAAep0F,GACzC,MAAMmnG,EAAY1J,GAAoBz9F,GACtC,QAASmnG,IAA8C,IAAjCA,EAAU/S,EAAMvpF,MAAM,EAAG,GACjD,CC2tB8Cq8F,CAAY9S,EAAOp0F,IAC7D,GAAIinG,EAASjxG,OAAQ,CACnB,MAAMoxG,EAAYH,EAAS/mG,OAAQk0F,GAEE,IAAjCA,EAAM36C,YAAY,OAAQ,IACO,IAAjC26C,EAAM36C,YAAY,OAAQ,IAG9BnI,EAAO,GAAEtxC,UAAeonG,EAAUpxG,OAAS,EAAIoxG,EAAU,GAAKH,EAAS,GAGvED,EAASA,EAAO9mG,OAAQk0F,IAAsC,IAA5B6S,EAASxtE,QAAQ26D,GAAa,IAIpE9iD,EAAMoxD,cAAgBsE,CACxB,CAEA,SAAS/C,GAAY55F,EAAOg9F,EAAWC,GACrC,MAAMC,EAAaF,EAAUC,GACzBC,IACFl9F,EAAMi9F,GAAiBC,EAE3B,CAmBA,SAAS3C,GAAsB1a,EAAMsa,GAC/Bta,EAAKxC,mBACPwC,EAAKvC,gBAAkBp5E,KAAKqkE,MAAMsX,EAAKxC,oBACtB,MAAR8c,KAAU7c,kBACnBuC,EAAKvC,gBAAkB6c,EAASrb,oBAG7Bqe,EAAgBtd,EAAKvC,mBACxBuC,EAAKvC,gBAAkB,KACvBuC,EAAKxC,mBAAqB,KAE9B,CAEA,SAASyd,GACPjb,EACAgb,EACAlpG,EACA8rF,GAEAoC,EAAKnD,OAASme,EAASpB,IACnBoB,EAASuC,WACXvd,EAAK9C,aAAa8d,EAASuC,WAE7Bvd,EAAK54C,MAAQt1C,EACbkuF,EAAKrC,GAAK,cACNC,IACFoC,EAAKpC,UAAYA,GAEnBoC,EAAKtB,YAAc,IACrB,CAEA,SAAS+b,GACPza,EACApC,EACAx2C,GAEA44C,EAAKpC,UAAYA,EACjB,MAAQkF,sBAAuB17C,IAE3B07C,EAAmBh3F,QACnBg3F,EAAmBA,EAAmBh3F,OAAS,GAAG8xF,YAChDA,IACJxrD,OAAOkP,KAAKs8C,GAAW7oF,KACpB6vF,GAAWhH,EAAWgH,GAAQ6K,qBAGjC3M,EAAmBlxF,KAAKouF,EAE5B,CCjuBA,IAAkBwd,GAAmB,4FAOnBC,GAAiB,gDCzInC,SAASC,GACPzhD,GAEA,MAAQnmD,QAASmmD,EAEjB,OAAQnmD,GACN,KAAK0nG,GAAoBG,YACvB,OAAOF,GAAkB1gB,MAC3B,KAAKygB,GAAoBI,eACvB,OAAOH,GAAkBI,SAC3B,QACE,OAAOJ,GAAkBK,KAE/B,CAEA,SAASC,GACPzyG,EACA2wD,GAEA,IAAI/wD,EAAMI,EAASJ,IAGnB,YAAYD,IAARC,GAA8C,IAAzBA,EAAIqkC,QAAQ,YAEnCrkC,EAAM+wD,EAAQ/wD,KAETA,CACT,CAEA,MAAM8yG,GAOJ30G,YAAY40G,GAAUz0G,KANLy0G,SAAG,OACHC,QAEb9rE,OAAOjO,OAAO,MAAK36B,KACfw5F,aAAmC,KAGzCx5F,KAAKy0G,IAAMA,EACXz0G,KAAK20G,mBACP,CAEOC,UAAUC,GAA6B,CAEvCC,WACL90G,KAAK+0G,wBACP,CAEQJ,oBACN,MAAQF,OAAQz0G,KAChBy0G,EAAInxF,GAAG2lE,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACxDy0G,EAAInxF,GAAG2lE,EAAOkB,cAAenqF,KAAKi1G,eAAgBj1G,MAClDy0G,EAAInxF,GAAG2lE,EAAO0B,oBAAqB3qF,KAAKk1G,oBAAqBl1G,MAC7Dy0G,EAAInxF,GAAG2lE,EAAO+B,uBAAwBhrF,KAAKm1G,uBAAwBn1G,KACrE,CAEQo1G,sBACN,MAAQX,OAAQz0G,KAChBy0G,EAAIY,IAAIpsB,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACzDy0G,EAAIY,IAAIpsB,EAAOkB,cAAenqF,KAAKi1G,eAAgBj1G,MACnDy0G,EAAIY,IAAIpsB,EAAO0B,oBAAqB3qF,KAAKk1G,oBAAqBl1G,MAC9Dy0G,EAAIY,IAAIpsB,EAAO+B,uBAAwBhrF,KAAKm1G,uBAAwBn1G,KACtE,CAKQs1G,qBACN7iD,GAEA,MAAM/iB,EAAS1vC,KAAKy0G,IAAI/kE,OAIlB2kD,EAAS,IAHC3kD,EAAO6lE,SACR7lE,EAAO2kD,QAEY3kD,GAElC,YAAKglE,QAAQjiD,EAAQnmD,MAAQ+nF,EACtBA,CACT,CAEQmhB,kBACN/iD,GAEA,OAAOzyD,KAAK00G,QAAQjiD,EAAQnmD,KAC9B,CAEQmpG,oBAAoBC,GACtB11G,KAAK00G,QAAQgB,WACR11G,KAAK00G,QAAQgB,EAExB,CAKQX,yBACN,UAAWW,KAAe11G,KAAK00G,QAAS,CACtC,MAAMrgB,EAASr0F,KAAK00G,QAAQgB,GACxBrhB,GACFA,EAAO3tB,UAGT1mE,KAAKy1G,oBAAoBC,EAAW,CAExC,CAEOhvC,UACL1mE,KAAKw5F,aAAe,KACpBx5F,KAAKo1G,sBACLp1G,KAAK+0G,wBACP,CAEQC,kBACN3tF,EACA7mB,GAEA,MAAQkB,OAAQlB,EAChBR,KAAKw5F,aAAe,KACpBx5F,KAAKshD,KAAK,CACRh5C,GAAI,KACJs1C,MAAO,EACP+3D,aAAc,OACdrpG,KAAM0nG,GAAoB4B,SAC1Bl0G,MACAm0G,mBAAoB,MAExB,CAEQZ,eAAe5tF,EAA6B7mB,GAClD,MAAQ8H,KAAIs1C,QAAOl8C,MAAKm0G,sBAAuBr1G,EAC/CR,KAAKshD,KAAK,CACRh5C,KACAs1C,QACA+3D,aAAc,OACdrpG,KAAM0nG,GAAoB8B,MAC1Bp0G,MACAm0G,sBAEJ,CAEQX,oBACN7tF,EACA7mB,GAEA,MAAQ8H,KAAIynG,UAASruG,MAAKm0G,sBAAuBr1G,EACjDR,KAAKshD,KAAK,CACRh5C,KACAynG,UACAnyD,MAAO,KACP+3D,aAAc,OACdrpG,KAAM0nG,GAAoBG,YAC1BzyG,MACAm0G,sBAEJ,CAEQV,uBACN9tF,EACA7mB,GAEA,MAAQ8H,KAAIynG,UAASruG,MAAKm0G,sBAAuBr1G,EACjDR,KAAKshD,KAAK,CACRh5C,KACAynG,UACAnyD,MAAO,KACP+3D,aAAc,OACdrpG,KAAM0nG,GAAoBI,eAC1B1yG,MACAm0G,sBAEJ,CAEQv0D,KAAKmR,GAAsC,MACjD,MAAM/iB,EAAS1vC,KAAKy0G,IAAI/kE,OAKxB,IAgBIqmE,EAhBA1hB,EAASr0F,KAAKw1G,kBAAkB/iD,GACpC,GAAI4hC,EAAQ,CACV,MAAM2hB,EAAgB3hB,EAAO5hC,QAC7B,GAAIujD,GAAiBA,EAAct0G,MAAQ+wD,EAAQ/wD,IAGjD,YADAquF,GAAOJ,MAAM,+CAGfI,GAAOF,IACJ,yDAAwDp9B,EAAQnmD,QAEnE+nF,EAAO2B,OAAK,CAkBd,GAXE+f,EADEtjD,EAAQnmD,OAAS0nG,GAAoB4B,SAC1BlmE,EAAOumE,mBAAmBjnG,QAE1B8iF,GAAc,GAAIpiD,EAAOwmE,mBAAmBlnG,QAAS,CAChEmnG,aAAc,KACdC,WAAY,OAGhB/hB,EAASr0F,KAAKs1G,qBAAqB7iD,GAI/B4jD,OAAJA,EAAI5jD,EAAQojD,qBAARQ,EAA4BxE,KAAM,CACpC,IAAIyE,EAiBJ,GAfE7jD,EAAQnmD,OAAS0nG,GAAoB8B,OACnB,OAAlBrjD,EAAQ7U,MAER04D,EAAet2G,KAAKy0G,IAAI3qG,OAAO2oD,EAAQ7U,OAAOqwB,QAE9Cxb,EAAQnmD,OAAS0nG,GAAoBG,aACtB,OAAf1hD,EAAQnqD,GAERguG,EAAet2G,KAAKy0G,IAAI8B,YAAY9jD,EAAQnqD,IAAI2lE,QAEhDxb,EAAQnmD,OAAS0nG,GAAoBI,gBACtB,OAAf3hD,EAAQnqD,KAERguG,EAAet2G,KAAKy0G,IAAI+B,eAAe/jD,EAAQnqD,IAAI2lE,SAEjDqoC,EAAc,CAChB,MAAMzd,EAAayd,EAAazd,WAC1B4d,EAAiBH,EAAape,eACpC,GAAIW,GAAc4d,EAAgB,CAChC,MAAMC,GAC6C,IAAjDr/F,KAAK+/C,IAAiB,EAAbyhC,EAAiC,GAAjB4d,GAC3BV,EAAajkB,GAAc,GAAIikB,EAAY,CACzCY,qBAAsBt/F,KAAK++E,IACzBsgB,GACAX,EAAWY,sBAEbC,cAAev/F,KAAK++E,IAClBsgB,GACAX,EAAWY,uBAEd,GAKP,MAAME,EACJd,EAAWK,YAAcL,EAAWI,cAAgB,GAiEtD9hB,EAAO/yC,KAAKmR,EAhE8B,CACxCsjD,aACAh2D,QAASg2D,EAAWa,cACpBE,SAAUD,EAAyBE,aAAe,EAClDC,WAAYH,EAAyBI,cAAgB,EACrDC,cAAeL,EAAyBM,iBAAmB,GAGG,CAC9DC,UAAWA,CAACt1G,EAAUizF,EAAOtiC,EAAS4kD,MACpC,MAAMhjB,GAASr0F,KAAKw1G,kBAAkB/iD,GAGtCzyD,KAAKy1G,oBAAoBhjD,EAAQnmD,MAEjC,MAAM8hG,GAAStsG,EAAStB,KAGU,IAA9B4tG,GAAOroE,QAAQ,YAWnBgvD,EAAMjC,QAAQtyE,MAAQ4O,YAAYC,MAC9B2+E,GAAWsJ,gBAAgBlJ,IAC7BpuG,KAAKu3G,2BACHz1G,EACAizF,EACAtiC,EACA4kD,IAAkB,KAClBhjB,IAGFr0F,KAAKw3G,qBAAqB11G,EAAUizF,EAAOtiC,EAAS4kD,KApBpDr3G,KAAKy3G,2BACH31G,EACA2wD,EACA,IAAI01B,MAAM,uBACVkvB,IAAkB,KAClBtiB,EAegE,EAGtE2iB,QAASA,CAAC51G,EAAU2wD,EAAS4kD,EAAgBtiB,MAC3C/0F,KAAK23G,mBACHllD,EACA4kD,GACA,EACAv1G,EACAizF,GACF,EAEF6iB,UAAWA,CAAC7iB,EAAOtiC,EAAS4kD,KAC1Br3G,KAAK23G,mBACHllD,EACA4kD,GACA,OACA51G,EACAszF,EACF,GAON,CAEQyiB,qBACN11G,EACAizF,EACAtiC,EACA4kD,GAEA,MAAM5C,EAAMz0G,KAAKy0G,IACXrG,EAAStsG,EAAStB,KAElBkB,EAAM6yG,GAAezyG,EAAU2wD,GAE/BolD,EAAe7J,GAAW8J,oBAAoB1J,EAAQ1sG,GAE5D,GAAIm2G,EAAate,qBAQf,YAPAv5F,KAAKy3G,2BACH31G,EACA2wD,EACAolD,EAAate,qBACb8d,EACAtiB,GAKJ,MACEsZ,kBACAvkG,SACAwkG,cACAC,eACAtW,mBACAuB,iBACEqe,EAEJ73G,KAAKw5F,aAAeA,GAEpB,MACEjG,MAAOgjB,GAAc,GACrB3G,UAAWmI,GACX,kBAAmBC,IACjBhK,GAAWiK,yBAAyB7J,EAAQ1sG,EAAKm2G,GAEjDtB,GAAYj0G,SAEsBi0G,GAAYhrG,KAC7C2sG,KAAgBA,GAAWx2G,MAS5BoI,EAAO,GAAG6lG,aACT7lG,EAAO,GAAGqmF,MAAMoD,QAEjBxD,GAAOF,IACL,8GAEF0mB,GAAY5oC,QAAQ,CAClBrhE,KAAM,OACNyN,KAAM,OACNg2F,QAAS,OACT/gG,SAAS,EACTkhG,YAAY,EACZC,QAAQ,EACR7nG,IAAI,EACJ6nF,MAAO,IAAID,GAAS,IACpBue,QAAS,EACT/sG,IAAK,MAKX+yG,EAAInrC,QAAQ2f,EAAOc,gBAAiB,CAClCjgF,SACAysG,eACAwB,aACAC,YACA3J,kBACA3sG,MACAqzF,QACAsiB,iBACA/I,cACAC,eACAtW,mBACAuB,iBAEJ,CAEQ+d,2BACNz1G,EACAizF,EACAtiC,EACA4kD,EACAhjB,GAEA,MAAMogB,EAAMz0G,KAAKy0G,KACTnsG,KAAIs1C,QAAOtxC,QAASmmD,EAEtB/wD,EAAM6yG,GAAezyG,EAAU2wD,GAC/B+9C,EAAaxe,EAAgB1pF,GAAiBA,EAAgB,EAC9D6vG,GAAU/lB,EAAgBx0C,GAC3BA,EACD4yD,EACE4H,GAAYlE,GAAsBzhD,GAClC6jD,GAA6BtI,GAAWqK,mBAC5Cv2G,EAAStB,KACTkB,EACAy2G,GACAC,GACA5H,EACAxwG,KAAKw5F,cAOP,GAAIltF,IAAS0nG,GAAoB4B,SAAU,CACzC,MAAM0C,GAA2B,CAC/BnoB,MAAO,IAAID,GAAS,IACpBue,QAAS,EACTxgC,QAASqoC,GACTv8F,KAAM,GACNrY,OAGF+yG,EAAInrC,QAAQ2f,EAAOc,gBAAiB,CAClCjgF,OAAQ,CAACwuG,IACT/B,YAAa,GACb70G,MACAqzF,QACAsiB,iBACA/I,YAAa,KACbC,YAAa,KACbF,gBAAiB,KACjBpW,gBAAiB,KACjBuB,aAAc,MACf,CAIHzE,EAAMjC,QAAQ3X,IAAM/rD,YAAYC,MAGhCojC,EAAQ6jD,aAAeA,GAEvBt2G,KAAKu4G,qBACHjC,GACAx0G,EACAizF,EACAtiC,EACA4kD,EACAhjB,EAEJ,CAEQojB,2BACN31G,EACA2wD,EACA5xC,EACAw2F,EACAtiB,GAEA/0F,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAaa,uBACtB6qB,MAAO/lD,EAAQnmD,OAAS0nG,GAAoB4B,SAC5Cl0G,IAAKI,EAASJ,IACdsvC,IAAKnwB,EACLA,QACA43F,OAAQ53F,EAAM2oF,QACd1nG,WACA2wD,UACA4kD,iBACAtiB,SAEJ,CAEQ4iB,mBACNllD,EACA4kD,EACAt3D,GAAU,EACVj+C,EACAizF,GAEA,IAAIyU,EAAW,aACbzpD,EACI,UACA,SAAWj+C,EAAW,YAAcA,EAAS42G,KAAO,IAAM,8BACrCjmD,EAAQnmD,OAC/BmmD,EAAQnmD,OAAS0nG,GAAoB8B,MACvCtM,GAAY,KAAI/2C,EAAQ7U,aAAa6U,EAAQnqD,MAE7CmqD,EAAQnmD,OAAS0nG,GAAoBG,aACrC1hD,EAAQnmD,OAAS0nG,GAAoBI,kBAErC5K,GAAY,QAAO/2C,EAAQnqD,iBAAiBmqD,EAAQs9C,YAEtD,MAAMlvF,EAAQ,IAAIsnE,MAAMqhB,GACxBzZ,GAAOhtC,KAA2BymD,2BAClC,IAAIv7B,EAAU6e,GAAa0C,QACvBgpB,GAAQ,EAEZ,MAAMnkB,EAASr0F,KAAKw1G,kBAAkB/iD,GAEtC,OAAQA,EAAQnmD,MACd,KAAK0nG,GAAoB4B,SACvB3nC,EAAUluB,EACN+sC,GAAaY,sBACbZ,GAAaW,oBACjB+qB,GAAQ,EACR,MACF,KAAKxE,GAAoB8B,MACvB7nC,EAAUluB,EACN+sC,GAAaiB,mBACbjB,GAAagB,iBACjB0qB,GAAQ,EACR,MACF,KAAKxE,GAAoBG,YACvBlmC,EAAUluB,EACN+sC,GAAaqB,yBACbrB,GAAaoB,uBACjBsqB,GAAQ,EACR,MACF,KAAKxE,GAAoBI,eACvBnmC,EAAUluB,EACN+sC,GAAauB,4BACbvB,GAAasB,oBACjBoqB,GAAQ,EAIRnkB,GACFr0F,KAAKy1G,oBAAoBhjD,EAAQnmD,MAGnC,MAAMqsG,EAAuB,CAC3BrsG,KAAMkgF,GAAWC,cACjBxe,UACAuqC,QACA92G,IAAK+wD,EAAQ/wD,IACb2yF,SACA5hC,UACA5xC,QACAw2F,iBACAtiB,SAGEjzF,IAEF62G,EAAU72G,SAAQ82G,IAAKl3G,IADX21G,GAAgB31G,KAAO+wD,EAAQ/wD,IACflB,UAAMiB,GAAqBK,IAGzD9B,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAOysB,EACjC,CAEQJ,qBACNjC,EACAx0G,EACAizF,EACAtiC,EACA4kD,EACAhjB,GAEA,MAAMogB,EAAMz0G,KAAKy0G,KACTnoG,OAAMsxC,QAAOt1C,KAAIynG,UAAS8F,uBAAuBpjD,EACnD/wD,GAAM6yG,GAAezyG,EAAU2wD,GAC/B1O,GAASmwD,GAAsBzhD,GAC/BomD,GACqB,iBAAlBpmD,EAAQ7U,OAAsBmG,KAAWkwD,GAAkBK,KAC7D12D,OACDn8C,EACN,IAAK60G,EAAalf,UAAU90F,OAAQ,CAClC,MAAMue,GAAQ,IAAIsnE,MAAM,iCAexB,YAdAssB,EAAInrC,QAAQ2f,EAAOiD,MAAO,CACxB5/E,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAae,kBACtB2qB,OAAO,EACP92G,OACAmf,SACA43F,OAAQ53F,GAAM2oF,QACd1nG,WACA2wD,UACA7U,MAAOi7D,GACP90D,UACAszD,iBACAtiB,SAEF,CAEGuhB,EAAape,iBAChBoe,EAAa/c,qBAAuB,IAAIpR,MAAM,4BAEhD,MAAMtnE,GAAQy1F,EAAa/c,qBAC3B,GAAI14E,GACF4zF,EAAInrC,QAAQ2f,EAAOiD,MAAO,CACxB5/E,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAakB,oBACtBwqB,OAAO,EACP92G,OACAmf,SACA43F,OAAQ53F,GAAM2oF,QACd1nG,WACA2wD,UACA7U,MAAOi7D,GACP90D,UACAszD,iBACAtiB,eAcJ,OATIuhB,EAAa9e,MAAQnD,IACnBA,EAAOykB,cACTxC,EAAa7e,UAAYpD,EAAOykB,eAAiB,KAE9CzkB,EAAOykB,aAAeC,MAAMzC,EAAa7e,cAC5C6e,EAAa7e,UAAY,IAIrBnrF,GACN,KAAK0nG,GAAoB4B,SACzB,KAAK5B,GAAoB8B,MACvBrB,EAAInrC,QAAQ2f,EAAOmB,aAAc,CAC/Bnc,QAASqoC,EACT14D,MAAOi7D,IAAc,EACrBvwG,GAAIA,GAAM,EACVysF,QACAsiB,iBACAxB,wBAEF,MACF,KAAK7B,GAAoBG,YACvBM,EAAInrC,QAAQ2f,EAAO2B,mBAAoB,CACrC3c,QAASqoC,EACThuG,GAAIA,GAAM,EACVynG,QAASA,GAAW,GACpBhb,QACAsiB,iBACAxB,wBAEF,MACF,KAAK7B,GAAoBI,eACvBK,EAAInrC,QAAQ2f,EAAOgC,sBAAuB,CACxChd,QAASqoC,EACThuG,GAAIA,GAAM,EACVynG,QAASA,GAAW,GACpBhb,QACAsiB,iBACAxB,wBAIR,EC/rBK,SAASmD,GAAkBpY,EAAkBqY,GAClD,IAAI5xF,EACJ,IACEA,EAAQ,IAAI6xF,MAAM,WAKpB,OAFE7xF,EAAQjlB,SAAS+2G,YAAY,SAC7B9xF,EAAM+xF,UAAU,YAAY,GAAO,EACrC,CACC/xF,EAAcu5E,MAAQA,EACvBqY,EAAQI,cAAchyF,EACxB,CAEO,SAASiyF,GAAc1Y,EAAkB2Y,GAI9C,MAAMliF,EAAOupE,EAAMvpE,KAInB,GAHa,aAATA,IACFupE,EAAMvpE,KAAO,UAEXupE,EAAM4Y,OAAS5Y,EAAM4Y,KAAKC,WAAWF,EAAIjxG,IAC3C,IAEE,GADAs4F,EAAM8Y,OAAOH,IACR3Y,EAAM4Y,KAAKC,WAAWF,EAAIjxG,IAC7B,MAAM,IAAI6/E,MAA+BoxB,6BAW7C,OATSvoE,GACP++C,GAAOH,MAA4B5+C,2BACnC,MAAM2oE,EAAe,IAAK1d,KAAK2d,aAC7BL,EAAI9gD,UACJ8gD,EAAI/gD,QACJ+gD,EAAIx3G,MAEN43G,EAAarxG,GAAKixG,EAAIjxG,GACtBs4F,EAAM8Y,OAAOC,EACf,CAEW,aAATtiF,IACFupE,EAAMvpE,KAAOA,EAEjB,CAEO,SAASwiF,GAAiBjZ,GAI/B,MAAMvpE,EAAOupE,EAAMvpE,KAInB,GAHa,aAATA,IACFupE,EAAMvpE,KAAO,UAEXupE,EAAM4Y,KACR,QAAShxE,EAAIo4D,EAAM4Y,KAAKl3G,OAAQkmC,KAC9Bo4D,EAAMkZ,UAAUlZ,EAAM4Y,KAAKhxE,IAGlB,aAATnR,IACFupE,EAAMvpE,KAAOA,EAEjB,CAEO,SAAS0iF,GACdnZ,EACApgF,EACA26D,EACA6+B,GAEA,MAAM3iF,EAAOupE,EAAMvpE,KAKnB,GAJa,aAATA,IACFupE,EAAMvpE,KAAO,UAGXupE,EAAM4Y,MAAQ5Y,EAAM4Y,KAAKl3G,OAAS,EAAG,CACvC,MAAMk3G,EAkDH,SAASS,GACdT,EACAh5F,EACA26D,GAEA,MAAM++B,EAA4B,GAC5BC,EA1CR,SAASC,GACPZ,EACArxF,GAGA,GAAIA,EAAOqxF,EAAK,GAAG/gD,UACjB,OAAO,EAGT,MAAMjT,EAAMg0D,EAAKl3G,OAAS,EAC1B,GAAI6lB,EAAOqxF,EAAKh0D,GAAKgT,QACnB,OAAO,EAGT,IAAIpS,EAAO,EACPi0D,EAAQ70D,EAEZ,KAAOY,GAAQi0D,GAAO,CACpB,MAAMC,EAAMjjG,KAAKC,OAAO+iG,EAAQj0D,GAAQ,GAExC,GAAIj+B,EAAOqxF,EAAKc,GAAK7hD,UACnB4hD,EAAQC,EAAM,YACLnyF,EAAOqxF,EAAKc,GAAK7hD,WAAarS,EAAOZ,GAI9C,OAAO80D,EAHPl0D,EAAOk0D,EAAM,CAGNA,EAKX,OAAOd,EAAKpzD,GAAMqS,UAAYtwC,EAAOA,EAAOqxF,EAAKa,GAAO5hD,UACpDrS,EACAi0D,CACN,CAQ0BD,CAA0BZ,EAAMh5F,GACxD,GAAI25F,GAAkB,EACpB,QAAS3xE,EAAI2xE,EAAiB30D,EAAMg0D,EAAKl3G,OAAQkmC,EAAIgd,EAAKhd,IAAK,CAC7D,MAAM+wE,EAAMC,EAAKhxE,GACjB,GAAI+wE,EAAI9gD,WAAaj4C,GAAS+4F,EAAI/gD,SAAW2iB,EAC3C++B,EAAU9xG,KAAKmxG,QAAG,GACTA,EAAI9gD,UAAY0iB,EACzB,OAAO++B,EAIb,OAAOA,CACT,CApEiBD,CAAerZ,EAAM4Y,KAAMh5F,EAAO26D,GAC/C,QAAS3yC,EAAI,EAAGA,EAAIgxE,EAAKl3G,OAAQkmC,MAC1BwxE,GAAaA,EAAUR,EAAKhxE,MAC/Bo4D,EAAMkZ,UAAUN,EAAKhxE,GAAE,CAIhB,aAATnR,IACFupE,EAAMvpE,KAAOA,EAEjB,CCOA,IAAkBkjF,QAAcC,+BC5DhC,SAASC,KACP,YAAWxe,KAAS,KAKpB,OAAQA,KAAKye,eAAiBze,KAAK0e,QAAU1e,KAAK2d,YACpD,CAIA,MAAMgB,SACJ,MAAMC,EAAMJ,KACZ,IACE,IAAII,EAAI,EAAG/8D,OAAOg9D,kBAAmB,GAGvC,OADE,OAAOh9D,OAAOi9D,SAChB,CACA,OAAOj9D,OAAOg9D,iBAChB,EARMF,GAUN,SAASI,GAA+B9jE,EAAYiU,GAClD,OAAOjU,EAAKv3B,UAAY,IAAOwrC,CACjC,CAEA,SAAS8vD,GAAiB1iE,GACxB,OAAOs4C,WAAW5sC,KAChB1L,EACGv2C,QAAQ,MAAO,IACfA,QAAQ,qBAAsB,SAC9BA,QAAQ,MAAO,IACf+M,MAAM,MACTwuF,MACJ,CACA,MAAM2d,GASJr7G,YAAY40G,GAAKz0G,KARTy0G,SAAG,OACH0G,SAA6B,KAAIn7G,KACjC2W,MAAiC,KAAI3W,KACrCo7G,sBAGJ,GAGFp7G,KAAKy0G,IAAMA,EACXz0G,KAAKq7G,oBACP,CAEA30C,UACE1mE,KAAKs7G,uBACLt7G,KAAKm7G,SAAW,KAChBn7G,KAAK2W,MAAQ,KACb3W,KAAKo7G,sBAAwB,GAE7Bp7G,KAAKy0G,IAAM,IACb,CAEQ4G,qBACN,MAAQ5G,OAAQz0G,KAChBy0G,EAAInxF,GAAG2lE,EAAOE,eAAgBnpF,KAAKu7G,gBAAiBv7G,MACpDy0G,EAAInxF,GAAG2lE,EAAOG,gBAAiBppF,KAAKw7G,iBAAkBx7G,MACtDy0G,EAAInxF,GAAG2lE,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACxDy0G,EAAInxF,GAAG2lE,EAAO2C,sBAAuB5rF,KAAKy7G,sBAAuBz7G,MACjEy0G,EAAInxF,GAAG2lE,EAAOW,gBAAiB5pF,KAAK07G,iBAAkB17G,MACtDy0G,EAAInxF,GAAG2lE,EAAOoB,cAAerqF,KAAK27G,eAAgB37G,KACpD,CAEQs7G,uBACN,MAAQ7G,OAAQz0G,KAChBy0G,EAAIY,IAAIpsB,EAAOE,eAAgBnpF,KAAKu7G,gBAAiBv7G,MACrDy0G,EAAIY,IAAIpsB,EAAOG,gBAAiBppF,KAAKw7G,iBAAkBx7G,MACvDy0G,EAAIY,IAAIpsB,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACzDy0G,EAAIY,IAAIpsB,EAAO2C,sBAAuB5rF,KAAKy7G,sBAAuBz7G,MAClEy0G,EAAIY,IAAIpsB,EAAOW,gBAAiB5pF,KAAK07G,iBAAkB17G,MACvDy0G,EAAIY,IAAIpsB,EAAOoB,cAAerqF,KAAK27G,eAAgB37G,KACrD,CAGUu7G,gBACRl0F,EACA7mB,GAEAR,KAAK2W,MAAQnW,EAAKmW,KACpB,CAEU6kG,mBACHx7G,KAAKm7G,WAGVtB,GAAiB75G,KAAKm7G,UACtBn7G,KAAKm7G,SAAW,KAChBn7G,KAAK2W,MAAQ,KACb3W,KAAKo7G,sBAAwB,GAC/B,CAEQpG,oBACNh1G,KAAKo7G,sBAAwB,EAC/B,CAEAQ,YAAYjlG,GACV,MAAMiqF,EAAQ5gG,KAAK67G,YAAYllG,EAAMmlG,YACrClb,SAAMvpE,KAAO,SACNupE,CACT,CAEAib,YAAYC,GACV,GAAK97G,KAAK2W,MAGV,SAAS6xB,EAAI,EAAGA,EAAIszE,EAAWx5G,OAAQkmC,IAAK,CAC1C,MAAMuzE,EAAuBD,EAAWtzE,GACxC,GAAuB,aAAnBuzE,EAAUC,MAA2C,QAApBD,EAAUpyG,MAG7CqvG,UAAkB+C,EAAW/7G,KAAK2W,OAE3BolG,EAGX,OAAO/7G,KAAK2W,MAAMslG,aAAa,WAAY,MAAK,CAClD,CAEAR,sBACEp0F,EACA7mB,GAEA,IAAKR,KAAK2W,MACR,OAGF,MACE89F,KACE/kE,QAAUwsE,yBAAwBC,2BAElCn8G,KACJ,IAAKk8G,IAA2BC,EAC9B,OAGF,MAAQxa,WAAYnhG,EAGfR,KAAKm7G,WACRn7G,KAAKm7G,SAAWn7G,KAAK47G,YAAY57G,KAAK2W,QAGxC,MAAMkkG,EAAMJ,KAEZ,QAASjyE,EAAI,EAAGA,EAAIm5D,EAAQr/F,OAAQkmC,IAAK,CACvC,MAAMl8B,EAAOq1F,EAAQn5D,GAAGl8B,KACxB,GACGA,IAASiuG,UAAwB2B,IACjCC,EAED,SAGF,MAAMj4D,EAASk4D,GAAiBza,EAAQn5D,GAAGhoC,MAC3C,GAAI0jD,EAAQ,CACV,MAAMuU,EAAYkpC,EAAQn5D,GAAG27D,IAC7B,IAAI3rC,EAAkBC,EAAYkpC,EAAQn5D,GAAG9/B,SAEzC8vD,EAAUoiD,KACZpiD,EAAUoiD,IAGKpiD,EAAUC,GACX,IACdD,EAAUC,EA1KK,KA6KjB,QAAS2Z,GAAI,EAAGA,GAAIluB,EAAO5hD,OAAQ8vE,KAAK,CACtC,MAAMpuB,GAAQE,EAAOkuB,IAErB,IAAKgqC,GAAqBp4D,IAAQ,CAEhChkD,KAAKq8G,iBAAiB5jD,EAAWnsD,GAEjC,MAAMitG,GAAM,IAAIsB,EAAIpiD,EAAWD,EAAS,IACxC+gD,GAAI9sG,MAAQu3C,GACR13C,IACFitG,GAAIjtG,KAAOA,GAEbtM,KAAKm7G,SAASzB,OAAOH,GAAG,IAKlC,CAEA8C,iBAAiB5jD,EAAmBnsD,GAAsB,MACxD,MAAMktG,EAAoB,OAAhB8C,EAAGt8G,KAAKm7G,eAAQ,EAAbmB,EAAe9C,KAC5B,GAAIA,EACF,QAAShxE,EAAIgxE,EAAKl3G,OAAQkmC,KAAO,CAC/B,MAAM+wE,EAAMC,EAAKhxE,GAEf+wE,EAAIjtG,OAASA,GACbitG,EAAI9gD,UAAYA,GAChB8gD,EAAI/gD,UAAYoiD,KAEhBrB,EAAI/gD,QAAUC,GAItB,CAEAijD,iBACEr0F,GACE47B,cAAaG,YAAW92C,SAE1B,MAAQ6uG,WAAU1G,OAAQz0G,KAC1B,IAAKy0G,EACH,OAGF,MACE/kE,QAAUwsE,yBAAwBC,0BAChC1H,EACJ,GAAI0G,IAAae,GAA0BC,GAAwB,CACjE,IAAInC,EAGFA,EADW,UAAT1tG,EACWitG,GDlKWgD,YCmKrBhD,EAAYjtG,MACb6vG,EACgB,UAAT7vG,EACIitG,GACVA,EAAYjtG,OAASiuG,SAAuB2B,EAElC3C,GDzKWgD,YC0KpBhD,EAAYjtG,MACZ6vG,GACA5C,EAAYjtG,OAASiuG,SAAuB2B,EAElDnC,GAAkBoB,EAAUl4D,EAAaG,EAAW42D,EAAS,CAEjE,CAEA2B,eAAet0F,GAA+B4mD,YAC5C,IACGjuE,KAAK2W,QACLs3D,EAAQ8rB,qBACR/5F,KAAKy0G,IAAI/kE,OAAO8sE,4BAEjB,OAEF,MAAQpB,wBAAuBD,YAAan7G,MACpCu3F,cAAetpB,EACjBr9D,EAAMg4B,OAAOkP,KAAKy/C,GAExB,GAAI4jB,EAAU,CACZ,MAAMsB,EAAc7zE,OAAOkP,KAAKsjE,GAAuB5uG,OACpDlE,IAAQsI,EAAI0nB,SAAShwB,IAExB,QAASkgC,EAAIi0E,EAAYn6G,OAAQkmC,KAAO,CACtC,MAAMlgC,GAAKm0G,EAAYj0E,GACvBI,OAAOkP,KAAKsjE,EAAsB9yG,IAAIkxG,MAAMjwG,QAASlC,KACnD8zG,EAASrB,UAAUsB,EAAsB9yG,IAAIkxG,KAAKnyG,IAAI,UAEjD+zG,EAAsB9yG,GAAE,EAInC,MAAM6pG,EAAelkC,EAAQmpB,UAAUnpB,EAAQmpB,UAAU90F,OAAS,GAClE,GAAmB,IAAfsO,EAAItO,SAAiB0vF,EAAgBmgB,GAAcle,iBACrD,OAGGj0F,KAAKm7G,WACRn7G,KAAKm7G,SAAWn7G,KAAK47G,YAAY57G,KAAK2W,QAGxC,MAAM+lG,EACHvK,EAAale,gBAA6B,IAAOke,EAAa3xF,MAC3Dq6F,EAAMJ,KAEZ,QAASjyE,EAAI,EAAGA,EAAI53B,EAAItO,OAAQkmC,IAAK,CACnC,MAAMlgC,EAAKsI,EAAI43B,GACT8oE,GAAY/Z,EAAWjvF,GACvBq0G,GAAwBvB,EAAsB9yG,GAC9CkxG,GAAOmD,IAAuBnD,MAAQ,GAC5C,IAAIoD,GAAgBD,IAAuBC,gBAAiB,EAC5D,MAAMnkD,GAAYuiD,GAChB1J,GAAUnf,UACVuqB,GAEF,IAAIlkD,GAAUoiD,GACd,MAAM7oB,GAAUuf,GAAUvf,QAC1B,GAAIA,GACFv5B,GAAUwiD,GAA+BjpB,GAAS2qB,GAClDE,IAAgB,UACPtL,GAAUhf,YAAcsqB,GAAe,CAChD,MAAMC,GAA6BjsG,EAChCynB,OAAO,CAACykF,GAAgBx0G,MACvB,MAAMy0G,GAAYxlB,EAAWjvF,IAC7B,OACEy0G,GAAU9qB,QAAUqf,GAAUrf,OAC9B8qB,GAAUz0G,KAAOA,IACjBy0G,GAAU5qB,UAAYmf,GAAUnf,WAEhC2qB,GAAe10G,KAAK20G,IAEfD,IACN,IACFr5F,KAAK,CAACtV,GAAGE,KAAMF,GAAEgkF,UAAUxyE,UAAYtR,GAAE8jF,UAAUxyE,WAAW,GAC7Dk9F,KACFrkD,GAAUwiD,GACR6B,GAA2B1qB,UAC3BuqB,GAEFE,IAAgB,GAIpB,MAAM3N,GAAarmE,OAAOkP,KAAKw5D,GAAUjhB,MACzC,QAASje,GAAI,EAAGA,GAAI68B,GAAW3sG,OAAQ8vE,KAAK,CAC1C,MAAM/qE,GAAM4nG,GAAW78B,IACvB,GpB3U8B,QAFEoe,EoB6UHnpF,KpB1UzB,UAARmpF,GACQ,eAARA,GACQ,aAARA,GACwC,aAAxCA,GAC2C,gBAA3CA,EoBuUM,SAEF,IAAI+oB,GAAMC,GAAKnyG,IACf,GAAIkyG,GACEqD,KAAkBD,GAAsBC,gBAC1CrD,GAAI/gD,QAAUA,QAEX,CACL,IAAIh4D,GAAO8wG,GAAUjhB,KAAKhpF,IAC1BkyG,GAAM,IAAIsB,EAAIpiD,GAAWD,GAAS,IAC9B64B,GAAkBhqF,MACpB7G,GAAOy6G,GAAiBz6G,KAE1B+4G,GAAI9sG,MAAQ,CAAEpF,OAAK7G,SACnB+4G,GAAIjtG,KDhRkBglG,0BCiRtBiI,GAAIjxG,GAAKA,EACTtI,KAAKm7G,SAASzB,OAAOH,IACrBC,GAAKnyG,IAAOkyG,IAGhB6B,EAAsB9yG,GAAM,CAC1BkxG,QACAlI,aACAsL,kBpBrWD,IAAiCpsB,CoBwWtC,EC3Wa,MAAMwsB,GAUnBn9G,YAAY40G,GAAUz0G,KATdy0G,SAAG,OACM/kE,YAAM,OACf/4B,MAAiC,KAAI3W,KACrCs2G,aAAoC,KAAIt2G,KACxCwnB,YAAsB,EAACxnB,KACvBi9G,WAAqB,EAACj9G,KACtBk9G,SAA0B,KAAIl9G,KAC9Bm9G,kBAAoB,IAAMn9G,KAAKo9G,aAGrCp9G,KAAKy0G,IAAMA,EACXz0G,KAAK0vC,OAAS+kE,EAAI/kE,OAClB1vC,KAAK20G,mBACP,CAEI0I,cACF,OAAOr9G,KAAKk9G,UAAY,CAC1B,CAEII,iBACF,MAAQ5tE,SAAQ4mE,gBAAiBt2G,KACjC,YAAsCyB,IAAlCiuC,EAAO6tE,uBACF7tE,EAAO6tE,uBAETjH,EACH5mE,EAAO8tE,4BAA8BlH,EAAape,eAClD,CACN,CAEIulB,oBACF,MAAQnH,gBAAiBt2G,KACzB,GAAqB,OAAjBs2G,EACF,OAAO,KAET,MAAQ1d,WAAUD,eAAcT,kBAAmBoe,GAC3CoH,mBAAkBC,wBAAuBC,kBAC/C59G,KAAK0vC,OACDmuE,EAAa79G,KAAKy0G,IAAIoJ,WAC5B,IAAIJ,EAAgBG,GAAiBjlB,GAAgBC,EAarD,OAXEilB,EAAWH,kBACXG,EAAWF,uBACO,IAAlBF,KAEAA,OACuBh8G,IAArBi8G,EACIA,EACAC,EAAwBzlB,GAK9BulB,EACApmG,KAAK++E,IAHyB,EAI5Bp2F,KAAKi9G,WAL0B/kB,EASrC,CAEI4lB,uBACF,MAAMC,EAAW/9G,KAAKg+G,mBAChBP,EAAgBz9G,KAAKy9G,cACrBnH,EAAet2G,KAAKs2G,aAC1B,GAAiB,OAAbyH,GAAuC,OAAlBN,GAA2C,OAAjBnH,EACjD,OAAO,KAET,MAAMnc,EAAOmc,EAAanc,KAGpB/iC,EACJ+iC,GACEn6F,KAAK0vC,OAAOkuE,gBAAkBtH,EAAazd,YAC3Cyd,EAAape,gBACjB,OAAO7gF,KAAK++E,IAAI/+E,KAAK+/C,IALT+iC,EAAOmc,EAAane,cADX4lB,EAAWN,EAAgBz9G,KAAKi+G,aAMR7mD,EAC/C,CAEI6iC,YACF,MAAQqc,gBAAiBt2G,KACzB,OAAqB,OAAjBs2G,EACK,EAEFA,EAAarc,KACtB,CAEIgkB,kBACF,MAAQ3H,gBAAiBt2G,KACzB,OAAqB,OAAjBs2G,EACK,EAKFj/F,KAAK+/C,IAAIk/C,EAAa9b,IADM,GAD/Bx6F,KAAK0vC,OAAOkuE,gBAAkBtH,EAAazd,YAC3Cyd,EAAape,gBACqC,EACxD,CAEYgmB,0BACV,MAAQvnG,QAAO2/F,gBAAiBt2G,KAChC,IAAK2W,IAAU2/F,EACb,OAAO,EAET,MAAM6H,EAAiBxnG,EAAMynG,SAAS97G,OACtC,OACG67G,EACGxnG,EAAMynG,SAASjjC,IAAIgjC,EAAiB,GACpC7H,EAAanc,MAAQn6F,KAAKwnB,WAElC,CAEOk/C,UACL1mE,KAAKo1G,sBACLp1G,KAAKw7G,mBACLx7G,KAAKs2G,aAAe,KAEpBt2G,KAAKy0G,IAAMz0G,KAAKm9G,kBAAoB,IACtC,CAEQxI,oBACN30G,KAAKy0G,IAAInxF,GAAG2lE,EAAOE,eAAgBnpF,KAAKu7G,gBAAiBv7G,MACzDA,KAAKy0G,IAAInxF,GAAG2lE,EAAOG,gBAAiBppF,KAAKw7G,iBAAkBx7G,MAC3DA,KAAKy0G,IAAInxF,GAAG2lE,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MAC7DA,KAAKy0G,IAAInxF,GAAG2lE,EAAOoB,cAAerqF,KAAK27G,eAAgB37G,MACvDA,KAAKy0G,IAAInxF,GAAG2lE,EAAOiD,MAAOlsF,KAAK03G,QAAS13G,KAC1C,CAEQo1G,sBACNp1G,KAAKy0G,IAAIY,IAAIpsB,EAAOE,eAAgBnpF,KAAKu7G,gBAAiBv7G,MAC1DA,KAAKy0G,IAAIY,IAAIpsB,EAAOG,gBAAiBppF,KAAKw7G,iBAAkBx7G,MAC5DA,KAAKy0G,IAAIY,IAAIpsB,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MAC9DA,KAAKy0G,IAAIY,IAAIpsB,EAAOoB,cAAerqF,KAAK27G,eAAgB37G,MACxDA,KAAKy0G,IAAIY,IAAIpsB,EAAOiD,MAAOlsF,KAAK03G,QAAS13G,KAC3C,CAEQu7G,gBACNl0F,EACA7mB,GAEAR,KAAK2W,MAAQnW,EAAKmW,MAClB3W,KAAK2W,MAAM4yB,iBAAiB,aAAcvpC,KAAKm9G,kBACjD,CAEQ3B,mBACFx7G,KAAK2W,QACP3W,KAAK2W,MAAM0nG,oBAAoB,aAAcr+G,KAAKm9G,mBAClDn9G,KAAK2W,MAAQ,KAEjB,CAEQq+F,oBACNh1G,KAAKs2G,aAAe,KACpBt2G,KAAKk9G,SAAW,KAChBl9G,KAAKi9G,WAAa,CACpB,CAEQtB,eACNt0F,GACE4mD,YAEFjuE,KAAKs2G,aAAeroC,EAChBA,EAAQ2pB,UACV53F,KAAKo9G,cAEFnvC,EAAQupB,MAAQx3F,KAAK2W,OACxB3W,KAAK2W,MAAM0nG,oBAAoB,aAAcr+G,KAAKm9G,kBAEtD,CAEQzF,QAAQrwF,EAAqB7mB,GAAiB,MAChDA,EAAKytE,UAAY6e,GAAaoC,uBAGlClvF,KAAKi9G,aACDqB,OAAJA,EAAIt+G,KAAKs2G,eAALgI,EAAmB9mB,MACrBzH,GAAOhtC,KACL,wEAGN,CAEQq6D,aACN,MAAQzmG,QAAO2/F,gBAAiBt2G,KAChC,IAAK2W,IAAU2/F,EACb,OAEFt2G,KAAKwnB,YAAc7Q,EAAM6Q,YAEzB,MAAM61F,EAAUr9G,KAAKu+G,iBACrB,GAAgB,OAAZlB,EACF,OAEFr9G,KAAKk9G,SAAWG,EAGhB,MAAQO,iBAAgBY,2BAA4Bx+G,KAAK0vC,OACzD,IAAKkuE,GAA8C,IAA5BY,EACrB,OAEF,MAAMf,EAAgBz9G,KAAKy9G,cAC3B,GAAsB,OAAlBA,EACF,OAEF,MAAMgB,EAAqBpB,EAAUI,EAI/BiB,EAAyBrnG,KAAK++E,IAClCp2F,KAAKs9G,WACLG,EAAgBnH,EAAape,gBAG/B,GACEoe,EAAa9e,MAFKinB,EAAqBC,GAIvCD,EAAqB,KACrBz+G,KAAKk+G,oBAAsB,EAC3B,CACA,MAAM9mD,EAAM//C,KAAK++E,IAAI,EAAG/+E,KAAK+/C,IAAI,EAAKonD,IAChCG,EACJtnG,KAAKkR,MACF,GAAK,EAAIlR,KAAK2yC,KAAI,IAAQy0D,EAAqBz+G,KAAKi+G,cACnD,IACA,GACNtnG,EAAMioG,aAAevnG,KAAK++E,IAAIh/B,EAAK//C,KAAK+/C,IAAI,EAAGunD,GAAK,MACpB,IAAvBhoG,EAAMioG,cAA6C,IAAvBjoG,EAAMioG,eAC3CjoG,EAAMioG,aAAe,EAEzB,CAEQZ,mBACN,MAAQ1H,gBAAiBt2G,KACzB,OAAqB,OAAjBs2G,EACK,KAEFA,EAAanc,KAAOmc,EAAa9b,GAC1C,CAEQ+jB,iBACN,MAAMR,EAAW/9G,KAAKg+G,mBACtB,OAAiB,OAAbD,EACK,KAEFA,EAAW/9G,KAAKwnB,WACzB,EC1NK,MAAMq3F,GAAa,CAAC,OAAQ,SAAU,SAAU,MAKvD,IAAkBC,MAAOC,GAAPD,OAAOE,MAAPF,MAAOG,KAkBlB,MAAMC,GAKXr/G,YAAYs/G,EAActN,EAAeuN,GAAgBp/G,KAJzDm/G,SAAG,OACHtN,UAAI,OACJuN,UAAI,EAGFp/G,KAAKm/G,IAAMA,EACXn/G,KAAK6xG,KAAOA,EACZ7xG,KAAKo/G,KAAOA,CACd,CAEAC,cAAcxZ,GACZ,MAAMnkG,EAAW,IAAIu6F,KAAKsN,IAAI1D,GAC9B,YAAiBpkG,IAAbzB,KAAKm/G,KACPz9G,EAAI4nG,aAAaz9C,IAAI,WAAY7rD,KAAKm/G,IAAI7kG,iBAE1B7Y,IAAdzB,KAAK6xG,MACPnwG,EAAI4nG,aAAaz9C,IAAI,YAAa7rD,KAAK6xG,KAAKv3F,YAE1Cta,KAAKo/G,MACP19G,EAAI4nG,aAAaz9C,IAAI,YAAa7rD,KAAKo/G,MAElC19G,EAAIwwC,IACb,EAGK,MAAMotE,GAqBXz/G,YAAYW,GAAmBR,KApBfu/G,YAAM,OACN5P,gBAAU,OACVlB,aAAO,OACP+Q,cAAQ,OACR/mG,YAAM,OACNnQ,QAAE,OACFyR,UAAI,OACJ80F,gBAAU,OACVl2F,WAAK,OACLq2F,mBAAa,OACtByQ,mBAAa,OACbxxC,aAAO,OACPyxC,cAAwB,EAAC1/G,KACzB2/G,UAAoB,EAAC3/G,KACrBiB,YAAM,OACN2+G,YAAsB,EAAC5/G,KACvB6/G,kBAAY,OACZn+G,SAAG,OACFo+G,OAAiB,EAGvB9/G,KAAK0B,IAAM,CAAClB,EAAKkB,KACjB1B,KAAKu/G,OAAS,CAAC/+G,EAAK2vF,OACpBnwF,KAAKyuG,QAAUjuG,EAAKiuG,QAChBjuG,EAAKytE,UACPjuE,KAAKiuE,QAAUztE,EAAKytE,SAEtBjuE,KAAKsI,GAAK9H,EAAK8H,IAAM,EACrBtI,KAAK+Z,KAAOvZ,EAAKuZ,KACjB/Z,KAAK2Y,MAAQnY,EAAKmY,OAAS,EAC3B3Y,KAAKyY,OAASjY,EAAKiY,QAAU,EAC7BzY,KAAK2vG,WAAanvG,EAAKmvG,WACvB3vG,KAAK6uG,WAAaruG,EAAKquG,WACvB7uG,KAAKgvG,cAAgBxuG,EAAKwuG,cAC1BhvG,KAAKw/G,SAAW,CAACh/G,EAAKquG,WAAYruG,EAAKmvG,YACpCnjG,OAAQ8iB,GAAMA,GACdpY,KAAK,KACLlV,QAAQ,YAAa,GAC1B,CAEI+9G,iBACF,OAAO1oG,KAAK+/C,IAAIp3D,KAAK4/G,YAAa5/G,KAAKyuG,QACzC,CAEIte,YACF,OAAOnwF,KAAKu/G,OAAOv/G,KAAK8/G,OAC1B,CAEItQ,gBACF,OAAOxvG,KAAKmwF,MAAM,eAAiB,GACrC,CAEI0V,UACF,OAAO7lG,KAAK0B,IAAI1B,KAAK8/G,SAAW,EAClC,CAEI9qB,YACF,OAAOh1F,KAAK8/G,MACd,CAEI9qB,UAAMvoF,GACR,MAAMuzG,EAAWvzG,EAAQzM,KAAK0B,IAAIY,OAC9BtC,KAAK8/G,SAAWE,IAClBhgH,KAAK0/G,cAAgB,EACrB1/G,KAAK2/G,UAAY,EACjB3/G,KAAKiuE,aAAUxsE,EACfzB,KAAK8/G,OAASE,EAElB,CAEIC,mBAAmC,MACrC,OAAOC,OAAPA,EAAOlgH,KAAKy/G,oBAALS,IAAqBlgH,KAAKg1F,MACnC,CAEImrB,kBAAkC,MACpC,OAAOC,OAAPA,EAAOpgH,KAAK6/G,mBAALO,IAAoBpgH,KAAKg1F,MAClC,CAEAqrB,YAAY7/G,GACVR,KAAK0B,IAAI0G,KAAK5H,EAAKkB,KACnB1B,KAAKu/G,OAAOn3G,KAAK5H,EAAK2vF,MACxB,EClJF,SAASmwB,GAAgBC,EAAoBC,GAC3C,MAAMC,EAAYD,EAAOhsB,SAEzB,GAAIxC,EAAgByuB,GAAY,CAG9B,IACIjqB,EADA9tF,EAAmB,EAEnB83G,EAAOrsB,GAAKosB,EAASpsB,IACvBzrF,EAAW+3G,EAAYF,EAAS//F,MAChCg2E,EAAO+pB,IAEP73G,EAAW63G,EAAS//F,MAAQigG,EAC5BjqB,EAAOgqB,GAELhqB,EAAK9tF,WAAaA,IACpB8tF,EAAK9tF,SAAWA,QAOhB83G,EAAOhgG,MAJAggG,EAAOrsB,GAAKosB,EAASpsB,GACXosB,EAAShsB,KAAOisB,EAAOjsB,IAExBgsB,EAASzrB,UACVyrB,EAAS//F,OAAS+/F,EAASzrB,UAAYyrB,EAAS//F,OAEhD+/F,EAAS//F,MAAQ+/F,EAAS73G,SAG5B2O,KAAK+/C,IAAImpD,EAAS//F,MAAQggG,EAAO93G,SAAU,EAE9D,CAEO,SAASg4G,GACdzyC,EACAuoB,EACAhC,EACAC,EACAC,EACAC,GAE4BF,EAASD,GACV,IACzBzE,GAAOhtC,KAAK,2CAA4CyzC,GACxD/B,EAASD,EAAWgC,EAAK9tF,SACzBisF,EAASD,EAAW8B,EAAK9tF,UAE3B,IAAImsF,EAAcL,EACdM,EAAYL,EAChB,MAAMksB,EAAenqB,EAAKhC,SACpBosB,EAAapqB,EAAK/B,OACxB,GAAIrC,EAAgBuuB,GAAe,CAEjC,MAAM/rB,GAAWv9E,KAAK4gB,IAAI0oF,EAAensB,GAIvCgC,EAAK5B,SAHFpC,EAAgBgE,EAAK5B,UAGRv9E,KAAK+/C,IAAIw9B,GAAU4B,EAAK5B,UAFxBA,GAKlBC,EAAcx9E,KAAK+/C,IAAIo9B,EAAUmsB,GACjCnsB,EAAWn9E,KAAK++E,IAAI5B,EAAUmsB,GAC9BjsB,EAAWr9E,KAAK++E,IAAI1B,EAAU8B,EAAK9B,UAEnCI,EAAYz9E,KAAK++E,IAAI3B,EAAQmsB,GAC7BnsB,EAASp9E,KAAK+/C,IAAIq9B,EAAQmsB,GAC1BjsB,EAASt9E,KAAK+/C,IAAIu9B,EAAQ6B,EAAK7B,OAAM,CAGvC,MAAMsF,EAAQzF,EAAWgC,EAAKh2E,MACX,IAAfg2E,EAAKh2E,QACPg2E,EAAKh2E,MAAQg0E,GAEfgC,EAAK9tF,SAAW+rF,EAAS+B,EAAKh2E,MAC9Bg2E,EAAKhC,SAAWA,EAChBgC,EAAK3B,YAAcA,EACnB2B,EAAK9B,SAAWA,EAChB8B,EAAK/B,OAASA,EACd+B,EAAK1B,UAAYA,EACjB0B,EAAK7B,OAASA,EAEd,MAAMR,GAAKqC,EAAKrC,GAEhB,IAAKlmB,GAAWkmB,GAAKlmB,EAAQ+pB,SAAW7D,GAAKlmB,EAAQkpB,MACnD,OAAO,EAET,IAAI3uD,GACJ,MAAMq4E,GAAU1sB,GAAKlmB,EAAQ+pB,QACvBZ,GAAYnpB,EAAQmpB,UAQ1B,IAFAA,GAAUypB,IAAWrqB,EAEhBhuD,GAAIq4E,GAASr4E,GAAI,EAAGA,KACvB83E,GAAgBlpB,GAAU5uD,IAAI4uD,GAAU5uD,GAAI,IAI9C,IAAKA,GAAIq4E,GAASr4E,GAAI4uD,GAAU90F,OAAS,EAAGkmC,KAC1C83E,GAAgBlpB,GAAU5uD,IAAI4uD,GAAU5uD,GAAI,IAE9C,OAAIylC,EAAQopB,cACVipB,GAAgBlpB,GAAUA,GAAU90F,OAAS,GAAI2rE,EAAQopB,cAG3DppB,EAAQ8oB,SAAW9oB,EAAQ+oB,gBAAiB,EACrCiD,CACT,CAsPO,SAAS6mB,GACdC,EACAC,GAEA,MAAMC,EACJD,EAAWhpB,QAAUgpB,EAAWvoB,gBAAkBsoB,EAAW/oB,QACzDkpB,EAAeH,EAAW3pB,UAC5B6pB,EAAQ,GAAKA,GAASC,EAAa5+G,QAGvC6+G,GAAWH,EAAYE,EAAaD,GAAOzgG,MAC7C,CAEO,SAAS2gG,GAAWlzC,EAAuBztD,GAChD,GAAIA,EAAO,CACT,MAAM42E,EAAYnpB,EAAQmpB,UAC1B,QAAS5uD,EAAIylC,EAAQwqB,gBAAiBjwD,EAAI4uD,EAAU90F,OAAQkmC,IAC1D4uD,EAAU5uD,GAAGhoB,OAASA,EAEpBytD,EAAQopB,eACVppB,EAAQopB,aAAa72E,OAASA,GAGpC,CAyDO,SAAS4gG,GACdxjE,EACAu2C,EACAktB,GACa,MACb,OAAU,MAALzjE,KAAOqwB,QAGLqzC,GAASC,OAADA,EAAC3jE,EAAMqwB,cAANszC,IAAejqB,SAAUnD,EAAIktB,GAFpC,IAGX,CAEO,SAASC,GACdhqB,EACAnD,EACAktB,GAEA,GAAI/pB,EACF,QAAS9uD,EAAI8uD,EAASh1F,OAAQkmC,KAAO,CACnC,MAAMqpE,EAAOva,EAAS9uD,GACtB,GAAIqpE,EAAK31E,QAAUmlF,GAAaxP,EAAKt3D,SAAS45C,KAAOA,EACnD,OAAO0d,EAIb,OAAO,IACT,CC/dO,SAAS2P,GAAe3gG,GAC7B,OAAQA,EAAMotD,SACZ,KAAK6e,GAAayB,kBAClB,KAAKzB,GAAa+B,iBAClB,KAAK/B,GAAaiB,mBAClB,KAAKjB,GAAaY,sBAChB,OAAO,EAEX,OAAO,CACT,CAEO,SAAS+zB,GACd1L,EACAl1F,GAEA,MAAM6gG,EAAYF,GAAe3gG,GACjC,OAAOk1F,EAAW/mG,SAAW0yG,EAAY,UAAY,SAA1B,QAC7B,CAEO,SAASC,GACdC,EACAC,GAGA,MAAMC,EACoB,WAAxBF,EAAYG,QAAuB,EAAI1qG,KAAK6qD,IAAI,EAAG2/C,GACrD,OAAOxqG,KAAK++E,IACV0rB,EAAgBF,EAAY3K,aAC5B2K,EAAYzK,gBAEhB,CAEO,SAAS6K,GACdC,GAEA,gBACKA,GACA,CACD7L,WAAY,KACZD,aAAc,MAGpB,CAEO,SAAS+L,GACdN,EACAC,EACAH,EACAS,GAEA,QACIP,GACFC,EAAaD,EAAY7K,cAKtB,SAASqL,GAAmBD,GAEjC,OACkB,IAAfA,IAAyC,IAArBx8E,UAAU08E,UAC5BF,IAAeA,EAAa,KAAOA,EAAa,IAEvD,CAVKC,CAAmBD,MAAiBT,EAEzC,CCzDA,MAAMY,GAAe,CAgBnB3rF,OAAQ,SACNoD,EACAwoF,GAEA,IAAIC,EAAmB,EACnBC,EAAmB1oF,EAAKz3B,OAAS,EACjCogH,EAA8B,KAC9BC,EAA2B,KAE/B,KAAOH,GAAYC,GAAU,CAC3BC,GAAiBF,EAAWC,GAAY,EAAK,EAC7CE,EAAiB5oF,EAAK2oF,GAEtB,MAAME,EAAmBL,EAAaI,GACtC,GAAIC,EAAmB,EACrBJ,EAAWE,EAAe,YACjBE,EAAmB,GAG5B,OAAOD,EAFPF,EAAWC,EAAe,CAEnBC,EAIX,OAAO,IACT,GCaK,SAASE,GACdC,EACA1rB,EACA2rB,EAAoB,EACpBC,EAAiC,GAEjC,IAAIC,EAA4B,KAUhC,GATIH,EACFG,EACE7rB,EACG0rB,EAAa3uB,GAAiBiD,EAAU,GAAGjD,GAAgB,IACzD,KACgB,IAAd4uB,GAA0C,IAAvB3rB,EAAU,GAAG52E,QACzCyiG,EAAW7rB,EAAU,IAIrB6rB,GAEE,IADFC,GAA4BH,EAAWC,EAAwBC,GAG/D,OAAOA,EAGT,MAAME,EAAgBb,GAAa3rF,OACjCygE,EACA8rB,GAA4BhnB,KAAK,KAAM6mB,EAAWC,IAEpD,OAAIG,GAAkBA,IAAkBL,GAAiBG,EAIlDA,EAHEE,CAIX,CASO,SAASD,GACdH,EAAY,EACZC,EAAyB,EACzBjG,GAGA,GACEA,EAAUv8F,OAASuiG,GACnBhG,EAAUv8F,MAAQu8F,EAAUr0G,SAAWq6G,EAEvC,OAAO,EAgBT,MAAMK,EAA2B/rG,KAAK++E,IACpC4sB,EACAjG,EAAUr0G,UAAYq0G,EAAUnoB,SAAWmoB,EAAUnoB,SAAW,IAElE,OACEmoB,EAAUv8F,MAAQu8F,EAAUr0G,SAAW06G,GACvCL,EAEO,EAEPhG,EAAUv8F,MAAQ4iG,EAA2BL,GAC7ChG,EAAUv8F,OAGH,EAGF,CACT,CAUO,SAAS6iG,GACdC,EACAN,EACAjG,GAEA,MAAMqG,EAIA,IAHJ/rG,KAAK++E,IACH4sB,EACAjG,EAAUr0G,UAAYq0G,EAAUnoB,SAAWmoB,EAAUnoB,SAAW,IAKpE,OAD2BmoB,EAAUtnB,oBAAsB,GAC/B2tB,EAA2BE,CACzD,CCnJA,MAAMC,GAAgC,IAoftC,SAASC,GACPC,EACAjjH,EACAkjH,GAGA,GACEt0F,YAAYC,MAAQo0F,EAAmBE,gBACvCJ,GAEA,OAAO,EAGT,MAAMK,EAAmBH,EAAmBx1C,QAC5C,GAAIztE,EAAKytE,UAAY6e,GAAa4B,UAAYk1B,GAAoBpjH,EAAKg2F,KAAM,CAC3E,MACMqtB,EAAgBhB,GACpB,KACAe,EAAiBxsB,UAHF52F,EAAKg2F,KAAKh2E,OAM3B,GAAIqjG,IAAkBA,EAAczuB,IAClC,OAAO,EAIX,GACEsuB,GACAD,EAAmB34D,OAAOxoD,OAASohH,EAAoB54D,OAAOxoD,OAC9D,CACA,MAAMwhH,EACJL,EAAmB34D,OAAO24D,EAAmB34D,OAAOxoD,OAAS,GAC/D,GACEshH,GACAE,EAAmBttB,MACnBh2F,EAAKg2F,MACLn/E,KAAK4gB,IAAI6rF,EAAmBttB,KAAKh2E,MAAQhgB,EAAKg2F,KAAKh2E,OACf,EAAlCojG,EAAiB1rB,eAEnB,OAAO,EAGX,OAAO,CACT,CCjiBe,MAAM6rB,GAQnBlkH,YAAY40G,EAAUuP,GAAmBhkH,KAP/By0G,SAAG,OACHtjE,OAAgB,EAAEnxC,KAClBikH,kBAA2B,EAAEjkH,KAC7BkkH,SAAmB,EAAKlkH,KACxB6vF,SAAG,OACH9sC,UAAI,EAGZ/iD,KAAK6vF,IAAME,GAAOF,IAAIqM,KAAKnM,GAAWi0B,SACtChkH,KAAK+iD,KAAOgtC,GAAOhtC,KAAKm5C,KAAKnM,GAAWi0B,SACxChkH,KAAKy0G,IAAMA,CACb,CAEO/tC,UACL1mE,KAAKmkH,aAELnkH,KAAKy0G,IAAMz0G,KAAK6vF,IAAM7vF,KAAK+iD,KAAO,IACpC,CAEUohE,aACRjkE,aAAalgD,KAAKmxC,OAClBnxC,KAAKmxC,OAAQ,CACf,CAEOyjE,YACL50G,KAAKkkH,SAAU,EACflkH,KAAKikH,kBAAmB,EACxBjkH,KAAKokH,cACP,CAEOtP,WACL90G,KAAKkkH,SAAU,EACflkH,KAAKmkH,YACP,CAEUE,aACRC,EACAt8F,GAEA,MAAM+wE,EAAmB/wE,GAAU+wE,iBACnC,GAAIA,EAAkB,CACpB,IAAIwrB,GAAa,EACjB,QAAS/7E,EAAI,EAAGA,EAAIuwD,EAAiBz2F,OAAQkmC,IAAK,CAChD,MAAM6nD,EAAO0I,EAAiBvwD,GAC9B,IAAIq9D,EACJ,IACEA,EAAM,IAAI5J,KAAKsN,IAAIlZ,EAAK+f,IAAKpoF,EAAStmB,KAAKwwC,IAM7C,OALSrxB,GACPkvE,GAAOhtC,KACgDliC,0DAEvDglF,EAAMxV,EAAK+f,KAAO,EACpB,CAGA,GAAIvK,IAAQye,EAAa,CACvBC,EAAa/7E,EACb,MACSq9D,IAAQye,EAAY1rF,UAAU,EAAGitE,EAAIvjG,UAC9CiiH,EAAa/7E,GAGjB,IAAmB,IAAf+7E,EAAmB,CACrB,MAAMl0B,EAAO0I,EAAiBwrB,GACxBpF,EAAMl3F,SAASooE,EAAK,cAAgBroE,GAAU4xE,WACpD,IAAIiY,EAAO5pF,SAASooE,EAAK,eAAiBroE,GAAU8xE,cACpD,GAAI95F,KAAKy0G,IAAI/kE,OAAOkuE,eAAgB,CAClC,MAAM4G,EAAcntG,KAAK++E,IACvBpuE,EAASwyE,IAAMxyE,EAAS6wE,WACxB7wE,EAASkwE,gBAEP2Z,GAAQ,GAAK2S,EAAcx8F,EAAS6wE,aACtCgZ,GAAQ,GAGZ,OAAO,IAAIqN,GACTC,EACAtN,GAAQ,EAAIA,OAAOpwG,EACnBq9G,MACF,EAGN,CAEUsF,aAAaK,IACS,IAA1BzkH,KAAKikH,mBACPjkH,KAAKikH,iBAAmBhoB,KAAK7sE,YAAYC,MAG7C,CAEUq1F,mBACRC,GAEA,OACE3kH,KAAKkkH,WACHS,KACAA,EAASjjH,OACTijH,EAAS12C,SAAW02C,EAAS12C,QAAQupB,KAE3C,CAEUotB,qBACRD,GAEA,OACiB,IAAf3kH,KAAKmxC,QACqB,IAA1BnxC,KAAKikH,kBACLjkH,KAAK0kH,mBAAmBC,EAE5B,CAEUE,eACR3oF,EACA17B,EACAskH,GAEA,MAAQ72C,UAAS8mB,SAAUv0F,EAGrB6uB,EAAM4sE,KAAK7sE,YAAYC,MACvB01F,EAAUhwB,EAAM7zF,QAAQ2xF,MAC1Bx7E,KAAK+/C,IAAI,EAAG/nC,EAAM0lE,EAAM7zF,QAAQ2xF,OAChC,EAIJ,GAHA5kB,EAAQypB,iBAAmB78E,KAAKwU,MAAQ01F,EAGpC92C,EAAQupB,MAAQstB,WAAiBttB,KAAM,CAezC,GAdAvpB,EAAQyrB,SAASorB,GACbA,GACF9kH,KAAK6vF,IACc3zD,sBACf+xC,EAAQ2pB,SACJ,aAAe3pB,EAAQ2rB,WAAa,IAAM3rB,EAAQ6rB,cAClD,YAKNgrB,GAAmB72C,EAAQmpB,UAAU90F,OAAS,GLtBjD,SAAS0iH,GACdjE,EACAC,GAGA,IAAItQ,EAAsC,KAC1C,MAAMwQ,EAAeH,EAAW3pB,UAChC,QAAS5uD,EAAI04E,EAAa5+G,OAAS,EAAGkmC,GAAK,EAAGA,IAAK,CACjD,MAAMy8E,EAAU/D,EAAa14E,GAAG0sD,YAChC,GAAI+vB,EAAS,CACXvU,EAAqBuU,EACrB,OAIAlE,EAAW1pB,qBAEN0pB,EAAW1pB,aAAa5C,OAIjC,IACIywB,EADAC,EAAW,EA0Df,GAkIK,SAASC,GACdrE,EACAC,EACAqE,GAEA,MAAM5sB,EAAkBuoB,EAAWvoB,gBAC7Bj4E,EACJnJ,KAAK+/C,IAAI2pD,EAAW/oB,QAASgpB,EAAWhpB,SAAWgpB,EAAWhpB,QAC1D7c,GACH4lC,EAAW1pB,aAAe,EAAI,IAC9BoB,EACGuoB,EAAW7pB,MACX9/E,KAAK++E,IAAI2qB,EAAW5pB,MAAO6pB,EAAW7pB,QAC1C6pB,EAAWhpB,QACPipB,EAAQD,EAAWhpB,QAAU+oB,EAAW/oB,QACxCstB,EAAWtE,EAAW3pB,aACxB2pB,EAAW5pB,UAAU/vC,OAAO25D,EAAW3pB,cACvC2pB,EAAW5pB,UACTmuB,EAAWxE,EAAW1pB,aACxB0pB,EAAW3pB,UAAU/vC,OAAO05D,EAAW1pB,cACvC0pB,EAAW3pB,UAEf,QAAS5uD,EAAIhoB,EAAOgoB,GAAK2yC,EAAK3yC,IAAK,CACjC,MAAMg9E,EAAUD,EAAStE,EAAQz4E,GACjC,IAAIi9E,EAAUH,EAAS98E,GACnBiwD,IAAoBgtB,GAAWj9E,EAAIiwD,IAErCgtB,EAAUzE,EAAW5pB,UAAU5uD,GAAKg9E,GAElCA,GAAWC,GACbJ,EAAeG,EAASC,EAAO,CAGrC,CA3NEL,CACErE,EACAC,EACA,CAACwE,EAAmBC,KACdD,EAAQnyB,SAIV8xB,EAAWK,EAAQjxB,GAAKkxB,EAAQlxB,IAGhCuf,EAAgB0R,EAAQhxB,WACxBkxB,EAAgBF,EAAQ/wB,UAExBgxB,EAAQjlG,MAAQilG,EAAQjxB,SAAWgxB,EAAQhxB,SAC3CixB,EAAQ/wB,SAAW8wB,EAAQ9wB,SAC3B+wB,EAAQ5wB,YAAc2wB,EAAQ3wB,YAE9B4wB,EAAQhxB,OAAS+wB,EAAQ/wB,OACzBgxB,EAAQ9wB,OAAS6wB,EAAQ7wB,OACzB8wB,EAAQ3wB,UAAY0wB,EAAQ1wB,UAC5B2wB,EAAQ/8G,SACL88G,EAAQ/wB,OAAqB+wB,EAAQhxB,SAEpCixB,EAAQ/8G,WACVw8G,EAAUO,GAIZzE,EAAWjqB,SAAWiqB,EAAWhqB,gBAAiB,GAEpDyuB,EAAQnyB,kBAAoBkyB,EAAQlyB,kBACpCmyB,EAAQpxB,OAASmxB,EAAQnxB,OACzBoxB,EAAQ1wB,MAAQywB,EAAQzwB,MACxB0wB,EAAQzwB,MAAQwwB,EAAQxwB,MACpBwwB,EAAQtwB,cACVuwB,EAAQvwB,YAAcswB,EAAQtwB,YAC9Bwb,EAAqB8U,EAAQtwB,eAK/Bwb,IACuBsQ,EAAW3pB,aAChC2pB,EAAW5pB,UAAU/vC,OAAO25D,EAAW3pB,cACvC2pB,EAAW5pB,WACE7tF,QAASitF,IAAS,QAE9BA,EAAKtB,aACNsB,EAAKtB,YAAY7B,UAA6B,OAAvBsyB,EAAKjV,QAAkB,EAAlBiV,EAAoBtyB,WAEhDmD,EAAKtB,YAAcwb,KAKrBsQ,EAAWvoB,gBAEb,GADAuoB,EAAW/nB,kBAAoB+nB,EAAW5pB,UAAU7rF,KAAMirF,IAAUA,GAChEwqB,EAAW/nB,kBAAmB,CAChClJ,GAAOhtC,KACL,+EAEF,QAASva,EAAIw4E,EAAWvoB,gBAAiBjwD,KACvCw4E,EAAW5pB,UAAUqO,QAEvBub,EAAWhpB,QAAUgpB,EAAW5pB,UAAU,GAAGjD,GAC7C6sB,EAAWjpB,QAAUipB,EAAW5pB,UAAU,GAAG7C,QACpCysB,EAAWxoB,oBACpBwoB,EAAWzpB,WAoEjB,SAASquB,GACPC,EACAC,EACAptB,GAEA,MAAMnB,EAAazF,GAAc,GAAI+zB,GACrC,OAAIntB,GACFA,EAA0BnvF,QAASjB,WAC1BivF,EAAWjvF,EAAE,GAGxBsgC,OAAOkP,KAAKguE,GAAiBv8G,QAASjB,IACpC,MAAMgpG,EAAY,IAAIhgB,GAAUw0B,EAAgBx9G,GAAI+nF,KAAMkH,EAAWjvF,IACjEgpG,EAAU/e,QACZgF,EAAWjvF,GAAMgpG,EAEjBvhB,GAAOhtC,KACqDk8B,+DAAK8mC,UAC7DD,EAAgBx9G,GAAI+nF,SAExB,GAGGkH,CACT,CA5F8BquB,CACtB7E,EAAWxpB,WACXypB,EAAWzpB,WACXypB,EAAWtoB,4BAKjB,MAAMstB,EAAehF,EAAW5pB,UAChC,GAAI+tB,EAAU,CACZp1B,GAAOhtC,KAAK,gEACZ,QAASva,EAAI,EAAGA,EAAIw9E,EAAa1jH,OAAQkmC,IACvCw9E,EAAax9E,GAAG+rD,IAAM4wB,EAGtBnE,EAAWvoB,kBACbuoB,EAAWjpB,QAAUipB,EAAW5pB,UAAU,GAAG7C,IA8E1C,SAAS0xB,GACdC,EACAC,EACAd,GAEA,GAAIa,GAAYC,EAAU,CACxB,IAAIlF,EAAQ,EACZ,QAASz4E,EAAI,EAAGgd,EAAM0gE,EAAS5jH,OAAQkmC,GAAKgd,EAAKhd,IAAK,CACpD,MAAM49E,EAAUF,EAAS19E,GACnB69E,EAAUF,EAAS39E,EAAIy4E,GAE3BmF,GACAC,GACAD,EAAQlqF,QAAUmqF,EAAQnqF,OAC1BkqF,EAAQ7rE,SAAS45C,KAAOkyB,EAAQ9rE,SAAS45C,GAEzCkxB,EAAee,EAASC,GAExBpF,KAIR,CAhGEgF,CACElF,EAAWzpB,SACX0pB,EAAW1pB,SACX,CAAC8uB,EAAeC,KACdA,EAAQ/yB,kBAAoB8yB,EAAQ9yB,kBACpC+yB,EAAQtxB,MAAQqxB,EAAQrxB,QAKxBmwB,EACFxE,GACEM,EACAkE,EACAA,EAAQ1wB,SACR0wB,EAAQzwB,OACRywB,EAAQxwB,SACRwwB,EAAQvwB,QAMVmsB,GAAcC,EAAYC,GAGxBgF,EAAa1jH,SACf0+G,EAAW7oB,cAAgB6oB,EAAW7mB,KAAO6rB,EAAa,GAAGxlG,OAG/DwgG,EAAW9nB,eAAiB6nB,EAAW7nB,eACvC8nB,EAAW5nB,WAAa2nB,EAAW3nB,WACnC,MAAM1B,EAAmBspB,EAAWtpB,iBACpC,GAAIspB,EAAWppB,UAAYF,EAAkB,CAC3C,MAAMyC,EAAO6mB,EAAW7mB,KACnB6mB,EAAW5nB,aACd4nB,EAAW9nB,eAAiBxB,EAC5BspB,EAAW5nB,WAAae,GAE1B6mB,EAAW7nB,aAAezB,EAC1BspB,EAAW3nB,SAAWc,OAEtB6mB,EAAW7nB,aAAe4nB,EAAW5nB,aACrC6nB,EAAW3nB,SAAW0nB,EAAW1nB,SACjC2nB,EAAWtpB,iBAAmBqpB,EAAWrpB,gBAE7C,CKtIQstB,CAAaF,EAAiB72C,IAE3BjuE,KAAKkkH,UAAYj2C,EAAQupB,KAC5B,OAEF,IAAIqe,EACAsJ,EACAtN,EACJ,GAAI5jC,EAAQqqB,gBAAkBrqB,EAAQkpB,OAASlpB,EAAQ2pB,SAAU,CAE/D,MAAMgmB,GAAiB59G,KAAKy0G,IAAI/kE,OAAOkuE,eACjChkB,GAAa3rB,EAAQ2rB,WACrB0sB,GAAQr4C,EAAQkpB,MAChB2C,GAAgB7rB,EAAQ6rB,cAExBysB,GAAW3sB,KAAe0sB,IADG,IAAlBxsB,IAKfqlB,EAAMoH,GAAWD,GAAQ,EAAI1sB,GAC7BiY,EAAO0U,GAHgB3I,GAAiB,EAAI9jB,GAGPA,GAAgB,GAErDqlB,EAAMmH,GAAQ,EAIhB,MAAME,GAAev4C,EAAQusB,IAE7B,IAAIgqB,GAAcntG,KAAK++E,IADRowB,GAAev4C,EAAQwpB,UAE3BxpB,EAAQ4qB,WACQ,IAAzB5qB,EAAQiqB,gBAEV,GAAIssB,GAAc,EAAG,CACnB,GAAIM,GAAmBN,GAAcM,EAAgB9rB,WAGnDh5F,KAAK+iD,KACF,oCAAmC+hE,EAAgB9rB,kBAAkBwrB,yBAAkCv2C,EAAQusB,OAElHgqB,GAAc,MACT,CACL,MAAMiC,GAAWpvG,KAAKC,MAAMktG,GAAcv2C,EAAQiqB,gBAClDinB,GAAOsH,QACMhlH,IAATowG,IAIFA,GAHcx6F,KAAKkR,MAChBi8F,GAAcv2C,EAAQiqB,eAAkBjqB,EAAQ4qB,aAIrD74F,KAAK6vF,IACF,oBACC5hB,EAAQwpB,4BACS+uB,GAAa5tE,QAC9B,aACU4rE,cAAuBiC,cAAoB5U,IACzD,CAEF5jC,EAAQ+qB,WAAawrB,GAQvB,GANA3O,EAAqB71G,KAAK0mH,sBACxBz4C,EACAztE,EAAKq1G,mBACLsJ,EACAtN,GAEE+L,KAAmB2I,GAErB,YADAvmH,KAAKokH,aAAavO,EAClB,MAEO5nC,EAAQqqB,iBACjBud,EAAqB71G,KAAK0mH,sBACxBz4C,EACAztE,EAAKq1G,mBACLsJ,EACAtN,IAGJ,MAAM8U,EAAa3mH,KAAKy0G,IAAImS,sBAGtBC,GLsKL,SAASC,GACd9F,EACA+F,EAA+B12E,KAE/B,IAAIw2E,EAAiB,IAAO7F,EAAW9oB,eAEvC,GAAI8oB,EAAWrpB,QAAS,CAEtB,MAAMP,EAAY4pB,EAAW5pB,UAE7B,GACEA,EAAU90F,QAFuB,EAGjCukH,EAA8CE,EAC9C,CACA,MAAMC,EACuC,IAA3C5vB,EAAUA,EAAU90F,OAAS,GAAGoG,SAC9Bs+G,EAAsBH,IACxBA,EAAiBG,SAQrBH,GAAkB,EAGpB,OAAOxvG,KAAKkR,MAAMs+F,EACpB,CKnM6BC,CACrB74C,EAFuD,KAA3BA,EAAQksB,MADrBwsB,EAAaA,EAAWxrC,IAAMwrC,EAAWnhE,IAAM,KAM5DyoB,EAAQ0pB,SAAWtoE,EAAMrvB,KAAKikH,iBAAmB4C,KACnD7mH,KAAKikH,iBAAmBlvB,EAAM7zF,QAAQsf,YAG5B/e,IAAR09G,GAAqBlxC,EAAQqqB,eAC/Bt4F,KAAKikH,iBACHlvB,EAAM7zF,QAAQ2xF,MACdg0B,IACsB,IAArB54C,EAAQ4qB,YAAqB,MAEN,IAA1B74F,KAAKikH,kBACLjkH,KAAKikH,iBAAmB4C,GAAiBx3F,EAEzCrvB,KAAKikH,iBAAmB50F,EACfrvB,KAAKikH,iBAAmB50F,GAAO,IACxCrvB,KAAKikH,kBAAoB4C,IAE3B,IAAII,GAA2BjnH,KAAKikH,iBAAmB50F,EACvD43F,GAA2B5vG,KAAK+/C,IAAI,EAAG6vD,IACvCjnH,KAAK6vF,IACF,wBAAuB3zD,QAAY7kB,KAAKkR,MACvC0+F,UAmBJjnH,KAAKmxC,MAAQ8qD,KAAKj8C,WAChB,IAAMhgD,KAAKokH,aAAavO,GACxBoR,GACF,MAEAjnH,KAAKmkH,YAET,CAEQuC,sBACNz4C,EACAi5C,EACA/H,EACAtN,GAEA,IAAIuN,ENvPD,SAAS+H,GAAal5C,EAAuBkxC,GAClD,MAAQ5mB,eAAcC,oBAAmBrB,SAAUlpB,EAEnD,OAAIsqB,SADyB92F,IAAR09G,EAAoBA,EAAMhoB,EAAQ,GACpBoB,EAC7BC,EACKsmB,MAEFA,OAEFA,KACT,CM6OeqI,CAAal5C,EAASkxC,GACjC,OAA8B,MAA1B+H,KAA4B9H,MAAQnxC,EAAQgrB,oBAC9CkmB,EAAM+H,EAA2B/H,IACjCtN,EAAOqV,EAA2BrV,KAClCuN,EAAON,OAEF,IAAII,GAAiBC,EAAKtN,EAAMuN,EACzC,CAEUgI,WAAWC,GACnB,MAAMC,EAAeD,EAAWp5C,QAC1ByzC,EAAYF,GAAe6F,GAC3BE,EAAcF,EAAWE,aACvBhkG,SAAQs+F,aAAa,EAAGD,eAAgB2F,GAAe,GACzDp3E,IACFo3E,KACA3F,IDpS4B4F,ICqS7BjkG,IACGgkG,EAAYE,UDtScC,ICuS1BnkG,GACN,GAAI4sB,EAAO,OAET,GADAnwC,KAAKikH,kBAAmB,EACpBpC,GAAcD,EAAY7K,YAC5B,OAAO,EAET,GAAI2K,GAAaiG,OAAJA,EAAIN,EAAW50D,UAAXk1D,EAAoB9R,mBAEnC71G,KAAK+iD,KACF,6BAA4B8+D,EAAa,KACxCD,EAAY7K,sBACHuQ,kCAEbtnH,KAAKokH,mBACA,CACL,MAAM9zE,EAAQqxE,GAAcC,EAAaC,GAEzC7hH,KAAKmxC,MAAQ8qD,KAAKj8C,WAAW,IAAMhgD,KAAKokH,eAAgB9zE,GACxDtwC,KAAK+iD,KAC0B8+D,+BAAa,KACxCD,EAAY7K,sBACHuQ,SAAoBh3E,MACjC,CAGF+2E,EAAWO,YAAa,EACxBL,EAAYE,UAAW,EAEzB,OAAOt3E,CACT,EC9TF,IAAI03E,GAEW,MAAMC,WAAwB/D,GAW3ClkH,YACE40G,EACAsT,GAEA7yE,MAAMu/D,EAAK,sBAAsBz0G,KAd3BgoH,QAAmB,GAAEhoH,KACrBioH,aAAsB,EAAEjoH,KACxBkoH,iBAAW,OACXC,aAA6B,KAAInoH,KACjCooH,mBAA4B,EAAEpoH,KAC9BqoH,kBAA2B,EAAEroH,KAC7BsoH,cAAQ,OAETC,sBAAgB,EAOrBvoH,KAAKsoH,SAAWP,EAChB/nH,KAAKq7G,oBACP,CAEQA,qBACN,MAAQ5G,OAAQz0G,KAChBy0G,EAAInxF,GAAG2lE,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACxDy0G,EAAInxF,GAAG2lE,EAAOc,gBAAiB/pF,KAAKwoH,iBAAkBxoH,MACtDy0G,EAAInxF,GAAG2lE,EAAOmB,aAAcpqF,KAAKyoH,cAAezoH,MAChDy0G,EAAInxF,GAAG2lE,EAAOsB,eAAgBvqF,KAAK0oH,gBAAiB1oH,MACpDy0G,EAAInxF,GAAG2lE,EAAOyB,qBAAsB1qF,KAAK2oH,qBAAsB3oH,MAC/Dy0G,EAAInxF,GAAG2lE,EAAOuC,YAAaxrF,KAAK4oH,aAAc5oH,MAC9Cy0G,EAAInxF,GAAG2lE,EAAOiD,MAAOlsF,KAAK03G,QAAS13G,KACrC,CAEQs7G,uBACN,MAAQ7G,OAAQz0G,KAChBy0G,EAAIY,IAAIpsB,EAAOa,iBAAkB9pF,KAAKg1G,kBAAmBh1G,MACzDy0G,EAAIY,IAAIpsB,EAAOc,gBAAiB/pF,KAAKwoH,iBAAkBxoH,MACvDy0G,EAAIY,IAAIpsB,EAAOmB,aAAcpqF,KAAKyoH,cAAezoH,MACjDy0G,EAAIY,IAAIpsB,EAAOsB,eAAgBvqF,KAAK0oH,gBAAiB1oH,MACrDy0G,EAAIY,IAAIpsB,EAAOyB,qBAAsB1qF,KAAK2oH,qBAAsB3oH,MAChEy0G,EAAIY,IAAIpsB,EAAOuC,YAAaxrF,KAAK4oH,aAAc5oH,MAC/Cy0G,EAAIY,IAAIpsB,EAAOiD,MAAOlsF,KAAK03G,QAAS13G,KACtC,CAEO0mE,UACL1mE,KAAKs7G,uBACLt7G,KAAKsoH,SAAW,KAChBtoH,KAAK6oH,cACL3zE,MAAMwxB,SACR,CAEOkuC,YACU50G,KAAKgoH,QAGbz+G,QAASq0C,IACdA,EAAM+hE,UAAY,EAClB/hE,EAAM8hE,cAAgB,IAGxBxqE,MAAM0/D,WACR,CAEQiU,cACN7oH,KAAKkoH,iBAAczmH,EACnBzB,KAAKqoH,kBAAmB,EACxBroH,KAAKooH,mBAAoB,EACzBpoH,KAAKmoH,aAAe,KACpBnoH,KAAKgoH,QAAU,EACjB,CAEQhT,kBACN3tF,EACA7mB,GAEAR,KAAK6oH,aACP,CAEUL,iBACRnhG,EACA7mB,GAEA,MAAMsJ,EAAkB,GAClBg/G,EAAqC,GAC3C,IAAIC,EAGJvoH,EAAKsJ,OAAOP,QAASy/G,IAA6B,MAChD,MAAM/Z,EAAa+Z,EAAY74B,OAIuB,KAAlD84B,WAAYtZ,iBAAZsZ,IAAwBljF,QAAQ,iBAClC8hF,QAAoB,kBAAkBxvE,KAAK1S,UAAUD,YACjDmiF,KACFmB,EAAYrZ,gBAAaluG,IAI7B,MACE8xF,QACAqb,SACA,aAAcsa,EACd,aAAcC,GACdC,cACAxZ,cACEX,EAIEsC,GAAc8X,GAFbF,IAAW,OAE0BH,EAAYva,WAAW2a,MAAcF,KAAata,IAC9Fma,EAAeD,EAASvX,IAEnBwX,EAKHA,EAAa1I,YAAY2I,IAJzBD,EAAe,IAAIzJ,GAAM0J,GACzBF,EAASvX,IAAYwX,EACrBj/G,EAAO1B,KAAK2gH,IAKdO,GAAWP,EAAc,QAASx1B,GAClC+1B,GAAWP,EAAc,OAAQnZ,GAAS,GAG5C5vG,KAAKupH,0BAA0Bz/G,EAAQtJ,EACzC,CAEQ+oH,0BACNC,EACAhpH,GAEA,IAAI+1G,EAA+B,GAC/BC,EAAkC,GAElCiT,GAAkB,EAClBC,GAAkB,EAClBC,GAAkB,EAGlB7/G,EAAS0/G,EAAiBh9G,OAC5B,EAAGmjG,cAAYd,cAAYl2F,SAAOF,UAAQu2F,qBACxCya,SAAuB9wG,KAASF,KAChCixG,QAAsB7a,IACtB8a,QAAsBha,MAEN,MAAbX,OAAe1sG,WACdqtG,IAAcnC,GAAsBmC,GAAY,aAChDd,IAAcrB,GAAsBqB,GAAY,YAYxD,IANK4a,GAAmBC,IAAoBC,IAC1C7/G,EAASA,EAAO0C,OACd,EAAGqiG,cAAYl2F,SAAOF,eAAeo2F,OAAiBl2F,KAASF,MAI7C,IAAlB3O,EAAOxH,OAiBT,YAfAq/C,QAAQC,UAAU//C,KAAK,KACrB,GAAI7B,KAAKy0G,IAAK,CACZ,MAAM5zF,GAAQ,IAAIsnE,MAChB,qDAEFnoF,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAac,mCACtB4qB,OAAO,EACP92G,IAAKlB,EAAKkB,IACVmf,SACA43F,OAAQ53F,GAAM2oF,SACf,IAMHhpG,EAAK+1G,cACPA,EAAc/1G,EAAK+1G,YAAY/pG,OAC5Bo0F,KACEA,GAAM+O,YAAcnC,GAAsB5M,GAAM+O,WAAY,UAGjEia,GAAsBrT,IAGpB/1G,EAAKu3G,YACPvB,EAAiBh2G,EAAKu3G,UACtB6R,GAAsBpT,IAGxB,MAAMqT,EAAiB//G,EAAOqN,MAAM,GAEpCrN,EAAO2Z,KAAK,CAACtV,GAAGE,KACVF,GAAEgiF,MAAM,gBAAkB9hF,GAAE8hF,MAAM,eAC5BhiF,GAAEgiF,MAAM,eAAiB,KAAO9hF,GAAE8hF,MAAM,eAAiB,IAC7D,GACA,EAEFhiF,GAAEsgG,UAAYpgG,GAAEogG,QACXtgG,GAAEsgG,QAAUpgG,GAAEogG,QAEnBtgG,GAAEgiF,MAAM,gBAAkB9hF,GAAE8hF,MAAM,cAElChiF,GAAEgiF,MAAMY,qBAAqB,cAC7B1iF,GAAE8hF,MAAMY,qBAAqB,cAG7B5iF,GAAEgiF,MAAM25B,QAAUz7G,GAAE8hF,MAAM25B,MAE1B37G,GAAEgiF,MAAMY,qBAAqB,SAC7B1iF,GAAE8hF,MAAMY,qBAAqB,SAG7B04B,GAAmBt7G,GAAEsK,SAAWpK,GAAEoK,OAC7BtK,GAAEsK,OAASpK,GAAEoK,OAEf,GAGT,IAAIsxG,EAAuBF,EAAe,GAC1C,GAAI7pH,KAAKsoH,WACPx+G,EAAS9J,KAAKsoH,SAAS0B,mBAAmBlgH,GACtCA,EAAOxH,SAAWunH,EAAevnH,QACnC,QAASkmC,GAAI,EAAGA,GAAIqhF,EAAevnH,OAAQkmC,KACzC,GAAIqhF,EAAerhF,IAAGgnE,YAAc1lG,EAAO,GAAG0lG,UAAW,CACvDua,EAAuBF,EAAerhF,IACtC,MAMRxoC,KAAKgoH,QAAUl+G,EAGf,QAAS0+B,GAAI,EAAGA,GAAI1+B,EAAOxH,OAAQkmC,KACjC,GAAI1+B,EAAO0+B,MAAOuhF,EAAsB,CACtC/pH,KAAKioH,YAAcz/E,GACnBxoC,KAAK6vF,IACF,oBAAmB/lF,EAAOxH,yCAAyCynH,EAAqBtb,WAE3F,MAMJ,MACMwb,GAA4B,CAChCngH,SACAysG,cACAC,iBACAlI,YAAa9tG,EAAK8tG,YAClBC,YAAa/tG,EAAK+tG,YAClB2b,WAAYlqH,KAAKioH,YACjBlzB,MAAOv0F,EAAKu0F,MACZ4B,MAAOgzB,EACP/yB,MAAO8yB,EACPS,WAXgBR,IAAoBD,IAWZnT,EAAYhrG,KAAM8pC,MAAQA,GAAE3zC,MAEtD1B,KAAKy0G,IAAInrC,QAAQ2f,EAAOe,gBAAiBigC,KAGrCjqH,KAAKy0G,IAAI/kE,OAAO06E,eAAiBpqH,KAAKy0G,IAAI4V,iBAC5CrqH,KAAKy0G,IAAIG,UAAU50G,KAAKy0G,IAAI/kE,OAAOmlE,cAEvC,CAEI/qG,aACF,OAA4B,IAAxB9J,KAAKgoH,QAAQ1lH,OACR,KAEFtC,KAAKgoH,OACd,CAEIpqE,YACF,OAAO59C,KAAKooH,iBACd,CAEIxqE,UAAM0sE,GACR,MAAMxgH,EAAS9J,KAAKgoH,QACpB,GAAsB,IAAlBl+G,EAAOxH,OACT,OAGF,GAAIgoH,EAAW,GAAKA,GAAYxgH,EAAOxH,OAAQ,CAE7C,MAAMue,EAAQ,IAAIsnE,MAAM,qBAClBqwB,EAAQ8R,EAAW,EASzB,GARAtqH,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWK,YACjB5e,QAAS6e,GAAamB,mBACtBrwC,MAAO0sE,EACP9R,QACA33F,QACA43F,OAAQ53F,EAAM2oF,UAEZgP,EACF,OAEF8R,EAAWjzG,KAAK++E,IAAIk0B,EAAUxgH,EAAOxH,OAAS,EAAC,CAGjD,MAAMioH,EAAiBvqH,KAAKooH,kBACtBoC,EAAYxqH,KAAKmoH,aACjBsC,EAAgBD,EAAYA,EAAUr6B,MAAM,mBAAgB1uF,EAC5Dm8C,EAAQ9zC,EAAOwgH,GACf9a,EAAY5xD,EAAMuyC,MAAM,cAI9B,GAHAnwF,KAAKooH,kBAAoBkC,EACzBtqH,KAAKmoH,aAAevqE,EAGlB2sE,IAAmBD,GACnB1sE,EAAMqwB,SACNu8C,GACAC,IAAkBjb,EAElB,OAGFxvG,KAAK6vF,IACmBy6B,0BACpB9a,EAAY,iBAAmBA,EAAY,iBAC9B+a,IACbE,EAAgB,iBAAmBA,EAAgB,MAIvD,MAAMC,EAAyC54B,GAAc,GAAIl0C,EAAO,CACtEA,MAAO0sE,EACPvK,WAAYniE,EAAMmiE,WAClB5vB,MAAOvyC,EAAMuyC,MACb0V,IAAKjoD,EAAMioD,IACX7Q,MAAOp3C,EAAMo3C,eAGR01B,EAAmBnL,cAEnBmL,EAAmB5K,OAC1B9/G,KAAKy0G,IAAInrC,QAAQ2f,EAAOgB,gBAAiBygC,GAEzC,MAAMpU,EAAe14D,EAAMqwB,QAC3B,IAAKqoC,GAAgBA,EAAa9e,KAAM,CAEtC,MAAMitB,EAAmBzkH,KAAKqkH,aAAazmE,EAAMioD,IAAK2kB,GAAWv8C,SACjEjuE,KAAKokH,aAAaK,EAAgB,CAEtC,CAEIkG,kBACF,OAAO3qH,KAAKqoH,gBACd,CAEIsC,gBAAYL,GACdtqH,KAAKqoH,iBAAmBiC,OACC7oH,IAArBzB,KAAKkoH,cACPloH,KAAKkoH,YAAcoC,IAGJ,IAAbA,IACFtqH,KAAK49C,MAAQ0sE,EAEjB,CAEIJ,iBACF,OAAOlqH,KAAKioH,WACd,CAEIiC,eAAWI,GACbtqH,KAAKioH,YAAcqC,CACrB,CAEIM,iBAGF,QAAyBnpH,IAArBzB,KAAKkoH,YAA2B,CAClC,MAAM2C,EAAmB7qH,KAAKy0G,IAAI/kE,OAAOk7E,WACzC,YAAyBnpH,IAArBopH,EACKA,EAEA7qH,KAAKioH,YAGd,OAAOjoH,KAAKkoH,WAEhB,CAEI0C,eAAWN,GACbtqH,KAAKkoH,YAAcoC,CACrB,CAEU5S,QAAQrwF,EAAqB7mB,GACjCA,EAAKg4G,QAAUh4G,EAAKiyD,SAKtBjyD,EAAKiyD,QAAQnmD,OAAS0nG,GAAoB8B,OAC1Ct1G,EAAKiyD,QAAQ7U,QAAU59C,KAAK49C,OAE5B59C,KAAKonH,WAAW5mH,EAEpB,CAGUooH,aAAavhG,GAA6BmvE,SAClD,QAAa/0F,IAAT+0F,GAAsBA,EAAKlqF,OAAS2nG,GAAkBK,KAAM,CAC9D,MAAM12D,EAAQ59C,KAAKgoH,QAAQxxB,EAAK54C,YAClBn8C,IAAVm8C,IACFA,EAAM+hE,UAAY,GAGxB,CAEU8I,cAAcphG,EAA4B7mB,GAAuB,MACzE,MAAQo9C,QAAOqwB,WAAYztE,EACrBsqH,EAAW9qH,KAAKgoH,QAAQpqE,GAEf,MAAf,IAAKktE,EAKH,OAJA9qH,KAAK+iD,KAA4BnF,iCAC7BmtE,OAAJA,EAAIvqH,EAAKq1G,qBAALkV,EAAyB3L,OAC3BnxC,EAAQgrB,mBAAoB,IAM5Br7C,IAAU59C,KAAKooH,mBAEc,IAA3B0C,EAASpL,gBACXoL,EAASnL,UAAY,GAEvB3/G,KAAK6kH,eAAejnE,EAAOp9C,EAAMsqH,EAAS78C,UACjC+8C,OAAJA,EAAIxqH,EAAKq1G,qBAALmV,EAAyB5L,OAElCnxC,EAAQgrB,mBAAoB,EAEhC,CAEU0vB,qBACRthG,EACA7mB,GAEA,MAAM2nH,EAAenoH,KAAKmoH,aAC1B,IAAKA,EACH,OAGF,MAAMlI,EAAejgH,KAAKy0G,IAAI8B,YAAY/1G,EAAK8H,IAAIynG,QACnD,GACEoY,EAAa1I,eACb0I,EAAalI,eAAiBA,EAC9B,CACA,IAAIjrB,GAAQ,EACZ,QAASxsD,EAAI,EAAGA,EAAI2/E,EAAa1I,cAAcn9G,OAAQkmC,IACrD,GAAI2/E,EAAa1I,cAAcj3E,KAAOy3E,EAAc,CAClDjrB,EAAQxsD,EACR,OAIU,IAAVwsD,GAAgBA,IAAUmzB,EAAanzB,QACzCmzB,EAAanzB,MAAQA,EACjBh1F,KAAKkkH,SACPlkH,KAAK40G,YAAS,CAItB,CAEUwP,aAAaK,GACrBvvE,MAAMkvE,eACN,MAAMgE,EAAoBpoH,KAAKooH,kBACzBD,EAAenoH,KAAKmoH,aAE1B,GAAIA,GAAgBnoH,KAAK0kH,mBAAmByD,GAAe,CACzD,MAAM7/G,EAAK6/G,EAAanzB,MACxB,IAAItzF,EAAMymH,EAAatiB,IACvB,GAAI4e,EACF,IACE/iH,EAAM+iH,EAAiBpF,cAAc39G,EAKvC,OAJSmf,GACP7gB,KAAK+iD,KAC0DliC,iEAEjE,CAGF,MAAM2uF,EAAY2Y,EAAah4B,MAAM,cACrCnwF,KAAK6vF,IACF,uBAAsBu4B,SACK3mH,IAA1BgjH,GAAkBtF,IACd,UACAsF,EAAiBtF,IACjB,SACAsF,EAAiB5S,KACjB,UACErC,EAAY,YAAcA,EAAY,UAAUlnG,EAAK,KAC3D6/G,EAAazmH,IAAIY,UACfZ,KAKN1B,KAAKmkH,aACLnkH,KAAKy0G,IAAInrC,QAAQ2f,EAAOkB,cAAe,CACrCzoF,MACAk8C,MAAOwqE,EACP9/G,KACAutG,mBAAoB4O,GAAoB,MACzC,CAEL,CAEIwG,oBACF,OAA8B,IAA1BjrH,KAAKqoH,iBACAroH,KAAKqoH,iBAELroH,KAAKy0G,IAAIyW,aAEpB,CAEID,kBAAcE,GAChBnrH,KAAK49C,MAAQutE,GACiB,IAA1BnrH,KAAKqoH,mBACProH,KAAKy0G,IAAIyW,cAAgBC,EAE7B,CAEAC,YAAYvS,EAAY7jB,GACtB,MAAMq2B,EAA+BA,CAAC3pH,EAAK4G,IAAOA,IAAO0sF,EACnDlrF,EAAS9J,KAAKgoH,QAAQx7G,OAAO,CAACoxC,EAAO1hB,IACrCA,IAAU28E,IAIVj7D,EAAMl8C,IAAIY,OAAS,QAAeb,IAAVuzF,GAC1Bp3C,EAAMl8C,IAAMk8C,EAAMl8C,IAAI8K,OAAO6+G,GACzBztE,EAAM6hE,gBACR7hE,EAAM6hE,cAAgB7hE,EAAM6hE,cAAcjzG,OACxC6+G,IAGAztE,EAAMiiE,eACRjiE,EAAMiiE,aAAejiE,EAAMiiE,aAAarzG,OACtC6+G,IAGJztE,EAAMo3C,MAAQ,GACP,IAELh1F,KAAKsoH,UACPtoH,KAAKsoH,SAAS8C,YAAYxtE,IAErB,KAGT59C,KAAKy0G,IAAInrC,QAAQ2f,EAAOsB,eAAgB,CAAEzgF,UAC5C,CAEQ4+G,gBACNrhG,GACEvd,WAEFA,EAAOP,QAAQ,CAACq0C,EAAO1hB,KACrB,MAAQ+xC,WAAYrwB,EACT,MAAPqwB,KAASmpB,WACXnpB,EAAQmpB,UAAU7tF,QAASgxC,IACzBA,EAASqD,MAAQ1hB,GAClB,GAGLl8B,KAAKgoH,QAAUl+G,CACjB,EAGK,SAASw/G,GACd1rE,EACAtxC,EACAhE,GAEKA,IAGQ,UAATgE,GACGsxC,EAAM6hE,gBACT7hE,EAAM6hE,cAAgB,IAExB7hE,EAAM6hE,cAAc7hE,EAAMl8C,IAAIY,OAAS,GAAKgG,GAC1B,SAATgE,IACJsxC,EAAMiiE,eACTjiE,EAAMiiE,aAAe,IAEvBjiE,EAAMiiE,aAAajiE,EAAMl8C,IAAIY,OAAS,GAAKgG,GAE/C,CAEA,SAASshH,GAAsB0B,GAC7B,MAAMrd,EAAS,GACfqd,EAAO/hH,QAASq3F,IACd,MAAMmP,EAAUnP,EAAMmP,SAAW,GACjCnP,EAAMt4F,GAAK2lG,EAAO8B,GAAW9B,EAAO8B,IAAY,EAChD9B,EAAO8B,IAAO,EAElB,CClmBO,MAAMwb,GAiBX1rH,YAAY40G,GAAUz0G,KAhBdwrH,gBACN5iF,OAAOjO,OAAO,MAAK36B,KACbyrH,iBACN7iF,OAAOjO,OAAO,MAAK36B,KACbo3F,UACNxuD,OAAOjO,OAAO,MAAK36B,KACb0rH,WAIG9iF,OAAOjO,OAAO,MAAK36B,KAEtB2rH,cAAwB,GAAG3rH,KAC3By0G,SAAG,OACHmX,SAAmB,EAGzB5rH,KAAKy0G,IAAMA,EAEXz0G,KAAKq7G,oBACP,CAEQA,qBACN,MAAQ5G,OAAQz0G,KAChBy0G,EAAInxF,GAAG2lE,EAAOS,gBAAiB1pF,KAAK6rH,iBAAkB7rH,MACtDy0G,EAAInxF,GAAG2lE,EAAO6C,cAAe9rF,KAAK8rH,eAAgB9rH,MAClDy0G,EAAInxF,GAAG2lE,EAAOuC,YAAaxrF,KAAK4oH,aAAc5oH,KAChD,CAEQs7G,uBACN,MAAQ7G,OAAQz0G,KAChBy0G,EAAIY,IAAIpsB,EAAOS,gBAAiB1pF,KAAK6rH,iBAAkB7rH,MACvDy0G,EAAIY,IAAIpsB,EAAO6C,cAAe9rF,KAAK8rH,eAAgB9rH,MACnDy0G,EAAIY,IAAIpsB,EAAOuC,YAAaxrF,KAAK4oH,aAAc5oH,KACjD,CAEO0mE,UACL1mE,KAAKs7G,uBAELt7G,KAAKo3F,UAEHp3F,KAAKwrH,gBAELxrH,KAAKyrH,iBACLzrH,KAAK0rH,WACH,IACN,CAMOK,gBACLC,EACA5T,GAEA,MAAM6T,EAAcjsH,KAAKwrH,gBAAgBpT,GACzC,GAAI6T,EACF,QAASzjF,EAAIyjF,EAAY3pH,OAAQkmC,KAAO,CACtC,MAAM0jF,EAAaD,EAAYzjF,GAC/B,IAAK0jF,EACH,MAEF,MAAMC,EAAcD,EAAW/wC,IAC/B,GACE+wC,EAAW1rG,OAASwrG,GACJ,OAAhBG,GACAH,GAAYG,EAEZ,OAAOD,EAIb,OAAOlsH,KAAKosH,gBAAgBJ,EAAU5T,EACxC,CAOOgU,gBACLJ,EACA5T,GAEA,MAAQhhB,aAAcp3F,KAChB83C,EAAOlP,OAAOkP,KAAKs/C,GACzB,QAAS5uD,EAAIsP,EAAKx1C,OAAQkmC,KAAO,CAC/B,MAAM6jF,EAAiBj1B,EAAUt/C,EAAKtP,IACtC,GAAI6jF,GAAgBrzF,KAAK1sB,OAAS8rG,GAAaiU,EAAejO,SAAU,CACtE,MAAM5nB,EAAO61B,EAAerzF,KAC5B,GAAIw9D,EAAKh2E,OAASwrG,GAAYA,GAAYx1B,EAAKrb,IAC7C,OAAOqb,GAIb,OAAO,IACT,CAOO81B,uBACLC,EACAC,EACAC,EACAC,GAEI1sH,KAAK0rH,aACP1rH,KAAK0rH,WAAWa,GAAoBC,GAItC,MAAMG,EAAkBD,GAAcnyE,SAAS45C,KAAM,EACrDvrD,OAAOkP,KAAK93C,KAAKo3F,WAAW7tF,QAASlC,IACnC,MAAMglH,EAAiBrsH,KAAKo3F,UAAU/vF,GAItC,IAHKglH,GAGDM,GAAmBN,EAAerzF,KAAKm7D,GACzC,OAEF,IAAKk4B,EAAejO,WAAaiO,EAAeprH,OAI9C,YAHIorH,EAAerzF,KAAK1sB,OAASmgH,GAC/BzsH,KAAK4sH,eAAeP,EAAerzF,OAIvC,MAAM6zF,EAASR,EAAe/lE,MAAMimE,GAC/BM,GAGLA,EAAO1kG,KAAK5c,KAAM4c,IAChB,MAAM2kG,GAAiB9sH,KAAK+sH,eAC1B5kG,EAAKqsE,SACLrsE,EAAKssE,OACL+3B,GAEF,OAAIM,GAEF9sH,KAAK4sH,eAAeP,EAAerzF,MAE9B8zF,GACR,EAEL,CAMOE,uBAAuBxsH,GAC5B,MAAMkrH,EAAa1rH,KAAK0rH,YAChBl1B,OAAMqb,QAASrxG,EACvB,IAAKkrH,GAA0B,gBAAZl1B,EAAKrC,GACtB,OAGF,MAAM84B,EAAUC,GAAe12B,GACzB61B,EAAiBrsH,KAAKo3F,UAAU61B,GACtC,IAAKZ,EACH,OAEF,MAAMc,GAAc32B,EAAKnD,OACzBzqD,OAAOkP,KAAK4zE,GAAYniH,QAASgjH,IAC/B,MAAMa,EAAa52B,EAAKlD,kBAAkBi5B,GACrCa,IAKLf,EAAe/lE,MAAMimE,GAAoBvsH,KAAKqtH,iBAC5C72B,EACAqb,EAHcsb,IAAqC,IAAvBC,EAAWj3B,QADvBu1B,EAAWa,IAO7B,GAEFF,EAAeprH,OAAS,KACpB2nC,OAAOkP,KAAKu0E,EAAe/lE,OAAOhkD,QACpC+pH,EAAejO,UAAW,EACtBiO,EAAerzF,KAAKm8D,UACtBn1F,KAAKyrH,iBAAiBY,EAAerzF,KAAK1sB,MAAQ+/G,GAE/CiB,GAAUjB,IAEbrsH,KAAKutH,YAAa/2B,EAAKrC,GAAgB,EAAGqC,EAAKlqF,OAIjDtM,KAAK4sH,eAAeP,EAAerzF,KAEvC,CAEQu0F,YAAYC,EAAkBpV,GACpC,MAAM6T,EAAcjsH,KAAKwrH,gBAAgBpT,GACpC6T,IAGLjsH,KAAKwrH,gBAAgBpT,GAAa6T,EAAYz/G,OAC3CqlG,GAAUA,EAAKt3D,SAAS45C,IAAiBq5B,GAE9C,CAEOC,aAAaj3B,EAAgBk3B,GAClC,MAAMT,EAAUC,GAAe12B,GAC/B,IAAI61B,EAAiBrsH,KAAKo3F,UAAU61B,IAC/BZ,GAAkBqB,IACrBrB,EAAiBrsH,KAAKo3F,UAAU61B,GAAW,CACzCj0F,KAAMw9D,EACN21B,YAAa,KACblrH,OAAQ,KACRm9G,UAAU,EACV93D,MAAO1d,OAAOjO,OAAO,OAEnB67D,EAAKpB,MACPp1F,KAAK4rH,SAAU,IAGfS,IACFA,EAAeprH,OAAS,KACxBorH,EAAejO,UAAW,EAE9B,CAEQiP,iBACN9yE,EACAs3D,EACA1b,EACAq2B,GAEA,MAAMpO,EAAkC,CACtCj2F,KAAM,GACNguE,WAEI3B,EAAWj6C,EAAS/5B,MACpBi0E,EAASl6C,EAAS4gC,IAClB2Z,EAAYv6C,EAASu6C,WAAaL,EAClCI,EAAct6C,EAASs6C,aAAeL,EAC5C,QAAShsD,EAAI,EAAGA,EAAIgkF,EAAUlqH,OAAQkmC,IAAK,CACzC,MAAMiwB,EAAY+zD,EAAUhsG,MAAMgoB,GAAKxoC,KAAK2rH,cACtCnzD,GAAUg0D,EAAUrxC,IAAI3yC,GAAKxoC,KAAK2rH,cACxC,GAAI92B,GAAep8B,GAAaq8B,GAAat8B,GAAS,CAGpD4lD,EAASj2F,KAAK/f,KAAK,CACjBosF,SAAUn9E,KAAK+/C,IAAIo9B,EAAUg4B,EAAUhsG,MAAMgoB,IAC7CisD,OAAQp9E,KAAK++E,IAAI3B,EAAQ+3B,EAAUrxC,IAAI3yC,MAEzC,SACSgsD,EAAWh8B,IAAWi8B,EAASh8B,EACxC2lD,EAASjoB,SAAU,EAGnBioB,EAASj2F,KAAK/f,KAAK,CACjBosF,SAAUn9E,KAAK+/C,IAAIo9B,EAAUg4B,EAAUhsG,MAAMgoB,IAC7CisD,OAAQp9E,KAAK++E,IAAI3B,EAAQ+3B,EAAUrxC,IAAI3yC,WACxC,GACQisD,GAAUh8B,EAEnB,MAGJ,OAAO2lD,CACT,CAKOuP,mBAAmBxlG,GACxB,IACIylG,EACAn1D,EACAD,EAHAq1D,EAAgC,KAIhCC,EAAsB,EAC1B,MAAQnC,gBAAev0B,aAAcp3F,KACrC4oC,cAAOkP,KAAKs/C,GAAW7tF,QAASlC,IAC9B,MAAMglH,EAAiBj1B,EAAU/vF,GAC5BglH,GAGDiB,GAAUjB,KACZ5zD,EAAY4zD,EAAerzF,KAAKxY,MAAQmrG,EACxCnzD,EAAU6zD,EAAerzF,KAAKmiD,IAAMwwC,EAChCxjG,GAAQswC,GAAatwC,GAAQqwC,IAE/Bo1D,EAAcv2G,KAAK++E,IAAIjuE,EAAOswC,EAAWD,EAAUrwC,GAC/C2lG,GAAeF,IACjBC,EAAexB,EAAerzF,KAC9B80F,EAAcF,OAKfC,CACT,CAEOE,kBAAkBzhH,GACvB,MAAM0hH,EAAqBhuH,KAAKyrH,iBAAiBn/G,GACjD,YACyB7K,IAAvBusH,IACCA,EAAmB5P,UAAYkP,GAAUU,GAE9C,CAEOC,SAAS1zE,GACd,MAAM0yE,EAAUC,GAAe3yE,GACzB8xE,EAAiBrsH,KAAKo3F,UAAU61B,GAEtC,OAAIZ,EACGA,EAAejO,SAETkP,GAAUjB,GAlUI6B,uCA0U7B,CAEQnB,eACNv4B,EACAC,EACA+3B,GAEA,IAAI/zD,EACAD,EACJ,QAAShwB,EAAI,EAAGA,EAAIgkF,EAAUlqH,OAAQkmC,IAAK,CAGzC,GAFAiwB,EAAY+zD,EAAUhsG,MAAMgoB,GAAKxoC,KAAK2rH,cACtCnzD,EAAUg0D,EAAUrxC,IAAI3yC,GAAKxoC,KAAK2rH,cAC9Bn3B,GAAY/7B,GAAag8B,GAAUj8B,EACrC,OAAO,EAGT,GAAIi8B,GAAUh8B,EAEZ,OAAO,EAIX,OAAO,CACT,CAEQmwD,aAAavhG,EAA2B7mB,GAC9C,MAAQg2F,OAAMqb,QAASrxG,EAGvB,GAAgB,gBAAZg2F,EAAKrC,IAAwBqC,EAAKvB,YACpC,OAIF,MAAMh0F,EAAS4wG,EAAO,KAAOrxG,EAEvBysH,EAAUC,GAAe12B,GAC/Bx2F,KAAKo3F,UAAU61B,GAAW,CACxBj0F,KAAMw9D,EACN21B,YAAa,KACblrH,SACAm9G,UAAU,EACV93D,MAAO1d,OAAOjO,OAAO,MAEzB,CAEQkxF,iBACNxkG,EACA7mB,GAEA,MAAQg2F,OAAMqb,OAAM6Z,cAAelrH,EACnC,GAAgB,gBAAZg2F,EAAKrC,GACP,OAEF,MAAMs4B,EAAej2B,EAAKlqF,KAC1B,GAAIulG,EAAM,CACR,IAAIoa,EAAcjsH,KAAKwrH,gBAAgBiB,GAClCR,IACHjsH,KAAKwrH,gBAAgBiB,GAAgBR,EAAc,IAErDA,EAAY7jH,KAAKypG,EAAI,CAGvB7xG,KAAK0rH,WAAaA,EAClB9iF,OAAOkP,KAAK4zE,GAAYniH,QAASgjH,IAE/BvsH,KAAKssH,uBACHC,EAFgBb,EAAWa,GAI3BE,EACA5a,EACF,EAEJ,CAEQia,eAAezkG,EAA6B7mB,GAClDR,KAAKgtH,uBAAuBxsH,EAC9B,CAEQ2tH,YAAY5zE,GAClB,MAAM0yE,EAAUC,GAAe3yE,GAC/B,QAASv6C,KAAKo3F,UAAU61B,EAC1B,CAEOmB,SAAS9hH,GAAkC,MAChD,QAAS+hH,OAADA,EAACruH,KAAKwrH,gBAAgBl/G,MAArB+hH,EAA4B/rH,OACvC,CAEOgsH,uBACL9tG,EACA26D,EACAsxC,EACA8B,EACAC,GAEID,IAAgBvuH,KAAK4rH,SAGzBhjF,OAAOkP,KAAK93C,KAAKo3F,WAAW7tF,QAASlC,IACnC,MAAMglH,EAAiBrsH,KAAKo3F,UAAU/vF,GACtC,IAAKglH,EACH,OAEF,MAAM71B,EAAO61B,EAAerzF,KACxBw9D,EAAKlqF,OAASmgH,GAAiB8B,IAAgB/3B,EAAKpB,KAItDoB,EAAKh2E,MAAQ26D,GACbqb,EAAKrb,IAAM36D,IACV6rG,EAAejO,UAAYoQ,IAE5BxuH,KAAK4sH,eAAep2B,EAAI,EAG9B,CAEOo2B,eAAeryE,GACpB,MAAM0yE,EAAUC,GAAe3yE,GAC/BA,EAASw6C,MAAM9zF,OAAS,EACxBs5C,EAAS87C,4BACT,MAAM41B,EAAcjsH,KAAKwrH,gBAAgBjxE,EAASjuC,MAClD,GAAI2/G,EAAa,CACf,MAAMwC,EAAal0E,EAAS45C,GAC5Bn0F,KAAKwrH,gBAAgBjxE,EAASjuC,MAAQ2/G,EAAYz/G,OAC/CqlG,GAASA,EAAKt3D,SAAS45C,KAAOs6B,EACjC,QAEKzuH,KAAKo3F,UAAU61B,GAClB1yE,EAAS46C,gBACJn1F,KAAKyrH,iBAAiBlxE,EAASjuC,KAE1C,CAEOoiH,qBACL1uH,KAAKo3F,UAAYxuD,OAAOjO,OAAO,MAC/B36B,KAAKyrH,iBAAmB7iF,OAAOjO,OAAO,MACtC36B,KAAKwrH,gBAAkB5iF,OAAOjO,OAAO,MACrC36B,KAAK4rH,SAAU,CACjB,EAGF,SAAS0B,GAAUjB,GAAyC,UAC1D,OACEA,EAAejO,WACdiO,EAAerzF,KAAKo8D,MACnBu5B,OADsBA,EACtBtC,EAAe/lE,MAAMswC,YAArB+3B,IAA4Bx4B,WAC5By4B,OADmCA,EACnCvC,EAAe/lE,MAAMqwC,YAArBi4B,IAA4Bz4B,WAC5B04B,OADmCA,EACnCxC,EAAe/lE,MAAMuwC,iBAArBg4B,IAAiC14B,SAEvC,CAEA,SAAS+2B,GAAe3yE,GACtB,MAAQ,GAAEA,EAASjuC,QAAQiuC,EAASqD,SAASrD,EAASy6C,SAASz6C,EAAS45C,IAC1E,CCreA,MAAM26B,GAAiBz3G,KAAK6qD,IAAI,EAAG,IAEpB,MAAM6sD,GAKnBlvH,YAAY6vC,GAAmB1vC,KAJd0vC,YAAM,OACf2kD,OAA+C,KAAIr0F,KACnDgvH,iBAA0B,EAGhChvH,KAAK0vC,OAASA,CAChB,CAEAg3B,UACM1mE,KAAKq0F,SACPr0F,KAAKq0F,OAAO3tB,UACZ1mE,KAAKq0F,OAAS,KAElB,CAEA2B,QACMh2F,KAAKq0F,QAEPr0F,KAAKq0F,OAAO2B,OAEhB,CAEA10C,KACEk1C,EACAy4B,GAEA,MAAMvtH,EAAM80F,EAAK90F,IACjB,IAAKA,EACH,OAAOigD,QAAQE,OACb,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAawB,gBACtBkqB,OAAO,EACPhiB,OACA31E,MAAO,IAAIsnE,MACR,6BAA2BzmF,EAAM,YAAc,QAElD21G,eAAgB,QAItBr3G,KAAKg2F,QAEL,MAAMtmD,EAAS1vC,KAAK0vC,OACdy/E,EAAkBz/E,EAAO0/E,QACzBC,EAAiB3/E,EAAO2kD,OAE9B,OAAO,IAAI1yC,QAAQ,CAACC,EAASC,KAI3B,GAHI7hD,KAAKq0F,QACPr0F,KAAKq0F,OAAO3tB,UAEV8vB,EAAKpB,IAEP,YADAvzC,EAAOytE,GAAmB94B,IAG5B,MAAMnC,EACHr0F,KAAKq0F,OACNmC,EAAKnC,OACH86B,EACI,IAAIA,EAAgBz/E,GACnB,IAAI2/E,EAAe3/E,GACtBsmE,EAAgBuZ,GAAoB/4B,GACpCuf,EAAaiM,GACjBtyE,EAAO8/E,eAAexgH,SAElBygH,GAAoC,CACxC1Z,aACAh2D,QAASg2D,EAAWa,cACpBE,SAAU,EACVE,WAAY,EACZE,cAAe,EACfwY,cAA2B,gBAAZl5B,EAAKrC,GAAuB9jD,IAAWy+E,IAGxDt4B,EAAKzB,MAAQV,EAAOU,MACpBV,EAAO/yC,KAAK00D,EAAeyZ,GAAc,CACvCrY,UAAWA,CAACt1G,GAAUizF,GAAOtiC,GAAS4kD,MACpCr3G,KAAK2vH,YAAYn5B,EAAMnC,GACvB,IAAIuT,GAAU9lG,GAAStB,KACnBiyD,GAAQm9D,SAAWp5B,EAAKnB,cAC1BmB,EAAKnB,YAAY0Q,GAAK,IAAIlV,WAAW+W,GAAQzwF,MAAM,EAAG,KACtDywF,GAAUA,GAAQzwF,MAAM,KAE1ByqC,EAAQ,CACN40C,OACAqb,KAAM,KACNjK,WACAyP,mBACD,EAEHK,QAASA,CAAC51G,GAAU2wD,GAAS4kD,GAAgBtiB,MAC3C/0F,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAawB,gBACtBkqB,OAAO,EACPhiB,OACA10F,SAAQ82G,IAAIl3G,MAAKlB,UAAMiB,GAAcK,IACrC+e,MAAO,IAAIsnE,MAAoBrmF,iBAAS42G,QAAQ52G,GAASC,QACzDs1G,kBACAtiB,WAEJ,EAEF86B,QAASA,CAAC96B,GAAOtiC,GAAS4kD,MACxBr3G,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAayC,iBACtBipB,OAAO,EACPhiB,OACA31E,MAAO,IAAIsnE,MAAM,WACjBkvB,kBACAtiB,WAEJ,EAEF6iB,UAAWA,CAAC7iB,GAAOtiC,GAAS4kD,MAC1Br3G,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAayB,kBACtBiqB,OAAO,EACPhiB,OACA31E,MAAO,IAAIsnE,MAAO,iBAAgBsnC,GAAa1vE,aAC/Cs3D,kBACAtiB,WAEJ,EAEFk6B,WAAYA,CAACl6B,GAAOtiC,GAASjyD,GAAM62G,MAC7B4X,GACFA,EAAW,CACTz4B,OACAqb,KAAM,KACNjK,QAASpnG,GACT62G,mBACD,GAGN,EAEL,CAEOyY,SACLt5B,EACAqb,EACAod,GAEAjvH,KAAKg2F,QAEL,MAAMtmD,EAAS1vC,KAAK0vC,OACdy/E,EAAkBz/E,EAAO0/E,QACzBC,EAAiB3/E,EAAO2kD,OAE9B,OAAO,IAAI1yC,QAAQ,CAACC,EAASC,KAI3B,GAHI7hD,KAAKq0F,QACPr0F,KAAKq0F,OAAO3tB,UAEV8vB,EAAKpB,KAAOyc,EAAKzc,IAEnB,YADAvzC,EAAOytE,GAAmB94B,EAAMqb,IAGlC,MAAMxd,EACHr0F,KAAKq0F,OACNmC,EAAKnC,OACH86B,EACI,IAAIA,EAAgBz/E,GACnB,IAAI2/E,EAAe3/E,GACtBsmE,EAAgBuZ,GAAoB/4B,EAAMqb,GAE1CkE,EAAaiM,GACjBtyE,EAAO8/E,eAAexgH,SAElBygH,GAAoC,CACxC1Z,aACAh2D,QAASg2D,EAAWa,cACpBE,SAAU,EACVE,WAAY,EACZE,cAAe,EACfwY,cAAeZ,IAGjBjd,EAAK9c,MAAQV,EAAOU,MACpBV,EAAO/yC,KAAK00D,EAAeyZ,GAAc,CACvCrY,UAAWA,CAACt1G,GAAUizF,GAAOtiC,GAAS4kD,MACpCr3G,KAAK2vH,YAAYn5B,EAAMnC,GACvBr0F,KAAK+vH,oBAAoBv5B,EAAMqb,GAC/B,MAAMme,GAAiC,CACrCx5B,OACAqb,OACAjK,QAAS9lG,GAAStB,KAClB62G,mBAEF4X,EAAWe,IACXpuE,EAAQouE,GAAc,EAExBtY,QAASA,CAAC51G,GAAU2wD,GAAS4kD,GAAgBtiB,MAC3C/0F,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAawB,gBACtBkqB,OAAO,EACPhiB,OACAqb,OACA/vG,SAAQ82G,IACNl3G,IAAKs0G,EAAct0G,IACnBlB,UAAMiB,GACHK,IAEL+e,MAAO,IAAIsnE,MAAoBrmF,iBAAS42G,QAAQ52G,GAASC,QACzDs1G,kBACAtiB,WAEJ,EAEF86B,QAASA,CAAC96B,GAAOtiC,GAAS4kD,MACxB7gB,EAAKzB,MAAMrC,QAAUmf,EAAK9c,MAAMrC,QAChC1yF,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAayC,iBACtBipB,OAAO,EACPhiB,OACAqb,OACAhxF,MAAO,IAAIsnE,MAAM,WACjBkvB,kBACAtiB,WAEJ,EAEF6iB,UAAWA,CAAC7iB,GAAOtiC,GAAS4kD,MAC1Br3G,KAAK2vH,YAAYn5B,EAAMnC,GACvBxyC,EACE,IAAIqtE,GAAU,CACZ5iH,KAAMkgF,GAAWC,cACjBxe,QAAS6e,GAAayB,kBACtBiqB,OAAO,EACPhiB,OACAqb,OACAhxF,MAAO,IAAIsnE,MAAO,iBAAgBsnC,GAAa1vE,aAC/Cs3D,kBACAtiB,WAEJ,GAEH,EAEL,CAEQg7B,oBAAoBv5B,EAAgBqb,GAC1C,MAAMoe,EAAYz5B,EAAKzB,MACjBm7B,EAAYre,EAAK9c,MACjBo7B,EAAYD,EAAUjlG,MAE5B,GADAglG,EAAUhvH,QAAUivH,EAAUjvH,OAC1BkvH,EAAW,CACb,MAAMC,EAAgB/4G,KAAKkR,MAAMiuE,EAAK9tF,SAAWmpG,EAAKnpG,UAChD2nH,EAAiBh5G,KAAK++E,IAC1B/+E,KAAKkR,MAAM0nG,EAAUhvH,OAASkvH,GAC9BC,GAGIE,GADoBF,EAAgBC,GAEpBh5G,KAAKkR,MAAM0nG,EAAUhvH,OAASovH,GACpDJ,EAAUhlG,MAAQglG,EAAUhvH,OAASqvH,OAErCL,EAAUhlG,MAAQ5T,KAAK+/C,IAAI64D,EAAUhvH,OAAQgvH,EAAUhlG,OAEzD,MAAMslG,EAAcN,EAAU/uH,QACxBsvH,EAAcN,EAAUhvH,QAC1BqvH,EAAY/vG,MAEd+vG,EAAY19B,OAAS29B,EAAY39B,MAAQ29B,EAAYhwG,OAErD+vG,EAAY/vG,MAAQgwG,EAAYhwG,MAChC+vG,EAAY19B,MAAQ29B,EAAY39B,OAElC09B,EAAYp1C,IAAMq1C,EAAYr1C,GAChC,CAEQw0C,YAAYn5B,EAAgBnC,GAClCmC,EAAKnC,OAAS,KACVr0F,KAAKq0F,SAAWA,IAClB4H,KAAK/7C,aAAalgD,KAAKgvH,iBACvBhvH,KAAKq0F,OAAS,MAEhBA,EAAO3tB,SACT,EAGF,SAAS6oD,GACP/4B,EACAqb,EAAoB,MAEpB,MAAM4e,EAAuB5e,GAAQrb,EAC/Bwf,EAAuC,CAC3Cxf,OACAqb,OACA8D,aAAc,cACdj0G,IAAK+uH,EAAQ/uH,IACbgvH,QAAS,GACTC,WAAY,EACZC,SAAU,GAENpwG,EAAQiwG,EAAQ58B,qBAChB1Y,EAAMs1C,EAAQ78B,mBACpB,GAAI5B,EAAgBxxE,IAAU4xE,EAAgBjX,GAAM,OAClD,IAAI01C,EAAiBrwG,EACjBswG,EAAe31C,EACnB,GAAgB,gBAAZqb,EAAKrC,IAAqD,aAA7B48B,WAAK17B,kBAAL07B,IAAkBnrB,QAAsB,CAIvE,MAAMorB,EAAc71C,EAAM36D,EACtBwwG,EAAc,KAChBF,EAAe31C,GAAO,GAAM61C,EAAc,KAE9B,IAAVxwG,IACFw1F,EAAc4Z,SAAU,EACxBiB,EAAiBrwG,EAAQ,IAG7Bw1F,EAAc2a,WAAaE,EAC3B7a,EAAc4a,SAAWE,EAE3B,OAAO9a,CACT,CAEA,SAASsZ,GAAmB94B,EAAgBqb,GAC1C,MAAMhxF,EAAQ,IAAIsnE,MAAaqO,SAAKpB,IAAM,MAAQ,qBAC5CujB,EAAgC,CACpCrsG,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa4B,SACtB8pB,OAAO,EACPhiB,OACA31E,QACAw2F,eAAgB,MAElB,OAAIxF,IACF8G,EAAU9G,KAAOA,IAElBA,GAAcrb,GAAMzB,MAAMrC,SAAU,EAC9B,IAAIw8B,GAAUvW,EACvB,CAEO,MAAMuW,WAAkB/mC,MAE7BtoF,YAAYW,GACV00C,MAAM10C,EAAKqgB,MAAM2oF,SAASxpG,KAFZQ,UAAI,EAGlBR,KAAKQ,KAAOA,CACd,EC5Va,MAAMywH,GAKnBpxH,YAAY6vC,GAAmB1vC,KAJd0vC,YAAM,OAChBwhF,gBAAuD,GAAElxH,KACzDmxH,cAAsC,KAG3CnxH,KAAK0vC,OAASA,CAChB,CAEAsmD,MAAM1pF,GACJ,UAAWu5F,KAAO7lG,KAAKkxH,gBAAiB,CACtC,MAAM78B,EAASr0F,KAAKkxH,gBAAgBrrB,GAAKxR,OACzC,GAAIA,EAAQ,CACV,GAAI/nF,GAAQA,IAAS+nF,EAAO5hC,QAAQ+jC,KAAKlqF,KACvC,OAEF+nF,EAAO2B,OAAK,EAGlB,CAEAvvC,SACE,UAAWo/C,KAAO7lG,KAAKkxH,gBAAiB,CACtC,MAAME,EAAUpxH,KAAKkxH,gBAAgBrrB,IAGnCurB,EAAQC,wBACRD,EAAQ/7B,YAAY4Q,4BAEbjmG,KAAKkxH,gBAAgBrrB,EAAG,CAGrC,CAEAn/B,UACE1mE,KAAKymD,SACL,UAAWo/C,KAAO7lG,KAAKkxH,gBAAiB,CACtC,MAAM78B,EAASr0F,KAAKkxH,gBAAgBrrB,GAAKxR,OACrCA,GACFA,EAAO3tB,SAAO,CAGlB1mE,KAAKkxH,gBAAkB,EACzB,CAEAI,mBACE96B,EACAvoB,EAAwB6e,GAAa8B,eACrC/tE,EACAw2F,EACAv1G,GAEA,OAAO,IAAIotH,GAAU,CACnB5iH,KAAMkgF,GAAWC,cACjBxe,UACAuqC,OAAO,EACPhiB,OACA10F,WACA+e,QACAw2F,kBAEJ,CAEAka,UACEC,EACAl4B,GAEA,GAAIt5F,KAAKmxH,eAAiBnxH,KAAK0vC,OAAO+hF,WAAY,CAEhD,MAAQt9B,KAAII,MAAOi9B,EACnB,QAAShpF,EAAI,EAAGA,EAAI8wD,EAAmBh3F,OAAQkmC,IAAK,CAClD,MAAMguD,EAAO8C,EAAmB9wD,GAChC,GACE+rD,GAAMiC,EAAKjC,KACH,gBAAPJ,GAAoC,gBAAZqC,EAAKrC,IAAwBA,EAAKqC,EAAKrC,IAChE,CACAn0F,KAAKmxH,cACFO,sBAAsBl7B,GACtB30F,KAAM8vH,IACLn7B,EAAKZ,aAAa+7B,EAAe,GAErC,QAIR,CAEArwE,KAAKk1C,GACH,OAAKA,EAAKnB,aAAemB,EAAKd,WAAa11F,KAAKmxH,cAEvCnxH,KAAKmxH,cACTO,sBAAsBl7B,GACtB30F,KAAM8vH,GACE3xH,KAAK4xH,aAAap7B,EAAMm7B,IAI9B3xH,KAAK4xH,aAAap7B,EAC3B,CAEAo7B,aACEp7B,EACAm7B,GACwB,QACpBA,GACFn7B,EAAKZ,aAAa+7B,GAEpB,MAAMt8B,EAAcmB,EAAKnB,YACzB,IAAKA,EAAa,CAChB,MAAMx0E,EAAQ,IAAIsnE,MAChBwpC,EACK,gEAA+DA,IAChE,uDAEN,OAAOhwE,QAAQE,OACb7hD,KAAKsxH,mBAAmB96B,EAAM1J,GAAa8B,eAAgB/tE,GAC7D,CAEF,MAAMglF,EAAMxQ,EAAYwQ,IACxB,IAAKA,EACH,OAAOlkD,QAAQE,OACb7hD,KAAKsxH,mBACH96B,EACA1J,GAAa8B,eACb,IAAIzG,MAAO,qBAAoB0d,QAIrC,IAAIurB,EAAUpxH,KAAKkxH,gBAAgBrrB,GAEnC,GAAW,OAAXgsB,EAAIT,MAAS/7B,YAAYhuF,IACvBguF,SAAYhuF,IAAM+pH,EAAQ/7B,YAAYhuF,IAC/Bs6C,QAAQC,QAAQ,CAAE40C,OAAM46B,YAGJ,MAA7B,GAAW,OAAXU,EAAIV,MAASW,eACX,OAAQC,OAARA,EAAQZ,EAAQC,6BAARW,IAAgCC,WACtC,UAAKxwH,EACL,IAAK,iBACL,IAAK,SACL,IAAK,mBACH,OAAO2vH,EAAQW,eAAelwH,KAAMqwH,IAElC78B,EAAYhuF,IAAM6qH,EAAcd,QAAQ/7B,YAAYhuF,IAC7C,CAAEmvF,OAAM46B,aAevB,OAPAA,EAAUpxH,KAAKkxH,gBAAgBrrB,GAAO,CACpCxQ,cACA08B,eAAgB,KAChB19B,OAAQ,KACRg9B,uBAAwB,MAGlBh8B,EAAYuQ,QAClB,IAAK,cACL,IAAK,aACL,IAAK,kBACL,IAAK,iBACH,MAA8B,aAA1BvQ,EAAYQ,UAEP71F,KAAKmyH,YAAYf,EAAS56B,GAE5Bx2F,KAAKoyH,WAAWhB,EAAS56B,GAClC,IAAK,UACH,OAAOx2F,KAAKmyH,YAAYf,EAAS56B,GACnC,QACE,OAAO70C,QAAQE,OACb7hD,KAAKsxH,mBACH96B,EACA1J,GAAa8B,eACb,IAAIzG,MACwCkN,4CAAYuQ,aAKlE,CAEAwsB,WAAWhB,EAAwB56B,GACjC,MAAM07B,EAA+B,CAAE17B,OAAM46B,WAC7C,GAAIpxH,KAAKmxH,eAAiBnxH,KAAK0vC,OAAO+hF,WAAY,CAChD,MAAMY,EACJryH,KAAKmxH,cAAcmB,QAAQJ,GAC7B,GAAIG,EACF,OAAQjB,EAAQW,eAAiBM,EAAyBxwH,KACvD0wH,IACCnB,EAAQC,uBAAyBkB,EAC1BL,KAER1yE,MAAO3+B,IAERuwG,QAAQW,eAAiB,KACnBlxG,GACP,CAGL,OAAO8gC,QAAQC,QAAQswE,EACzB,CAEAC,YAAYf,EAAwB56B,GAClC,MAAM9mD,EAAS1vC,KAAK0vC,OAEd4kD,EAAY,IAAIk+B,EADP9iF,EAAO2kD,QACO3kD,GAC7B8mD,SAAKlC,UAAY88B,EAAQ/8B,OAASC,EAE1B88B,EAAQW,eAAiB,IAAIpwE,QAAQ,CAACC,EAASC,KACrD,MAAMm0D,EAAkC,CACtCob,UACA56B,OACAmf,aAAc,cACdj0G,IAAK0vH,EAAQ/7B,YAAYwQ,KAMrBkQ,EAAarmE,EAAO+iF,cAAczjH,QA2FxCslF,EAAUhzC,KAAK00D,EA1F2B,CACxCD,aACAh2D,QAASg2D,EAAWa,cACpBE,SAAU,EACVE,WAAY,EACZE,cAAe,GAG0C,CACzDE,UAAWA,CACTt1G,GACAizF,GACAtiC,GACA4kD,MAEA,MAAQ7gB,QAAM46B,WAAS1vH,IAAKmkG,IAAQpzC,GACpC,IAAK+jC,GAAKnB,aAAe+7B,KAAYpxH,KAAKkxH,gBAAgBrrB,IACxD,OAAOhkD,EACL7hD,KAAKsxH,mBACH96B,GACA1J,GAAa8B,eACb,IAAIzG,MAAM,gDACVkvB,KAKN+Z,GAAQ/7B,YAAYhuF,IAAMmvF,GAAKnB,YAAYhuF,IAAM,IAAIwpF,WACnD/uF,GAAStB,MAIXg2F,GAAKlC,UAAY,KACjB88B,GAAQ/8B,OAAS,KACjBzyC,EAAQ,CAAE40C,QAAM46B,YAAS,EAG3B1Z,QAASA,CACP51G,GACA2wD,GACA4kD,GACAtiB,MAEA/0F,KAAK2vH,YAAYl9D,IACjB5Q,EACE7hD,KAAKsxH,mBACH96B,EACA1J,GAAa8B,eACb,IAAIzG,MACD,cAAarmF,GAAS42G,oBAAoB52G,GAASC,QAEtDs1G,GAAcuB,IACZl3G,IAAKs0G,EAAct0G,IAAKlB,UAAMiB,GAAcK,KAElD,EAGF81G,UAAWA,CACT7iB,GACAtiC,GACA4kD,MAEAr3G,KAAK2vH,YAAYl9D,IACjB5Q,EACE7hD,KAAKsxH,mBACH96B,EACA1J,GAAa+B,iBACb,IAAI1G,MAAM,yBACVkvB,IAEJ,EAGFwY,QAASA,CACP96B,GACAtiC,GACA4kD,MAEAr3G,KAAK2vH,YAAYl9D,IACjB5Q,EACE7hD,KAAKsxH,mBACH96B,EACA1J,GAAayC,iBACb,IAAIpH,MAAM,uBACVkvB,IAEJ,GAIuD,EAE/D,CAEQsY,YAAYl9D,GAClB,MAAQ+jC,OAAM46B,UAAS1vH,IAAKmkG,GAAQpzC,EAC9B4hC,EAAS+8B,EAAQ/8B,OACnBmC,EAAKlC,YAAcD,IACrBmC,EAAKlC,UAAY,KACjB88B,EAAQ/8B,OAAS,aAEZr0F,KAAKkxH,gBAAgBrrB,GACxBxR,GACFA,EAAO3tB,SAEX,ECrUa,MAAMgsD,GAMnB7yH,cAAcG,KALG2yH,gBAAU,OACnBC,WAA4B,KAAI5yH,KAChC6yH,cAA+B,KAAI7yH,KACnC8yH,eAAiB,EAGvB9yH,KAAK2yH,WAAa3yH,KAAK+yH,KAAK72B,KAAKl8F,KACnC,CAEO0mE,UACL1mE,KAAKgzH,sBACLhzH,KAAKizH,oBACP,CAEUD,sBAERhzH,KAAKkzH,gBACLlzH,KAAK4C,eACP,CAEUqwH,qBAAqB,CAExBE,cACL,QAASnzH,KAAK6yH,aAChB,CAEOO,cACL,QAASpzH,KAAK4yH,UAChB,CAMOpwH,YAAY6wH,GACjB,OAAKrzH,KAAK6yH,gBACR7yH,KAAK8yH,eAAiB,EACtB9yH,KAAK6yH,cAAgB52B,KAAKz5F,YAAYxC,KAAK2yH,WAAYU,IAChD,EAGX,CAKOzwH,gBACL,QAAI5C,KAAK6yH,gBACP52B,KAAKr5F,cAAc5C,KAAK6yH,eACxB7yH,KAAK6yH,cAAgB,MACd,EAGX,CAKOK,gBACL,QAAIlzH,KAAK4yH,aACP32B,KAAK/7C,aAAalgD,KAAK4yH,YACvB5yH,KAAK4yH,WAAa,MACX,EAGX,CAOOG,OACL/yH,KAAK8yH,iBACuB,IAAxB9yH,KAAK8yH,iBACP9yH,KAAKszH,SAGDtzH,KAAK8yH,eAAiB,GAExB9yH,KAAKuzH,gBAEPvzH,KAAK8yH,eAAiB,EAE1B,CAEOS,gBACLvzH,KAAKkzH,gBACLlzH,KAAK4yH,WAAa32B,KAAKj8C,WAAWhgD,KAAK2yH,WAAY,EACrD,CAMUW,SAAe,ECnG3B,MAAME,GAA2B,CAC/BlxH,OAAQ,EACRke,MAAOA,IAAM,EACb26D,IAAKA,IAAM,GAGN,MAAMs4C,GAIX5wH,kBAAkB8T,EAAmBq1G,GACnC,IACE,GAAIr1G,EAAO,CACT,MAAMynG,EAAWqV,GAAaC,YAAY/8G,GAC1C,QAAS6xB,EAAI,EAAGA,EAAI41E,EAAS97G,OAAQkmC,IACnC,GAAIwjF,GAAY5N,EAAS59F,MAAMgoB,IAAMwjF,GAAY5N,EAASjjC,IAAI3yC,GAC5D,OAAO,EAOb,QAEF,OAAO,CACT,CAEA3lC,kBACE8T,EACAiwE,EACA+sC,GAEA,IACE,GAAIh9G,EAAO,CACT,MAAMi9G,EAAYH,GAAaC,YAAY/8G,GACrCynG,EAA8B,GACpC,IAAI51E,EACJ,IAAKA,EAAI,EAAGA,EAAIorF,EAAUtxH,OAAQkmC,IAChC41E,EAASh2G,KAAK,CAAEoY,MAAOozG,EAAUpzG,MAAMgoB,GAAI2yC,IAAKy4C,EAAUz4C,IAAI3yC,KAGhE,OAAOxoC,KAAK6zH,aAAazV,EAAUx3B,EAAK+sC,EAAe,CAKzD,QAEF,MAAO,CAAEnuE,IAAK,EAAGhlC,MAAOomE,EAAKzL,IAAKyL,EAAKktC,eAAWryH,EACpD,CAEAoB,oBACEu7G,EACAx3B,EACA+sC,GAOA/sC,EAAMvvE,KAAK+/C,IAAI,EAAGwvB,GAElBw3B,EAAS36F,KAAK,SAAUtV,EAAGE,GAEzB,OADaF,EAAEqS,MAAQnS,EAAEmS,OAIhBnS,EAAE8sE,IAAMhtE,EAAEgtE,GAErB,GAEA,IAAI44C,EAA+B,GACnC,GAAIJ,EAIF,QAASnrF,EAAI,EAAGA,EAAI41E,EAAS97G,OAAQkmC,IAAK,CACxC,MAAMwrF,EAAUD,EAAUzxH,OAC1B,GAAI0xH,EAAS,CACX,MAAMC,EAAUF,EAAUC,EAAU,GAAG74C,IAEnCijC,EAAS51E,GAAGhoB,MAAQyzG,EAAUN,EAK5BvV,EAAS51E,GAAG2yC,IAAM84C,IACpBF,EAAUC,EAAU,GAAG74C,IAAMijC,EAAS51E,GAAG2yC,KAI3C44C,EAAU3rH,KAAKg2G,EAAS51E,GAAE,MAI5BurF,EAAU3rH,KAAKg2G,EAAS51E,GAAE,MAI9BurF,EAAY3V,EAGd,IAGI8V,EAHAC,EAAY,EAMZC,EAAsBxtC,EACtBm8B,EAAoBn8B,EACxB,QAASp+C,EAAI,EAAGA,EAAIurF,EAAUzxH,OAAQkmC,IAAK,CACzC,MAAMhoB,EAAQuzG,EAAUvrF,GAAGhoB,MACrB26D,EAAM44C,EAAUvrF,GAAG2yC,IAEzB,GAAIyL,EAAM+sC,GAAmBnzG,GAASomE,EAAMzL,EAE1Ci5C,EAAc5zG,EACduiG,EAAY5nC,EACZg5C,EAAYpR,EAAYn8B,UACfA,EAAM+sC,EAAkBnzG,EAAO,CACxC0zG,EAAkB1zG,EAClB,OAGJ,MAAO,CACLglC,IAAK2uE,EACL3zG,MAAO4zG,GAAe,EACtBj5C,IAAK4nC,GAAa,EAClB+Q,UAAWI,EAEf,CAMArxH,mBAAmB8T,GACjB,IACE,OAAOA,EAAMynG,QAIf,OAHS5rG,GACPu9E,UAAOF,IAAI,+BAAgCr9E,GACpCghH,EACT,CACF,EClKK,MAAMa,GAiBXx0H,YACE+9C,EACAu2C,EACA7rF,EACAmuD,EAAO,EACPo7C,GAAO,EACP1b,GAAU,GACVn2F,KAvBc49C,WAAK,OACLu2C,QAAE,OACF0d,UAAI,OACJvpG,QAAE,OACFmuD,UAAI,OACJ0/B,aAAO,OACPm+B,YA4BT,CAAE9zG,MAAO,EAAG+zG,aAAc,EAAGC,WAAY,EAAGr5C,IAAK,GA3B7Bn7E,KACX+yF,UAEZ,CACF4D,MAuBK,CAAEn2E,MAAO,EAAG+zG,aAAc,EAAGC,WAAY,EAAGr5C,IAAK,GAtBtDyb,MAsBK,CAAEp2E,MAAO,EAAG+zG,aAAc,EAAGC,WAAY,EAAGr5C,IAAK,GArBtD0b,WAqBK,CAAEr2E,MAAO,EAAG+zG,aAAc,EAAGC,WAAY,EAAGr5C,IAAK,IAVtDn7E,KAAK49C,MAAQA,EACb59C,KAAKm0F,GAAKA,EACVn0F,KAAKsI,GAAKA,EACVtI,KAAKy2D,KAAOA,EACZz2D,KAAK6xG,KAAOA,EACZ7xG,KAAKm2F,QAAUA,CACjB,EChCK,SAASs+B,GAAoBr9B,EAAuB7C,GACzD,IAAImgC,EAA6B,KAEjC,QAASlsF,EAAI,EAAGgd,EAAM4xC,EAAU90F,OAAQkmC,EAAIgd,EAAKhd,IAAK,CACpD,MAAMmsF,EAAcv9B,EAAU5uD,GAC9B,GAAImsF,GAAeA,EAAYpgC,KAAOA,EAAI,CACxCmgC,EAAYC,EACZ,OAIJ,OAAOD,CACT,CA0CA,SAASE,GAAoBp+B,EAAgBq+B,GAC3C,GAAIr+B,EAAM,CACR,MAAMh2E,EAAQg2E,EAAKh2E,MAAQq0G,EAC3Br+B,EAAKh2E,MAAQg2E,EAAKhC,SAAWh0E,EAC7Bg2E,EAAK/B,OAASj0E,EAAQg2E,EAAK9tF,SAE/B,CAEO,SAASosH,GAAmBD,EAAiB5mD,GAElD,MAAMmpB,EAAYnpB,EAAQmpB,UAC1B,QAAS5uD,EAAI,EAAGgd,EAAM4xC,EAAU90F,OAAQkmC,EAAIgd,EAAKhd,IAC/CosF,GAAoBx9B,EAAU5uD,GAAIqsF,GAGhC5mD,EAAQopB,cACVu9B,GAAoB3mD,EAAQopB,aAAcw9B,GAE5C5mD,EAAQ+oB,gBAAiB,CAC3B,CA6GO,SAAS+9B,GACd9mD,EACA+mD,GAEA,IAAK/mD,EAAQ8rB,qBAAuBi7B,EAAWj7B,mBAC7C,OAGF,MAAM3C,EAAYnpB,EAAQmpB,UACpB69B,EAAeD,EAAW59B,UAChC,IAAKA,EAAU90F,SAAW2yH,EAAa3yH,OACrC,OAMF,MACM4yH,EAAUD,EADG59G,KAAKkR,MAAM0sG,EAAa3yH,OAAS,GAAK,GAEnDk0F,EACJi+B,GAAoBr9B,EAAW89B,EAAQ3gC,KACvC6C,EAAU//E,KAAKkR,MAAM6uE,EAAU90F,OAAS,GAAK,GAEzC6yH,EAASD,EAAQjhC,gBACjBmhC,EAAY5+B,EAAKvC,gBACR,OAAXkhC,GAAiC,OAAdC,GAKvBN,IADeM,EAAYD,GAAU,KAAQ3+B,EAAKh2E,MAAQ00G,EAAQ10G,OACxCytD,EAC5B,CC7Ne,MAAMonD,GAInBx1H,YAAYy1H,EAAsBvvB,GAAgB/lG,KAH1Cs1H,YAAM,OACNC,WAAK,EAGXv1H,KAAKs1H,OAASA,EACdt1H,KAAKu1H,MAAQxvB,CACf,CAEAyvB,QAAQh1H,EAAmB6G,GACzB,OAAOrH,KAAKs1H,OAAOE,QAAQ,CAAEz7G,KAAM,UAAWgsF,GAAI/lG,KAAKu1H,OAASluH,EAAK7G,EACvE,ECXa,MAAMi1H,GAInB51H,YAAYy1H,EAAQjuH,GAAKrH,KAHjBs1H,YAAM,OACNjuH,SAAG,EAGTrH,KAAKs1H,OAASA,EACdt1H,KAAKqH,IAAMA,CACb,CAEAquH,YACE,OAAO11H,KAAKs1H,OAAOK,UAAU,MAAO31H,KAAKqH,IAAK,CAAE0S,KAAM,YAAa,EAAO,CACxE,UACA,WAEJ,ECDa,MAAM67G,GAyBnB/1H,cAAcG,KAxBN61H,KAAsB,CAC5B,EAAK,EAAK,EAAK,EAAK,EAAK,GAAM,GAAM,GAAM,IAAM,GAAM,IACxD71H,KACO81H,OAA6B,CACnC,IAAIC,YAAY,KAChB,IAAIA,YAAY,KAChB,IAAIA,YAAY,KAChB,IAAIA,YAAY,MACjB/1H,KACOg2H,UAAgC,CACtC,IAAID,YAAY,KAChB,IAAIA,YAAY,KAChB,IAAIA,YAAY,KAChB,IAAIA,YAAY,MACjB/1H,KACOi2H,KAAoB,IAAIF,YAAY,KAAI/1H,KACxCk2H,QAAuB,IAAIH,YAAY,KAAI/1H,KAC3CqH,IAAmB,IAAI0uH,YAAY,GAAE/1H,KAErCm2H,OAAiB,EAACn2H,KAClBo2H,QAAkB,EAACp2H,KACnBq2H,iBAAW,OACXC,oBAAc,EAGpBt2H,KAAKu2H,WACP,CAGAC,yBAAyBC,GACvB,MAAMC,EAAO,IAAIlvB,SAASivB,GACpBE,EAAW,IAAIZ,YAAY,GACjC,QAASvtF,EAAI,EAAGA,EAAI,EAAGA,IACrBmuF,EAASnuF,GAAKkuF,EAAKE,UAAc,EAAJpuF,GAG/B,OAAOmuF,CACT,CAEAJ,YACE,MAAMN,EAAOj2H,KAAKi2H,KACZC,EAAUl2H,KAAKk2H,QACfJ,EAAS91H,KAAK81H,OACde,EAAUf,EAAO,GACjBgB,EAAUhB,EAAO,GACjBiB,EAAUjB,EAAO,GACjBkB,EAAUlB,EAAO,GACjBE,EAAYh2H,KAAKg2H,UACjBiB,EAAajB,EAAU,GACvBkB,EAAalB,EAAU,GACvBmB,EAAanB,EAAU,GACvBoB,GAAapB,EAAU,GAEvB9mG,GAAI,IAAI6mG,YAAY,KAC1B,IAAI11H,GAAI,EACJg3H,GAAK,EACL7uF,GAAI,EACR,IAAKA,GAAI,EAAGA,GAAI,IAAKA,KAEjBtZ,GAAEsZ,IADAA,GAAI,IACCA,IAAK,EAEJA,IAAK,EAAK,IAItB,IAAKA,GAAI,EAAGA,GAAI,IAAKA,KAAK,CACxB,IAAI8uF,GAAKD,GAAMA,IAAM,EAAMA,IAAM,EAAMA,IAAM,EAAMA,IAAM,EACzDC,GAAMA,KAAO,EAAW,IAALA,GAAa,GAChCrB,EAAK51H,IAAKi3H,GACVpB,EAAQoB,IAAMj3H,GAGd,MAAMk3H,GAAKroG,GAAE7uB,IACPm3H,GAAKtoG,GAAEqoG,IACPE,GAAKvoG,GAAEsoG,IAGb,IAAIniF,GAAa,IAARnmB,GAAEooG,IAAqB,SAALA,GAC3BT,EAAQx2H,IAAMg1C,IAAK,GAAOA,KAAM,EAChCyhF,EAAQz2H,IAAMg1C,IAAK,GAAOA,KAAM,GAChC0hF,EAAQ12H,IAAMg1C,IAAK,EAAMA,KAAM,GAC/B2hF,EAAQ32H,IAAKg1C,GAGbA,GAAU,SAALoiF,GAAwB,MAALD,GAAsB,IAALD,GAAmB,SAAJl3H,GACxD42H,EAAWK,IAAOjiF,IAAK,GAAOA,KAAM,EACpC6hF,EAAWI,IAAOjiF,IAAK,GAAOA,KAAM,GACpC8hF,EAAWG,IAAOjiF,IAAK,EAAMA,KAAM,GACnC+hF,GAAWE,IAAMjiF,GAGZh1C,IAGHA,GAAIk3H,GAAKroG,GAAEA,GAAEA,GAAEuoG,GAAKF,MACpBF,IAAMnoG,GAAEA,GAAEmoG,MAHVh3H,GAAIg3H,GAAK,EAMf,CAEA3B,UAAUgC,GAER,MAAMrwH,EAAMrH,KAAKw2H,yBAAyBkB,GAC1C,IAAIC,GAAU,EACVxsE,EAAS,EAEb,KAAOA,EAAS9jD,EAAI/E,QAAUq1H,GAC5BA,EAAUtwH,EAAI8jD,KAAYnrD,KAAKqH,IAAI8jD,GACnCA,IAGF,GAAIwsE,EACF,OAGF33H,KAAKqH,IAAMA,EACX,MAAM+uH,EAAWp2H,KAAKo2H,QAAU/uH,EAAI/E,OAEpC,GAAgB,IAAZ8zH,GAA6B,IAAZA,GAA6B,IAAZA,EACpC,MAAM,IAAIjuC,MAAM,wBAA0BiuC,GAG5C,MAAMD,EAAUn2H,KAAKm2H,OAA6B,GAAnBC,EAAU,EAAI,GAC7C,IAAIwB,EACAC,EAEJ,MAAMxB,EAAer2H,KAAKq2H,YAAc,IAAIN,YAAYI,GAClDG,EAAkBt2H,KAAKs2H,eAAiB,IAAIP,YAAYI,GACxD2B,EAAO93H,KAAKi2H,KACZJ,GAAO71H,KAAK61H,KAEZG,GAAYh2H,KAAKg2H,UACjBiB,GAAajB,GAAU,GACvBkB,GAAalB,GAAU,GACvBmB,GAAanB,GAAU,GACvBoB,GAAapB,GAAU,GAE7B,IAAI+B,GACA1iF,GAEJ,IAAKuiF,EAAQ,EAAGA,EAAQzB,EAAQyB,IAC1BA,EAAQxB,EACV2B,GAAO1B,EAAYuB,GAASvwH,EAAIuwH,IAGlCviF,GAAI0iF,GAEAH,EAAQxB,GAAY,GAEtB/gF,GAAKA,IAAK,EAAMA,KAAM,GAGtBA,GACGyiF,EAAKziF,KAAM,KAAO,GAClByiF,EAAMziF,KAAM,GAAM,MAAS,GAC3ByiF,EAAMziF,KAAM,EAAK,MAAS,EAC3ByiF,EAAS,IAAJziF,IAGPA,IAAKwgF,GAAM+B,EAAQxB,EAAW,IAAM,IAC3BA,EAAU,GAAKwB,EAAQxB,GAAY,IAE5C/gF,GACGyiF,EAAKziF,KAAM,KAAO,GAClByiF,EAAMziF,KAAM,GAAM,MAAS,GAC3ByiF,EAAMziF,KAAM,EAAK,MAAS,EAC3ByiF,EAAS,IAAJziF,KAGTghF,EAAYuB,GAASG,IAAQ1B,EAAYuB,EAAQxB,GAAW/gF,MAAO,GAGrE,IAAKwiF,EAAW,EAAGA,EAAW1B,EAAQ0B,IACpCD,EAAQzB,EAAS0B,EAEfxiF,GADa,EAAXwiF,EACExB,EAAYuB,GAEZvB,EAAYuB,EAAQ,GAIxBtB,EAAeuB,GADbA,EAAW,GAAKD,GAAS,EACAviF,GAGzB4hF,GAAWa,EAAKziF,KAAM,KACtB6hF,GAAWY,EAAMziF,KAAM,GAAM,MAC7B8hF,GAAWW,EAAMziF,KAAM,EAAK,MAC5B+hF,GAAWU,EAAS,IAAJziF,KAGpBihF,EAAeuB,GAAYvB,EAAeuB,KAAc,CAE5D,CAGAG,uBAAuBlwE,GACrB,OACGA,GAAQ,IACA,MAAPA,IAAkB,GACX,SAAPA,IAAoB,EACrBA,IAAS,EAEd,CAEA0tE,QAAQyC,EAA+B9sE,EAAgBoqE,GACrD,MAAM2C,EAAUl4H,KAAKo2H,QAAU,EACzBE,EAAiBt2H,KAAKs2H,eACtB6B,EAAUn4H,KAAKk2H,QAEfF,EAAYh2H,KAAKg2H,UACjBiB,EAAajB,EAAU,GACvBkB,EAAalB,EAAU,GACvBmB,EAAanB,EAAU,GACvBoB,EAAapB,EAAU,GAEvBoC,GAAap4H,KAAKw2H,yBAAyBjB,GACjD,IAAI8C,GAAcD,GAAW,GACzBE,GAAcF,GAAW,GACzBG,GAAcH,GAAW,GACzBI,GAAcJ,GAAW,GAE7B,MAAMK,GAAa,IAAIC,WAAWT,GAC5BU,GAAc,IAAID,WAAWD,GAAWn2H,QAE9C,IAAIs2H,GAAIC,GAAIC,GAAIC,GACZC,GAAIC,GAAIC,GAAIC,GACZC,GAAaC,GAAaC,GAAaC,GAEvC3B,GAAOpvF,GACX,MAAMgxF,GAAWx5H,KAAKg4H,uBAEtB,KAAO7sE,EAASstE,GAAWn2H,QAAQ,CAcjC,IAbA82H,GAAcI,GAASf,GAAWttE,IAClCkuE,GAAcG,GAASf,GAAWttE,EAAS,IAC3CmuE,GAAcE,GAASf,GAAWttE,EAAS,IAC3CouE,GAAcC,GAASf,GAAWttE,EAAS,IAE3C6tE,GAAKI,GAAc9C,EAAe,GAClC2C,GAAKM,GAAcjD,EAAe,GAClC4C,GAAKI,GAAchD,EAAe,GAClC6C,GAAKE,GAAc/C,EAAe,GAElCsB,GAAQ,EAGHpvF,GAAI,EAAGA,GAAI0vF,EAAS1vF,KACvBowF,GACE3B,EAAW+B,KAAO,IAClB9B,EAAY+B,IAAM,GAAM,KACxB9B,EAAY+B,IAAM,EAAK,KACvB9B,EAAgB,IAAL+B,IACX7C,EAAesB,IACjBiB,GACE5B,EAAWgC,KAAO,IAClB/B,EAAYgC,IAAM,GAAM,KACxB/B,EAAYgC,IAAM,EAAK,KACvB/B,EAAgB,IAAL4B,IACX1C,EAAesB,GAAQ,GACzBkB,GACE7B,EAAWiC,KAAO,IAClBhC,EAAYiC,IAAM,GAAM,KACxBhC,EAAY6B,IAAM,EAAK,KACvB5B,EAAgB,IAAL6B,IACX3C,EAAesB,GAAQ,GACzBmB,GACE9B,EAAWkC,KAAO,IAClBjC,EAAY8B,IAAM,GAAM,KACxB7B,EAAY8B,IAAM,EAAK,KACvB7B,EAAgB,IAAL8B,IACX5C,EAAesB,GAAQ,GAEzBoB,GAAKJ,GACLK,GAAKJ,GACLK,GAAKJ,GACLK,GAAKJ,GAELnB,IAAgB,EAIlBgB,GACGT,EAAQa,KAAO,KAAO,GACtBb,EAASc,IAAM,GAAM,MAAS,GAC9Bd,EAASe,IAAM,EAAK,MAAS,EAC9Bf,EAAa,IAALgB,IACR7C,EAAesB,IACjBiB,GACGV,EAAQc,KAAO,KAAO,GACtBd,EAASe,IAAM,GAAM,MAAS,GAC9Bf,EAASgB,IAAM,EAAK,MAAS,EAC9BhB,EAAa,IAALa,IACR1C,EAAesB,GAAQ,GACzBkB,GACGX,EAAQe,KAAO,KAAO,GACtBf,EAASgB,IAAM,GAAM,MAAS,GAC9BhB,EAASa,IAAM,EAAK,MAAS,EAC9Bb,EAAa,IAALc,IACR3C,EAAesB,GAAQ,GACzBmB,GACGZ,EAAQgB,KAAO,KAAO,GACtBhB,EAASa,IAAM,GAAM,MAAS,GAC9Bb,EAASc,IAAM,EAAK,MAAS,EAC9Bd,EAAa,IAALe,IACR5C,EAAesB,GAAQ,GAGzBe,GAAYxtE,GAAUquE,GAASZ,GAAKP,IACpCM,GAAYxtE,EAAS,GAAKquE,GAAST,GAAKT,IACxCK,GAAYxtE,EAAS,GAAKquE,GAASV,GAAKP,IACxCI,GAAYxtE,EAAS,GAAKquE,GAASX,GAAKL,IAGxCH,GAAce,GACdd,GAAce,GACdd,GAAce,GACdd,GAAce,GAEdpuE,GAAkB,EAGpB,OAAOwtE,GAAYp7B,MACrB,ECrUa,MAAMk8B,GAYnB55H,YAAY6vC,GAAqBgqF,sBAAqB,GAAS,IAI7D,GAJiE15H,KAX3D25H,YAAsB,EAAI35H,KAC1B05H,wBAAkB,OAClBpE,OAA8B,KAAIt1H,KAClC45H,kBAAyC,KAAI55H,KAC7CqH,IAA0B,KAAIrH,KAC9B65H,WAAgC,KAAI75H,KACpC85H,cAAmC,KAAI95H,KACvC+5H,UAAgC,KAAI/5H,KACpCg6H,cAAoC,KAAIh6H,KACxCi6H,iBAAW,EAGjBj6H,KAAKi6H,YAAcvqF,EAAOwqF,kBAC1Bl6H,KAAK05H,mBAAqBA,EAEtBA,EACF,IACE,MAAMS,EAAgBl+B,KAAKm+B,OACvBD,IACFn6H,KAAKs1H,OACH6E,EAAc7E,QACZ6E,EAAsBE,aAG5B,QAGgB,OAAhBr6H,KAAKs1H,SACPt1H,KAAKi6H,aAAc,EAEvB,CAEAvzD,UACE1mE,KAAKs1H,OAAS,KACdt1H,KAAK45H,kBAAoB,KACzB55H,KAAKqH,IAAM,KACXrH,KAAK65H,WAAa,KAClB75H,KAAK85H,cAAgB,KACrB95H,KAAK+5H,UAAY,KACjB/5H,KAAKg6H,cAAgB,IACvB,CAEOM,SACL,OAAOt6H,KAAKi6H,WACd,CAEOprD,QACL,MAAQmrD,gBAAeF,iBAAkB95H,KACzC,IAAKg6H,GAAiBF,EACpB,YAAKr6F,QACE,KAET,MAAMj/B,EAAO,IAAIqwF,WAAWmpC,GAE5B,OADAh6H,KAAKy/B,QACDz/B,KAAK05H,mBD9DN,SAASa,GAAc1jF,GAC5B,MAAM2jF,EAAc3jF,EAAM6mD,WACpB+8B,EACJD,GAAe,IAAIhzB,SAAS3wD,EAAM0mD,QAAQm9B,SAASF,EAAc,GACnE,OAAIC,EACKt+B,GAAWtlD,EAAO,EAAG2jF,EAAcC,GAErC5jF,CACT,CCuDa0jF,CAAc/5H,GAEhBA,CACT,CAEOi/B,QACLz/B,KAAKg6H,cAAgB,KACrBh6H,KAAK+5H,UAAY,KACjB/5H,KAAK85H,cAAgB,KACjB95H,KAAK45H,oBACP55H,KAAK45H,kBAAoB,KAE7B,CAEOpE,QACLh1H,EACA6G,EACA0+F,GAEA,OAAI/lG,KAAKi6H,YACA,IAAIt4E,QAAQ,CAACC,EAASC,KAC3B7hD,KAAK26H,gBAAgB,IAAI9pC,WAAWrwF,GAAO6G,EAAK0+F,GAChD,MAAM60B,EAAgB56H,KAAK6uE,QACvB+rD,EACFh5E,EAAQg5E,EAAcr9B,QAEtB17C,EAAO,IAAIsmC,MAAM,4CAA2C,GAI3DnoF,KAAK66H,iBAAiB,IAAIhqC,WAAWrwF,GAAO6G,EAAK0+F,EAC1D,CAIO40B,gBACLn6H,EACA6G,EACA0+F,GAEA,MAAQg0B,YAAWC,gBAAeF,iBAAkB95H,KACpDA,KAAK86H,QAAQ,kBAMThB,IACFt5H,EAAO2gG,GAAiB24B,EAAet5H,GACvCR,KAAK85H,cAAgB,MAIvB,MAAMiB,EAAe/6H,KAAKg7H,cAAcx6H,GACxC,IAAKu6H,EAAaz4H,OAChB,OAAO,KAGLy3H,IACFh0B,EAAKg0B,GAGP,IAAIH,EAAoB55H,KAAK45H,kBACxBA,IACHA,EAAoB55H,KAAK45H,kBAAoB,IAAIhE,IAEnDgE,EAAkBlE,UAAUruH,GAE5B,MAAMa,EAAS8xH,EAKf,OAHAh6H,KAAKg6H,cAAgBJ,EAAkBpE,QAAQuF,EAAax9B,OAAQ,EAAGwI,GACvE/lG,KAAK+5H,UAAY59B,GAAW4+B,GAAc,IAAKx9B,OAE1Cr1F,GACI,IAGX,CAEO2yH,iBACLr6H,EACA6G,EACA0+F,GAEA,MAAMuvB,EAASt1H,KAAKs1H,OACpB,OAAIt1H,KAAKqH,MAAQA,IAAQrH,KAAK65H,cAC5B75H,KAAKqH,IAAMA,EACXrH,KAAK65H,WAAa,IAAIpE,GAAWH,EAAQjuH,IAEpCrH,KAAK65H,WACTnE,YACA7zH,KAAMo5H,GAEA3F,GAGLt1H,KAAK86H,QAAQ,yBACE,IAAIzF,GAAUC,EAAQ,IAAIzkC,WAAWkV,IACtCyvB,QAAQh1H,EAAK+8F,OAAQ09B,IAJ1Bt5E,QAAQE,OAAO,IAAIsmC,MAAM,gCAMnC3oC,MAAOxO,IACN++C,GAAOhtC,KACJ,wDAAuD/R,EAAIj3B,SAASi3B,EAAIw4D,WAGpExpG,KAAKk7H,iBAAiB16H,EAAM6G,EAAK0+F,IAE9C,CAEQm1B,iBAAiB16H,EAAM6G,EAAK0+F,GAClC/lG,KAAKi6H,aAAc,EACnBj6H,KAAK25H,YAAa,EAClB35H,KAAK26H,gBAAgBn6H,EAAM6G,EAAK0+F,GAChC,MAAM60B,EAAgB56H,KAAK6uE,QAC3B,GAAI+rD,EACF,OAAOA,EAAcr9B,OAEvB,MAAM,IAAIpV,MAAM,wDAClB,CAEQ6yC,cAAcx6H,GACpB,IAAIu6H,EAAev6H,EACnB,MAAM26H,EAAa36H,EAAK8B,OAAU9B,EAAK8B,OApLxB,GAqLf,OAAI64H,IAAe36H,EAAK8B,SACtBy4H,EAAe5+B,GAAW37F,EAAM,EAAG26H,GACnCn7H,KAAK85H,cAAgB39B,GAAW37F,EAAM26H,IAEjCJ,CACT,CAEQD,QAAQM,GACTp7H,KAAK25H,aAGV5pC,GAAOF,IAAoBurC,qBAC3Bp7H,KAAK25H,YAAa,EACpB,ECpIa,MAAM0B,WACX3I,GAmCR7yH,YACE40G,EACA6mB,EACAhnC,EACA0vB,EACAyI,GAEAv3E,QAAQl1C,KAvCAy0G,SAAG,OAEHqO,aAAgC,KAAI9iH,KACpCu7H,YAA+B,KAAIv7H,KACnCs7H,qBAAe,OACfE,WAAyC,KAAIx7H,KAC7Cu2E,OAxBD,UAwB+Bv2E,KAC9BysH,kBAAY,OACZ91G,MAAiC,KAAI3W,KACrCy7H,YAAiC,KAAIz7H,KACrC0vC,YAAM,OACNulD,aAAuB,EAAKj1F,KAC5B07H,gBAA0B,EAAC17H,KAC3B27H,iBAA2B,EAAC37H,KAC5B60G,cAAwB,EAAC70G,KACzBi4F,gBAAiC,KAAIj4F,KACrC47H,gBAA0B,EAAK57H,KAC/B67H,UAAoB,EAAC77H,KACrB8J,OAA8B,KAAI9J,KAClC87H,oBAAc,OACdxnC,eAAS,OACTynC,gBAAiC,KAAI/7H,KACrCg8H,oBAA8B,EAAKh8H,KACnCi8H,eAAS,OACTC,QAA+B,GAAEl8H,KACjCm8H,WAAmC,KAAIn8H,KACvCo8H,SAAiC,KAAIp8H,KAE9BgkH,UAAoB,GAAEhkH,KAC7B6vF,SAAG,OACH9sC,UAAI,EAUZ/iD,KAAKysH,aAAeA,EACpBzsH,KAAKgkH,UAAYA,EACjBhkH,KAAK6vF,IAAME,GAAOF,IAAIqM,KAAKnM,GAAWi0B,SACtChkH,KAAK+iD,KAAOgtC,GAAOhtC,KAAKm5C,KAAKnM,GAAWi0B,SACxChkH,KAAKy0G,IAAMA,EACXz0G,KAAK87H,eAAiB,IAAI/M,GAAeta,EAAI/kE,QAC7C1vC,KAAKs0F,UAAYA,EACjBt0F,KAAKs7H,gBAAkBA,EACvBt7H,KAAK0vC,OAAS+kE,EAAI/kE,OAClB1vC,KAAKi8H,UAAY,IAAIxC,GAAUhlB,EAAI/kE,QACnC+kE,EAAInxF,GAAG2lE,EAAOc,gBAAiB/pF,KAAKwoH,iBAAkBxoH,KACxD,CAEUszH,SACRtzH,KAAKq8H,WACP,CAEUA,YAAY,CAGfznB,UAAUC,GAA6B,CAEvCC,WACL90G,KAAK87H,eAAe9lC,QACpBh2F,KAAKs0F,UAAU0B,MAAMh2F,KAAKysH,cAC1B,MAAMj2B,EAAOx2F,KAAKu7H,YACV,MAAJ/kC,KAAMnC,SACRmC,EAAKV,gBACL91F,KAAKs7H,gBAAgB1O,eAAep2B,IAEtCx2F,KAAKs8H,kBACLt8H,KAAKu7H,YAAc,KACnBv7H,KAAK8iH,aAAe,KACpB9iH,KAAK4C,gBACL5C,KAAKkzH,gBACLlzH,KAAKU,MA7FE,SA8FT,CAEU67H,aACR5V,EACArQ,GAIA,GACEA,EAAa9e,MACbmvB,EAAWmN,YACVnN,EAAWxrC,MACXn7E,KAAK2W,MAEN,OAAO,EAET,MAAM2gF,EAAWgf,EAAahf,SAG9B,GAAY,MAARA,KAAUh1F,OAAQ,CACpB,MAAMikH,EAAWjvB,EAASA,EAASh1F,OAAS,GAU5C,OAJyBmxH,GAAa+I,WACpCx8H,KAAK2W,MACL4vG,EAAS/lG,MAAQ+lG,EAAS79G,SAAW,EACvC,CAMF,OAAO1I,KAAKs7H,gBAAgBvN,kBAD1BzX,EAAalf,UAAUkf,EAAalf,UAAU90F,OAAS,GAAGgK,KAE9D,CAEUmwH,kBAC0C,MAAlD,GAAIz8H,KAAK8J,QAAmC,OAAzB9J,KAAK+7H,gBACtB,OAAOW,OAAPA,EAAO18H,KAAK8J,OAAO9J,KAAK+7H,uBAAjBW,IAAmCzuD,OAE9C,CAEUstC,gBACRl0F,EACA7mB,GAEA,MAAMmW,EAAS3W,KAAK2W,MAAQ3W,KAAKy7H,YAAcj7H,EAAKmW,MACpD3W,KAAKm8H,WAAan8H,KAAK28H,eAAezgC,KAAKl8F,MAC3CA,KAAKo8H,SAAWp8H,KAAK48H,aAAa1gC,KAAKl8F,MACvC2W,EAAM4yB,iBAAiB,UAAWvpC,KAAKm8H,YACvCxlH,EAAM4yB,iBAAiB,QAASvpC,KAAKo8H,UACrC,MAAM1sF,EAAS1vC,KAAK0vC,OAChB1vC,KAAK8J,QAAU4lC,EAAO06E,eApJnB,YAoJoCpqH,KAAKU,OAC9CV,KAAK40G,UAAUllE,EAAOmlE,cAE1B,CAEU2G,mBACR,MAAM7kG,EAAQ3W,KAAK2W,MACV,MAALA,KAAOkmH,QACT78H,KAAK6vF,IAAI,sDACT7vF,KAAK60G,cAAgB70G,KAAK07H,gBAAkB,GAI1C/kH,GAAS3W,KAAKm8H,YAAcn8H,KAAKo8H,WACnCzlH,EAAM0nG,oBAAoB,UAAWr+G,KAAKm8H,YAC1CxlH,EAAM0nG,oBAAoB,QAASr+G,KAAKo8H,UACxCp8H,KAAKm8H,WAAan8H,KAAKo8H,SAAW,MAEhCp8H,KAAKs0F,WACPt0F,KAAKs0F,UAAU7tC,SAEjBzmD,KAAK2W,MAAQ3W,KAAKy7H,YAAc,KAChCz7H,KAAK47H,gBAAiB,EACtB57H,KAAKs7H,gBAAgB5M,qBACrB1uH,KAAK80G,UACP,CAEU6nB,iBACR,MAAQjtF,SAAQ6rF,cAAa5kH,QAAO8kH,cAAa/6H,SAAUV,KACrDwnB,EAAsB7Q,EAAQA,EAAM6Q,YAAc,EAClDm/F,EAAa8M,GAAa9M,WAC9B8U,GAA4B9kH,EAC5B6Q,EACAkoB,EAAOotF,eAST,GANA98H,KAAK6vF,IACF,oBACCmC,EAAgBxqE,GAAeA,EAAYoxB,QAAQ,GAAKpxB,aAC9C9mB,KAnLT,UAsLDV,KAAKU,MACPV,KAAK+8H,yBAAiB,GACbxB,EAAa,CAEtB,MAAMyB,EAAYttF,EAAOszE,uBACnBia,EAAkB1B,EAAY/6G,MAAQw8G,EACtCE,EACJ3B,EAAY/6G,MAAQ+6G,EAAY7yH,SAAWs0H,EAE7C,IACGrW,EAAWnhE,KACZ03E,EAAgBvW,EAAWnmG,OAC3By8G,EAAkBtW,EAAWxrC,IAC7B,CACA,MAAMgiD,EAAe31G,EAAc01G,GAE/B11G,EAAcy1G,GAAmBE,KAC/BA,GAAgB5B,EAAYlnC,SAC9Br0F,KAAK6vF,IACH,mFAEF0rC,EAAYzlC,gBACZ91F,KAAK+8H,qBAEP/8H,KAAK8iH,aAAe,OAKtBnsG,IAEF3W,KAAKs7H,gBAAgBhN,uBACnB9mG,EACA6oB,IACArwC,KAAKysH,cACL,GAGFzsH,KAAK07H,gBAAkBl0G,IAIpBxnB,KAAK47H,iBAAmBjV,EAAWnhE,MACtCxlD,KAAK27H,iBAAmB37H,KAAK60G,cAAgBrtF,GAI/CxnB,KAAKuzH,eACP,CAEUqJ,eAER58H,KAAK60G,cAAgB70G,KAAK07H,gBAAkB,CAC9C,CAEUlT,iBACRnhG,EACA7mB,GAEAR,KAAKi4F,gBAAkBz3F,EAAKy3F,gBAC5Bj4F,KAAKk8H,QAAU,EACjB,CAEUlJ,sBACRhzH,KAAK80G,WACL5/D,MAAM89E,qBACR,CAEUC,qBACRjzH,KAAKU,MAnQE,UAoQHV,KAAK87H,gBACP97H,KAAK87H,eAAep1D,UAElB1mE,KAAKs0F,WACPt0F,KAAKs0F,UAAU5tB,UAEb1mE,KAAKi8H,WACPj8H,KAAKi8H,UAAUv1D,UAGjB1mE,KAAKy0G,IACHz0G,KAAK6vF,IACL7vF,KAAK+iD,KACL/iD,KAAKi8H,UACLj8H,KAAKs0F,UACLt0F,KAAK87H,eACL97H,KAAKs7H,gBACH,KACJpmF,MAAM+9E,oBACR,CAEUmK,aACR5mC,EACA54C,EACAy/E,GAEAr9H,KAAKs9H,qBAAqB9mC,EAAM54C,EAAOy/E,EACzC,CAEQC,qBACN9mC,EACA54C,EACAy/E,GAkBAr9H,KAAKu9H,YAAY/mC,EAAM54C,EAAOy/E,EAf5B78H,IAEA,GAAIR,KAAKw9H,mBAAmBhnC,GAO1B,OANAx2F,KAAK+iD,KACSyzC,cAAKrC,KACf3zF,EAAKqxG,KAAO,OAASrxG,EAAKqxG,KAAK31E,MAAQ,eAC5Bs6D,EAAK54C,2CAEpB59C,KAAKs7H,gBAAgB1O,eAAep2B,GAGtCA,EAAKzB,MAAMpC,aACX3yF,KAAKy9H,4BAA4Bj9H,EAAI,GAIpCqB,KAAMrB,IACL,IAAKA,EAEH,OAEF,MAAME,EAAQV,KAAKU,MACfV,KAAKw9H,mBAAmBhnC,IA1TpB,iBA4TJ91F,IACEV,KAAKu7H,aA1TR,YA0TuB76H,KAEtBV,KAAKs7H,gBAAgB1O,eAAep2B,GACpCx2F,KAAKU,MAlUT,SAuUI,YAAaF,IACfR,KAAK6vF,IAAK,mBAAkB2G,EAAKrC,eAAeqC,EAAK54C,SACrD59C,KAAKy0G,IAAInrC,QAAQ2f,EAAOuC,YAAahrF,IAIvCR,KAAK09H,4BAA4Bl9H,GAAI,GAEtCg/C,MAAOi5D,IAhVH,YAiVCz4G,KAAKU,OAxUR,UAwUmCV,KAAKU,QAGzCV,KAAK+iD,KAAK01D,GACVz4G,KAAK29H,qBAAqBnnC,GAAI,EAEpC,CAEUonC,qBAAqBpnC,GAAgB,MAC7C,MAAQ8kC,mBAAoBt7H,KAE5B,GXnY2B69H,cWkYTvC,EAAgBrN,SAASz3B,GACA,CAEzC,MACMq9B,EAAe7zH,KAAK89H,iBACxB99H,KAAKy7H,YAFcjlC,EAAKlqF,MAKpByxH,EAAyB1mH,KAAK+/C,IAClCo/B,EAAK9tF,SACLmrH,EAAeA,EAAaruE,IAAMxlD,KAAK0vC,OAAOsuF,iBAE5Ch+H,KAAKi+H,sBAAsBF,IAC7BzC,EAAgB1O,eAAep2B,EAAI,MAEU,KAAtC0nC,cAAKzC,kBAALyC,IAAkB9f,SAAS97G,QAEpCg5H,EAAgB5M,qBACP4M,EAAgBlN,SAAS53B,EAAKlqF,QAEvCgvH,EAAgBtO,uBAAuB,CACrCx2B,OACAqb,KAAM,KACN9c,MAAOyB,EAAKzB,MACZzsF,GAAIkuF,EAAKlqF,OX1Zc4hH,YW4ZrBoN,EAAgBrN,SAASz3B,IAC3B8kC,EAAgB1O,eAAep2B,GAGrC,CAEU2nC,gBACRl7E,EACAG,EACA92C,EAAgC,MAE1B22C,EAAcG,GAMpBpjD,KAAKy0G,IAAInrC,QAAQ2f,EAAOW,gBADe,CAAE3mC,cAAaG,YAAW92C,QAEnE,CAEU8xH,iBAAiB5nC,EAAgB54C,GACzC59C,KAAKu9H,YAAY/mC,EAAM54C,GACpB/7C,KAAMrB,IACL,IAAKA,GAAQR,KAAKw9H,mBAAmBhnC,KAAUx2F,KAAK8J,OAClD,MAAM,IAAIq+E,MAAM,qBAGlB,OAAO3nF,IAERqB,KAAMrB,IACL,MAAQi0G,OAAQz0G,MACR4nG,WAAYpnG,EACd69H,EAAc7nC,EAAKnB,YAGzB,GACEuS,GACAA,EAAQlK,WAAa,GACrB2gC,GACAA,EAAYh3H,KACZg3H,EAAYt4B,IACW,YAAvBs4B,EAAYz4B,OACZ,CACA,MAAMntC,EAAYwjC,KAAK7sE,YAAYC,MAEnC,OAAOrvB,KAAKi8H,UACTzG,QACC,IAAI3kC,WAAW+W,GACfy2B,EAAYh3H,IAAIk2F,OAChB8gC,EAAYt4B,GAAGxI,QAEhB/9C,MAAOxO,IACNyjE,QAAInrC,QAAQ2f,EAAOiD,MAAO,CACxB5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa0B,mBACtBgqB,OAAO,EACP33F,MAAOmwB,EACPynE,OAAQznE,EAAIw4D,QACZhT,SAEIxlD,IAEPnvC,KAAMy8H,IACL,MAAM9lE,EAAUyjC,KAAK7sE,YAAYC,MACjColF,SAAInrC,QAAQ2f,EAAOwC,eAAgB,CACjC+K,OACAoR,QAAS02B,EACTvpC,MAAO,CACLwpC,OAAQ9lE,EACR+lE,SAAUhmE,KAGdh4D,EAAKonG,QAAU02B,EAER99H,GACR,CAGL,OAAOA,IAERqB,KAAMrB,IACL,MAAQ+6H,cAAa9mB,MAAK3qG,UAAW9J,KACrC,IAAK8J,EACH,MAAM,IAAIq+E,MAAM,qCAGlB,MAAM4M,EAAQyB,EAAKzB,MACnB/0F,KAAKU,MA3cL,OA4cAk9C,EAAM8hE,cAAgB,EACtBlpB,EAAKh2F,KAAO,IAAIqwF,WAAWrwF,EAAKonG,SAChC7S,EAAMjC,QAAQtyE,MAAQu0E,EAAMhC,UAAUvyE,MAAQy7E,KAAK7sE,YAAYC,MAC/D0lE,EAAMjC,QAAQ3X,IAAM4Z,EAAMhC,UAAU5X,IAAM8gB,KAAK7sE,YAAYC,MAGvD7uB,EAAKg2F,OAAS+kC,GAChB9mB,EAAInrC,QAAQ2f,EAAO6C,cAAe,CAChCiJ,QACAyB,KAAM+kC,EACN1pB,KAAM,KACNvpG,GAAIkuF,EAAKlqF,OAGbtM,KAAK+yH,MAAI,GAEVvzE,MAAOi5D,IA7dH,YA8dCz4G,KAAKU,OArdR,UAqdmCV,KAAKU,QAGzCV,KAAK+iD,KAAK01D,GACVz4G,KAAK29H,qBAAqBnnC,GAAI,EAEpC,CAEUgnC,mBAAmBhnC,GAC3B,MAAQ+kC,eAAgBv7H,KACxB,OACGw2F,IACA+kC,GACD/kC,EAAK54C,QAAU29E,EAAY39E,OAC3B44C,EAAKrC,KAAOonC,EAAYpnC,IACxBqC,EAAKxB,QAAUumC,EAAYvmC,KAE/B,CAEUypC,qBAAqBjoC,EAAgBqb,GAAmB,YAChE,MAAMl7F,EAAQ3W,KAAKy7H,YAAcz7H,KAAKy7H,YAAcz7H,KAAK2W,MACzD3W,KAAK6vF,IACF,YAAW2G,EAAKlqF,YAAYkqF,EAAKrC,KAChC0d,EAAO,UAAYA,EAAK31E,MAAQ,SAEhCl8B,KAAKysH,eAAiBxY,GAAkBK,KAAO,QAAU,WACvD9d,EAAK54C,iBAA8B,OAAd8gF,EAACloC,EAAKhC,UAAQkqC,EAAIC,KAAK/lF,QAAQ,OAC3C,OADiDgmF,EAC5DpoC,EAAK/B,QAAMmqC,EAAID,KACf/lF,QAAQ,gBACRjiC,EC9iBI,SAAU4Y,GAClB,IAAIsgE,EAAM,GACV,MAAMrqC,EAAMj2B,EAAEjtB,OACd,QAASkmC,EAAI,EAAGA,EAAIgd,EAAKhd,IACvBqnD,GAAWtgE,MAAE/O,MAAMgoB,GAAGoQ,QAAQ,MAAMrpB,EAAE4rD,IAAI3yC,GAAGoQ,QAAQ,MAGvD,OAAOi3C,CACT,CDuiBUgvC,CAAoBpL,GAAaC,YAAY/8G,IAC7C,iBAGR3W,KAAKU,MA/fD,OAggBCiW,KAIF3W,KAAK47H,gBACNplC,EAAKlqF,MAAQ2nG,GAAkBK,MAC/B39F,EAAMynG,SAAS97G,SACfw8H,cAAKvD,kBAALuD,IAAkB3qC,OAAwB,OAAtB4qC,EAAK/+H,KAAK8iH,mBAAY,EAAjBic,EAAmB5qC,MAE5Cn0F,KAAK47H,gBAAiB,EACtB57H,KAAKg/H,kBAEPh/H,KAAK+yH,OACP,CAEUiM,iBAAiB,CAEjBtB,4BAA4BuB,GACpC,MAAQzD,cAAex7H,KACvB,IAAKw7H,EACH,OAEF,MAAQhlC,OAAMqb,OAAMqtB,eAAgBD,EAE9B3tF,GACH4tF,GACsB,IAAvBA,EAAY58H,QACZ48H,EAAY3zH,KAAM4zH,IAAgBA,GAC9BC,EAAY,IAAI/K,GACpB79B,EAAK54C,MACL44C,EAAKrC,GACLqC,EAAKzB,MAAMpC,WAAa,EACxB,EACAkf,EAAOA,EAAK31E,OAAQ,GACnBoV,GAEHkqF,EAAW3sD,MAAMuwD,EACnB,CAGU3B,4BACRjnC,GACA,CAEQ+mC,YACR/mC,EACA54C,EACAy/E,EAAkC,KAClCgC,GACkD,MAClD,MAAMpxD,EAAUrwB,GAAOqwB,QACvB,IAAKjuE,KAAK8J,SAAWmkE,EACnB,MAAM,IAAIka,MAC2Bla,qCAAU,GAAK,cAItD,IAAIqxD,EAA0D,KA6B9D,IA5BI9oC,EAAKd,WAA8B,OAAjBq7B,EAACv6B,EAAKnB,cAAL07B,EAAkB1pH,KAuB7BmvF,EAAKd,WAAaznB,EAAQqrB,mBAAmBh3F,QACvDtC,KAAKs0F,UAAUi9B,UAAU/6B,EAAMvoB,EAAQqrB,qBAvBvCt5F,KAAK6vF,IACF,mBAAkB2G,EAAKrC,UAAUlmB,EAAQ+pB,WAAW/pB,EAAQkpB,WACxC,wBAAnBn3F,KAAKgkH,UAAsC,QAAU,WACnDxtB,EAAK54C,SAEX59C,KAAKU,MA/jBI,cAgkBTV,KAAKu7H,YAAc/kC,EACnB8oC,EAAoBt/H,KAAKs0F,UAAUhzC,KAAKk1C,GAAM30F,KAAMqwH,IAClD,IAAKlyH,KAAKw9H,mBAAmBtL,EAAc17B,MACzC,YAAKie,IAAInrC,QAAQ2f,EAAOoD,WAAY6lC,GAnkB/B,gBAokBDlyH,KAAKU,QACPV,KAAKU,MAtkBT,QAwkBSwxH,IAGXlyH,KAAKy0G,IAAInrC,QAAQ2f,EAAOmD,YAAa,CAAEoK,SACd,OAArBx2F,KAAKu7H,cACP+D,EAAoB39E,QAAQE,OAC1B,IAAIsmC,MAAyD,wDAOnEk1C,EAAmBhmH,KAAK+/C,IAAIo/B,EAAKh2E,MAAO68G,GAAoB,GACxDr9H,KAAK0vC,OAAOkuE,gBAA8B,gBAAZpnB,EAAKrC,GAAsB,CAC3D,MAAMmD,EAAWrpB,EAAQqpB,SACzB,GAAIA,GAAY+nC,EAAkB,CAC5BhC,EAAmB7mC,EAAKrb,KAAOlN,EAAQopB,eACzCb,EAAOvoB,EAAQopB,cAEjB,MAAMgqB,EAAYrhH,KAAKu/H,YAAYjoC,EAAUd,EAAM6mC,GACnD,GAAIhc,GAAY,EAAI,CAClB,MAAMxP,GAAOva,EAAS+pB,GActB,IAAIn5G,GA+BJ,OA5CAlI,KAAK6vF,IACiB2G,sBAAKrC,SAAS0d,GAAK31E,aACrCs6D,EAAKjC,mBACUtmB,EAAQ+pB,WACvB/pB,EAAQkpB,mBACIkqB,KAAa/pB,EAASh1F,OAAS,MACxB,wBAAnBtC,KAAKgkH,UAAsC,QAAU,YAClDxtB,EAAK54C,kBAAkBjF,WAC1B0kF,EAAiBzkF,QAAQ,OAG7B54C,KAAK27H,iBAAmB9pB,GAAKrxF,MAAQqxF,GAAKnpG,SAC1C1I,KAAKU,MAzmBC,eA4mBJwH,GADEo3H,EACOA,EACNz9H,KAAMqwH,KAEFA,IACDlyH,KAAKw9H,mBAAmBtL,GAAc17B,MAE/B,KAEFx2F,KAAKw/H,gBACVhpC,EACAqb,GACAj0D,EACAyhF,IAGH7/E,MAAO3+B,IAAU7gB,KAAKy/H,oBAAoB5+G,KAEpC7gB,KAAKw/H,gBACZhpC,EACAqb,GACAj0D,EACAyhF,GACA7/E,MAAO3+B,IAAqB7gB,KAAKy/H,oBAAoB5+G,KAEzD7gB,KAAKy0G,IAAInrC,QAAQ2f,EAAOqC,aAAc,CACpCkL,OACAqb,QACAwrB,qBAEuB,OAArBr9H,KAAKu7H,YACA55E,QAAQE,OACb,IAAIsmC,MAEJ,6DAGGjgF,OAENsuF,EAAK90F,KACN1B,KAAK0/H,iBAAiBpoC,EAAU+lC,GAGhC,OAAO17E,QAAQC,QAAQ,KAAI,EAKjC5hD,KAAK6vF,IACiB2G,sBAAKrC,UAAUqC,EAAKjC,MACtCtmB,EAAU,OAASA,EAAQ+pB,QAAU,IAAM/pB,EAAQkpB,MAAQ,KAAO,KAC9C,wBAAnBn3F,KAAKgkH,UAAsC,QAAU,YACtDxtB,EAAK54C,kBACMjF,WAAW0kF,EAAiBzkF,QAAQ,OAG/Cw5C,EAAgBoE,EAAKrC,MAAkBn0F,KAAKi1F,cAC9Cj1F,KAAK27H,iBAAmBnlC,EAAKh2E,MAAQg2E,EAAK9tF,UAE5C1I,KAAKU,MAtqBO,eAyqBZ,MAAMi/H,EAAiB3/H,KAAK0vC,OAAOkwF,YACnC,IAAI13H,EA6BJ,OA3BEA,EADEy3H,GAAkBL,EACXA,EACNz9H,KAAMqwH,IACAA,GAAiBlyH,KAAKw9H,mBAAmBtL,GAAe17B,MACpD,KAEFx2F,KAAK87H,eAAex6E,KAAKk1C,EAAM6oC,IAEvC7/E,MAAO3+B,GAAU7gB,KAAKy/H,oBAAoB5+G,IAIpC8gC,QAAQx2C,IAAI,CACnBnL,KAAK87H,eAAex6E,KAClBk1C,EACAmpC,EAAiBN,OAAmB59H,GAEtC69H,IAECz9H,KAAK,EAAEg+H,OACDF,GAAkBE,GAAkBR,GACvCA,EAAiBQ,GAEZA,IAERrgF,MAAO3+B,GAAU7gB,KAAKy/H,oBAAoB5+G,IAE/C7gB,KAAKy0G,IAAInrC,QAAQ2f,EAAOqC,aAAc,CAAEkL,OAAM6mC,qBACrB,OAArBr9H,KAAKu7H,YACA55E,QAAQE,OACb,IAAIsmC,MAA0D,uDAG3DjgF,CACT,CAEQs3H,gBACNhpC,EACAspC,EACAliF,EACAyhF,GAEA,OAAO,IAAI19E,QACT,CAACC,EAA4BC,KAA6B,MACxD,MAAMq9E,EAAgC,GAChCa,EAA+B,OAAhBxe,EAAG3jE,EAAMqwB,cAAO,EAAbszC,EAAejqB,SACjCw4B,EAAYje,IAChB7xG,KAAK87H,eACFhM,SAASt5B,EAAMqb,EAAMwtB,GACrBx9H,KAAMmuH,KACLkP,EAAYrtB,EAAK31E,OAAS8zF,GAC1B,MAAMgQ,GAAahQ,GAAene,KAClC7xG,KAAKy0G,IAAInrC,QAAQ2f,EAAOuC,YAAawkC,IACrC,MAAMiQ,GACJ7e,GAAYxjE,EAAO44C,EAAKrC,GAAc0d,EAAK31E,MAAQ,IACnDolF,GAASye,EAAiBvpC,EAAKrC,GAAc0d,EAAK31E,MAAQ,GAC5D,IAAI+jG,GAGF,OAAOr+E,EAAQ,CACb40C,OACAqb,KAAMmuB,GACNd,gBALFpP,EAASmQ,GAMR,GAGJzgF,MAAMqC,EAAM,EAEjBiuE,EAASgQ,EAAQ,EAGvB,CAEQL,oBAAoB5+G,GAC1B,GAAI,SAAUA,EAAO,CACnB,MAAMrgB,EAAOqgB,EAAMrgB,KACfqgB,EAAMrgB,MAAQA,EAAKytE,UAAY6e,GAAayC,iBAC9CvvF,KAAKkgI,sBAAsB1/H,EAAKg2F,KAAMh2F,EAAKqxG,MAE3C7xG,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO1rF,EAAiB,MAGlDR,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWK,YACjB5e,QAAS6e,GAAawC,mBACtBt+C,IAAKnwB,EACLA,QACA23F,OAAO,IAGX,OAAO,IACT,CAEU2nB,uBAAuBf,GAC/B,MAAM3sE,EAAUzyD,KAAKogI,kBAAkBhB,GACvC,IAAK3sE,GAvwBE,YAuwBSzyD,KAAKU,MAQnB,aANGV,KAAKu7H,aA/wBH,YAgxBHv7H,KAAKU,OAvwBJ,UAwwBDV,KAAKU,QAELV,KAAKU,MAlxBL,SAsxBJ,MAAQ81F,OAAMqb,OAAMj0D,SAAU6U,EACxBpjC,EAAM4sE,KAAK7sE,YAAYC,MAC7BmnE,EAAKzB,MAAMjC,QAAQ3X,IAAM9rD,EACrBwiF,IACFA,EAAK9c,MAAMjC,QAAQ3X,IAAM9rD,GAE3BrvB,KAAKqgI,kBAAkB7pC,EAAMqb,EAAMj0D,EAAOwhF,EAAUjpC,QACtD,CAEUiqC,kBACRhB,GAEA,MAAQt1H,SAAQyxH,eAAgBv7H,MACxB49C,MAAOi7D,EAAY1kB,KAAI0d,KAAMwP,GAAc+d,EACnD,GAAW,MAANt1H,MAAS+uG,GACZ,YAAK91D,KACF,oDAAmDoxC,cAAe0kB,8CAE9D,KAET,MAAMj7D,EAAQ9zC,EAAO+uG,GACfhH,EAAOwP,GAAY,EAAKD,GAAYxjE,EAAOu2C,EAAIktB,GAAa,KAC5D7qB,EAAOqb,EACTA,EAAKt3D,SlBpbN,SAAS+lF,GACd1iF,EACAu2C,EACAonC,GAEA,GAAU,MAAL39E,MAAOqwB,QACV,OAAO,KAET,MAAMqoC,EAAe14D,EAAMqwB,QAC3B,IAAI1zB,EACF+7D,EAAalf,UAAUjD,EAAKmiB,EAAate,SAK3C,OAJIz9C,IAGJA,EAAW+7D,EAAajf,aACpB98C,GAAYA,EAAS45C,KAAOA,GACvB55C,EAEL45C,EAAKmiB,EAAate,SAAWujC,GAAeA,EAAYpnC,KAAOA,EAC1DonC,EAEF,IACT,CkB+ZQ+E,CAAkB1iF,EAAOu2C,EAAIonC,GACjC,OAAK/kC,GAGD+kC,GAAeA,IAAgB/kC,IACjCA,EAAKzB,MAAQwmC,EAAYxmC,OAEpB,CAAEyB,OAAMqb,OAAMj0D,UALZ,IAMX,CAEU2iF,mBACR//H,EACAg2F,EACAqb,EACAutB,GACA,MACA,IAAK5+H,GAzzBE,YAyzBMR,KAAKU,MAChB,OAGF,MAAQ0gG,QAAOC,SAAU7gG,EACzB,IAAI+8F,EAAS6D,EACTA,GAASC,IAEX9D,EAAS4D,GAAiBC,EAAOC,IAGxB,OAAPm/B,EAACjjC,MAAQj7F,SAYbtC,KAAKy0G,IAAInrC,QAAQ2f,EAAOQ,iBARa,CACnCn9E,KAAM9L,EAAK8L,KACXkqF,OACAqb,OACAutB,YACAr7E,OAAQyyC,EAAKlqF,KACb9L,KAAM+8F,IAIJ/8F,EAAKigI,SAAWjgI,EAAKk2F,cAAgBmb,GAEvC7xG,KAAK0gI,eAAelqC,GAExB,CAEUkqC,eAAelqC,GACvB,MAAM7/E,EAAQ3W,KAAK2W,MACnB,IAAKA,EACH,OAGF,IAAK88G,GAAa+I,WAAW7lH,EAAOA,EAAM6Q,aAExC,YADAxnB,KAAKm+H,gBAAgB,EAAG3nC,EAAKh2E,OAI/B,MAAMgH,EAAc7Q,EAAM6Q,YACpBm/F,EAAa8M,GAAa9M,WAAWhwG,EAAO6Q,EAAa,GAEzDm5G,EAAkBtpH,KAAK++E,IACU,EAArCp2F,KAAK0vC,OAAOszE,uBACG,IAHIxsB,EAAK9tF,UAKpB8X,EAAQnJ,KAAK+/C,IACjB//C,KAAK++E,IAAII,EAAKh2E,MAAQmgH,EAAiBha,EAAWxrC,IAAMwlD,GACxDn5G,EAAcm5G,GAEZnqC,EAAKh2E,MAAQA,EAAQmgH,GACvB3gI,KAAKm+H,gBAAgB39G,EAAOg2E,EAAKh2E,MAErC,CAEUs9G,iBACR8C,EACAt0H,GAEA,MAAMs6E,EAAM5mF,KAAK6gI,kBACjB,OAAKruC,EAAgB5L,GAGd5mF,KAAK8gI,sBAAsBF,EAAYh6C,EAAKt6E,GAF1C,IAGX,CAEUw0H,sBACRF,EACAh6C,EACAt6E,GAEA,MACEojC,QAAUotF,kBACR98H,KACE2mH,EAAa8M,GAAa9M,WAAWia,EAAYh6C,EAAKk2C,GAE5D,GAAuB,IAAnBnW,EAAWnhE,UAAsC/jD,IAAzBklH,EAAWmN,UAAyB,CAC9D,MAAMiN,EAAoB/gI,KAAKs7H,gBAAgBlP,gBAAgBxlC,EAAKt6E,GACpE,GAAIy0H,GAAqBpa,EAAWmN,UAAYiN,EAAkB5lD,IAChE,OAAOs4C,GAAa9M,WAClBia,EACAh6C,EACAvvE,KAAK+/C,IAAIuvD,EAAWmN,UAAWgJ,GACjC,CAGJ,OAAOnW,CACT,CAEUqa,mBAAmBC,GAC3B,MAAQvxF,UAAW1vC,KACnB,IAAIkhI,EACJ,OACEA,EADED,EACU5pH,KAAK+/C,IACd,EAAI1nB,EAAOyxF,cAAiBF,EAC7BvxF,EAAOsuF,iBAGGtuF,EAAOsuF,gBAEd3mH,KAAK++E,IAAI8qC,EAAWxxF,EAAO0xF,mBACpC,CAEUnD,sBAAsBoD,GAC9B,MAAM3xF,EAAS1vC,KAAK0vC,OAEpB,OAAIA,EAAO0xF,qBADOC,GAAa3xF,EAAOsuF,mBAGpCtuF,EAAO0xF,oBAAsB,EAC7BphI,KAAK+iD,KAAM,+BAA8BrT,EAAO0xF,wBACzC,EAGX,CAEUrV,gBACRC,EACAS,EAAkCxY,GAAkBK,MAEpD,MAAMgtB,EAAathI,KAAKs7H,gBAAgBvP,gBACtCC,EACA/X,GAAkBK,MAEpB,OAAIgtB,GAAc,aAAcA,EACvBA,EAAW/mF,SAEb+mF,CACT,CAEUC,gBACR36C,EACA0vB,GAEA,MAAMlf,EAAYkf,EAAalf,UACzBoqC,EAAUpqC,EAAU90F,OAE1B,IAAKk/H,EACH,OAAO,KAIT,MAAQ9xF,UAAW1vC,KACbwgB,EAAQ42E,EAAU,GAAG52E,MAC3B,IAAIg2E,EAEJ,GAAI8f,EAAa9e,KAAM,CACrB,MAAMiqC,EAA0B/xF,EAAO+xF,wBACvC,GAAID,EAAUC,EACZ,YAAK1+E,KACF,iDAAgDy+E,YAAkBC,MAE9D,MAONnrB,EAAavf,WACb/2F,KAAKg8H,qBACiB,IAAvBh8H,KAAK60G,gBAELre,EAAOx2F,KAAK0hI,uBAAuBprB,EAAclf,GACjDp3F,KAAK60G,cAAgBre,EACjBx2F,KAAKy0G,IAAIqJ,kBAAoBtnB,EAAKh2E,MAClComE,QAEGA,GAAOpmE,IAEhBg2E,EAAOY,EAAU,IAWnB,OAPKZ,IAIHA,EAAOx2F,KAAK2hI,sBAAsB/6C,EAHtBl3C,EAAOkuE,eACftH,EAAalc,QACbkc,EAAajc,YAC2Bic,IAGvCt2G,KAAK4hI,0BAA0BprC,EACxC,CAEUqrC,cAAcrrC,EAAgB6mC,GACtC,MAAMyE,EAAe9hI,KAAKs7H,gBAAgBrN,SAASz3B,GACnD,OXliC2BurC,OWmiCxBD,GXniCwB5T,YWoiCtB4T,KAA4CtrC,EAAKpB,MACpDp1F,KAAK27H,iBAAmB0B,CAE5B,CAEU2E,2BACRxrC,EACA8f,EACAqQ,EACA8F,EACAyU,GAEA,MAAMe,EAAWzrC,EAAKpB,IAChB8sC,EAAeliI,KAAKuhI,gBACxBvhI,KAAK27H,iBACLrlB,GAEF,GAAqB,OAAjB4rB,EACF,OAAOA,EAGT,GADA1rC,EAAO0rC,EACHD,GAAYzrC,IAASA,EAAKpB,KAAOuxB,EAAWmN,UAAW,CAEzD,MAAMqO,EAAiBniI,KAAK8gI,sBAC1B9gI,KAAKy7H,YAAcz7H,KAAKy7H,YAAcz7H,KAAK2W,MAC3CgwG,EAAWmN,UACXrH,GAEF,GACqB,OAAnB0V,GACAxb,EAAWnhE,IAAM28E,EAAe38E,KAAO07E,EAGvC,YAAKrxC,IAC2B48B,6DAA0Cj2B,EAAKrC,MAExE,KAGX,OAAOqC,CACT,CAEAorC,0BAA0BprC,GAExB,OAAIA,YAAMtB,aAAoB,MAAJsB,KAAMtB,YAAY10F,MAASR,KAAKi1F,YAInDuB,EAHEA,EAAKtB,WAIhB,CAEAqqC,YACEjoC,EACAd,EACA6mC,GAEA,IAAI4C,GAAW,EACXmC,GAAa,EACbC,GAAyB,EAC7B,QAAS75F,EAAI,EAAGgd,EAAM8xC,EAASh1F,OAAQkmC,EAAIgd,EAAKhd,IAAK,CACnD,MAAMqpE,EAAOva,EAAS9uD,GAEtB,GADA65F,EAAyBA,IAA2BxwB,EAAKnb,YACrDupC,GAAW,GAAM5C,EAAmBxrB,EAAKrxF,MAC3C,MAEF,MAAMvf,EAAS4wG,EAAK5wG,OAChBA,EACFg/H,GAAW,GAEVmC,GAAcvwB,EAAKnb,aAAe2rC,IACnCxwB,EAAKt3D,WAAai8C,IAElBypC,EAAWz3F,GAEb45F,EAAanhI,EAEf,OAAOg/H,CACT,CAEQP,iBACNpoC,EACA+lC,GAEA,MAAM9W,EAAWjvB,EAASA,EAASh1F,OAAS,GAC5C,OAAOikH,GAAY8W,EAAmB9W,EAAS/lG,OAAS+lG,EAAStlH,MACnE,CAOUygI,uBACRprB,EACAlf,GAEA,MAAM0rB,EAAe9iH,KAAK8iH,aAC1B,IAAItsB,EAAwB,KAC5B,GAAIssB,GAYF,GAXIxM,EAAavc,qBAEf/5F,KAAK6vF,IACF,+DAA8DizB,EAAa7uB,mBAE9EuC,EfppCD,SAAS8rC,GACdlrC,EACAmrC,EACAvf,GAEA,GACe,OAAbuf,IACCtrH,MAAMw6C,QAAQ2lC,KACdA,EAAU90F,SACV0vF,EAAgBuwC,GAEjB,OAAO,KAKT,GAAIA,GADanrC,EAAU,GAAGnD,iBACF,GAC1B,OAAO,KAIT,GAAIsuC,IADWnrC,EAAUA,EAAU90F,OAAS,GAAGmzF,oBACpB,GACzB,OAAO,KAGTutB,EAAyBA,GAA0B,EACnD,QAASwf,EAAM,EAAGA,EAAMprC,EAAU90F,SAAUkgI,EAAK,CAC/C,MAAMhsC,EAAOY,EAAUorC,GACvB,GAAInf,GAAuBkf,EAAUvf,EAAwBxsB,GAC3D,OAAOA,EAIX,OAAO,IACT,CeknCe8rC,CACLlrC,EACA0rB,EAAartB,mBACbz1F,KAAK0vC,OAAOszE,0BAGXxsB,EAAM,CAET,MAAMisC,EAAY3f,EAAa3uB,GAAgB,EAC/C,GACEsuC,GAAYnsB,EAAate,SACzByqC,GAAYnsB,EAAanf,MACzB,CACA,MAAM8rB,EAAW7rB,EAAUqrC,EAAWnsB,EAAate,SAE/C8qB,EAAavuB,KAAO0uB,EAAS1uB,KAC/BiC,EAAOysB,EACPjjH,KAAK6vF,IACF,8DACC2G,EAAMrC,MAEV,CAKCqC,IACHA,EfjhCH,SAASksC,GACdtrC,EACA7C,GAEA,OAAO+tB,GAAa3rF,OAAOygE,EAAY2lB,GACjCA,EAAUxoB,GAAKA,EACV,EACEwoB,EAAUxoB,GAAKA,GACjB,EAEA,EAGb,CeogCiBmuC,CAAetrC,EAAW0rB,EAAavuB,IAC1CiC,GACFx2F,KAAK6vF,IACF,8DAA6D2G,EAAKrC,MACrE,MAID,CAEL,MAAMwuC,EAAY3iI,KAAKy0G,IAAIqJ,iBACT,OAAd6kB,IACFnsC,EAAOx2F,KAAK2hI,sBACVgB,EACA3iI,KAAKi1F,YAAcqhB,EAAajc,YAAcic,EAAanc,KAC3Dmc,GACF,CAIJ,OAAO9f,CACT,CAKUmrC,sBACR5e,EACA5nC,EACAm7B,GAEA,MAAQ5mE,UAAW1vC,KACnB,IAAM8iH,gBAAiB9iH,MACjBo3F,YAAWD,SAAUmf,EAC3B,MAAQjf,gBAAiBif,EACnB0mB,EAAYttF,EAAOszE,uBACnB1rB,EAAWgf,EAAahf,SAExBsrC,KACJlzF,EAAOkuE,gBACC,MAARtmB,KAAUh1F,QACV+0F,GAQF,IAAIb,GAgBJ,GAtBIosC,GAAgBvrC,IAAiBr3F,KAAKi1F,cAExCmC,EAAYA,EAAU/vC,OAAOgwC,GAC7BF,EAAQE,EAAalD,IAQrBqC,GAJEusB,EAAY5nC,EAIP0nC,GACLC,EACA1rB,EACA2rB,EANsBA,EAAY5nC,EAAM6hD,EAAY,EAAIA,GAWnD5lC,EAAUA,EAAU90F,OAAS,GAGlCk0F,GAAM,CACR,MAAMqsC,GAAWrsC,GAAKrC,GAAKmiB,EAAate,QAGlC8qC,GAAY9iI,KAAKs7H,gBAAgBrN,SAASz3B,IAOhD,IXnvCyBurC,OW8uCvBe,IX9uCuB5U,YW+uCtB4U,IAAuCtsC,GAAKpB,OAE7C0tB,EAAetsB,IAGfssB,GACAtsB,GAAKrC,KAAO2uB,EAAa3uB,MACvByuC,GAAgBtrC,EAAS,GAAG/8C,SAAS45C,GAAKqC,GAAKrC,KAI/B2uB,GAAgBtsB,GAAK54C,QAAUklE,EAAallE,MAC/C,CACb,MAAMmlF,GAAW3rC,EAAUyrC,GAAW,GAKpCrsC,GAHAA,GAAKrC,GAAKgD,GX9vCS4qC,OW+vCnB/hI,KAAKs7H,gBAAgBrN,SAAS8U,IAEvBA,GAEA,MAKf,OAAOvsC,EACT,CAEUwsC,sBAAsB1sB,GAC9B,MAAQ5mE,SAAQ/4B,SAAU3W,KAC1B,IAAK2W,EACH,OAEF,MAAMmnG,EAAmB99G,KAAKy0G,IAAIqJ,iBAC5Bt2F,EAAc7Q,EAAM6Q,YAEpB2zD,EAAMm7B,EAAanc,KACnB8oC,EACJz7G,GAHY8uF,EAAalf,UAAU,GAAG52E,MAGfkvB,EAAOszE,wBAC9Bx7F,GAAe2zD,EAGM,OAArB2iC,GACAnnG,EAAMjO,SAAWo1G,IAChBt2F,EAAcs2F,IAAqBmlB,MAQhCA,GAAuBtsH,EAAMusH,WAAa,GAC5C17G,EAAc2zD,QALoB15E,IAAlCiuC,EAAO6tE,uBACH7tE,EAAO6tE,uBACP7tE,EAAO8tE,4BAA8BlH,EAAape,mBAKjDl4F,KAAK47H,iBACR57H,KAAK27H,iBAAmB7d,GAGtBnnG,EAAMusH,aACRljI,KAAK+iD,KACF,aAAYv7B,EAAYoxB,QACvB,gEAC6DuiC,6BAA+B2iC,EAAiBllE,QAC7G,MAGJjiC,EAAM6Q,YAAcs2F,GAI5B,CAEUqlB,eACRl1D,EACA62C,GAEA,MAAQh7G,SAAQiyH,kBAAiBjZ,gBAAiB9iH,KAC5CwqH,EACgB,OAApBuR,EAA2BjyH,EAAQiyH,GAAmB,KAIlDz5H,EAAS2rE,EAAQmpB,UAAU90F,OACjC,IAAKA,EACH,YAAKygD,KAAM,iCACJ,EAET,MAAMqgF,EAAen1D,EAAQmpB,UAAU,GAAG52E,MACpC6iH,GAAkBve,EAClBwe,EAAUr1D,EAAQ+oB,gBAAkB8c,EAAgBsvB,GAC1D,GAAIC,IAAoBC,IAAYF,EAAe,EL9vChD,SAASG,GACdC,EACAhZ,EACAv8C,GAEKu8C,IA6BP,SAASiZ,GACPD,EACAv1D,EACAu8C,GAEA,GA9GK,SAASkZ,GACdF,EACAhZ,EACAv8C,GAEA,SAAIu8C,EAAUv8C,WAEVA,EAAQipB,MAAQjpB,EAAQ8pB,SACvByrC,GAAYA,EAASjvC,GAAKtmB,EAAQ8pB,SAMzC,CAgGM2rC,CAA6BF,EAAUhZ,EAAWv8C,GAAU,CAC9D,MAAM01D,EA9FH,SAASC,GACdC,EACAC,EACApkC,EAAyB,GAEzB,MAAMqkC,EAAYF,EAAYzsC,UACxB4sC,EAAWF,EAAW1sC,UAE5B,IAAK4sC,EAAS1hI,SAAWyhI,EAAUzhI,OAEjC,YADAytF,GAAOF,IAAI,yBAIb,MAAMo0C,EAAgBxP,GAAoBsP,EAAWC,EAAS,GAAGzvC,IAEjE,GAAK0vC,KAAkBA,GAAkBA,EAAczvC,UAKvD,OAAOyvC,EAJLl0C,GAAOF,IAAI,wCAKf,CAyE0B+zC,CACpBpZ,EAAUv8C,QACVA,GAEE01D,GAAiB3xC,EAAgB2xC,EAAcnjH,SACjDuvE,GAAOF,IACJ,0EAAyE5hB,EAAQvsE,OAEpFozH,GAAmB6O,EAAcnjH,MAAOytD,GAAO,CAGrD,CA3CEw1D,CAAqBD,EAAUv1D,EAASu8C,IACnCv8C,EAAQ+oB,gBAAkBwzB,EAAUv8C,SAiDpC,SAASi2D,GAASj2D,EAAuBk2D,GAE9C,IACGA,EAAY/sC,UAAU90F,SACtB2rE,EAAQ8rB,qBACRoqC,EAAYpqC,mBAEb,OAKF,MAAMqqC,EAAUD,EAAY/sC,UAAU,GAAGnD,gBACnCowC,EAASp2D,EAAQmpB,UAAU,GAAGnD,gBAE9B4gC,GAAWwP,EAASD,GAAW,IAAOD,EAAY/sC,UAAU,GAAG52E,MACjEq0G,GAAWziC,EAAgByiC,KAC7B9kC,GAAOF,IACJ,6CACCw0C,EAASD,gBACIvP,EAAQj8E,QAAQ,MAAMq1B,EAAQvsE,QAE/CozH,GAAmBD,EAAS5mD,GAEhC,CArEIi2D,CAASj2D,EAASu8C,EAAUv8C,UAG3BA,EAAQ+oB,gBACTwzB,EAAUv8C,UACTA,EAAQwqB,iBAKTqoB,GAAc0J,EAAUv8C,QAASA,GAErC,CKsuCMs1D,CAAYzgB,EAAc0H,EAAWv8C,GACrC,MAAMq2D,EAAsBr2D,EAAQmpB,UAAU,GAAG52E,MACjD,YAAKqvE,IACF,0BAAyBy0C,EAAoB1rF,QAAQ,gBACpDksE,EAAkBA,EAAgB9sB,QAAU,SACzC/pB,EAAQ+pB,oBACX8qB,EAAeA,EAAa3uB,GAAK,mBACpB7xF,KAEVgiI,EAET,OAAOlB,CACT,CAEUmB,iBAAiBt2D,GAGzB,OACEA,EAAQupB,MACRvpB,EAAQqqB,gBACRrqB,EAAQ4qB,YACR5qB,EAAQ+qB,WACN3hF,KAAK+/C,IAAI6W,EAAQ0qB,aAAmC6rC,EAArBv2D,EAAQ4qB,WAE7C,CAEU4rC,iBAAiBx2D,EAAuB4mD,GAEhD,IAAIhgB,EAAgB70G,KAAK60G,cAIzB,GAHIA,EAAgBggB,IAClBhgB,GAAgB,IAEI,IAAlBA,IAAiD,IAAzB70G,KAAK07H,gBAAwB,CAGvD,MAAMgJ,EAAwD,OAAzB1kI,KAAKi4F,gBACpCA,EAAkBysC,EACpB1kI,KAAKi4F,gBACLhqB,EAAQgqB,gBACY,OAApBA,GAA4BytB,EAAgBztB,IAC9C4c,EAAgBggB,EAAU58B,EACtBA,EAAkB,IACpB4c,GAAiB5mC,EAAQkqB,eAE3B0c,EAAgBx9F,KAAK++E,IACnB/+E,KAAK+/C,IAAIy9D,EAAShgB,GAClBggB,EAAU5mD,EAAQkqB,eAEpBn4F,KAAK6vF,IACF,qBAAoBoI,cACnBysC,EAA+B,eAAiB,6CACZ7vB,KAExC70G,KAAK60G,cAAgBA,GACZ5mC,EAAQupB,KAGjBqd,EAAgB70G,KAAKy0G,IAAIqJ,kBAAoB+W,EAE7C70H,KAAK60G,cAAgBA,EAAgB,EAEvC70G,KAAK07H,gBAAkB7mB,EAEzB70G,KAAK27H,iBAAmB9mB,CAC1B,CAEUgsB,kBACR,MAAQlqH,SAAU3W,KAElB,IAAI4mF,EAAM,EACV,OAAI5mF,KAAK47H,gBAAkBjlH,EACzBiwE,EAAMjwE,EAAM6Q,YACHxnB,KAAK27H,mBACd/0C,EAAM5mF,KAAK27H,kBAGN/0C,CACT,CAEQs5C,sBAAsB1pC,EAAgBqb,GACxC7xG,KAAKw7H,YAA0B,gBAAZhlC,EAAKrC,IAAwBqC,EAAKzB,MAAMrC,UAC7D1yF,KAAK+iD,KACF,YAAWyzC,EAAKrC,KAAK0d,EAAO,SAAWA,EAAK31E,MAAQ,eACnDs6D,EAAK54C,qBAGT59C,KAAK29H,qBAAqBnnC,GAE9B,CAEUmnC,qBAAqBnnC,KAE1Bx2F,KAAKu7H,cACJv7H,KAAKw9H,mBAAmBhnC,IA73CF,+BA83CtBx2F,KAAKU,SAEPV,KAAKU,MAn4CH,OAq4CN,CAEUikI,yBACRC,EACApkI,GAEA,GAAIA,EAAK4+H,YAAc5+H,EAAKg2F,KAAM,CAChC,MAAM/jC,EAAUzyD,KAAKogI,kBAAkB5/H,EAAK4+H,WACxC3sE,IACFjyD,EAAKg2F,KAAO/jC,EAAQ+jC,MAGxB,MAAMA,EAAOh2F,EAAKg2F,KAElB,IAAKA,GAAQA,EAAKlqF,OAASs4H,IAAe5kI,KAAK8J,OAC7C,OAEiC,MAAnC,GAAI9J,KAAKw9H,mBAAmBhnC,GAI1B,YAHAx2F,KAAK+iD,KACF,oDAAmDyzC,EAAK90F,SAAyB,OAAlBmjI,EAAE7kI,KAAKu7H,kBAAW,EAAhBsJ,EAAkBnjI,OAIxF,MAAMojI,EAAoBtkI,EAAKytE,UAAY6e,GAAa4B,SACpDo2C,GACF9kI,KAAKs7H,gBAAgB7N,aAAaj3B,GAAM,GAG1C,MAAM+wB,EAAc/mH,EAAK+mH,aACjBhkG,SAAQs+F,aAAa,EAAGD,eAAgB2F,GAAe,GAC/D,GACEA,Gdz8C8BC,Ic08C9BjkG,GACAq+F,EACA,CACK5hH,KAAK47H,iBACR57H,KAAKg8H,oBAAqB,EAC1Bh8H,KAAK27H,iBAAmB37H,KAAK60G,eAE/B,MAAMvkE,EAAQqxE,GAAcC,EAAaC,GACzC7hH,KAAK+iD,KACF,YAAWyzC,EAAKrC,SAASywC,KAAcpuC,EAAK54C,sBAC3Cp9C,EAAKytE,6BACe4zC,EAAa,KACjCD,EAAY7K,kBACPzmE,OAETi3E,EAAYE,UAAW,EACvBznH,KAAK67H,UAAY5/B,KAAK7sE,YAAYC,MAAQihB,EAC1CtwC,KAAKU,MAn7CmB,4BAm7CLqkI,MACVnjB,GAAe2F,GACxBvnH,KAAKglI,oBAAoBJ,GACrB/iB,EAAaD,EAAY7K,YAEtB+tB,IACHvd,EAAYE,UAAW,GAGzB13B,GAAOhtC,KACFviD,KAAKytE,0CAA0C4zC,OAItD7hH,KAAKU,MA57CF,QA+7CLV,KAAKuzH,eACP,CAEU0R,2BAA2BzkI,GAEnC,GAv8CO,YAu8CHR,KAAKU,OAt8CH,WAs8C8BV,KAAKU,MAAwB,CAC/D,MAAM+rH,EAAejsH,EAAKujD,OACpB8vE,EAAe7zH,KAAK89H,iBACxB99H,KAAKy7H,YACLhP,GAIIrO,EAAWyV,GAAgBA,EAAaruE,IAAM,GAChD44D,GACFp+G,KAAKi+H,sBAAsBpK,EAAaruE,KAE1C,MAAM0/E,GAAe9mB,EACrB,OAAI8mB,GAIFllI,KAAK+iD,KACiE0pE,gFAGpEjsH,EAAKg2F,OACPx2F,KAAKs7H,gBAAgB1O,eAAepsH,EAAKg2F,MACzCx2F,KAAK27H,iBAAmBn7H,EAAKg2F,KAAKh2E,OAEpCxgB,KAAK+8H,oBACEmI,EAET,OAAO,CACT,CAEUF,oBAAoBJ,GACxBA,IAAe3wB,GAAkB1gB,QAEnCvzF,KAAKu7H,YAAc,MAIhBv7H,KAAK47H,iBACR57H,KAAKg8H,oBAAqB,GAp/CrB,YAs/CHh8H,KAAKU,QACPV,KAAKU,MAt/CH,OAw/CN,CAEUykI,mBACRxuH,EACAyuH,EACA3Y,GAEA,IAAK91G,EACH,OAIF,MAAM0uH,EAAqB5R,GAAaC,YAAY/8G,GACpD3W,KAAKs7H,gBAAgBhP,uBACnB8Y,EACAC,EACA5Y,GAjgDG,UAmgDDzsH,KAAKU,OACPV,KAAK+8H,mBAET,CAEUA,oBACR/8H,KAAK6vF,IAAI,uBACT7vF,KAAKu7H,YAAc,KACnBv7H,KAAK8iH,aAAe,KACpB9iH,KAAKU,MAnhDD,MAohDN,CAEU4kI,wBAAwB1nF,GAGhC,IAAK59C,KAAK47H,eAAgB,CACxB57H,KAAKg8H,oBAAqB,EAC1B,MAAM/tD,EAAUjuE,KAAK8J,OAAS9J,KAAK8J,OAAO8zC,GAAOqwB,QAAU,KAChD,MAAPA,KAASupB,MAEXx3F,KAAK60G,eAAgB,EACrB70G,KAAKykI,iBAAiBx2D,EAAS,GAC/BjuE,KAAK+8H,qBAEL/8H,KAAK27H,iBAAmB37H,KAAK60G,cAGnC,CAEU0wB,wBAAwBnG,GAChCp/H,KAAK+iD,KACF,wDAAuDq8E,EAAUjrC,eAAeirC,EAAUxhF,2CAE7F59C,KAAKwlI,wBACLxlI,KAAKslI,wBAAwBlG,EAAUxhF,OACvC59C,KAAK+8H,mBACP,CAEUyI,sBAAsBhlH,EAAgB,GAC9CxgB,KAAKs7H,gBAAgBhN,uBACnB9tG,EACA6vB,IACArwC,KAAKysH,cACL,GACA,EAEJ,CAEQ4T,kBACN7pC,EACAqb,EACAj0D,EACAu4C,GACA,MACA,MAAMloB,EAAUrwB,EAAMqwB,QACtB,GAAKA,EAAL,CA2CA,GAvCerlC,OAAOkP,KAAK0+C,EAAKlD,mBAAmBj7D,OACjD,CAACnwB,EAAQoE,KACP,MAAMonB,EAAO8iE,EAAKlD,kBAAkBhnF,GACpC,GAAIonB,EAAM,CACR,MAAM+xG,EAAiB/xG,EAAK+gE,OAAS/gE,EAAK8gE,SAC1C,GAAIixC,GAAkB,EAIpB,YAAK1iF,KACF,4BAA2ByzC,EAAKrC,MAAM7nF,wBAA2Bm5H,MAE7Dv9H,IAAU,EAEnB,MAAM+xF,GAAQ9D,EACV,EACAuqB,GACEzyC,EACAuoB,EACA9iE,EAAK8gE,SACL9gE,EAAK+gE,OACL/gE,EAAKghE,SACLhhE,EAAKihE,QAEX,YAAK8f,IAAInrC,QAAQ2f,EAAOqB,kBAAmB,CACzCrc,UACArwB,QACAq8C,SACA3tF,OACAkqF,OACAh2E,MAAOkT,EAAK8gE,SACZrZ,IAAKznD,EAAK+gE,UAEL,EAET,OAAOvsF,IAET,GAGA01C,EAAM8hE,cAAgB,UACc,QAAZ,OAAfgmB,EAAI1lI,KAACw7H,iBAAU,EAAfkK,EAAiB7kH,OAAgB,CAC1C,MAAMA,EAAQ,IAAIsnE,MACcqO,gCAAKrC,eAAev2C,EAAMt1C,0DAW1D,GATAtI,KAAK+iD,KAAKliC,EAAM2oF,SAChBxpG,KAAKy0G,IAAInrC,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa2B,mBACtB+pB,OAAO,EACP33F,QACA21E,OACAiiB,OAAS,yBAAwBjiB,EAAKrC,gBAAgBv2C,EAAMl8C,UAEzD1B,KAAKy0G,IACR,OAEFz0G,KAAKs8H,iBAAe,CAGtBt8H,KAAKU,MA3nDC,SA4nDNV,KAAKy0G,IAAInrC,QAAQ2f,EAAO4C,YAAa,CAAE2K,OAAMqb,QA/D3C,MADA7xG,KAAK+iD,KAAK,0BAiEd,CAEUu5E,kBACJt8H,KAAKw7H,aACPx7H,KAAKw7H,WAAW90D,UAChB1mE,KAAKw7H,WAAa,KAEtB,CAEUmK,mBAAmBnlI,GACR,kBAAfA,EAAK6mB,QACPrnB,KAAKs8H,kBACLt8H,KAAK+8H,oBAET,CAEIr8H,UAAM4iE,GACR,MAAMsiE,EAAgB5lI,KAAKu2E,OACvBqvD,IAAkBtiE,IACpBtjE,KAAKu2E,OAASjT,EACdtjE,KAAK6vF,IAAK,GAAE+1C,MAAkBtiE,KAElC,CAEI5iE,YACF,OAAOV,KAAKu2E,MACd,EEntDF,SAASsvD,KACP,OAAO5pC,KAAK6pC,cAAiB7pC,KAAa8pC,kBAC5C,CCHO,SAASC,GAAW15H,EAAO,GAAI25H,EAAiB,KACrD,MAAO,CACL35H,OACAhE,IAAI,EACJ49H,KAAK,EACLD,iBACAE,gBAAgB,EAChBxkC,QAAS,GACT8+B,QAAS,EAEb,CCKA,MAAM2F,GAAoCvmI,mBAC9BwmI,iBAAW,OACXC,eAAS,OACTC,WAAqB,EAACvmI,KACtBwmI,WAAgC,KAAIxmI,KACpCymI,QAAyB,KAAIzmI,KAC7Bk8H,QAAoC,KAAIl8H,KACxC0mI,QAAyB,IAAI,CAEvCC,iBACEzxC,EACAya,EACAd,EACA+3B,GAEA5mI,KAAKsmI,UAAY,CACfh6H,KAAM,MACNhE,GAAI,EACJ49H,KAAK,EACLD,eAAgB,IAChBE,eAAgB,EAChBxkC,QAAS,GACT8+B,QAAS,EAEb,CAEAoG,eAAeC,GACb9mI,KAAKk8H,QAAU4K,EACf9mI,KAAK+mI,iBACP,CAEAA,kBACE/mI,KAAKymI,QAAU,KACfzmI,KAAK0mI,QAAU,KACf1mI,KAAKumI,WAAa,CACpB,CAEA7pC,SAASl8F,EAAkB2qD,GACzB,OAAO,CACT,CAEA67E,YACEpmC,EACApgG,EACA2qD,GACmB,CAGrB87E,MAAMzmI,EAAkBghG,GAClBxhG,KAAKwmI,aACPhmI,EAAO2gG,GAAiBnhG,KAAKwmI,WAAYhmI,GACzCR,KAAKwmI,WAAa,MAGpB,IAEIU,EAFApqC,EAAkCsf,GAAe57G,EAAM,GACvD2qD,EAAS2xC,EAAUA,EAAQx6F,OAAS,EAExC,MAAMs+F,EAAQ5gG,KAAKqmI,YACblrB,EAAWn7G,KAAKsmI,UAChB3oC,EAAYb,ErCgEOt8F,KAC3B,MAAM0jD,EAAkB24C,GAAar8F,GAErC,QAASgoC,EAAI,EAAGA,EAAI0b,EAAO5hD,OAAQkmC,IAAK,CACtC,MAAMwb,EAAQE,EAAO1b,GAErB,GAAIm0D,GAAiB34C,GACnB,OAAOw5C,GAAcx5C,EAAkC,GqCvE7Bo4D,CAAiBtf,QAAWr7F,EAClDa,EAAS9B,EAAK8B,OAyBpB,KAtBmB,OAAjBtC,KAAKymI,SACgB,IAApBzmI,KAAKumI,YAAoBv0C,EAAgB2L,MAE1C39F,KAAKymI,QAAUU,GAAUxpC,EAAW6D,EAAYxhG,KAAKk8H,SACrDl8H,KAAK0mI,QAAU1mI,KAAKymI,SAGD,OAAjBzmI,KAAK0mI,UACP1mI,KAAK0mI,QAAU1mI,KAAKymI,SAIlB3pC,GAAWA,EAAQx6F,OAAS,GAC9B64G,EAASxZ,QAAQv5F,KAAK,CACpB+7F,IAAKnkG,KAAK0mI,QACVU,IAAKpnI,KAAK0mI,QACVlmI,KAAMs8F,EACNxwF,K1BLwBiwG,U0BMxB7zG,SAAUo1C,OAAOg9D,oBAId3vD,EAAS7oD,GAAQ,CACtB,GAAItC,KAAK08F,SAASl8F,EAAM2qD,GAAS,CAC/B,MAAMnH,EAAQhkD,KAAKgnI,YAAYpmC,EAAOpgG,EAAM2qD,GACxCnH,GACFhkD,KAAKumI,aACLvmI,KAAK0mI,QAAU1iF,EAAMqjF,OAAOljC,IAC5Bh5C,GAAUnH,EAAM1hD,OAChB4kI,EAAgB/7E,GAEhBA,EAAS7oD,OAEF85G,GAAa57G,EAAM2qD,IAE5B2xC,EAAUsf,GAAe57G,EAAM2qD,GAC/BgwD,EAASxZ,QAAQv5F,KAAK,CACpB+7F,IAAKnkG,KAAK0mI,QACVU,IAAKpnI,KAAK0mI,QACVlmI,KAAMs8F,EACNxwF,K1B5BsBiwG,U0B6BtB7zG,SAAUo1C,OAAOg9D,oBAEnB3vD,GAAU2xC,EAAQx6F,OAClB4kI,EAAgB/7E,GAEhBA,IAEF,GAAIA,IAAW7oD,GAAU4kI,IAAkB5kI,EAAQ,CACjD,MAAMglI,EAAcnrC,GAAW37F,EAAM0mI,GAEnClnI,KAAKwmI,WADHxmI,KAAKwmI,WACWrlC,GAAiBnhG,KAAKwmI,WAAYc,GAElCA,GAKxB,MAAO,CACLpvB,WAAYtX,EACZ2mC,WAAYvB,KACZ7qB,WACAY,UAAWiqB,KAEf,CAEAwB,eACEhnI,EACAynG,EACAzG,GAEA,OAAO7/C,QAAQE,OACb,IAAIsmC,MAAU,iEAElB,CAEAtZ,MAAM2yB,GAEJ,MAAMglC,EAAaxmI,KAAKwmI,WACxB,OAAIA,IACFxmI,KAAKwmI,WAAa,KAClBxmI,KAAKinI,MAAMT,EAAY,IAGlB,CACLtuB,WAAYl4G,KAAKqmI,YACjBkB,WAAYvB,KACZ7qB,SAAUn7G,KAAKsmI,UACfvqB,UAAWiqB,KAEf,CAEAt/D,UAAU,EASL,MAAMygE,GAAYA,CACvBxpC,EACA6D,EACA06B,IAEI9pC,EAAgBuL,GACE,GAAbA,EAKW,IAAb6D,GAHW06B,EACM,IAAnBA,EAAQh6B,SAAoBg6B,EAAQ38B,UACrC,GCpBC,SAASkoC,EAAgBjnI,EAAkB2qD,GAChD,OAAwB,MAAjB3qD,EAAK2qD,IAAkD,MAAV,IAAnB3qD,EAAK2qD,EAAS,GACjD,CAEO,SAASu8E,EAAgBlnI,EAAkB2qD,GAChD,OAA0B,EAAnB3qD,EAAK2qD,EAAS,GAAY,EAAI,CACvC,CAEO,SAASw8E,EAAmBnnI,EAAkB2qD,GACnD,OACuB,EAAnB3qD,EAAK2qD,EAAS,KAAc,GAC7B3qD,EAAK2qD,EAAS,IAAM,GACA,IAAnB3qD,EAAK2qD,EAAS,MAAe,CAEnC,CAMO,SAASixC,EAAS57F,EAAkB2qD,GAIzC,OAAOA,EAAS,EAAI3qD,EAAK8B,QAAUmlI,EAAgBjnI,EAAM2qD,EAC3D,CAUO,SAASy8E,GAAMpnI,EAAkB2qD,GAGtC,GAAIixC,EAAS57F,EAAM2qD,GAAS,CAE1B,MAAM08E,EAAeH,EAAgBlnI,EAAM2qD,GAC3C,GAAIA,EAAS08E,GAAgBrnI,EAAK8B,OAChC,OAAO,EAGT,MAAMwlI,EAAcH,EAAmBnnI,EAAM2qD,GAC7C,GAAI28E,GAAeD,EACjB,OAAO,EAGT,MAAME,EAAY58E,EAAS28E,EAC3B,OAAOC,IAAcvnI,EAAK8B,QAAU85F,EAAS57F,EAAMunI,EAAS,CAE9D,OAAO,CACT,CAEO,SAASC,EACdpnC,EACAqnC,EACAznI,EACA2qD,EACAwkD,GAEA,IAAK/O,EAAMsnC,WAAY,CACrB,MAAMx4F,EAhNH,SAASy4F,GACdF,EACAznI,EACA2qD,EACAwkD,GAEA,IAAIy4B,EACAC,EACAC,EACA54F,EACJ,MAAMhK,EAAYC,UAAUD,UAAUh5B,cAChC67H,EAAgB54B,EAChB64B,EAAoB,CACxB,KAAO,MAAO,KAAO,KAAO,MAAO,KAAO,KAAO,MAAO,KAAO,KAAO,MACtE,IAAM,MAGRJ,EAAqD,IAAf,IAAnB5nI,EAAK2qD,EAAS,MAAe,GAChD,MAAMs9E,GAAwC,GAAnBjoI,EAAK2qD,EAAS,MAAe,EACxD,KAAIs9E,EAAoBD,EAAkBlmI,OAAS,GASnDgmI,UAAwC,EAAnB9nI,EAAK2qD,EAAS,KAAc,EAEjDm9E,IAAyC,IAAnB9nI,EAAK2qD,EAAS,MAAe,EACnD4kC,GAAOF,IACa8f,kCAAyBy4B,oBAAiCK,KAG1E,WAAWpwF,KAAK3S,GACd+iG,GAAqB,GACvBL,EAAiB,EACjB14F,EAAS,IAAIz4B,MAAM,GAInBoxH,EAA6BI,EAAoB,IAEjDL,EAAiB,EACjB14F,EAAS,IAAIz4B,MAAM,GACnBoxH,EAA6BI,IAGW,IAAjC/iG,EAAUK,QAAQ,YAC3BqiG,EAAiB,EACjB14F,EAAS,IAAIz4B,MAAM,GACnBoxH,EAA6BI,IAK7BL,EAAiB,EACjB14F,EAAS,IAAIz4B,MAAM,GAGhB04F,KACuC,IAArCA,EAAW5pE,QAAQ,gBACkB,IAApC4pE,EAAW5pE,QAAQ,gBACrB4pE,GAAc84B,GAAqB,EAKrCJ,EAA6BI,EAAoB,IAK9C94B,IACqC,IAApCA,EAAW5pE,QAAQ,eACjB0iG,GAAqB,GAA2B,IAAtBH,GAC1B,WAAWjwF,KAAK3S,MAClBiqE,GAAoC,IAAtB24B,KAEhBF,EAAiB,EACjB14F,EAAS,IAAIz4B,MAAM,IAErBoxH,EAA6BI,IAqCjC/4F,EAAO,GAAK04F,GAAkB,EAE9B14F,EAAO,KAA2B,GAApB+4F,IAA6B,EAC3C/4F,EAAO,KAA2B,EAApB+4F,IAA6B,EAE3C/4F,EAAO,IAAM44F,GAAqB,EACX,IAAnBF,IAEF14F,EAAO,KAAoC,GAA7B24F,IAAsC,EACpD34F,EAAO,IAAmC,EAA7B24F,IAAsC,EAGnD34F,EAAO,IAAM,EACbA,EAAO,GAAK,GAEP,CACLA,SACAw4F,WAAYM,EAAkBC,GAC9BC,aAAcJ,EACd5nC,MAAO,WAAa0nC,EACpBG,iBAxHAN,EAAS3+D,QAAQ2f,EAAOiD,MAAO,CAC7B5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa2B,mBACtB+pB,OAAO,EACPC,OAAS,+BAA8BgwB,KAsH7C,CAkEmBN,CAAeF,EAAUznI,EAAM2qD,EAAQwkD,GACtD,IAAKjgE,EACH,OAEFkxD,EAAMlxD,OAASA,EAAOA,OACtBkxD,EAAMsnC,WAAax4F,EAAOw4F,WAC1BtnC,EAAM8nC,aAAeh5F,EAAOg5F,aAC5B9nC,EAAMF,MAAQhxD,EAAOgxD,MACrBE,EAAM2nC,cAAgB74F,EAAO64F,cAC7Bx4C,GAAOF,IACW+Q,kBAAMF,eAAehxD,EAAOw4F,wBAAwBx4F,EAAOg5F,eAC7E,CAEJ,CAEO,SAASC,EAAiBT,GAC/B,OAAQ,OAAgBA,CAC1B,CAkBO,SAASlB,EACdpmC,EACApgG,EACA2qD,EACAg5C,EACAoiC,GAEA,MACMqC,EAAQzkC,EAAMoiC,EADEoC,EAAiB/nC,EAAMsnC,YAEvCzyF,EAzBD,SAASozF,EACdroI,EACA2qD,GAGA,MAAM08E,EAAeH,EAAgBlnI,EAAM2qD,GAC3C,GAAIA,EAAS08E,GAAgBrnI,EAAK8B,OAAQ,CAExC,MAAMwlI,EAAcH,EAAmBnnI,EAAM2qD,GAAU08E,EACvD,GAAIC,EAAc,EAEhB,MAAO,CAAED,eAAcC,eAG7B,CAWiBe,CAAiBroI,EAAM2qD,GACtC,IAAIuE,EACJ,GAAIja,EAAQ,CACV,MAAQqyF,cAAaD,iBAAiBpyF,EAChCnzC,GAASulI,GAAeC,EACxBgB,GAAUzxH,KAAK+/C,IAAI,EAAGjM,EAAS7oD,GAAS9B,EAAK8B,QAE/CwmI,IACFp5E,EAAO,IAAImhC,WAAWvuF,GAASulI,IAC/Bn4E,EAAK7D,IAAIrrD,EAAKi8F,SAAStxC,EAAS08E,GAAcrnI,EAAK8B,QAAS,IAE5DotD,EAAOlvD,EAAKi8F,SAAStxC,EAAS08E,GAAc18E,EAAS7oD,IAGvD,MAAM+kI,GAAsB,CAC1B33E,OACAy0C,IAAKykC,GAEP,OAAKE,IACHloC,EAAMe,QAAQv5F,KAAKi/H,IAGd,CAAEA,UAAQ/kI,UAAQwmI,YAG3B,MAAMxmI,EAAS9B,EAAK8B,OAAS6oD,EAC7BuE,SAAO,IAAImhC,WAAWvuF,GACtBotD,EAAK7D,IAAIrrD,EAAKi8F,SAAStxC,EAAQ3qD,EAAK8B,QAAS,GAKtC,CAAE+kI,OAJmB,CAC1B33E,OACAy0C,IAAKykC,GAEUtmI,SAAQwmI,SAAS,EACpC,CC9RA,MAAMC,GAAoB,iBCrB1B,IAAIC,GAA+B,KAEnC,MAAMC,GAAc,CAClB,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAC3E,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GACxE,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IACzE,IAAK,IAAK,IAAK,IAAK,IAAK,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAC1E,KAGIC,GAAkB,CACtB,MAAO,KAAO,KAAO,MAAO,KAAO,KAAO,MAAO,KAAO,KAGpDC,GAAsB,CAE1B,CACE,EACA,GACA,IACA,IAGF,CACE,EACA,EACA,EACA,GAGF,CACE,EACA,GACA,IACA,IAGF,CACE,EACA,IACA,IACA,KAIEC,GAAc,CAClB,EACA,EACA,EACA,GAGK,SAASpC,GACdpmC,EACApgG,EACA2qD,EACAg5C,EACAoiC,GAGA,GAAIp7E,EAAS,GAAK3qD,EAAK8B,OACrB,OAGF,MAAMmzC,EAAS4zF,GAAY7oI,EAAM2qD,GACjC,GAAI1V,GAAU0V,EAAS1V,EAAOqyF,aAAetnI,EAAK8B,OAAQ,CACxD,MACMsmI,EAAQzkC,EAAMoiC,GAD4B,IAAzB9wF,EAAO6zF,gBAA2B7zF,EAAO8zF,YAE1DlC,EAAS,CACb33E,KAAMlvD,EAAKi8F,SAAStxC,EAAQA,EAAS1V,EAAOqyF,aAC5C3jC,IAAKykC,EACLxB,IAAKwB,GAGPhoC,SAAMlxD,OAAS,GACfkxD,EAAM8nC,aAAejzF,EAAOizF,aAC5B9nC,EAAMsnC,WAAazyF,EAAO8zF,WAC1B3oC,EAAMe,QAAQv5F,KAAKi/H,GAEZ,CAAEA,SAAQ/kI,OAAQmzC,EAAOqyF,YAAagB,QAAS,GAE1D,CAEO,SAASO,GAAY7oI,EAAkB2qD,GAC5C,MAAMq+E,EAAehpI,EAAK2qD,EAAS,IAAM,EAAK,EACxCs+E,EAAajpI,EAAK2qD,EAAS,IAAM,EAAK,EACtCu+E,EAAgBlpI,EAAK2qD,EAAS,IAAM,EAAK,GACzCw+E,EAAmBnpI,EAAK2qD,EAAS,IAAM,EAAK,EAClD,GACkB,IAAhBq+E,GACiB,IAAjBE,GACiB,KAAjBA,GACoB,IAApBC,EACA,CACA,MACMC,EAAcppI,EAAK2qD,EAAS,IAAM,EAGlC0+E,EACoD,IAAxDZ,GAA+B,IAFf,IAAhBO,EAAoB,EAAIC,EAA0B,IAAdA,EAAkB,EAAI,GAEtBC,EAAe,GAG/CH,EACJL,GAAsC,GAFtB,IAAhBM,EAAoB,EAAoB,IAAhBA,EAAoB,EAAI,GAENG,GACtCjB,GAA+B,IAAhBkB,EAAoB,EAAI,EACvCE,GAAoBX,GAAoBK,GAAaC,GACrDM,GAAcX,GAAYK,GAC1BH,GAAsC,EAApBQ,GAAwBC,GAC1CjC,GACJzwH,KAAKC,MAAOwyH,GAAoBD,EAAWN,GAfzB/oI,EAAK2qD,EAAS,IAAM,EAAK,IAgB3C4+E,GAEF,GAAsB,OAAlBf,GAAwB,CAE1B,MAAM9gI,IADYy9B,UAAUD,WAAa,IAChBQ,MAAM,kBAC/B8iG,GAAgB9gI,GAAS+f,SAAS/f,GAAO,IAAM,EAIjD,QAFwB8gI,IAAiBA,IAAiB,IAI1C,IAAdS,GACAI,GAAW,OACK,IAAhBD,IAGAppI,EAAK2qD,EAAS,GAAwB,IAAnB3qD,EAAK2qD,EAAS,IAG5B,CAAEo+E,aAAYb,gBAAcZ,eAAawB,oBAEpD,CAEO,SAAS7B,GAAgBjnI,EAAkB2qD,GAChD,OACmB,MAAjB3qD,EAAK2qD,IACyB,MAAV,IAAnB3qD,EAAK2qD,EAAS,KACe,IAAV,EAAnB3qD,EAAK2qD,EAAS,GAEnB,CAEO,SAASixC,GAAS57F,EAAkB2qD,GAIzC,OAAOA,EAAS,EAAI3qD,EAAK8B,QAAUmlI,GAAgBjnI,EAAM2qD,EAC3D,CAQO,SAASy8E,GAAMpnI,EAAkB2qD,GAGtC,GAAIA,EAAS,EAAI3qD,EAAK8B,QAAUmlI,GAAgBjnI,EAAM2qD,GAAS,CAI7D,MAAM1V,EAAS4zF,GAAY7oI,EAAM2qD,GACjC,IAAI28E,EAAcD,EACR,MAANpyF,KAAQqyF,cACVA,EAAcryF,EAAOqyF,aAGvB,MAAMC,EAAY58E,EAAS28E,EAC3B,OAAOC,IAAcvnI,EAAK8B,QAAU85F,GAAS57F,EAAMunI,EAAS,CAE9D,OAAO,CACT,CC1KA,MAAMiC,GAMJnqI,YAAYW,GAAkBR,KALtBQ,UAAI,OACLypI,oBAAc,OACbniF,UAAI,OACJoiF,mBAAa,EAGnBlqI,KAAKQ,KAAOA,EAEZR,KAAKiqI,eAAiBzpI,EAAKk9F,WAE3B19F,KAAK8nD,KAAO,EAEZ9nD,KAAKkqI,cAAgB,CACvB,CAGAC,WACE,MAAM3pI,EAAOR,KAAKQ,KACZypI,EAAiBjqI,KAAKiqI,eACtBje,EAAWxrH,EAAKk9F,WAAausC,EAC7BG,EAAe,IAAIv5C,WAAW,GAC9Bw5C,EAAiBhzH,KAAK++E,IAAI,EAAG6zC,GACnC,GAAuB,IAAnBI,EACF,MAAM,IAAIliD,MAAM,sBAGlBiiD,EAAav+E,IAAIrrD,EAAKi8F,SAASuvB,EAAUA,EAAWqe,IACpDrqI,KAAK8nD,KAAO,IAAI0/C,SAAS4iC,EAAa7sC,QAAQq5B,UAAU,GAExD52H,KAAKkqI,cAAiC,EAAjBG,EACrBrqI,KAAKiqI,gBAAkBI,CACzB,CAGAC,SAASt9H,GACP,IAAIu9H,EACJv9H,EAAQqK,KAAK++E,IAAIppF,EAA6B,EAAtBhN,KAAKiqI,eAAqBjqI,KAAKkqI,eACnDlqI,KAAKkqI,cAAgBl9H,GACvBhN,KAAK8nD,OAAS96C,EACdhN,KAAKkqI,eAAiBl9H,IAGtBu9H,GADAv9H,GAAShN,KAAKkqI,gBACO,EACrBl9H,GAASu9H,GAAa,EACtBvqI,KAAKiqI,gBAAkBM,EACvBvqI,KAAKmqI,WACLnqI,KAAK8nD,OAAS96C,EACdhN,KAAKkqI,eAAiBl9H,EAE1B,CAGAw9H,SAAS/zE,GACP,IAAIg0E,EAAOpzH,KAAK++E,IAAIp2F,KAAKkqI,cAAezzE,GACxC,MAAMi0E,EAAO1qI,KAAK8nD,OAAU,GAAK2iF,EAMjC,GALIh0E,EAAO,IACTs5B,GAAOlvE,MAAM,2CAGf7gB,KAAKkqI,eAAiBO,EAClBzqI,KAAKkqI,cAAgB,EACvBlqI,KAAK8nD,OAAS2iF,YACLzqI,KAAKiqI,eAAiB,GAG/B,MAAM,IAAI9hD,MAAM,qBAFhBnoF,KAAKmqI,UAE8B,CAIrC,OADAM,EAAOh0E,EAAOg0E,EACVA,EAAO,GAAKzqI,KAAKkqI,cACXQ,GAAQD,EAAQzqI,KAAKwqI,SAASC,GAE/BC,CAEX,CAGAC,SACE,IAAIC,EACJ,IACEA,EAAmB,EACnBA,EAAmB5qI,KAAKkqI,gBACtBU,EAEF,GAAK5qI,KAAK8nD,KAAQ,aAAe8iF,EAE/B,YAAK9iF,OAAS8iF,EACd5qI,KAAKkqI,eAAiBU,EACfA,EAIX,YAAKT,WACES,EAAmB5qI,KAAK2qI,QACjC,CAGAE,UACE7qI,KAAKsqI,SAAS,EAAItqI,KAAK2qI,SACzB,CAGAG,SACE9qI,KAAKsqI,SAAS,EAAItqI,KAAK2qI,SACzB,CAGAI,UACE,MAAMC,EAAMhrI,KAAK2qI,SACjB,OAAO3qI,KAAKwqI,SAASQ,EAAM,GAAK,CAClC,CAGAC,SACE,MAAMP,EAAO1qI,KAAK+qI,UAClB,OAAI,EAAOL,EAED,EAAIA,IAAU,GAEf,GAAMA,IAAS,EAE1B,CAIAQ,cACE,OAA4B,IAArBlrI,KAAKwqI,SAAS,EACvB,CAGAW,YACE,OAAOnrI,KAAKwqI,SAAS,EACvB,CAGAY,aACE,OAAOprI,KAAKwqI,SAAS,GACvB,CAGAa,WACE,OAAOrrI,KAAKwqI,SAAS,GACvB,CASAc,gBAAgBt+H,GACd,IAEIu+H,EAFAC,EAAY,EACZC,EAAY,EAEhB,QAASr5D,EAAI,EAAGA,EAAIplE,EAAOolE,IACP,IAAdq5D,IACFF,EAAavrI,KAAKirI,SAClBQ,GAAaD,EAAYD,EAAa,KAAO,KAE/CC,EAA0B,IAAdC,EAAkBD,EAAYC,CAE9C,CAUAC,UAKE,IAIIC,EACAC,EACApjG,EANAqjG,EAAsB,EACtBC,EAAuB,EACvBC,EAAqB,EACrBC,EAAwB,EAI5B,MAAMb,EAAYnrI,KAAKmrI,UAAUjvC,KAAKl8F,MAChCwqI,EAAWxqI,KAAKwqI,SAAStuC,KAAKl8F,MAC9B+qI,EAAU/qI,KAAK+qI,QAAQ7uC,KAAKl8F,MAC5BkrI,EAAclrI,KAAKkrI,YAAYhvC,KAAKl8F,MACpCsqI,GAAWtqI,KAAKsqI,SAASpuC,KAAKl8F,MAC9B8qI,GAAS9qI,KAAK8qI,OAAO5uC,KAAKl8F,MAC1B6qI,GAAU7qI,KAAK6qI,QAAQ3uC,KAAKl8F,MAC5BsrI,GAAkBtrI,KAAKsrI,gBAAgBpvC,KAAKl8F,MAElDmrI,IACA,MAAMc,GAAad,IAMnB,GALAX,EAAS,GACTF,GAAS,GACTa,IACAN,KAGiB,MAAfoB,IACe,MAAfA,IACe,MAAfA,IACe,MAAfA,IACe,KAAfA,IACe,KAAfA,IACe,KAAfA,IACe,MAAfA,IACe,MAAfA,GACA,CACA,MAAMC,GAAkBnB,IAQxB,GAPwB,IAApBmB,IACF5B,GAAS,GAGXO,KACAA,KACAP,GAAS,GACLY,IAGF,IADAU,EAAuC,IAApBM,GAAwB,EAAI,GAC1C1jG,EAAI,EAAGA,EAAIojG,EAAkBpjG,IAC5B0iG,KAGAI,GADE9iG,EAAI,EACU,GAEA,GAAE,CAM5BqiG,KACA,MAAMsB,GAAkBpB,IACxB,GAAwB,IAApBoB,GACFpB,SAAO,GACsB,IAApBoB,GAKT,IAJA7B,GAAS,GACTQ,KACAA,KACAa,EAAiCZ,IAC5BviG,EAAI,EAAGA,EAAImjG,EAAgCnjG,IAC9CsiG,KAGJD,KACAP,GAAS,GACT,MAAM8B,GAAsBrB,IACtBsB,GAA4BtB,IAC5BuB,GAAmB9B,EAAS,GACT,IAArB8B,IACFhC,GAAS,GAGXA,GAAS,GACLY,MAEFW,EAAsBd,IACtBe,EAAuBf,IACvBgB,EAAqBhB,IACrBiB,EAAwBjB,KAE1B,IAAIwB,GAA+B,CAAC,EAAG,GACvC,GAAIrB,KAEEA,IAGF,OADuBC,KAErB,KAAK,EACHoB,GAAa,CAAC,EAAG,GACjB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,EACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,GACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,GACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,GACHA,GAAa,CAAC,GAAI,IAClB,MACF,KAAK,GACHA,GAAa,CAAC,IAAK,IACnB,MACF,KAAK,GACHA,GAAa,CAAC,EAAG,GACjB,MACF,KAAK,GACHA,GAAa,CAAC,EAAG,GACjB,MACF,KAAK,GACHA,GAAa,CAAC,EAAG,GACjB,MACF,KAAK,IACHA,GAAa,CACVpB,KAAe,EAAKA,IACpBA,KAAe,EAAKA,KAO/B,MAAO,CACLxyH,MAAOtB,KAAKm1H,KACkB,IAA3BJ,GAAsB,GACC,EAAtBP,EACuB,EAAvBC,GAEJrzH,QACG,EAAI6zH,KAAqBD,GAA4B,GAAK,IAC1DC,GAAmB,EAAI,IACrBP,EAAqBC,GAC1BO,WAAYA,GAEhB,CAEAE,gBAEE,YAAKtB,YAELnrI,KAAK+qI,UAEE/qI,KAAK+qI,SACd,ECrVF,MAAM2B,GAIJ7sI,YAAYooI,EAA2Bv4F,EAAmBu4D,GAAkBjoG,KAHpEioG,aAAO,OACPg0B,eAAS,EAGfj8H,KAAKioG,QAAUA,EACfjoG,KAAKi8H,UAAY,IAAIxC,GAAU/pF,EAAQ,CACrCgqF,oBAAoB,GAExB,CAEAiT,cAAcC,GACZ,OAAO5sI,KAAKi8H,UAAUzG,QACpBoX,EACA5sI,KAAKioG,QAAQ5gG,IAAIk2F,OACjBv9F,KAAKioG,QAAQlC,GAAGxI,OAEpB,CAGQsvC,iBACNlrC,EACAmrC,EACA5gF,GAEA,MAAM6gF,EAAUprC,EAAQmrC,GAAap9E,KACrC,GAAIq9E,EAAQzqI,QAAU,GAGpB,OAEF,MAAMsqI,EAAgBG,EAAQtwC,SAC5B,GACAswC,EAAQzqI,OAAUyqI,EAAQzqI,OAAS,IAE/B0qI,EAAkBJ,EAAcrvC,OAAOpmF,MAC3Cy1H,EAAc5qC,WACd4qC,EAAc5qC,WAAa4qC,EAActqI,QAG3CtC,KAAK2sI,cAAcK,GAAiBnrI,KAAMorI,IACxC,MAAM3O,EAAgB,IAAIztC,WAAWo8C,GACrCF,EAAQlhF,IAAIyyE,EAAe,IAEtBt+H,KAAKi8H,UAAU3B,UAClBt6H,KAAKktI,kBAAkBvrC,EAASmrC,EAAc,EAAG5gF,EAAQ,EAG/D,CAEAghF,kBACEvrC,EACAmrC,EACA5gF,GAEA,MAAS4gF,IAAe,CACtB,GAAIA,GAAenrC,EAAQr/F,OAEzB,YADA4pD,IAIF,KAAIy1C,EAAQmrC,GAAap9E,KAAKptD,OAAS,KAIvCtC,KAAK6sI,iBAAiBlrC,EAASmrC,EAAa5gF,GAEvClsD,KAAKi8H,UAAU3B,WAClB,OAGN,CAGA6S,oBAAoBC,GAClB,MAAMC,EAC0C,GAA9Ch2H,KAAKC,OAAO81H,EAAY9qI,OAAS,IAAM,KAAY,GAC/CsqI,EAAgB,IAAIU,UAAUD,GACpC,IAAIE,EAAY,EAChB,QACMC,EAAW,GACfA,EAAWJ,EAAY9qI,OAAS,GAChCkrI,GAAY,IAAKD,GAAa,GAE9BX,EAAc/gF,IACZuhF,EAAY3wC,SAAS+wC,EAAUA,EAAW,IAC1CD,GAIJ,OAAOX,CACT,CAEAa,oBACEL,EACA9O,GAEA,MAAMoP,EAAqB,IAAI78C,WAAWytC,GAC1C,IAAIkP,EAAW,EACf,QACMD,EAAY,GAChBA,EAAYH,EAAY9qI,OAAS,GACjCirI,GAAa,IAAKC,GAAY,GAE9BJ,EAAYvhF,IACV6hF,EAAmBjxC,SAAS+wC,EAAUA,EAAW,IACjDD,GAIJ,OAAOH,CACT,CAEAO,iBACEhsC,EACAmrC,EACAc,EACA1hF,EACA6gF,GAEA,MAAMK,EAAchpC,GAAW2oC,EAAQvsI,MACjCosI,EAAgB5sI,KAAKmtI,oBAAoBC,GAE/CptI,KAAK2sI,cAAcC,EAAcrvC,QAAQ17F,KACtCorI,IACCF,EAAQvsI,KAAOR,KAAKytI,oBAAoBL,EAAaH,GAEhDjtI,KAAKi8H,UAAU3B,UAClBt6H,KAAK6tI,kBAAkBlsC,EAASmrC,EAAac,EAAY,EAAG1hF,EAAQ,EAI5E,CAEA2hF,kBACElsC,EACAmrC,EACAc,EACA1hF,GAEA,GAAIy1C,aAAmB9Q,WACrB,MAAM,IAAI1I,MAAM,6CAGlB,MAAS2kD,IAAec,EAAY,EAAG,CACrC,GAAId,GAAenrC,EAAQr/F,OAEzB,YADA4pD,IAIF,MAAM4hF,EAAWnsC,EAAQmrC,GAAaiB,MACtC,OACMH,GAAaE,EAASxrI,QADnBsrI,IAAa,CAKpB,MAAMb,EAAUe,EAASF,GACzB,KACEb,EAAQvsI,KAAK8B,QAAU,IACL,IAAjByqI,EAAQzgI,MAA+B,IAAjBygI,EAAQzgI,OAKjCtM,KAAK2tI,iBACHhsC,EACAmrC,EACAc,EACA1hF,EACA6gF,GAGG/sI,KAAKi8H,UAAU3B,WAClB,QAIR,ECvIF,MAAM0T,GAAgB,IAEtB,MAAMC,GAoBJpuI,YACEooI,EACAv4F,EACAw+F,GACAluI,KAvBeioI,cAAQ,OACRv4F,YAAM,OACfw+F,mBAAa,OAEbC,UAAuC,KAAInuI,KAC3CouI,WAAqB,EAAKpuI,KAC1B2vG,gBAAU,OACVd,gBAAU,OACVv3B,UAAoB,EAACt3E,KACrBquI,QAAiB,EAAEruI,KAEnBsuI,eAAS,OACTjI,iBAAW,OACXC,eAAS,OACTiI,eAAS,OACTC,YAAiC,KAAIxuI,KACrCyuI,UAAoC,KAAIzuI,KACxC85H,cAAmC,KAOzC95H,KAAKioI,SAAWA,EAChBjoI,KAAK0vC,OAASA,EACd1vC,KAAKkuI,cAAgBA,CACvB,CAEArrI,aAAarC,GACX,MAAMkuI,EAAaT,GAAUS,WAAWluI,GACxC,OAAIkuI,EAAa,GACf3+C,GAAOhtC,KACmD2rF,8DAGtC,IAAfA,CACT,CAEA7rI,kBAAkBrC,GAChB,MAAM8B,EAAS9B,EAAK8B,OACpB,IAAIqsI,EACFt3H,KAAK++E,IAAI43C,IAAmBxtI,EAAK8B,OAAS0rI,IAAiB,EACzDxlG,EAAI,EACR,KAAOA,EAAImmG,GAAY,CAErB,IAAIC,GAAW,EACXC,GAAc,EACdC,EAAY,EAChB,QAAS18D,EAAI5pC,EAAG4pC,EAAI9vE,EAAQ8vE,GAAK47D,GAC/B,IAAgB,KAAZxtI,EAAK4xE,GAyBF,IAAI08D,EAET,OAAO,EAEP,MAZA,GAhBAA,KACoB,IAAhBD,IACFA,EAAcz8D,EAEM,IAAhBy8D,IACFF,EACEt3H,KAAK++E,IACHy4C,EAAcb,MACdxtI,EAAK8B,OAAS0rI,IACZ,IAGLY,IACHA,EAAiC,IAAtBG,GAASvuI,EAAM4xE,IAI1Bw8D,GACAE,EAAY,IACM,IAAhBD,GAAqBC,EAAY,GACjC18D,EAAI47D,GAAgBW,GAEtB,OAAOE,CAMT,CAGJrmG,IAEF,OAAO,CACT,CAKA3lC,mBACEyJ,EACA5D,GAEA,MAAO,CACL85E,UACW,UAATl2E,GAA6B,UAATA,EAAmB,kBAAe7K,EACxD6K,OACAhE,GAAIm2F,GAAqBnyF,GACzB45H,KAAK,EACLD,eAAgB,IAChBE,eAAgB,EAChBxkC,QAAS,GACT8+B,QAAS,EACT/3H,SAAmB,UAAT4D,EAAmB5D,OAAWjH,EAE5C,CAMOklI,iBACLzxC,EACAya,EACAd,EACA+3B,GAEA5mI,KAAKouI,WAAY,EACjBpuI,KAAKquI,QAAS,EAEdruI,KAAKsuI,UAAYL,GAAUryB,YAAY,SACvC57G,KAAKqmI,YAAc4H,GAAUryB,YAC3B,QACAgrB,GAEF5mI,KAAKsmI,UAAY2H,GAAUryB,YAAY,OACvC57G,KAAKuuI,UAAYN,GAAUryB,YAAY,QACvC57G,KAAKqmI,YAAY2I,aAAe,MAGhChvI,KAAKwuI,YAAc,KACnBxuI,KAAKyuI,UAAY,KACjBzuI,KAAK85H,cAAgB,KACrB95H,KAAK2vG,WAAaA,EAClB3vG,KAAK6uG,WAAaA,EAClB7uG,KAAKs3E,UAAYsvD,CACnB,CAEOC,iBAAiB,CAEjBE,kBACL,MAAQV,cAAaiI,YAAWhI,aAActmI,KAC1CqmI,IACFA,EAAY4I,QAAU,MAEpBX,IACFA,EAAUW,QAAU,MAElB3I,IACFA,EAAU2I,QAAU,MAEtBjvI,KAAKwuI,YAAc,KACnBxuI,KAAKyuI,UAAY,KACjBzuI,KAAK85H,cAAgB,IACvB,CAEOmN,MACLzmI,EACAghG,EACA0tC,GAAc,EACdrgE,GAAQ,GAMR,IAAIsgE,EAJCD,IACHlvI,KAAKmuI,UAAY,MAKnB,MAAM5G,EAAavnI,KAAKsuI,UAClBp2B,EAAal4G,KAAKqmI,YAClBlrB,EAAWn7G,KAAKsmI,UAChBvqB,EAAY/7G,KAAKuuI,UAEvB,IAAIa,EAAQ7H,EAAWrB,IACnBmJ,EAAU9H,EAAW0H,QACrBK,GAAUp3B,EAAWguB,IACrBqJ,GAAQp0B,EAAS+qB,IACjBsJ,GAAYt3B,EAAW+2B,QACvBnyC,GAAUqe,EAAS8zB,QACnBQ,GAA4B,KAC5BrB,GAAYpuI,KAAKouI,UACjBsB,GAAQ1vI,KAAKquI,OAEb7oF,GAAMhlD,EAAK8B,OAOf,GANItC,KAAK85H,gBAEPt0E,IADAhlD,EAAO2gG,GAAiBnhG,KAAK85H,cAAet5H,IACjC8B,OACXtC,KAAK85H,cAAgB,MAGnBt0E,GAAMwoF,KAAkBn/D,EAC1B,YAAKirD,cAAgBt5H,EACd,CACL03G,aACAqvB,aACApsB,WACAY,aAIJ,MAAM2yB,GAAar3H,KAAK+/C,IAAI,EAAG62E,GAAUS,WAAWluI,IACpDglD,KAAQA,GAAMkpF,IAAcV,GACxBxoF,GAAMhlD,EAAKk9F,aAAe7uB,IAC5B7uE,KAAK85H,cAAgB,IAAIjpC,WACvBrwF,EAAK+8F,OACL/3C,GACAhlD,EAAK+8F,OAAOG,WAAal4C,KAK7B,IAAImqF,GAAiB,EACrB,QAASnvH,GAAQkuH,GAAYluH,GAAQglC,GAAKhlC,IAASwtH,GACjD,GAAoB,KAAhBxtI,EAAKggB,IAAiB,CACxB,MAAMovH,MAA2B,GAAlBpvI,EAAKggB,GAAQ,IACtB0lH,GAAM6I,GAASvuI,EAAMggB,IAI3B,IAAI2qC,GACJ,IAJ+B,GAAlB3qD,EAAKggB,GAAQ,KAAc,EAI9B,GAGR,GAFA2qC,GAAS3qC,GAAQ,EAAIhgB,EAAKggB,GAAQ,GAE9B2qC,KAAW3qC,GAAQwtH,GACrB,cAGF7iF,GAAS3qC,GAAQ,EAEnB,OAAQ0lH,IACN,KAAKkJ,EACCQ,KACEP,IAAYF,EAAMU,GAASR,KAC7BrvI,KAAK8vI,YAAYvI,EAAYxrB,EAAWozB,GAAK,GAG/CE,EAAU,CAAE7uI,KAAM,GAAIi2D,KAAM,IAE1B44E,IACFA,EAAQ7uI,KAAK4H,KAAK5H,EAAKi8F,SAAStxC,GAAQ3qC,GAAQwtH,KAChDqB,EAAQ54E,MAAQj2C,GAAQwtH,GAAgB7iF,IAE1C,MACF,KAAKmkF,GACH,GAAIM,GAAK,CACP,GAAIJ,KAAcL,EAAMU,GAASL,KAC/B,OAAQt3B,EAAW82B,cACjB,IAAK,MACHhvI,KAAK+vI,YAAY73B,EAAYi3B,GAC7B,MACF,IAAK,MACHnvI,KAAKgwI,aAAa93B,EAAYi3B,GAIpCK,GAAY,CAAEhvI,KAAM,GAAIi2D,KAAM,GAE5B+4E,KACFA,GAAUhvI,KAAK4H,KAAK5H,EAAKi8F,SAAStxC,GAAQ3qC,GAAQwtH,KAClDwB,GAAU/4E,MAAQj2C,GAAQwtH,GAAgB7iF,IAE5C,MACF,KAAKokF,GACCK,KACE9yC,KAAYqyC,EAAMU,GAAS/yC,MAC7B98F,KAAKiwI,YAAY90B,EAAUg0B,GAG7BryC,GAAU,CAAEt8F,KAAM,GAAIi2D,KAAM,IAE1BqmC,KACFA,GAAQt8F,KAAK4H,KAAK5H,EAAKi8F,SAAStxC,GAAQ3qC,GAAQwtH,KAChDlxC,GAAQrmC,MAAQj2C,GAAQwtH,GAAgB7iF,IAE1C,MACF,KAAK,EACCykF,KACFzkF,IAAU3qD,EAAK2qD,IAAU,GAG3BukF,GAAQ1vI,KAAKquI,OAAS6B,GAAS1vI,EAAM2qD,IAErC,MACF,KAAKukF,GAAO,CACNE,KACFzkF,IAAU3qD,EAAK2qD,IAAU,GAG3B,MAAMglF,GAAaC,GACjB5vI,EACA2qD,GACAnrD,KAAKkuI,cACLgB,GASFE,EAAQe,GAAWE,IACfjB,EAAQ,IACV7H,EAAWrB,IAAMkJ,GAGnBE,GAAUa,GAAWx5C,MACjB24C,GAAU,IACZp3B,EAAWguB,IAAMoJ,GACjBp3B,EAAW82B,aAAemB,GAAWnB,cAEvCO,GAAQY,GAAWzxC,IACf6wC,GAAQ,IACVp0B,EAAS+qB,IAAMqJ,IAGE,OAAfE,KAAwBrB,KAC1Br+C,GAAOhtC,KACmBviC,iDAA4BivH,mCAA2Cf,+BAEjGe,GAAa,KAEbjvH,GAAQkuH,GAAa,KAEvBN,GAAYpuI,KAAKouI,WAAY,EAC7B,KACF,CACA,KAAK,GACL,KAAK,KACH,MACF,QACEqB,GAAavJ,GACb,MAGJyJ,KAIJ,GAAIA,GAAiB,EAAG,CACtB,MAAM9uH,GAAQ,IAAIsnE,MACPwnD,uDAEX3vI,KAAKioI,SAAS36G,KAAK27D,EAAOiD,MAAOjD,EAAOiD,MAAO,CAC7C5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa2B,mBACtB+pB,OAAO,EACP33F,SACA43F,OAAQ53F,GAAM2oF,SACf,CAGH+9B,EAAW0H,QAAUI,EACrBn3B,EAAW+2B,QAAUO,GACrBr0B,EAAS8zB,QAAUnyC,GAEnB,MAAMwzC,GAA6B,CACjCp4B,aACAqvB,aACApsB,WACAY,aAGF,OAAIltC,GACF7uE,KAAKuwI,wBAAwBD,IAGxBA,EACT,CAEOzhE,QACL,MAAQirD,iBAAkB95H,KAE1B,IAAIkI,EAYJ,OAbAlI,KAAK85H,cAAgB,KAGnB5xH,EADE4xH,EACO95H,KAAKinI,MAAMnN,GAAe,GAAI,GAAO,GAErC,CACPyN,WAAYvnI,KAAKsuI,UACjBp2B,WAAYl4G,KAAKqmI,YACjBlrB,SAAUn7G,KAAKsmI,UACfvqB,UAAW/7G,KAAKuuI,WAGpBvuI,KAAKuwI,wBAAwBroI,GACzBlI,KAAKmuI,UACAnuI,KAAKw1H,QAAQttH,EAAQlI,KAAKmuI,WAE5BjmI,CACT,CAEQqoI,wBAAwBD,GAC9B,MAAQp4B,aAAYqvB,aAAYpsB,WAAUY,aAAcu0B,EAClDjB,EAAU9H,EAAW0H,QACrBO,EAAYt3B,EAAW+2B,QACvBnyC,EAAUqe,EAAS8zB,QAEzB,IAAIE,EAcJ,GAbIE,IAAYF,EAAMU,GAASR,KAC7BrvI,KAAK8vI,YACHvI,EACAxrB,EACAozB,GACA,GAEF5H,EAAW0H,QAAU,MAGrB1H,EAAW0H,QAAUI,EAGnBG,IAAcL,EAAMU,GAASL,IAAa,CAC5C,OAAQt3B,EAAW82B,cACjB,IAAK,MACHhvI,KAAK+vI,YAAY73B,EAAYi3B,GAC7B,MACF,IAAK,MACHnvI,KAAKgwI,aAAa93B,EAAYi3B,GAGlCj3B,EAAW+2B,QAAU,UAER,MAATO,KAAW/4E,MACbs5B,GAAOF,IACL,iEAKJqoB,EAAW+2B,QAAUO,EAGnB1yC,IAAYqyC,EAAMU,GAAS/yC,KAC7B98F,KAAKiwI,YAAY90B,EAAUg0B,GAC3Bh0B,EAAS8zB,QAAU,MAGnB9zB,EAAS8zB,QAAUnyC,CAEvB,CAEO0qC,eACLhnI,EACAynG,EACAzG,GAEA,MAAM8uC,EAActwI,KAAKinI,MACvBzmI,EACAghG,GACA,GACCxhG,KAAK0vC,OAAOkwF,aAETuO,EAAanuI,KAAKmuI,UAAY,IAAIzB,GACtC1sI,KAAKioI,SACLjoI,KAAK0vC,OACLu4D,GAEF,OAAOjoG,KAAKw1H,QAAQ8a,EAAanC,EACnC,CAEQ3Y,QACN8a,EACAnC,GAEA,OAAO,IAAIxsF,QAASC,IAClB,MAAQs2D,aAAYqvB,cAAe+I,EAC/Bp4B,EAAWvW,SAAuC,QAA5BuW,EAAW82B,aACnCb,EAAUjB,kBAAkBh1B,EAAWvW,QAAS,EAAG,KAC7C4lC,EAAW5lC,QACbwsC,EAAUN,kBAAkBtG,EAAW5lC,QAAS,EAAG,EAAG,KACpD//C,EAAQ0uF,EAAW,GAGrB1uF,EAAQ0uF,EAAW,GAGd/I,EAAW5lC,SACpBwsC,EAAUN,kBAAkBtG,EAAW5lC,QAAS,EAAG,EAAG,KACpD//C,EAAQ0uF,EAAW,EACpB,EAGP,CAEO5pE,UACL1mE,KAAKs3E,UAAY,CACnB,CAEQw4D,YACNlvC,EACAmb,EACAozB,EACAqB,GAEA,MAAMzC,EAAQ/tI,KAAKywI,aAAa7vC,EAAOuuC,EAAI3uI,MAE3C,IACI4H,EADAqmI,EAAYzuI,KAAKyuI,UAEjBiC,GAAW,EAEdvB,EAAY3uI,KAAO,KAIhBiuI,GAAaV,EAAMzrI,SAAWs+F,EAAM+vC,WACtCC,GAAenC,EAAW7tC,GAC1B6tC,EAAYzuI,KAAKyuI,UAAYoC,IAAgB,EAAO1B,EAAIhrC,IAAKgrC,EAAI/H,IAAK,KAGxE2G,EAAMxkI,QAASmmD,IACb,OAAQA,EAAKpjD,MAEX,KAAK,EAAG,CACNlE,GAAO,EACFqmI,IACHA,EAAYzuI,KAAKyuI,UAAYoC,IAC3B,EACA1B,EAAIhrC,IACJgrC,EAAI/H,IACJ,KAQJqH,EAAUzqF,OAAQ,EAClB,MAAMxjD,EAAOkvD,EAAKlvD,KAElB,GAAIkwI,GAAYlwI,EAAK8B,OAAS,EAAG,CAE/B,MAAMwuI,EAAY,IAAI9G,GAAUxpI,GAAMisI,iBAOtB,IAAdqE,GACc,IAAdA,GACc,IAAdA,GACc,IAAdA,KAEArC,EAAUpnI,KAAM,GAGpB,KAEF,CACA,KAAK,EACHe,GAAO,EAEFqmI,IACHA,EAAYzuI,KAAKyuI,UAAYoC,IAC3B,EACA1B,EAAIhrC,IACJgrC,EAAI/H,IACJ,KAQJqH,EAAUpnI,KAAM,EAChBonI,EAAUzqF,OAAQ,EAClB,MAEF,KAAK,EACH57C,GAAO,EAIP07F,GACEp0C,EAAKlvD,KACL,EACA2uI,EAAIhrC,IACJ4X,EAAUpa,SAEZ,MAGF,KAAK,EAOH,GANAv5F,GAAO,EACPsoI,GAAW,GAKN9vC,EAAMmwC,IAAK,CACd,MAAMA,EAAMrhF,EAAKlvD,KAEXkvC,GADmB,IAAIs6F,GAAU+G,GACPrF,UAChC9qC,EAAMjoF,MAAQ+2B,GAAO/2B,MACrBioF,EAAMnoF,OAASi3B,GAAOj3B,OACtBmoF,EAAM2rC,WAAa78F,GAAO68F,WAC1B3rC,EAAMmwC,IAAM,CAACA,GACbnwC,EAAMl4F,SAAW1I,KAAKs3E,UACtB,MAAM05D,GAAaD,EAAIt0C,SAAS,EAAG,GACnC,IAAIw0C,GAAc,QAClB,QAASzoG,GAAI,EAAGA,GAAI,EAAGA,KAAK,CAC1B,IAAI+1D,GAAIyyC,GAAWxoG,IAAGluB,SAAS,IAC3BikF,GAAEj8F,OAAS,IACbi8F,GAAI,IAAMA,IAGZ0yC,IAAe1yC,GAEjBqC,EAAMF,MAAQuwC,GAEhB,MAEF,KAAK,EACH7oI,GAAO,EAKFw4F,EAAMswC,MACTtwC,EAAMswC,IAAM,CAACxhF,EAAKlvD,OAGpB,MAEF,KAAK,EACH4H,GAAO,EACPw4F,EAAM+vC,UAAW,EACblC,GACFmC,GAAenC,EAAW7tC,GAG5B6tC,EAAYzuI,KAAKyuI,UAAYoC,IAC3B,EACA1B,EAAIhrC,IACJgrC,EAAI/H,IACa,IAEnB,MAEF,KAAK,GACHh/H,GAAO,EACP,MACF,QACEA,GAAO,EACHqmI,IACFA,EAAU7+C,OAAS,eAAiBlgC,EAAKpjD,KAAO,KAKlDmiI,GAAarmI,GACDqmI,EAAUV,MAClB3lI,KAAKsnD,EAAI,GAIf8gF,GAAQ/B,IACVmC,GAAenC,EAAW7tC,GAC1B5gG,KAAKyuI,UAAY,KAErB,CAEQ0C,eAAexvC,GAAsB,MAC3C,IACIyvC,EADA3C,EAAYzuI,KAAKyuI,UAMrB,KAHKA,GAAwC,IAA3BA,EAAUV,MAAMzrI,UAChCmsI,EAAY9sC,EAAQA,EAAQr/F,OAAS,IAE1B,OAAb+uI,EAAI5C,MAAWV,MAAO,CACpB,MAAMA,EAAQU,EAAUV,MACxBqD,EAAWrD,EAAMA,EAAMzrI,OAAS,EAAC,CAEnC,OAAO8uI,CACT,CAEQX,aACN7vC,EACA/pD,GAMA,MAAM2O,EAAM3O,EAAM6mD,WAClB,IAAIh9F,EAAQkgG,EAAM0wC,WAAa,EAC/B,MAAMC,EAAY7wI,EACZqtI,EAAQ,GAKd,IACIthI,EACAwmC,EACAu+F,EAHAhpG,EAAI,EAIJipG,GAAgB,EAChBC,GAAuB,EAY3B,KATc,IAAVhxI,IAEF+wI,EAAgB,EAEhBC,GAA0B,GAAX76F,EAAM,GACrBn2C,EAAQ,EACR8nC,EAAI,GAGCA,EAAIgd,GAGT,GAFA/4C,EAAQoqC,EAAMrO,KAET9nC,EAIL,GAAc,IAAVA,EAKJ,GAAK+L,EACK,GACW,IAAVA,EAAa,CACtB,GAAIglI,GAAiB,EAAG,CACtB,MAAM/hF,GAAO,CACXlvD,KAAMq2C,EAAM4lD,SAASg1C,EAAejpG,EAAI9nC,EAAQ,GAChD4L,KAAMolI,IAGR3D,EAAM3lI,KAAKsnD,GAAI,KACV,CAKL,MAAM0hF,GAAWpxI,KAAKmxI,eAAevwC,EAAMe,SAC3C,GAAIyvC,KACEG,GAAa/oG,GAAK,EAAI+oG,GAIpBH,GAAS1wI,QAEX0wI,GAAS5wI,KAAO4wI,GAAS5wI,KAAKi8F,SAC5B,EACA20C,GAAS5wI,KAAKk9F,WAAa6zC,IAKjCt+F,EAAWzK,EAAI9nC,EAAQ,EACnBuyC,EAAW,GAAG,CAEhB,MAAM0+F,GAAM,IAAI9gD,WAAWugD,GAAS5wI,KAAKk9F,WAAazqD,GACtD0+F,GAAI9lF,IAAIulF,GAAS5wI,KAAM,GACvBmxI,GAAI9lF,IAAIhV,EAAM4lD,SAAS,EAAGxpD,GAAWm+F,GAAS5wI,KAAKk9F,YACnD0zC,GAAS5wI,KAAOmxI,GAChBP,GAAS1wI,MAAQ,GAKnB8nC,EAAIgd,GACNgsF,EAAsB,GAAX36F,EAAMrO,GAEjBipG,EAAgBjpG,EAChBkpG,GAAeF,EACf9wI,EAAQ,GAGRA,GAAQ,OAGVA,EAAQ,OApDRA,EAAQ,OALRA,EAAQ+L,EAAQ,EAAI,OAJpB/L,EAAQ+L,EAAQ,EAAI,EAgExB,GAAIglI,GAAiB,GAAK/wI,GAAS,EAAG,CACpC,MAAMgvD,GAAO,CACXlvD,KAAMq2C,EAAM4lD,SAASg1C,EAAejsF,GACpCl5C,KAAMolI,GACNhxI,MAAOA,GAETqtI,EAAM3lI,KAAKsnD,GAAI,CAIjB,GAAqB,IAAjBq+E,EAAMzrI,OAAc,CAEtB,MAAM8uI,GAAWpxI,KAAKmxI,eAAevwC,EAAMe,SAC3C,GAAIyvC,GAAU,CACZ,MAAMO,GAAM,IAAI9gD,WAAWugD,GAAS5wI,KAAKk9F,WAAa7mD,EAAM6mD,YAC5Di0C,GAAI9lF,IAAIulF,GAAS5wI,KAAM,GACvBmxI,GAAI9lF,IAAIhV,EAAOu6F,GAAS5wI,KAAKk9F,YAC7B0zC,GAAS5wI,KAAOmxI,IAGpB/wC,SAAM0wC,UAAY5wI,EACXqtI,CACT,CAEQgC,YAAYnvC,EAA0BuuC,GAC5C,IAAIlsF,EAAc,EAClB,MAAMurF,EAAcxuI,KAAKwuI,YACzB,IAsBIrjF,EACA3F,EAsCA2+C,EA7DA3jG,EAAO2uI,EAAI3uI,KACf,GAAIguI,EAAa,CACfxuI,KAAKwuI,YAAc,KACnB,MAAMoD,EAAoBpD,EAAY1F,QAChC+I,GAAerD,EAAYnH,OAAO33E,KAAKguC,WAE7C,IAA0B,IAAtBk0C,EAA0B,CAC5B,MAAMD,GAAM,IAAI9gD,WAAWghD,GAAerxI,EAAKk9F,YAC/Ci0C,GAAI9lF,IAAI2iF,EAAYnH,OAAO33E,KAAM,GACjCiiF,GAAI9lF,IAAIrrD,EAAMqxI,IACdrxI,EAAOmxI,OACF,CACL,MAAMG,GAAqBD,GAAeD,EAC1CpD,EAAYnH,OAAO33E,KAAK7D,IACtBrrD,EAAKi8F,SAAS,EAAGm1C,GACjBE,IAEFlxC,EAAMe,QAAQv5F,KAAKomI,EAAYnH,QAC/BpkF,EAAcurF,EAAY1F,SAM9B,IAAK39E,EAASlI,EAAauC,EAAMhlD,EAAK8B,OAAQ6oD,EAAS3F,EAAM,IACvDusF,EAAcvxI,EAAM2qD,GADsCA,KAMhE,GAAIA,IAAWlI,EAAa,CAC1B,IAAIw1D,EACJ,MAAMu5B,GAAc7mF,EAAS3F,EAAM,EAEjCizD,EADEu5B,GACwD7mF,qDAEjD,kCAEX,MAAMtqC,GAAQ,IAAIsnE,MAAMswB,GAUxB,GATA1oB,GAAOhtC,KAAuB01D,uBAC9Bz4G,KAAKioI,SAAS36G,KAAK27D,EAAOiD,MAAOjD,EAAOiD,MAAO,CAC7C5/E,KAAMkgF,GAAWE,YACjBze,QAAS6e,GAAa2B,mBACtB+pB,OAAO,EACPoP,WAAYoqB,GACZnxH,SACA43F,YAEGu5B,GACH,OAaJ,GATAD,EACEnxC,EACA5gG,KAAKioI,SACLznI,EACA2qD,EACAnrD,KAAK2vG,iBAISluG,IAAZ0tI,EAAIhrC,IACNA,EAAMgrC,EAAIhrC,aACDqqC,EAOT,YADAz+C,GAAOhtC,KAAK,oCANU,CAGtB,MAAMkvF,EAAgBF,EAAsBnxC,EAAMsnC,YAClD/jC,EAAMqqC,EAAYnH,OAAOljC,IAAM8tC,EAG/B,CAIF,IACIjuF,EADAuiF,EAAa,EAEjB,KAAOp7E,EAAS3F,GAGd,IAFAxB,EAAQ+tF,EAAiBnxC,EAAOpgG,EAAM2qD,EAAQg5C,EAAKoiC,GACnDp7E,GAAUnH,EAAM1hD,OACX0hD,EAAM8kF,QAOJ,CACL9oI,KAAKwuI,YAAcxqF,EACnB,MAPA,IADAuiF,IACOp7E,EAAS3F,EAAM,IAChBusF,EAAcvxI,EAAM2qD,GADDA,KACvB,CASR,CAEQ6kF,aAAapvC,EAA0BuuC,GAC7C,MAAM3uI,EAAO2uI,EAAI3uI,KACX8B,EAAS9B,EAAK8B,OACpB,IAAIikI,EAAa,EACbp7E,EAAS,EACb,MAAMg5C,EAAMgrC,EAAIhrC,IAChB,QAAY1iG,IAAR0iG,EAKJ,KAAOh5C,EAAS7oD,GACd,GAAI4vI,GAAmB1xI,EAAM2qD,GAAS,CACpC,MAAMnH,EAAQkuF,GACZtxC,EACApgG,EACA2qD,EACAg5C,EACAoiC,GAEF,IAAIviF,EAKF,MAJAmH,GAAUnH,EAAM1hD,OAChBikI,GAGA,MAIFp7E,SAtBF4kC,GAAOhtC,KAAK,oCAyBhB,CAEQktF,YAAY90B,EAAgCg0B,GAClD,QAAgB1tI,IAAZ0tI,EAAIhrC,IAEN,YADApU,GAAOhtC,KAAK,oCAGd,MAAMovF,EAAYrgD,GAAc,GAAIq9C,EAAsB,CACxD7iI,KAAMtM,KAAKsuI,UAAY/zB,QhC94BGgC,UgC+4B1B7zG,SAAUo1C,OAAOg9D,oBAEnBK,EAASxZ,QAAQv5F,KAAK+pI,EACxB,EAGF,SAAStB,GACPxpI,EACA88F,EACAijC,EACAx3C,GAEA,MAAO,CACLvoF,MACA28C,OAAO,EACPmgD,MACAijC,MACA2G,MAAO,GACPn+C,QACAttF,OAAQ,EAEZ,CAEA,SAASysI,GAASvuI,EAAkB2qD,GAElC,QAA4B,GAAnB3qD,EAAK2qD,EAAS,KAAc,GAAK3qD,EAAK2qD,EAAS,EAC1D,CAEA,SAAS+kF,GAAS1vI,EAAkB2qD,GAElC,OAA6B,GAApB3qD,EAAK2qD,EAAS,MAAe,EAAK3qD,EAAK2qD,EAAS,GAC3D,CAEA,SAASilF,GACP5vI,EACA2qD,EACA+iF,EACAgB,GAEA,MAAMhnI,EAAS,CAAEyuF,OAAO,EAAI05C,KAAK,EAAI3xC,KAAK,EAAIswC,aAAc,OAEtDoD,EAAWjnF,EAAS,IADiB,GAAnB3qD,EAAK2qD,EAAS,KAAc,EAAK3qD,EAAK2qD,EAAS,IACzB,EAO9C,IADAA,GAAU,KAFc,GAApB3qD,EAAK2qD,EAAS,MAAe,EAAK3qD,EAAK2qD,EAAS,KAG7CA,EAASinF,GAAU,CACxB,MAAMlM,EAAM6I,GAASvuI,EAAM2qD,GAC3B,OAAQ3qD,EAAK2qD,IACX,KAAK,IACH,IAAK+jF,EAAa,CAChBn/C,GAAOF,IACL,0EAEF,MAGJ,KAAK,IAEkB,IAAjB3nF,EAAOyuF,QACTzuF,EAAOyuF,MAAQuvC,GAGjB,MAGF,KAAK,IAEgB,IAAfh+H,EAAOw2F,MACTx2F,EAAOw2F,IAAMwnC,GAGf,MAEF,KAAK,IACH,IAAKgJ,EAAa,CAChBn/C,GAAOF,IACL,uEAEF,MAGJ,KAAK,IAEgB,IAAf3nF,EAAOmoI,MACTnoI,EAAOmoI,IAAMnK,GAGf,MAIF,KAAK,EACL,KAAK,GAEwB,IAAvBgI,EAAcmE,OAAuC,IAAtBnE,EAAcoE,IAC/CviD,GAAOF,IAAI,oDACe,IAAjB3nF,EAAOyuF,QAChBzuF,EAAOyuF,MAAQuvC,EACfh+H,EAAO8mI,aAAe,OAExB,MAEF,KAAK,GACHj/C,GAAOhtC,KAAK,sCAShBoI,GAAkE,IAAlC,GAAnB3qD,EAAK2qD,EAAS,KAAc,EAAK3qD,EAAK2qD,EAAS,GAAM,CAEpE,OAAOjjD,CACT,CAEA,SAAS2nI,GAAS0C,GAChB,IACI/7C,EACAg8C,EACAC,EACAC,EACAC,EALAnqG,EAAI,EAMR,MAAMhoC,EAAO+xI,EAAO/xI,KAEpB,IAAK+xI,GAA0B,IAAhBA,EAAO97E,KACpB,OAAO,KAMT,KAAOj2D,EAAK,GAAG8B,OAAS,IAAM9B,EAAK8B,OAAS,GAAG,CAC7C,MAAMijG,EAAU,IAAI1U,WAAWrwF,EAAK,GAAG8B,OAAS9B,EAAK,GAAG8B,QACxDijG,EAAQ15C,IAAIrrD,EAAK,IACjB+kG,EAAQ15C,IAAIrrD,EAAK,GAAIA,EAAK,GAAG8B,QAC7B9B,EAAK,GAAK+kG,EACV/kG,EAAK6vD,OAAO,EAAG,EAAC,CAKlB,GAFAmmC,EAAOh2F,EAAK,IACOg2F,EAAK,IAAM,KAAOA,EAAK,IAAM,GAAKA,EAAK,KACxC,EAAG,CAInB,GAHAg8C,GAAUh8C,EAAK,IAAM,GAAKA,EAAK,GAG3Bg8C,GAAUA,EAASD,EAAO97E,KAAO,EACnC,OAAO,KAGT,MAAMm8E,EAAWp8C,EAAK,GACP,IAAXo8C,IAIFF,EACqB,WAAR,GAAVl8C,EAAK,IACc,SAAR,IAAXA,EAAK,KACc,OAAR,IAAXA,EAAK,KACc,KAAR,IAAXA,EAAK,MACM,IAAXA,EAAK,KAAc,EAEP,GAAXo8C,GACFD,EACsB,WAAR,GAAXn8C,EAAK,KACc,SAAR,IAAXA,EAAK,KACc,OAAR,IAAXA,EAAK,KACc,KAAR,IAAXA,EAAK,MACM,IAAXA,EAAK,KAAc,EAElBk8C,EAASC,EAAS,OACpB5iD,GAAOhtC,KACF1rC,QAAKkR,OACLmqH,EAASC,GAAU,+CAGxBD,EAASC,IAGXA,EAASD,GAGbD,EAAYj8C,EAAK,GAEjB,IAAIq8C,EAAqBJ,EAAY,EACrC,GAAIF,EAAO97E,MAAQo8E,EACjB,OAAO,KAETN,EAAO97E,MAAQo8E,EAEf,MAAM5D,EAAU,IAAIp+C,WAAW0hD,EAAO97E,MACtC,QAAS2b,GAAI,EAAG0gE,GAAUtyI,EAAK8B,OAAQ8vE,GAAI0gE,GAAS1gE,KAAK,CACvDokB,EAAOh2F,EAAK4xE,IACZ,IAAI5sB,GAAMgxC,EAAKkH,WACf,GAAIm1C,EACF,IAAIA,EAAqBrtF,GAAK,CAE5BqtF,GAAsBrtF,GACtB,SAGAgxC,EAAOA,EAAKiG,SAASo2C,GACrBrtF,IAAOqtF,EACPA,EAAqB,EAGzB5D,EAAQpjF,IAAI2qC,EAAMhuD,GAClBA,GAAKgd,GAEP,OAAIgtF,IAEFA,GAAUC,EAAY,GAEjB,CAAEjyI,KAAMyuI,EAAS9qC,IAAKuuC,EAAQtL,IAAKuL,EAAQntF,IAAKgtF,GAEzD,OAAO,IACT,CAEA,SAAS5B,GAAenC,EAA4BsE,GAClD,GAAItE,EAAUV,MAAMzrI,QAAUmsI,EAAUzqF,MAAO,CAE7C,QAAsBviD,IAAlBgtI,EAAUtqC,IAAmB,CAC/B,MAAMxC,EAAUoxC,EAASpxC,QACnBqxC,EAAYrxC,EAAQr/F,OAC1B,IAAI0wI,EAOF,YADAD,EAAStS,UANI,CACb,MAAMwS,EAAatxC,EAAQqxC,EAAY,GACvCvE,EAAUtqC,IAAM8uC,EAAW9uC,IAC3BsqC,EAAUrH,IAAM6L,EAAW7L,IAI3B,CAGJ2L,EAASpxC,QAAQv5F,KAAKqmI,EAAsB,CAE1CA,EAAU7+C,MAAMttF,QAClBytF,GAAOF,IAAI4+C,EAAUtqC,IAAM,IAAMsqC,EAAUrH,IAAM,IAAMqH,EAAU7+C,MAErE,CC1tCA,MAAMsjD,GACJrwI,sBACE69F,EACAgoC,GAEA,GACO,cADChoC,EACN,CACE,GAAqB,IAAjBgoC,EACF,OAAO,IAAI73C,WAAW,CAAC,EAAM,IAAM,EAAM,IAAM,GAAM,MAChD,GAAqB,IAAjB63C,EACT,OAAO,IAAI73C,WAAW,CACpB,GAAM,EAAM,GAAM,IAAM,EAAM,GAAM,EAAM,GAAM,MAE7C,GAAqB,IAAjB63C,EACT,OAAO,IAAI73C,WAAW,CACpB,EAAM,IAAM,EAAM,IAAM,GAAM,IAAM,EAAM,GAAM,GAAM,EAAM,IAC5D,EAAM,MAEH,GAAqB,IAAjB63C,EACT,OAAO,IAAI73C,WAAW,CACpB,EAAM,IAAM,EAAM,IAAM,GAAM,IAAM,EAAM,GAAM,GAAM,EAAM,IAC5D,EAAM,IAAM,GAAM,IAAM,EAAM,EAAM,KAEjC,GAAqB,IAAjB63C,EACT,OAAO,IAAI73C,WAAW,CACpB,EAAM,IAAM,EAAM,IAAM,GAAM,IAAM,EAAM,GAAM,GAAM,EAAM,IAC5D,EAAM,IAAM,GAAM,EAAM,IAAM,EAAM,GAAM,IAAM,EAAM,KAEnD,GAAqB,IAAjB63C,EACT,OAAO,IAAI73C,WAAW,CACpB,EAAM,IAAM,EAAM,IAAM,GAAM,IAAM,EAAM,GAAM,GAAM,EAAM,IAC5D,EAAM,IAAM,GAAM,EAAM,IAAM,EAAM,GAAM,IAAM,EAAM,EAAM,IAC5D,EAAM,GAAM,EAAM,KAItB,KAEF,CACE,GAAqB,IAAjB63C,EAEF,OAAO,IAAI73C,WAAW,CACpB,EAAK,GAAM,GAAM,IAAM,IAAM,GAAM,IAAM,IAAM,IAAM,EAAK,EAAK,EAC/D,EAAK,GAAM,EAAK,IAAM,IAAM,GAAK,GAAM,GAAM,GAAM,GAAM,GAAM,GAC/D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,KAEH,GAAqB,IAAjB63C,EAET,OAAO,IAAI73C,WAAW,CACpB,EAAK,GAAM,GAAM,IAAM,IAAM,GAAM,IAAM,IAAM,IAAM,EAAK,EAAK,EAC/D,EAAK,EAAK,IAAM,EAAK,EAAK,IAAM,IAAM,GAAK,GAAM,GAAM,GAAM,GAC7D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,KAEH,GAAqB,IAAjB63C,EAET,OAAO,IAAI73C,WAAW,CACpB,EAAK,GAAM,GAAM,IAAM,IAAM,GAAM,IAAM,IAAM,IAAM,EAAK,EAAK,EAC/D,EAAK,EAAK,IAAM,EAAK,EAAK,IAAM,IAAM,GAAK,GAAM,GAAM,GAAM,GAC7D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAAM,GAC5D,GAAM,IAGV,CAGN,ECpEF,MAAM2N,GAAannF,KAAK6qD,IAAI,EAAG,IAAM,EAAC,IAEhCixE,GAAG,MAAT,MAAMA,EAaJtwI,cAwCE,IAAI2lC,EACJ,IAAKA,KAxCL2qG,EAAI9pI,MAAQ,CACVsiG,KAAM,GACNynC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNpzC,KAAM,GACNqzC,KAAM,GACNtzC,KAAM,GACNuzC,KAAM,GACNC,KAAM,GACNC,KAAM,GACN/xC,KAAM,GACNgyC,KAAM,GACN9oC,KAAM,GACN,OAAQ,GACR+oC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACNC,KAAM,GACN5zC,KAAM,GACN6zC,KAAM,GACNC,KAAM,GACNpyC,KAAM,GACNC,KAAM,GACNH,KAAM,GACNhC,KAAM,GACNgB,KAAM,GACNN,KAAM,GACNT,KAAM,GACNs0C,KAAM,GACNC,KAAM,IAIEtB,EAAI9pI,MACR8pI,EAAI9pI,MAAMw/B,eAAeL,KAC3B2qG,EAAI9pI,MAAMm/B,GAAK,CACbA,EAAEsyD,WAAW,GACbtyD,EAAEsyD,WAAW,GACbtyD,EAAEsyD,WAAW,GACbtyD,EAAEsyD,WAAW,KAKnB,MAAM45C,EAAY,IAAI7jD,WAAW,CAC/B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,IACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IAGI8jD,EAAY,IAAI9jD,WAAW,CAC/B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,IACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACA,IACA,IACA,IACA,IAGFsiD,EAAIyB,WAAa,CACfh+C,MAAO89C,EACP/9C,MAAOg+C,GAGT,MAAMpB,EAAO,IAAI1iD,WAAW,CAC1B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,IACA,IACA,GACA,EACA,EACA,EACA,IAGIujD,EAAO,IAAIvjD,WAAW,CAC1B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IAGFsiD,EAAI0B,KAAO1B,EAAI2B,KAAO3B,EAAI4B,KAAOX,EAEjCjB,EAAI6B,KAAO,IAAInkD,WAAW,CACxB,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IAEFsiD,EAAI8B,KAAO,IAAIpkD,WAAW,CACxB,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IAEFsiD,EAAI+B,KAAO,IAAIrkD,WAAW,CACxB,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IAGFsiD,EAAIgC,KAAO,IAAItkD,WAAW,CACxB,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IAGF,MAAMukD,EAAa,IAAIvkD,WAAW,CAAC,IAAK,IAAK,IAAK,MAC5CwkD,EAAY,IAA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f,MAAMuzI,EAAsB,GAE5B,KAAOrtG,KACLqtG,EAAMrtG,GAAK2qG,EAAIxyC,KAAK2qB,EAAO9iF,IAG7B,OAAO2qG,EAAIqC,IAAI52C,MAAM,KAAM,CAACu0C,EAAI9pI,MAAM0qI,QAAS8B,GACjD,CAEAhzI,YAAY08F,EAAW72F,GACrBA,GAAY62F,EACZ,MAAMm2C,EAAoBr+H,KAAKC,MAAM5O,GAAY81F,GAAa,IACxDm3C,EAAoBt+H,KAAKC,MAAM5O,GAAY81F,GAAa,IACxDwG,EAAQ,IAAInU,WAAW,CAC3B,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACC0O,GAAa,GAAM,IACnBA,GAAa,GAAM,IACnBA,GAAa,EAAK,IACP,IAAZA,EACAm2C,GAAqB,GACpBA,GAAqB,GAAM,IAC3BA,GAAqB,EAAK,IACP,IAApBA,EACAC,GAAqB,GACpBA,GAAqB,GAAM,IAC3BA,GAAqB,EAAK,IACP,IAApBA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,IACA,IACA,IACA,MAEF,OAAOxC,EAAIqC,IAAIrC,EAAI9pI,MAAM2qI,KAAMhvC,EACjC,CAEAniG,YAAY+9F,GACV,MAAMe,EAAUf,EAAMe,SAAW,GAC3BqD,EAAQ,IAAInU,WAAW,EAAI8Q,EAAQr/F,QACzC,IAAIkmC,EACA6zC,EAGJ,IAAK7zC,EAAI,EAAGA,EAAIm5D,EAAQr/F,OAAQkmC,IAC9B6zC,EAAQslB,EAAQn5D,GAAG6zC,MACnB2oB,EAAMx8D,EAAI,GACP6zC,EAAMy5D,WAAa,EACnBz5D,EAAM05D,cAAgB,EACvB15D,EAAM25D,cAGV,OAAO7C,EAAIqC,IAAIrC,EAAI9pI,MAAM6qI,KAAMlvC,EACjC,CAEAniG,YAAY+9F,GACV,OAAOuyC,EAAIqC,IACTrC,EAAI9pI,MAAM8qI,KACVhB,EAAI1yC,KAAKG,GACTuyC,EAAIqC,IAAIrC,EAAI9pI,MAAMkrI,KAAMpB,EAAI0B,MAC5B1B,EAAIqC,IAAIrC,EAAI9pI,MAAMgrI,KAAMlB,EAAI2B,MAC5B3B,EAAIqC,IAAIrC,EAAI9pI,MAAMirI,KAAMnB,EAAI6B,MAC5B7B,EAAIqC,IAAIrC,EAAI9pI,MAAM+qI,KAAMjB,EAAI4B,MAEhC,CAEAlyI,YAAY+9F,GACV,IAEIp4D,EACAhoC,EACAglD,EAJAurF,EAAgB,GAChBG,EAAgB,GAMpB,IAAK1oG,EAAI,EAAGA,EAAIo4D,EAAMmwC,IAAIzuI,OAAQkmC,IAChChoC,EAAOogG,EAAMmwC,IAAIvoG,GACjBgd,EAAMhlD,EAAKk9F,WACXqzC,EAAI3oI,KAAMo9C,IAAQ,EAAK,KACvBurF,EAAI3oI,KAAW,IAANo9C,GAGTurF,EAAMA,EAAI1pF,OAAOpwC,MAAMquB,UAAUnuB,MAAM2xB,KAAKtoC,IAI9C,IAAKgoC,EAAI,EAAGA,EAAIo4D,EAAMswC,IAAI5uI,OAAQkmC,IAChChoC,EAAOogG,EAAMswC,IAAI1oG,GACjBgd,EAAMhlD,EAAKk9F,WACXwzC,EAAI9oI,KAAMo9C,IAAQ,EAAK,KACvB0rF,EAAI9oI,KAAW,IAANo9C,GAET0rF,EAAMA,EAAI7pF,OAAOpwC,MAAMquB,UAAUnuB,MAAM2xB,KAAKtoC,IAG9C,MAAMy1I,EAAO9C,EAAIqC,IACfrC,EAAI9pI,MAAM+pI,KACV,IAAIviD,WACF,CACE,EACAkgD,EAAI,GACJA,EAAI,GACJA,EAAI,GACJ,IACA,IAAOnwC,EAAMmwC,IAAIzuI,QAEhB+kD,OAAO0pF,GACP1pF,OAAO,CACNu5C,EAAMswC,IAAI5uI,SAEX+kD,OAAO6pF,KAGRv4H,EAAQioF,EAAMjoF,MACdF,EAASmoF,EAAMnoF,OACfy9H,EAAWt1C,EAAM2rC,WAAW,GAC5B4J,GAAWv1C,EAAM2rC,WAAW,GAElC,OAAO4G,EAAIqC,IACTrC,EAAI9pI,MAAMsiG,KACV,IAAI9a,WAAW,CACb,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACCl4E,GAAS,EAAK,IACP,IAARA,EACCF,GAAU,EAAK,IACP,IAATA,EACA,EACA,GACA,EACA,EACA,EACA,GACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,IACA,GACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,GACA,IACA,IACA,IACA,GACA,IACA,IACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,GACA,KAEFw9H,EACA9C,EAAIqC,IACFrC,EAAI9pI,MAAMgqI,KACV,IAAIxiD,WAAW,CACb,EACA,GACA,IACA,IACA,EACA,GACA,IACA,IACA,EACA,GACA,IACA,OAGJsiD,EAAIqC,IACFrC,EAAI9pI,MAAM4qI,KACV,IAAIpjD,WAAW,CACbqlD,GAAY,GACXA,GAAY,GAAM,IAClBA,GAAY,EAAK,IACP,IAAXA,EACAC,IAAY,GACXA,IAAY,GAAM,IAClBA,IAAY,EAAK,IACP,IAAXA,MAIR,CAEAtzI,YAAY+9F,GACV,MAAMw1C,EAAYx1C,EAAMlxD,OAAOptC,OAC/B,OAAO,IAAIuuF,WACT,CACE,EACA,EACA,EACA,EAEA,EACA,GAAOulD,EACP,EACA,EACA,EAEA,EACA,GAAOA,EACP,GACA,GACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EAEA,GAEC/uF,OAAO,CAAC+uF,IACR/uF,OAAOu5C,EAAMlxD,QACb2X,OAAO,CAAC,EAAM,EAAM,IAE3B,CAEAxkD,YAAY+9F,GACV,MAAMsnC,EAAatnC,EAAMsnC,WACzB,OAAOiL,EAAIqC,IACTrC,EAAI9pI,MAAM2hG,KACV,IAAIna,WAAW,CACb,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA+P,EAAM8nC,aACN,EACA,GACA,EACA,EACA,EACA,EACCR,GAAc,EAAK,IACP,IAAbA,EACA,EACA,IAEFiL,EAAIqC,IAAIrC,EAAI9pI,MAAMmqI,KAAML,EAAIK,KAAK5yC,IAErC,CAEA/9F,WAAW+9F,GACT,MAAMsnC,EAAatnC,EAAMsnC,WACzB,OAAOiL,EAAIqC,IACTrC,EAAI9pI,MAAM,QACV,IAAIwnF,WAAW,CACb,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA+P,EAAM8nC,aACN,EACA,GACA,EACA,EACA,EACA,EACCR,GAAc,EAAK,IACP,IAAbA,EACA,EACA,IAGN,CAEArlI,YAAY+9F,GACV,OAEWuyC,EAAIqC,IAAIrC,EAAI9pI,MAAMo3F,KAAM0yC,EAAIgC,KAFpB,UAAfv0C,EAAMt0F,KACmB,QAAvBs0F,EAAMouC,cAA0C,QAAhBpuC,EAAMF,MACCyyC,EAAIb,IAAI1xC,GAGVuyC,EAAInoC,KAAKpK,GAETuyC,EAAIxnC,KAAK/K,GAEtD,CAEA/9F,YAAY+9F,GACV,MAAMt4F,EAAKs4F,EAAMt4F,GACXI,EAAWk4F,EAAMl4F,SAAWk4F,EAAMrB,UAClC5mF,EAAQioF,EAAMjoF,MACdF,EAASmoF,EAAMnoF,OACfi9H,EAAoBr+H,KAAKC,MAAM5O,GAAY81F,GAAa,IACxDm3C,EAAoBt+H,KAAKC,MAAM5O,GAAY81F,GAAa,IAC9D,OAAO20C,EAAIqC,IACTrC,EAAI9pI,MAAM62F,KACV,IAAIrP,WAAW,CACb,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACCvoF,GAAM,GAAM,IACZA,GAAM,GAAM,IACZA,GAAM,EAAK,IACP,IAALA,EACA,EACA,EACA,EACA,EACAotI,GAAqB,GACpBA,GAAqB,GAAM,IAC3BA,GAAqB,EAAK,IACP,IAApBA,EACAC,GAAqB,GACpBA,GAAqB,GAAM,IAC3BA,GAAqB,EAAK,IACP,IAApBA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,EACA,GACA,EACA,EACA,EACCh9H,GAAS,EAAK,IACP,IAARA,EACA,EACA,EACCF,GAAU,EAAK,IACP,IAATA,EACA,EACA,IAGN,CAEA5V,YAAY+9F,EAAOg1C,GACjB,MAAMS,EAAwBlD,EAAIe,KAAKtzC,GACjCt4F,EAAKs4F,EAAMt4F,GACXguI,EAA+Bj/H,KAAKC,MACxCs+H,GAAuBp3C,GAAa,IAEhC+3C,EAA+Bl/H,KAAKC,MACxCs+H,GAAuBp3C,GAAa,IAEtC,OAAO20C,EAAIqC,IACTrC,EAAI9pI,MAAM44F,KACVkxC,EAAIqC,IACFrC,EAAI9pI,MAAM+4F,KACV,IAAIvR,WAAW,CACb,EACA,EACA,EACA,EACAvoF,GAAM,GACLA,GAAM,GAAM,IACZA,GAAM,EAAK,IACP,IAALA,KAGJ6qI,EAAIqC,IACFrC,EAAI9pI,MAAM84F,KACV,IAAItR,WAAW,CACb,EACA,EACA,EACA,EACAylD,GAAgC,GAC/BA,GAAgC,GAAM,IACtCA,GAAgC,EAAK,IACP,IAA/BA,EACAC,GAAgC,GAC/BA,GAAgC,GAAM,IACtCA,GAAgC,EAAK,IACP,IAA/BA,KAGJpD,EAAIlyC,KACFL,EACAy1C,EAAsB/zI,OACpB,GACA,GACA,EACA,GACA,EACA,GAEJ+zI,EAEJ,CAMAxzI,YA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","names":["i0","FooterComponent","constructor","appSiteService","router","this","ngOnInit","events","pipe","switchMap","x","handleLoadOrInjectFooter","subscribe","data","RoutesRecognized","state","root","firstChild","pageType","PageTypeEnum","_this","enabled","loaded","loading","injectFooter","loadFooter","portalId","_this2","siteConfiguration","PortalId","undefined","url","environment","fetch","then","response","text","replace","_this3","eval","footerHTMLCollection","document","getElementsByTagName","length","interval","setInterval","getComputedStyle","display","cssLoaded","clearInterval","static","_angular_core__WEBPACK_IMPORTED_MODULE_2__","selectors","SpinnerComponent","CommonModule","_angular_common__WEBPACK_IMPORTED_MODULE_1__","QueryStrings","About","da","en","Activities","AnnualPlan","AssignmentTypes","Assignments","AssetTopics","Audios","Categories","Class","Classes","CommonGoals","CollaborationTypes","Courses","DifficultyGroups","Documents","Downloads","Edit","Gallery","Genres","Geogebras","Grades","HasAudioBook","Illustrations","Images","Languages","Levels","Link","List","OnlyFavourite","OnlyLicense","Open","Page","Query","ReadingLevels","SeriesTitle","Student","SubTab","Subjects","Tab","Texts","Topics","Videos","Writers","Year","Periods","AudioPlayerTypeEnum","ContentTypeEnum","FacetTypeEnum","GTMEvent","LoadingKey","MenuTypeEnum","CoursePageTypeEnum","PeriodSelectorEnum","ProjectTypeEnum","PsLibraryFilterEnum","SectionTypeEnum","UmbSettingWidthEnum","UmbSettingAlignEnum","MissingTranslationHelper","handle","params","interpolateParams","param","key","factory","ActivityMapper","htmlService","mapActivitiesToTab2","activities","hasFavorite","SliderSettings","Type","MaxSlidesPerView","Items","mapActivitiesFromApi","trackingUrl","result","item","push","Id","id","Asset","asset","Duration","duration","Description","fixHtml","description","Title","title","Url","FavoriteLoaded","ObjectType","IsFavorite","Types","types","mapActivitiesToTab","forEach","activityWrapper","activity","Label","label","topics","writers","levels","IsLocked","locked","_angular_core__WEBPACK_IMPORTED_MODULE_3__","BookCollectionMapper","mapBookCollectionFromApi","collections","collection","Author","Creator","Name","Image","CoverImage","Copyright","FileType","Path","Dimensions","Icon","Owner","BookImpressionMapper","mapSelectImpressionsFromApi","all","selected","Slug","Selected","some","element","mapList","impressions2","map","impression2","slug","icon","BookLibraryMapper","helperService","bookMapper","translationService","mapFacetsFromApi","facets","facet","type","items","filter","value","toLowerCase","UrlTitle","facetResult","instant","Value","Count","count","getParameterByQueryStringAndSuffix","mapAutoCompleteFromApi","query","autocomplete","Suggestions","Books","BookCollections","autocompleteItems","queryPlusText","suggestions","book","mapBookFromApi2","DifficultyTypeEnum","BookDifficultiesMapper","appInitService","translate","mapBookDifficultyFromApi","difficulties","a","isSuperbog","b","find","getElement","isSuperreader","mapBookDifficultyFromApi2","lixTag","letTag","getElement2","lvlTag","splitTitle","split","default","core","BookMapper","bookDifficultiesMapper","bookImpressionMapper","assetMapper","mapBookFromApi","isFinished","HasAudio","Friends","Users","Progress","Difficulties","Impressions","hasAudioBook","coverImage","isFavorite","users","progress","impressions","mapBooksFromApi","books","mapBooksFromApi2","CourseFavoriteMapper","courseFavoriteApiService","userService","setTextsFavorite","isLoggedIn","ids","getFavoriteTextsByIds","catchError","EMPTY","elem","setTasksFavorite","getFavoriteTasksByIds","setCoursesFavorite","setFavorite","setActivitiesFavorite","getFavoriteActivitiesByIds","getFavoriteCourseByIds","tap","favorites","of","_angular_core__WEBPACK_IMPORTED_MODULE_6__","CourseLibraryMapper","courseMapper","levelService","getFacetItemTitle","course","convertLevelsToString","StatusLabel","statusLabel","BasePath","IsActive","getCourseIsActive","status","e","_angular_core__WEBPACK_IMPORTED_MODULE_8__","CourseTabsMapper","activityMapper","mapFavoriteTabsFromApi","courses","texts","tasks","TabsType","Length","mapCoursesFromApi","Pagination","CollectionSize","Index","PageSize","IsAvailable","mapTextsFromApi2","Tasks","mapTasksFromApi2","mapLibraryTabsFromApi","azureSearch","Tabs","mapTextsFromApi","library","pages","searchCount","isAvailable","Media","mapMediaFromApi","images","videos","audios","documents","geoGebras","mapCoursesFromApi2","mapTasksFromApi","assignments","page","genres","Authors","CourseTitle","courseTitle","NormalPages","normalPageCount","ShowNormalPages","showNormalPages","Period","period","Edition","edition","Highlights","highlights","Teaser","descriptionPreview","NormalPageCount","PageType","Locked","task","assignment","CollaborationTitle","collaborationType","CollaborationIcon","Assignment","CollaborationType","medias","aspectRatio16By9","expandable","media","svg","durationInSeconds","strPadLeft","durationString","pad","Array","join","slice","minutes","Math","floor","seconds","final","number","path","geoGebraId","thumbnailPath","getFileIconSvg","ThumbnailPath","assetId","Keywords","keywords","subjects","copyright","AspectRatio16By9","Expandable","basePath","Height","dimensions","height","Width","width","Svg","replaceCoursesTab","tab","replaceActivitiesTab","replaceTextsTab","replaceTasksTab","replaceImagesTab","replaceVideosTab","replaceAudiosTab","replaceDocumentsTab","replaceGeoGebrasTab","CourseMapper","Course","TitleMobile","truncateString","LessonOrDurationLabel","getLessonOrDurationLabel","Status","PromiseOfLearning","name","promiseOfLearning","PsArticleMapper","translateService","mapPsArticleFromApi","article","authors","toString","truncateHTML","teaser","ContentGridHtml","contentGridHtml","PublishDate","getLocalizedDate","Date","publishDate","image","Related","relatedArticles","Articles","mapPsArticlesFromApi","UseSlider","customUrl","getCustomUrl","articles","PsAssignmentMapper","mapPsAssignmentFromApi","truncate","AudioFilesCount","audioFilesCount","AudioFiles","audioFiles","fileExtension","FileName","fileName","Caption","caption","CopyrightText","copyrightText","subject","BackgroundColor","backgroundColor","TextColor","textColor","TeacherDocuments","teacherDocuments","Themes","themes","Thumbnail","thumbnail","DownloadUrl","downloadUrl","HasFiles","mapPsAssignmentsFromApi","AssetMapper","asset2","fileType","ChangeFormat","changeFormat","FileSize","fileSize","LayoutAudioModule","BaseModule","AudioPlayerModule","modulePrefix","GetTeamsAndClasses","createAction","SelectTeacherClassIdAction","props","SetSelectedStudent","SelectedBookTapNavigationAction","SelectBookPeriod","SetBookPeriod","SetOnlyBookPeriodTime","SetBookPeriodTime","GetTeamsAndClassesSuccess","GetTeacherClassesFailureAction","GetBookCollectionAction","GetBookCollectionSuccessAction","GetBookCollectionFailureAction","GetStudentsInClassSuccessAction","GetStudentsInClassFailureAction","ToggleBookCollectionFavouriteAction","ToggleBookContinueFavouriteAction","ToggleBookFinishedFavouriteAction","GetStudentsInClassAction","GetBooksForUser","GetBooksForUserSuccess","periodDateHelper","newDateSec","newDate","today","getTime","getUTCFullYear","getUTCMonth","getUTCDate","TeacherDashboardStoreEffects","actions$","apiService","store","bookCollectionMapper","loadingService","createEffect","ofType","TeacherDashboardStoreActions","start","mergeMap","getLounge","productId","stop","error","concatLatestFrom","select","selectorGetSelectedPeriodToDate","beginDate","postNext","TeamId","selectedClass","classId","ProjectGroupId","projectGroupId","IsDlpClass","isDlpClass","LevelIds","levelIds","StartDate","EndDate","studentsData","selectGetSelectedClass","_class","_bookCollectionData","bookCollectionData","getNext","userId","studentBooks","booksInProgress","BooksInProgress","booksFinished","BooksCompleted","ProjectGroup","teacherDashboardFeatureKey","getTeacherClassesSuccessReducer","createReducer","selectedStudent","selectedBookTab","selectedPeriod","selectedPeriodToDate","teamsAndClasses","students","bookCollection","initialTeacherDashboardState","on","action","newSortedData","sort","sortByDisplayName","bookTab","student","reducer","compare","DisplayName","localeCompare","sensitivity","selectTeacherClassState","createFeatureSelector","selectTeamsAndClasses","createSelector","selectGetSelectedStudent","selectGetSelectedStudentId","UserId","selectGetSelectedStudentName","selectorGetSelectedPeriod","selectStudentsByClass","selectorGetSelectedBookTab","selectGetBookCollection","selectBooksInProgress","selectBooksFinished","PlyrModule","AudioSelectionPlayerComponent","layoutAudioService","selectionService","gtmService","elementRef","autoplay","invertTime","disableContextMenu","settings","controls","source","src","Marks","marks","Selections","selections","AutoPlay","autoPlay","Highlight","highlight","SentenceButtons","sentenceButtons","ngOnChanges","selection","resetSelection","Target","prepare","ngOnDestroy","clearIntervals","player","removePlayer","resetFull","togglePartialDestroyed","playingInterval","loadedInterval","plyrInit","event","addPlayer","setSentenceButtonsEnabled","currentTime","autofocus","nativeElement","focus","plyrPlay","pauseOtherPlayers","pushTagWithUserType","handlePlyrEvents","previous","parseInt","Sentence","time","next","PreviousEnabled","NextEnabled","round","playing","play","highlightWord","plyrPause","detail","plyr","plyrEnded","onClickPreviousMark","found","onClickNextMark","increase","_angular_core__WEBPACK_IMPORTED_MODULE_1__","provide","Window","useValue","window","MissingTranslationHandler","useClass","imports","RouterModule","SharedPipeModule","LazyLoadImageModule","InlineSVGModule","baseUrl","FormsModule","ReactiveFormsModule","MatMenuModule","TranslateModule","NgbPaginationModule","BookDifficultiesComponent","SelectImpressionsModalComponent","dialogRef","bookImpressionService","take","close","firstValueFrom","getImpressions","observable","fetchAndUpdate","setRemaining","remaining","total","checkImpression","impression","target","checked","addSelectedImpressions","tag","removeSelectedImpressions","closeModal","MAT_DIALOG_DATA","ctx","BookTileComponent","bookFinishedService","dialog","bookContinueService","isBookFinished","removeFromList","setBookContinue","setBookFinished","onImpressionsClick","dialogConfig","MatDialogConfig","disableClose","autoFocus","restoreFocus","open","menuOpened","documentElement","classList","add","menuClosed","remove","onTileClick","CheckboxComponent","EventEmitter","onChange","changed","emit","DropdownComponent","dropdownService","breakpointsService","courseLibraryService","bookLibraryService","generateUUID","open$","dropdownOpen","large$","closeDropdown","large","onToggleDropdown","navigate","libraryUrl","underLarge$","isFagportal","displaySearchOnFagportal","displaySearchOnBoodAndReader","toggleDropdown","darkOverlay","filters","FiltersLoaded","initializeFilters","location","pathname","displaySearchField","zIndex","d","d2","performance","now","c","r","random","_angular_core__WEBPACK_IMPORTED_MODULE_4__","PsFavoriteService","addFavorite","postUmbraco","contentId","deleteFavorite","deleteUmbraco","FavoriteComponent","injector","bookFavoriteService","bookCollectionFavoriteService","psFavoriteService","psLibraryService","activityFavoriteService","toastClass","toastr","get","ToastrService","onFavoriteClick","apiLocked","subType","favorite","removeTextFavourite","addTextFavourite","removeTaskFavourite","addTaskFavourite","removeCourseFavourite","addCourseFavourite","unmarkBookAsFavourite","markBookAsFavourite","unmarkCollectionAsFavourite","markCollectionAsFavourite","unmarkActivityAsFavourite","markActivityAsFavourite","psDeleteFavourite","psAddFavourite","markFavorite","setFavoriteAndUnlockApi","toastAdd","removeFavorite","_this4","addTextFavorite","_this5","removeTextFavorite","_this6","removeTaskFavorite","_this7","addTaskFavorite","_this8","removeCourseFavorite","_this9","addCourseFavorite","_this10","setTotalFavoritesCount","_this11","_this12","addBookToFavorites","dispatch","_this13","deleteBookFromFavorites","_this14","addCollectionToFavorites","_this15","deleteCollectionFromFavorites","translationKey","info","toastrOptions","Injector","ctx_r5","ctx_r7","ManageBookCollectionComponent","bookCollectionService","toastrService","isTeacher","initializeBookCollections","getBookTileAvailableCollections","fetchCollectionStatus","getBooksInCollection","onAddToCollectionClick","addBookToCollection","success","bookTitle","collectionTitle","onRemoveFromCollectionClick","removeBookFromCollection","onClickCreateCollection","BookCardPreviewComponent","CourseCardPreviewComponent","LibrarySearchComponent","courseLibraryMapper","bookLibraryMapper","Subject","PreviewTile","isPs","ProjectType","filtersSubscription","unsubscribe","autoCompleteSubscription","data$","currentQuery","filterTextChanged","debounceTime","filterQuery","enterActivated","postAzureAutoComplete","onKeyup","trimmedQuery","trim","keyCode","activeQuery","onFocus","onClickAutoComplete","clearQuery","changeQuery","search","documentClick","closest","handleKeyup","which","LibrarySearchModule","BackgroundImagePipe","transform","pure","NextImagePipe","mode","assetDimensionsWidth","assetDimensionsHeight","getPercentageChange","oldNumber","newNumber","difference","useMode","useWidth","useHeight","currentRatio","closestRatio","abs","Ratio","availableDimensions","closestDimensions","reduce","includes","TruncatePipe","limit","ellipsis","cleanText","strip","substring","html","DOMParser","parseFromString","body","textContent","UmbracoImagePipe","quality","imgQuality","tempParameters","parameters","useWebP","ActivityFavoriteService","api","initService","getFavoriteActivitiesByProjectGroupId","mapGetFavoriteContentResponse","contentType","deleteNext","list","hours","Hours","Minutes","hasLicense","isShowcase","BookCollectionFavoriteService","ReplaySubject","asObservable","initialize","_angular_core__WEBPACK_IMPORTED_MODULE_5__","BookCollectionService","create","edit","putNext","delete","changePublic","patchNext","getMyBookCollections","isStudent","collectionId","bookId","BookBoxId","BookId","getTeamsAvailable","addTeamToCollection","teamId","removeTeamFromCollection","getBookById","getSingleInfoTile","tile","IsEmpty","IsInform","getEmptyBookCollectionList","amount","index","Loading","BookContinueService","percentage","Percentage","BookFavoriteService","BookFinishedService","getBookFinished","BookImpressionService","getSelectedImpressionsUrl","getImpressionsUrl","impressionId","addSelectedImpressionsUrl","withLatestFrom","_","impressionTags","removeSelectedImpressionsUrl","getImpressionPercentages","getImpressionPercentagesUrl","BookLibraryService","platformLocation","pageService","SearchLoaded","LoggedIn","SearchBody","Top","Skip","FacetCount","SeriesTitles","Facets","Collections","onPopState","urlQuery","getQueryParam","getQuerystringFacetList","getQuerystringFacetListAsBooleans","initializeSearch","postAzureSearch","showError","Total","results","postNextSearch","Fuzzy","setQueryString","replaceState","HttpParams","setQueryStringFacets","setQueryStringSearchBody","go","append","encodeStringArray","handleBookSearchResponse","changeFacet","mapFacet","toggleFacetOpen","reset","setFacets","changePage","pageIndex","scroll","_angular_core__WEBPACK_IMPORTED_MODULE_12__","CourseFavoriteApiService","getFavoriteCoursesByProjectGroupId","getFavoriteTextsByProjectGroupId","getFavoriteTasksByIdsByProjectGroupId","CourseLibraryService","courseFavoriteMapper","courseTabsMapper","MinShown","MinToCollapse","SearchIn","TabGroups","SearchCount","CurrentTab","Checked","getPageSize","onlyLicenseParam","onlyLicenseToggle","getKeyName","urlPage","tryParseInt","setCurrentTab","setFavorites","changeTab","onlyLicenseChange","clearPageIndex","replaceTabs","group","resetFacets","_angular_core__WEBPACK_IMPORTED_MODULE_16__","PsLibraryMapper","psAssignmentMapper","psArticleMapper","mapLibraryFromApi","classTags","itemsCount","subjectTags","topicTags","pagination","collectionSize","pageSize","PSLibraryService","psLibraryMapper","navbarService","setFiltersToUnloaded","Loaded","ContentType","PageIndex","SearchText","SelectedTopics","SelectedClasses","SelectedSubjects","OnlyFavorite","ShowSearch","ShowSubjectsInHeader","AssignmentsOpen","assignmentsOpen","post","postSearch","psTheme","Data","SelectedSubjectBackgroundColor","SelectedSubjectTextColor","resetFilters","selectedTopics","selectedSubjects","selectedClasses","searchText","onlyFavorite","useFallbackSubject","URLSearchParams","toggleFiltersOpen","FiltersOpen","setting","toggleSubjectFilter","toggleFilter","setAssignmentOpen","onlyFavoriteChange","assignmentTagClick","psAssignmentLibraryUrl$","navigateByUrl","skipLocationChange","articleTagClick","psArticleLibraryUrl$","_typeof","Symbol","iterator","obj","prototype","previousDevice","device","changeOrientationList","userAgent","navigator","television","haystack","needle","indexOf","hasClass","className","match","RegExp","addClass","currentClassNames","removeClass","handleOrientation","landscape","walkOnChangeOrientationList","setOrientationCache","newOrientation","macos","ios","iphone","ipod","ipad","windows","iPadOS13Up","platform","maxTouchPoints","android","androidPhone","androidTablet","blackberry","blackberryPhone","blackberryTablet","windowsPhone","windowsTablet","fxos","fxosPhone","fxosTablet","meego","cordova","protocol","nodeWebkit","process","mobile","tablet","desktop","i","portrait","screen","orientation","Object","hasOwnProperty","call","innerHeight","innerWidth","noConflict","onChangeOrientation","cb","orientationEvent","findMatch","arr","addEventListener","attachEvent","os","SiteConfigurationMapper","mapSiteConfigurationFromApi","ISBNs","isbns","category","portalProducts","externalId","NavbarId","menus","isActive","MegaMenuId","PrimaryColor","primaryColor","PrimaryTextColor","primaryTextColor","SecondaryColor","secondaryColor","SecondaryTextColor","secondaryTextColor","SiteBackgroundColor","siteBackgroundColor","SiteLinkColor","siteLinkColor","SiteTextColor","siteTextColor","HeaderColors","getPortalHeaderColors","ErrorPages","errorpages","StatusCode","statusCode","GoogleVerificationId","googleSiteVerificationCode","GoogleTagManagerId","googleGTM","FrontpageId","frontpage","LibraryCategories","mapLibraryCategories","portalSettings","logo","logoImageUrl","mobileLogoImageUrl","language","languageIsoCode","filtering","Text1","text1","Text2","text2","IconUrl","iconUrl","Emoji","emoji","BackgroundColorHex","backgroundColorHex","BookSubject","bookSubject","mapLibraryCategoryTag","BookTopic","bookTopic","PortalLevels","portalLevels","PrimaryBackgroundColor","SecondaryBackgroundColor","headerPrimaryBackgroundColor","headerPrimaryTextColor","headerSecondaryBackgroundColor","headerSecondaryTextColor","AppInitService","siteConfigurationMapper","httpClient","googleTagManagerService","cssColorService","setDefaultSiteConfiguration","Init","bk","canUseWebP","scrollLocked","scrollbarWidth","getScrollbarWidth","localStorage","removeItem","startup","setLang","lang","projectType","setAttribute","languagesToAdd","useLang$","use","addLangs","setDefaultLang","getUmbraco","hostName","userType","config","updateSiteManifest","setStylesheet","setTheme","addGoogleTagManager","SeoService","setGoogleVerificationId","iif","gethHostUrl","retry","configOrCount","Infinity","delay","resetOnSuccess","identity","operate","subscriber","innerSub","soFar","subscribeForRetry","syncUnsub","createOperatorSubscriber","err","resub","notifier","timer","innerFrom","notifierSubscriber","complete","Message","shouldUseTagManager","setId","addToDOM","manifestName","withCredentials","productName","head","link","createElement","rel","href","setCssColors","prefix","hex100","add100Suffix","variants","isLocalhost","appendChild","hexToRgb","style","setProperty","hostname","getErrorPage","outer","visibility","overflow","inner","offsetWidth","parentNode","removeChild","getContext","toDataURL","setISBNs","postInternalBackend","setHeaderHeight","HeaderHeight","DOCUMENT","BreadcrumbsService","setBreadcrumbs","BreakpointsService","breakpointObserver","mediaMatcher","BehaviorSubject","small","medium","xlarge","underLarge","breakpoints","matchMedia","matches","observe","DropdownService","openDropdown","DarkOverlay","ZIndex","ExtendedDialogService","MatDialog","componentOrTemplateRef","super","afterOpened","afterClosed","t","HeaderService","behind","setHeader","header","InitialBackgroundColor","InitialTextColor","ScrolledBackgroundColor","ScrolledTextColor","setBehind","hasHero","resetHeader","HelperService","hex","exec","lightenDarkenColor","color","percent","num","amt","g","hexToRGB","alpha","decodeURIComponent","array","encodeURIComponent","getCookie","cookie","extension","date","toLocaleDateString","year","month","day","entries","val","anyFiltersActive","show","getUmbracoAlign","align","fallback","keys","values","findIndex","getUmbracoWidth","getUmbracoPercentageWidth","getHttpsUrl","startsWith","test","isSafari","str","defaultValue","retValue","isLessons","parseFloat","toFixed","durationTransformed","queryString","urlParams","every","paramString","getParameterByName","getParameterByNameWithSuffix","suffix","EscapeHtmlPipe","sanitizer","content","bypassSecurityTrustHtml","HtmlService","domSanitizer","truncated","truncatedEndTagExpr","truncatedEndTagMatch","truncatedEndTag","startTagExpr","testString","startTagMatch","startTag","reverseHtml","reverseTagOpenExpr","tagMatch","tagName","fragment","ph","String","fromCharCode","reverse","TextToSpeechLanguageEnum","LayoutAudioService","Players","PartialDestroyed","instance","layoutAudio","Instance","Src","destroyed","setActiveLanguage","pause","removeAll","Full","Recorded","Partial","initializeFull","Enabled","FullExpanded","getFull","RecordedExpanded","CoordinatesAndText","Text","Language","InputText","polly","mapPollyToPlayer","toggleFullExpanded","expanded","findPlayer","players","removeFull","getPartial","removePartial","setRecorded","ShowSecondsControls","toggleRecordedExpanded","handleRecordedExpanded","toggleFullEnabled","_this16","gtmEvent","_this17","file","languages","Audio","mark","Words","_this18","LevelService","level","levelNumber","Number","y","current","finishCurrent","part1","part2","NavbarService","favoritesUrl","courseStudentAnswersUrl","courseAnnualPlanUrl","psArticleLibraryUrl","psAssignmentLibraryUrl","getNavbar","menuId","setLibrary","setCourseStudentAnswers","setCourseAnnualPlan","setPsArticleLibrary","setPsAssignmentLibrary","PageService","nextImagePipe","pageSettings","pageSettings$","loadPage","setPageSettings","pageId","catch","fromError","pageUrl","annualPlanUrl","studentAnswersUrl","courseLibraryUrl","bookLibraryUrl","timeout","setTimeout","courseAnnualPlanUrl$","clearTimeout","courseStudentAnswersUrl$","favoritesUrl$","libraryUrl$","tempStatusCode","htmlGridEditor","hero","textAlign","sectionAlign","headline","backgroundImageUrl","sectionsV2","columns","gridEditors","alignment","errorPageId","pageLoadSubscription","_angular_core__WEBPACK_IMPORTED_MODULE_9__","ScriptService","$document","load","scripts","promises","script","promise","Promise","resolve","reject","loadScript","onload","onerror","_angular_core__WEBPACK_IMPORTED_MODULE_0__","SelectionService","clearSelection","w","getSelection","empty","removeAllRanges","anchorNode","expandToWord","Selection","getCoordinatesAndText","getRangeAt","commonAncestorContainer","console","warn","rng2","startOffset","startContainer","nodeValue","endOffset","endContainer","setStart","setEnd","addRange","currentFrameAbsolutePosition","currentParentWindow","currentWindow","positions","rect","top","parent","frame","from","frames","frameElement","contentWindow","getBoundingClientRect","X","Y","accumulator","currentValue","node","nodes","nonWhitespaceMatcher","backwards","isSelectionBackwards","words","getTextNodes","nodeInput","parentElement","special","containsNode","nodeName","nodeType","contains","len","childNodes","focusNode","anchorOffset","focusOffset","foc","sel","lastIndexOf","selectedWord","ownerDocument","defaultView","coordinates","left","isCollapsed","range","createRange","collapsed","detach","getDomWords","getElementsByClassName","sentences","selectedMark","domWords","markIndex","wordIndex","textNodesUnder","textNode","htmlNode","nextSibling","concat","iterate","children","child","newNode","innerHTML","replaceChild","prepareForSelection","tempWords","word","outerHTML","shouldHaveBreak","querySelectorAll","words1","char","endsWith","meta","getMetaData","setMetaData","metaTitle","setTitle","defaultImage","logoImage","metaDescription","updateTag","property","excludeFromSearchEngines","production","fallbackLanguage","isRealProduction","toLocaleLowerCase","internalBackendUrl","origin","loginUsingMvcDotNet","apiLoungeBaseUrl","apiNextBaseUrl","apiNextSearchBaseUrl","apIUmbBaseUrl","assetBasePath","showPapertrailResponse","activityUrl","localHostName","invalidTimingValue","exp","RuntimeError","isBrowser","isNode","optimizeGroupPlayer","NoopAnimationPlayer","ɵAnimationGroupPlayer","normalizeKeyframes","driver","normalizer","keyframes","preStyles","Map","postStyles","errors","normalizedKeyframes","previousOffset","previousKeyframe","kf","offset","isSameOffset","normalizedKeyframe","prop","normalizedProp","normalizedValue","normalizePropertyName","PRE_STYLE","AUTO_STYLE","normalizeStyleValue","set","animationFailed","ngDevMode","listenOnPlayer","eventName","callback","onStart","copyAnimationEvent","onDone","onDestroy","phaseName","makeAnimationEvent","triggerName","fromState","toState","totalTime","disabled","_data","getOrSetDefaultValue","parseTimelineCommand","command","separatorPos","_contains","elm1","elm2","_query","selector","multi","_documentElement","getParentElement","host","Element","querySelector","_CACHED_BODY","_IS_WEBKIT","containsElement","invokeQuery","NoopAnimationDriver","validateStyleProperty","getBodyNode","containsVendorPrefix","charAt","toUpperCase","matchesElement","_element","_selector","computeStyle","animate","easing","previousPlayers","scrubberAccessRequested","AnimationDriver","ONE_SECOND","ENTER_CLASSNAME","LEAVE_CLASSNAME","NG_TRIGGER_CLASSNAME","NG_TRIGGER_SELECTOR","NG_ANIMATING_CLASSNAME","NG_ANIMATING_SELECTOR","resolveTimingValue","_convertTimeValueToMS","unit","resolveTiming","timings","allowNegativeValues","parseTimeExpression","delayMatch","easingVal","containsErrors","startIndex","negativeStepValue","negativeDelayValue","splice","copyObj","destination","convertToMap","styleMap","copyStyles","styles","backfill","getStyleAttributeString","writeStyleAttribute","styleAttrValue","getPropertyValue","camelCaseToDashCase","setStyles","formerStyles","camelProp","dashCaseToCamelCase","has","normalizeAnimationEntry","steps","isArray","sequence","PARAM_REGEX","extractStyleParams","lastIndex","original","varName","localVal","invalidParamValue","iteratorToArray","done","DASH_CASE_REGEXP","input","m","visitDslNode","visitor","context","visitTrigger","visitState","visitTransition","visitSequence","visitGroup","visitAnimate","visitKeyframes","visitStyle","visitReference","visitAnimateChild","visitAnimateRef","visitQuery","visitStagger","invalidNodeType","ANY_STATE","transitionValue","expressions","parseInnerTransitionStr","eventStr","parseAnimationAlias","alias","invalidTransitionAlias","invalidExpression","expr","separator","makeLambdaFromStates","TRUE_BOOLEAN_VALUES","Set","FALSE_BOOLEAN_VALUES","lhs","rhs","LHS_MATCH_BOOLEAN","RHS_MATCH_BOOLEAN","lhsMatch","rhsMatch","SELF_TOKEN_REGEX","buildAnimationAst","metadata","warnings","AnimationAstBuilderVisitor","build","_driver","AnimationAstBuilderContext","_resetContextStyleTimingState","currentQuerySelector","collectedStyles","queryCount","depCount","states","transitions","invalidTrigger","definitions","def","stateDef","n","transition","invalidDefinition","options","styleAst","astParams","containsDynamicStyles","missingSubs","sub","size","metadataName","invalidState","animation","matchers","parseTransitionExpr","normalizeAnimationOptions","s","furthestTime","step","innerAst","max","timingAst","constructTimingAst","makeTimingAst","strValue","v","ast","dynamic","currentAnimateTimings","styleMetadata","isEmpty","newStyleData","_styleAst","isEmptyStep","_makeStyleAst","_validateStyleAst","metadataStyles","styleTuple","collectedEasing","styleData","endTime","startTime","tuple","collectedEntry","updateCollectedStyle","invalidParallelAnimation","firstStart","firstEnd","secondStart","secondEnd","validateStyleParams","invalidStyleParams","invalidKeyframes","totalKeyframesWithOffsets","offsets","offsetsOutOfOrder","keyframesOutOfRange","offsetVal","consumeOffset","invalidOffset","keyframeOffsetsOutOfOrder","generatedOffset","keyframesMissingOffsets","animateDuration","durationUpToThisFrame","parentSelector","includeSelf","normalizeSelector","hasAmpersand","token","optional","originalSelector","invalidStagger","currentTransition","normalizeParams","createTimelineInstruction","preStyleProps","postStyleProps","subTimeline","ElementInstructionMap","_map","instructions","existingInstructions","clear","ENTER_TOKEN_REGEX","LEAVE_TOKEN_REGEX","rootElement","enterClassName","leaveClassName","startingStyles","finalStyles","subInstructions","AnimationTimelineBuilderVisitor","buildKeyframes","AnimationTimelineContext","currentTimeline","delayNextStep","timelines","timeline","containsAnimation","lastRootTimeline","allowOnlyTimelineStyles","elementInstructions","innerContext","createSubContext","_visitSubInstructions","transformIntoNewTimeline","previousNode","_applyAnimationRefDelays","animationsRefsOptions","animationRefOptions","animationDelay","animationDelayValue","instruction","instructionTimings","appendInstructionToTimeline","updateOptions","subContextCount","snapshotCurrentStyles","DEFAULT_NOOP_PREVIOUS_NODE","applyStylesToKeyframe","innerTimelines","mergeTimelineCollectedStyles","_visitTiming","incrementTime","hasCurrentStyleProperties","forwardFrame","applyEmptyStep","innerTimeline","forwardTime","elms","currentQueryTotal","sameElementTimeline","currentQueryIndex","parentContext","tl","maxTime","currentStaggerTime","startingTime","_enterClassName","_leaveClassName","initialTimeline","TimelineBuilder","skipIfExists","newOptions","optionsToUpdate","newParams","paramsToUpdate","_copyOptions","oldParams","newTime","fork","updatedTimings","builder","SubTimelineBuilder","stretchStartingKeyframe","elements","invalidQuery","_elementTimelineStylesLookup","_currentEmptyStepKeyframe","_globalTimelineStyles","_localTimelineStyles","_loadKeyframe","_keyframes","_currentKeyframe","hasPreStyleStep","_pendingStyles","_previousKeyframe","_updateStyle","_styleSummary","_backFill","flattenStyles","allStyles","allProperties","getFinalKeyframe","properties","details1","details0","finalKeyframes","keyframe","finalKeyframe","preProps","postProps","kf0","kf1","_stretchStartingKeyframe","newKeyframes","startingGap","newFirstKeyframe","oldFirstKeyframe","roundOffset","oldOffset","decimalPoints","mult","pow","AnimationStyleNormalizer","DIMENSIONAL_PROP_SET","WebAnimationsStyleNormalizer","propertyName","userProvidedProperty","normalizedProperty","strVal","valAndSuffixMatch","invalidCssUnitValue","createTransitionInstruction","isRemovalTransition","fromStyles","toStyles","queriedElements","EMPTY_OBJECT","AnimationTransitionFactory","_triggerName","_stateStyles","currentState","nextState","oneOrMoreTransitionsMatch","matchFns","fn","buildStyles","stateName","styler","currentOptions","nextOptions","skipAstBuild","transitionAnimationParams","currentStateStyles","nextAnimationParams","nextStateStyles","preStyleMap","postStyleMap","isRemoval","animationOptions","applyParamDefaults","buildAnimationTimelines","elm","queriedElementsList","userParams","defaults","AnimationStateStyles","defaultParams","combinedParams","AnimationTrigger","_normalizer","transitionFactories","balanceProperties","fallbackTransition","createFallbackTransition","containsQueries","matchTransition","f","matchStyles","stateMap","key1","key2","EMPTY_INSTRUCTION_MAP","TimelineAnimationEngine","bodyNode","register","registerFailed","_animations","_buildPlayer","autoStylesMap","inst","missingOrDestroyedAnimation","createAnimationFailed","_playersById","destroy","_getPlayer","missingPlayer","listen","baseEvent","args","restart","finish","init","setPosition","QUEUED_CLASSNAME","DISABLED_CLASSNAME","EMPTY_PLAYER_ARRAY","NULL_REMOVAL_STATE","namespaceId","setForRemoval","setForMove","hasAnimation","removedBeforeQueried","NULL_REMOVED_QUERIED_STATE","REMOVAL_FLAG","StateValue","isObj","normalizeTriggerValue","absorbOptions","VOID_VALUE","DEFAULT_STATE_VALUE","AnimationTransitionNamespace","hostElement","_engine","_queue","_hostClassName","phase","_triggers","missingTrigger","missingEvent","isTriggerEventValid","unsupportedTriggerEvent","listeners","_elementListeners","triggersWithStates","statesByElement","afterFlush","_getTrigger","trigger","unregisteredTrigger","defaultToFallback","TransitionAnimationPlayer","objEquals","k1","k2","reportError","eraseStyles","playersOnElement","playersByElement","queued","isFallbackTransition","totalQueuedPlayers","deregister","entry","clearElementCache","elementPlayers","_signalRemovalForInnerTriggers","namespaces","fetchNamespacesByElement","ns","triggerLeaveAnimation","afterFlushAnimationsDone","destroyAfterComplete","triggerStates","previousTriggersValues","markElementAsRemoved","processLeaveNode","prepareLeaveAnimationListeners","elementStates","visitedTriggers","listener","removeNode","engine","childElementCount","containsPotentialParentTransition","totalAnimations","currentPlayers","playersByQueriedElement","removalFlag","destroyInnerAnimations","_onRemovalComplete","insertNode","drainQueuedTransitions","microtaskId","markedForDestroy","d0","d1","p","elementContainsData","containsData","TransitionAnimationEngine","onRemovalComplete","_namespaceLookup","_namespaceList","_flushFns","_whenQuietFns","collectedEnterElements","collectedLeaveElements","queuedPlayers","createNamespace","_balanceNamespaceList","newHostElements","collectEnterElement","namespaceList","namespacesByHostElement","ancestor","ancestorNs","unshift","registerTrigger","_fetchNamespace","stateValue","isElementNode","insertBefore","details","markElementAsDisabled","disabledNodes","isHostElement","hostNS","_buildInstruction","subTimelines","skipBuildAst","containerElement","destroyActiveAnimationsForElement","finishActiveQueriedAnimationOnElement","whenRenderingDone","flush","cleanupFns","_flushAnimations","quietFns","triggerTransitionsFailed","skippedPlayers","skippedPlayersMap","queuedInstructions","allPreStyleElements","allPostStyleElements","disabledElementsSet","nodesThatAreDisabled","allTriggerElements","enterNodeMap","buildRootMap","enterNodeMapIds","allLeaveNodes","mergedLeaveNodes","leaveNodesWithoutAnimations","leaveNodeMapIds","leaveNodeMap","allPlayers","erroneousTransitions","previousValue","nodeIsOrphaned","stringMap","setVal","transitionFailed","allPreviousPlayersMap","animationElementMap","_beforeAnimationBuild","_getPreviousPlayers","prevPlayer","replaceNodes","replacePostStylesAsPre","postStylesMap","cloakAndComputeStyles","preStylesMap","pre","rootPlayers","subPlayers","NO_PARENT_ANIMATION_ELEMENT_DETECTED","overrideTotalTime","parentWithAnimation","parentsToAdd","detectedParent","innerPlayer","_buildAnimation","setRealPlayer","parentPlayers","parentPlayer","playersForElement","syncPlayerEvents","queriedPlayerResults","queriedInnerElements","j","queriedPlayers","activePlayers","removeNodesAfterAnimationDone","isQueriedElement","toStateValue","queriedElementPlayers","isRemovalAnimation","targetNameSpaceId","targetTriggerName","timelineInstruction","realPlayer","getRealPlayer","beforeDestroy","allQueriedPlayers","allConsumedElements","allSubElements","allNewPlayers","flattenGroupPlayers","finalPlayers","_flattenGroupPlayersRecur","wrappedPlayer","deleteOrUnsetInMap","currentValues","_containsRealPlayer","_player","_queuedCallbacks","callbacks","triggerCallback","_queueEvent","hasStarted","getPosition","cloakElement","oldValue","valuesMap","elementPropsMap","defaultStyle","cloakVals","failedElements","roots","rootMap","NULL_NODE","nodeSet","localRootMap","getRoot","AnimationGroupPlayer","postEntry","preEntry","AnimationEngine","_triggerCache","_transitionEngine","_timelineEngine","componentId","cacheKey","triggerBuildFailed","buildTrigger","onInsert","onRemove","disableAnimations","disable","eventPhase","SpecialCasedStyles","_startStyles","_endStyles","initialStyles","initialStylesByElement","_initialStyles","_state","WeakMap","filterNonAnimatableStyles","isNonAnimatableStyle","WebAnimationsPlayer","_specialStyles","_onDoneFns","_onStartFns","_onDestroyFns","_initialized","_finished","_started","_destroyed","_originalOnDoneFns","_originalOnStartFns","_duration","_delay","_onFinish","_preparePlayerBeforeStart","domPlayer","_triggerWebAnimation","_finalKeyframe","_resetDomPlayerState","_convertKeyframesToObject","kfs","fromEntries","cancel","currentSnapshot","methods","WebAnimationsDriver","validateAnimatableStyleProperty","playerOptions","fill","previousStyles","previousWebAnimationPlayers","allowPreviousPlayerStylesMerge","balancePreviousStylesIntoKeyframes","startingKeyframe","missingStyleProps","specialStyles","startStyles","endStyles","packageNonAnimatableStyles","BrowserAnimationBuilder","AnimationBuilder","rootRenderer","doc","_nextAnimationId","_renderer","createRenderer","encapsulation","ViewEncapsulation","issueAnimationCommand","BrowserAnimationFactory","AnimationFactory","_id","RendererAnimationPlayer","_command","_listen","renderer","DISABLE_ANIMATIONS_FLAG","AnimationRendererFactory","delegate","_zone","_currentId","_microtaskId","_animationCallbacksBuffer","_cdRecurDepth","_rendererCache","BaseAnimationRenderer","animationTriggers","AnimationRenderer","begin","_scheduleCountTask","scheduleListenerCallback","run","end","runOutsideAngular","i1","_onDestroy","destroyNode","namespace","createComment","createText","newChild","refChild","isMove","oldChild","selectRootElement","selectorOrNode","preserveContent","el","removeAttribute","setStyle","flags","removeStyle","setValue","resolveElementFromTarget","parseTriggerCallbackName","dotIndex","InjectableAnimationEngine","appRef","SHARED_ANIMATION_PROVIDERS","useFactory","instantiateDefaultStyleNormalizer","RendererFactory2","instantiateRendererFactory","zone","deps","DomRendererFactory2","NgZone","BROWSER_ANIMATIONS_PROVIDERS","ANIMATION_MODULE_TYPE","BROWSER_NOOP_ANIMATIONS_PROVIDERS","BrowserAnimationsModule","ngModule","providers","BrowserModule","NoopAnimationsModule","TranslateHttpLoader","http","getTranslation","RouteHasPage","seoService","canActivate","route","metaData","gtmTag","pageName","decodeURI","visitorType","pushTag","queryParams","SetGTMForRoute","SetPageForRoute","localStorageValue","getItem","frontpageLevel","JSON","parse","routes","loadChildren","module","PsArticleModule","PsAssignmentModule","PrintbarAssignmentModule","PsLibraryModule","PrintbarLibraryModule","BookInfoModule","BookTagModule","BookModule","BookCollectionModule","BookFavoritesModule","BookLibraryModule","BookTeacherDashboardModule","CourseFavoritesModule","CourseLibraryModule","CourseStudentAnswersModule","CourseAnnualPlanModule","__webpack_require__","CourseFrontpageModule","LoungeProxyModule","PageModule","EmptyModule","AppRoutingModule","scrollPositionRestoration","enableTracing","HeaderTypeEnum","MouseAndKeyboardService","extendedDialogService","mouseKeyboardService","loading$","isLoading","getElementById","removeHover","fixTabOffset","addFocus","handleKeydown","ctrlKey","preventDefault","tabs","hover","click","handleDropdown","handleArrow","removeFocus","closeAll","stopPropagation","isArrowDown","isArrowLeft","isArrowRight","isArrowUp","getAttribute","container","validElements","addHover","selectNext","selectPrev","button","loadingSubscription","dropDownSubscription","correctDistanceFromTop","clientHeight","scrollBy","WindowScrollService","platformId","getScrollY","isPlatformBrowser","fromEvent","startWith","scrollY","scrollTop","share","PLATFORM_ID","LinkTypeEnum","NavbarMapper","pushItemToArray","dropdownIndex","isHidden","contentTypeAlias","mapNavbarFromApi","navbar","row","rows","column","navbarItems","isLinkActive","isDropdownActive","urls","NavbarComponent","navbarMapper","dropdownsEnabled","MegaMenuService","getMegaMenu","MegaMenuMapper","mapMegaMenuFromApi","css","k","dropdown","l","hoverColor","Hover","ClassName","Color","createTextNode","MegaMenuComponent","megaMenuService","megaMenuMapper","megaMenu","ActivelyOpenedTab","UserComponent","user","onLogout","logout","HeaderDefaultComponent","windowScrollService","showLogin","hasMegaMenu","isSuperBogOrReader","favoriteUrl","siteName","pos","setScrolled","onLogin","login","verticalOffset","scrolled","maxScrollVal","BreadcrumbsComponent","breadcrumbsService","medium$","getRootUrl","URL_REGEX","FIRST_SEGMENT_REGEX","SLASH_DOT_REGEX","SLASH_DOT_DOT_REGEX","URLToolkit","buildAbsoluteURL","baseURL","relativeURL","opts","alwaysNormalize","basePartsForNormalise","parseURL","Error","normalizePath","buildURLFromParts","relativeParts","scheme","baseParts","netLoc","pathParts","builtParts","baseURLPath","newPath","parts","isFiniteNumber","isFinite","Events","MEDIA_ATTACHING","MEDIA_ATTACHED","MEDIA_DETACHING","MEDIA_DETACHED","BUFFER_RESET","BUFFER_CODECS","BUFFER_CREATED","BUFFER_APPENDING","BUFFER_APPENDED","BUFFER_EOS","BUFFER_FLUSHING","BUFFER_FLUSHED","MANIFEST_LOADING","MANIFEST_LOADED","MANIFEST_PARSED","LEVEL_SWITCHING","LEVEL_SWITCHED","LEVEL_LOADING","LEVEL_LOADED","LEVEL_UPDATED","LEVEL_PTS_UPDATED","LEVELS_UPDATED","AUDIO_TRACKS_UPDATED","AUDIO_TRACK_SWITCHING","AUDIO_TRACK_SWITCHED","AUDIO_TRACK_LOADING","AUDIO_TRACK_LOADED","SUBTITLE_TRACKS_UPDATED","SUBTITLE_TRACKS_CLEARED","SUBTITLE_TRACK_SWITCH","SUBTITLE_TRACK_LOADING","SUBTITLE_TRACK_LOADED","SUBTITLE_FRAG_PROCESSED","CUES_PARSED","NON_NATIVE_TEXT_TRACKS_FOUND","INIT_PTS_FOUND","FRAG_LOADING","FRAG_LOAD_EMERGENCY_ABORTED","FRAG_LOADED","FRAG_DECRYPTED","FRAG_PARSING_INIT_SEGMENT","FRAG_PARSING_USERDATA","FRAG_PARSING_METADATA","FRAG_PARSED","FRAG_BUFFERED","FRAG_CHANGED","FPS_DROP","FPS_DROP_LEVEL_CAPPING","ERROR","DESTROYING","KEY_LOADING","KEY_LOADED","LIVE_BACK_BUFFER_REACHED","BACK_BUFFER_REACHED","ErrorTypes","NETWORK_ERROR","MEDIA_ERROR","KEY_SYSTEM_ERROR","MUX_ERROR","OTHER_ERROR","ErrorDetails","KEY_SYSTEM_NO_KEYS","KEY_SYSTEM_NO_ACCESS","KEY_SYSTEM_NO_SESSION","KEY_SYSTEM_NO_CONFIGURED_LICENSE","KEY_SYSTEM_LICENSE_REQUEST_FAILED","KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED","KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED","KEY_SYSTEM_SESSION_UPDATE_FAILED","KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED","KEY_SYSTEM_STATUS_INTERNAL_ERROR","MANIFEST_LOAD_ERROR","MANIFEST_LOAD_TIMEOUT","MANIFEST_PARSING_ERROR","MANIFEST_INCOMPATIBLE_CODECS_ERROR","LEVEL_EMPTY_ERROR","LEVEL_LOAD_ERROR","LEVEL_LOAD_TIMEOUT","LEVEL_PARSING_ERROR","LEVEL_SWITCH_ERROR","AUDIO_TRACK_LOAD_ERROR","AUDIO_TRACK_LOAD_TIMEOUT","SUBTITLE_LOAD_ERROR","SUBTITLE_TRACK_LOAD_TIMEOUT","FRAG_LOAD_ERROR","FRAG_LOAD_TIMEOUT","FRAG_DECRYPT_ERROR","FRAG_PARSING_ERROR","FRAG_GAP","REMUX_ALLOC_ERROR","KEY_LOAD_ERROR","KEY_LOAD_TIMEOUT","BUFFER_ADD_CODEC_ERROR","BUFFER_INCOMPATIBLE_CODECS_ERROR","BUFFER_APPEND_ERROR","BUFFER_APPENDING_ERROR","BUFFER_STALLED_ERROR","BUFFER_FULL_ERROR","BUFFER_SEEK_OVER_HOLE","BUFFER_NUDGE_ON_STALL","INTERNAL_EXCEPTION","INTERNAL_ABORTED","UNKNOWN","noop","fakeLogger","trace","debug","log","exportedLogger","logger","DECIMAL_RESOLUTION_REGEX","ATTR_LIST_REGEX","AttrList","attrs","parseAttrList","attr","clientAttrs","decimalInteger","attrName","intValue","MAX_SAFE_INTEGER","hexadecimalInteger","stringValue","Uint8Array","hexadecimalIntegerAsNumber","decimalFloatingPoint","optionalFloat","enumeratedString","bool","decimalResolution","res","isSCTE35Attribute","DateRange","dateRangeAttr","dateRangeWithSameId","_startDate","_endDate","_badValueForSameId","previousAttr","ID","_extends","endDate","_isFiniteNumber","class","CLASS","startDate","_isFiniteNumber2","plannedDuration","endOnNext","isValid","_isFiniteNumber3","LoadStats","aborted","chunkCount","bwEstimate","first","parsing","buffering","ElementaryStreamTypes","BaseSegment","baseurl","_byteRange","_url","relurl","elementaryStreams","AUDIO","VIDEO","AUDIOVIDEO","setByteRange","byteRange","byteRangeEndOffset","byteRangeStartOffset","Fragment","_decryptdata","rawProgramDateTime","programDateTime","tagList","sn","levelkeys","loader","keyLoader","cc","startPTS","endPTS","startDTS","endDTS","deltaPTS","maxStartPTS","minEndPTS","stats","urlId","bitrateTest","initSegment","endList","gap","decryptdata","NONE","getDecryptData","keyFormats","endProgramDateTime","encrypted","_this$_decryptdata","setKeyFormat","keyFormat","abortRequests","_this$loader","abort","_this$keyLoader","setElementaryStreamInfo","partial","min","clearElementaryStreamInfo","Part","partAttrs","frag","fragOffset","independent","audio","video","audiovideo","LevelDetails","PTSKnown","alignedSliding","averagetargetduration","endCC","endSN","fragments","fragmentHint","partList","dateRanges","live","ageHeader","advancedDateTime","updated","advanced","availabilityDelay","misses","startCC","startSN","startTimeOffset","targetduration","totalduration","m3u8","version","canBlockReload","canSkipUntil","canSkipDateRanges","skippedSegments","recentlyRemovedDateranges","partHoldBack","holdBack","partTarget","preloadHint","renditionReports","tuneInGoal","deltaUpdateFailed","driftStartTime","driftEndTime","driftStart","driftEnd","encryptedFragments","playlistParsingError","variableList","hasVariableRefs","reloaded","partSnDiff","lastPartSn","partIndexDiff","lastPartIndex","hasProgramDateTime","levelTargetDuration","drift","runTime","edge","partEnd","fragmentEnd","_this$partList","_this$fragments","age","_this$partList2","_this$partList3","base64Decode","base64encodedStr","atob","charCodeAt","strToUtf8array","unescape","KeySystems","KeySystemFormats","keySystemFormatToKeySystemDomain","format","FAIRPLAY","PLAYREADY","WIDEVINE","CLEARKEY","KeySystemIds","keySystemDomainToKeySystemFormat","keySystem","getKeySystemsForConfig","drmSystems","widevineLicenseUrl","keySystemsToAttempt","requestMediaKeySystemAccess","self","bind","sliceUint8","isHeader","isFooter","getID3Data","front","readSize","subarray","canParse","isTimeStampFrame","getFrameData","getID3Frames","id3Data","frameData","decodeFrame","decodePrivFrame","decodeURLFrame","decodeTextFrame","owner","utf8ArrayToStr","privateData","buffer","readTimeStamp","timeStampFrame","byteLength","timestamp","exitOnNull","decoder","getTextDecoder","TextDecoder","decoded","decode","idx","char2","char3","out","Hex","h","UINT32_MAX","RemuxerTrackIdConfig","id3","bin2str","apply","readUint16","readUint32","readSint32","writeUint32","findBox","endbox","subresults","parseSegmentIndex","sidx","references","timescale","startByte","referencesCount","referenceIndex","referenceInfo","referenceSize","subsegmentDuration","earliestPresentationTime","parseInitSegment","traks","trak","tkhd","trackId","mdhd","hdlr","hdlrType","soun","vide","stsd","codec","trex","track","parseSinf","sinf","schm","computeRawDurationFromSamples","trun","sampleCount","appendUint8Array","data1","data2","temp","parseSamples","timeOffset","seiSamples","videoData","samples","isHEVCFlavor","moofs","moof","moofOffset","byteOffset","traf","baseTime","tfdt","tfhd","tfhdFlags","defaultSampleDuration","defaultSampleSizePresent","defaultSampleSize","defaultSampleFlagsPresent","tfhdOffset","isHEVC","delimit","baseCodec","dataOffsetPresent","dataOffset","firstSampleFlagsPresent","sampleDurationPresent","sampleDuration","sampleSizePresent","sampleSize","sampleFlagsPresent","sampleCompositionOffsetsPresent","compositionOffset","trunOffset","sampleOffset","ix","naluTotalSize","naluSize","isSEIMessage","parseSEIMessageFromNALu","naluHeader","naluType","unescapedData","headerSize","pts","discardEPB","seiPtr","payloadType","payloadSize","endOfCaptions","leftOver","providerCode","userStructure","userDataType","firstByte","totalBytes","byteArray","bytes","uuidStrArray","userDataBytes","uuid","userData","EPBPositions","newLength","newData","sourceIndex","shift","keyUriToKeyIdMap","LevelKey","method","uri","formatversions","iv","keyFormatVersions","isCommonEncryption","keyId","pssh","isSupported","createInitializationVector","segmentNumber","uint8View","keyBytes","convertDataUriToArrayBytes","colonsplit","keydata","semicolonsplit","commasplit","getKeyIdBytes","keyIdbytes","paddedkeyIdbytes","PlayReadyKeySystemUUID","mp4pssh","systemId","keyids","RangeError","kids","kidCount","DataView","setUint32","dataSize","mp4Box","payload","keyBytesUtf16","Uint16Array","keyByteStr","xmlKeyBytes","keyData","keyIdArray","changeEndianness","swap","to","cur","padded","VARIABLE_REPLACEMENT_REGEX","hasVariableReferences","substituteVariablesInAttributes","parsed","attributeNames","substituteVariables","variableReference","variableName","variableValue","addVariableDefinition","parentUrl","NAME","VALUE","QUERYPARAM","searchParams","URL","message","importVariableDefinition","sourceVariableList","IMPORT","getMediaSource","MediaSource","WebKitMediaSource","sampleEntryCodesISO","a3ds","alac","alaw","dra1","dtsc","dtse","dtsh","enca","g719","g726","m4ae","mha1","mha2","mhm1","mhm2","mlpa","mp4a","Opus","opus","samr","sawb","sawp","sevc","sqcp","ssmv","twos","ulaw","avc1","avc2","avc3","avc4","avcp","av01","drac","dva1","dvav","dvh1","dvhe","encv","hev1","hvc1","mjp2","mp4v","mvc1","mvc2","mvc3","mvc4","resv","rv60","s263","svc1","svc2","vp08","vp09","stpp","wvtt","isCodecSupportedInMp4","_MediaSource$isTypeSu","isTypeSupported","MASTER_PLAYLIST_REGEX","MASTER_PLAYLIST_MEDIA_REGEX","IS_MEDIA_PLAYLIST","LEVEL_PLAYLIST_REGEX_FAST","LEVEL_PLAYLIST_REGEX_SLOW","M3U8Parser","groups","mediaGroupId","avcdata","string","contentSteering","sessionData","sessionKeys","levelsWithKnownCodecs","bitrate","resolution","setCodecs","CODECS","videoCodec","convertAVC1ToAVCOTI","_level$unknownCodecs","unknownCodecs","attributes","sessionAttrs","dataId","sessionKey","parseKey","variableAttributes","contentSteeringAttributes","pathwayId","parseStartTimeOffset","groupsByType","audioCodec","SUBTITLES","textCodec","TYPE","groupId","instreamId","LANGUAGE","autoselect","forced","URI","groupCodec","findGroup","assignCodec","levelUrlId","multivariantVariableList","currentInitSegment","currentSN","currentPart","discontinuityCounter","prevFrag","firstPdtIndex","createNextFrag","setFragLevelKeys","assignProgramDateTime","value1","value2","skipAttrs","dateRange","levelKey","mapAttrs","setInitSegment","serverControlAttrs","partInfAttrs","previousFragmentPart","part","preloadHintAttrs","renditionReportAttrs","pop","fragmentLength","firstFragment","lastFragment","lastSn","backfillProgramDateTimes","fragPrev","keyTagAttributes","keyAttrs","decryptmethod","_keyAttrs$METHOD","METHOD","decrypturi","decryptiv","decryptkeyformatversions","KEYFORMATVERSIONS","decryptkeyformat","_keyAttrs$KEYFORMAT","KEYFORMAT","IV","resolvedUri","startAttributes","codecs","filtered","isCodecType","typeCodes","preferred","groupItem","codecProperty","codecValue","_isFiniteNumber4","BYTERANGE","PlaylistContextType","PlaylistLevelType","mapContextToLevelType","AUDIO_TRACK","SUBTITLE_TRACK","SUBTITLE","MAIN","getResponseUrl","PlaylistLoader","hls","loaders","registerListeners","startLoad","startPosition","stopLoad","destroyInternalLoaders","onManifestLoading","onLevelLoading","onAudioTrackLoading","onSubtitleTrackLoading","unregisterListeners","off","createInternalLoader","pLoader","getInternalLoader","resetInternalLoader","contextType","responseType","MANIFEST","deliveryDirectives","LEVEL","loadPolicy","loaderContext","manifestLoadPolicy","playlistLoadPolicy","timeoutRetry","errorRetry","_context$deliveryDire","levelDetails","audioTracks","subtitleTracks","targetDuration","maxLowLatencyPlaylistRefresh","maxTimeToFirstByteMs","maxLoadTimeMs","legacyRetryCompatibility","maxRetry","maxNumRetry","retryDelay","retryDelayMs","maxRetryDelay","maxRetryDelayMs","onSuccess","networkDetails","isMediaPlaylist","handleTrackOrLevelPlaylist","handleMasterPlaylist","handleManifestParsingError","onError","handleNetworkError","onTimeout","parsedResult","parseMasterPlaylist","subtitles","captions","parseMasterPlaylistMedia","audioTrack","levelId","levelType","parseLevelPlaylist","singleLevel","handlePlaylistLoaded","fatal","reason","code","errorData","_objectSpread2","levelIndex","getCacheAge","isNaN","sendAddTrackEvent","videoEl","Event","createEvent","initEvent","dispatchEvent","addCueToTrack","cue","cues","getCueById","addCue","textTrackCue","TextTrackCue","clearCurrentCues","removeCue","removeCuesInRange","predicate","getCuesInRange","cuesFound","firstCueInRange","getFirstCueIndexAfterTime","right","mid","MetadataSchema","emsg","getCueClass","WebKitDataCue","VTTCue","MAX_CUE_ENDTIME","Cue","POSITIVE_INFINITY","MAX_VALUE","dateRangeDateToTimelineSeconds","hexToArrayBuffer","ID3TrackController","id3Track","dateRangeCuesAppended","_registerListeners","_unregisterListeners","onMediaAttached","onMediaDetaching","onFragParsingMetadata","onBufferFlushing","onLevelUpdated","createTrack","getID3Track","textTracks","textTrack","kind","addTextTrack","enableEmsgMetadataCues","enableID3MetadataCues","ID3","updateId3CueEnds","_this$id3Track","audioId3","enableDateRangeMetadataCues","idsToRemove","dateTimeOffset","appendedDateRangeCues","durationKnown","nextDateRangeWithSameClass","filterMapArray","candidate","LatencyController","stallCount","_latency","timeupdateHandler","timeupdate","latency","maxLatency","liveMaxLatencyDuration","liveMaxLatencyDurationCount","targetLatency","liveSyncDuration","liveSyncDurationCount","lowLatencyMode","userConfig","liveSyncPosition","liveEdge","estimateLiveEdge","edgeStalled","forwardBufferLength","bufferedRanges","buffered","removeEventListener","_this$levelDetails","computeLatency","maxLiveSyncPlaybackRate","distanceFromTarget","liveMinLatencyDuration","rate","playbackRate","HdcpLevels","HlsSkip","No","Yes","v2","HlsUrlParameters","msn","skip","addDirectives","Level","_attrs","codecSet","audioGroupIds","fragmentError","loadError","realBitrate","textGroupIds","_urlId","maxBitrate","newValue","audioGroupId","_this$audioGroupIds","textGroupId","_this$textGroupIds","addFallback","updateFromToPTS","fragFrom","fragTo","fragToPTS","updateFragPTSDTS","fragStartPts","fragEndPts","fragIdx","adjustSliding","oldDetails","newDetails","delta","oldFragments","addSliding","getPartWith","partIndex","findPart","_level$details","isTimeoutError","getRetryConfig","isTimeout","getRetryDelay","retryConfig","retryCount","backoffFactor","backoff","getLoaderConfigWithoutReties","loderConfig","shouldRetry","httpStatus","retryForHttpStatus","onLine","BinarySearch","comparisonFn","minIndex","maxIndex","currentIndex","currentElement","comparisonResult","findFragmentByPTS","fragPrevious","bufferEnd","maxFragLookUpTolerance","fragNext","fragmentWithinToleranceTest","foundFragment","candidateLookupTolerance","pdtWithinToleranceTest","pdtBufferEnd","RENDITION_PENALTY_DURATION_MS","checkExpired","penalizedRendition","currentPenaltyState","lastErrorPerfMs","lastErrorDetails","candidateFrag","lastCandidateError","BasePlaylistController","logPrefix","requestScheduled","canLoad","clearTimer","loadPlaylist","switchParams","playlistUri","foundIndex","currentGoal","hlsUrlParameters","shouldLoadPlaylist","playlist","shouldReloadPlaylist","playlistLoaded","previousDetails","elapsed","mergeDetails","oldInit","PTSFrag","ccOffset","mapFragmentIntersection","intersectionFn","newFrags","oldFrags","oldFrag","newFrag","_isFiniteNumber5","_currentInitSegment","mergeDateRanges","oldDateRanges","deltaDateRanges","stringify","newFragments","mapPartIntersection","oldParts","newParts","oldPart","newPart","endSn","lastPart","lastAdvanced","segments","getDeliveryDirectives","bufferInfo","mainForwardBufferInfo","reloadInterval","computeReloadInterval","distanceToLiveEdgeMs","lastSegmentDuration","estimatedTimeUntilUpdate","previousDeliveryDirectives","getSkipValue","checkRetry","errorEvent","errorDetails","errorAction","RetryRequest","resolved","SendAlternateToPenaltyBox","_errorEvent$context","levelRetry","chromeOrFirefox","LevelController","contentSteeringController","_levels","_firstLevel","_startLevel","currentLevel","currentLevelIndex","manualLevelIndex","steering","onParsedComplete","onManifestLoaded","onLevelLoaded","onLevelsUpdated","onAudioTrackSwitched","onFragLoaded","resetLevels","levelSet","levelFromSet","levelParsed","_levelParsed$audioCod","FRAMERATE","PATHWAY","RESOLUTION","contentSteeringPrefix","addGroupId","filterAndSortMediaOptions","unfilteredLevels","resolutionFound","videoCodecFound","audioCodecFound","assignTrackIdsByGroup","unsortedLevels","SCORE","firstLevelInPlaylist","filterParsedLevels","edata","firstLevel","altAudio","autoStartLoad","forceStartLoad","newLevel","lastLevelIndex","lastLevel","lastPathwayId","levelSwitchingData","manualLevel","startLevel","configStartLevel","curLevel","_data$deliveryDirecti","_data$deliveryDirecti2","nextLoadLevel","nextAutoLevel","nextLevel","removeLevel","filterLevelAndGroupByIdIndex","tracks","FragmentTracker","activePartLists","endListFragments","timeRanges","bufferPadding","hasGaps","onBufferAppended","onFragBuffered","getAppendedFrag","position","activeParts","activePart","appendedPTS","getBufferedFrag","fragmentEntity","detectEvictedFragments","elementaryStream","timeRange","playlistType","appendedPart","appendedPartSn","removeFragment","esData","isNotBuffered","isTimeBuffered","detectPartialFragments","fragKey","getFragmentKey","isFragHint","streamInfo","getBufferedTimes","isPartial","removeParts","snToKeep","fragBuffered","force","getPartialFragment","timePadding","bestFragment","bestOverlap","isEndListAppended","lastFragmentEntity","getState","PARTIAL","hasFragment","hasParts","_this$activePartLists","removeFragmentsInRange","withGapOnly","unbufferedOnly","snToRemove","removeAllFragments","_fragmentEntity$range","_fragmentEntity$range2","_fragmentEntity$range3","MIN_CHUNK_SIZE","FragmentLoader","partLoadTimeout","onProgress","LoadError","FragmentILoader","fLoader","DefaultILoader","createGapLoadError","createLoaderContext","fragLoadPolicy","loaderConfig","highWaterMark","resetLoader","resetIV","onAbort","loadPart","updateStatsFromPart","partLoadedData","fragStats","partStats","partTotal","estTotalParts","estLoadedParts","estRemainingBytes","fragLoading","partLoading","segment","headers","rangeStart","rangeEnd","byteRangeStart","byteRangeEnd","_frag$decryptdata","fragmentLen","KeyLoader","keyUriToKeyInfo","emeController","keyInfo","mediaKeySessionContext","createKeyLoadError","loadClear","loadingFrag","emeEnabled","selectKeySystemFormat","keySystemFormat","loadInternal","_keyInfo","_keyInfo2","keyLoadPromise","_keyInfo$mediaKeySess","keyStatus","keyLoadedData","loadKeyHTTP","loadKeyEME","keySessionContextPromise","loadKey","keySessionContext","Loader","keyLoadPolicy","TaskLoop","_boundTick","_tickTimer","_tickInterval","_tickCallCount","tick","onHandlerDestroying","onHandlerDestroyed","clearNextTick","hasInterval","hasNextTick","millis","doTick","tickImmediate","noopBuffered","BufferHelper","getBuffered","maxHoleDuration","vbuffered","bufferedInfo","nextStart","buffered2","buf2len","buf2end","bufferStartNext","bufferLen","bufferStart","ChunkMetadata","transmuxing","executeStart","executeEnd","findFirstFragWithCC","firstFrag","currentFrag","adjustFragmentStart","sliding","adjustSlidingStart","alignMediaPlaylistByPDT","refDetails","refFragments","refFrag","refPDT","targetPDT","AESCrypto","subtle","aesIV","decrypt","FastAESKey","expandKey","importKey","AESDecryptor","rcon","subMix","Uint32Array","invSubMix","sBox","invSBox","ksRows","keySize","keySchedule","invKeySchedule","initTable","uint8ArrayToUint32Array_","arrayBuffer","view","newArray","getUint32","subMix0","subMix1","subMix2","subMix3","invSubMix0","invSubMix1","invSubMix2","invSubMix3","xi","sx","x2","x4","x8","keyBuffer","sameKey","ksRow","invKsRow","sbox","prev","networkToHostOrderSwap","inputArrayBuffer","nRounds","invSBOX","initVector","initVector0","initVector1","initVector2","initVector3","inputInt32","Int32Array","outputInt32","t0","t1","t2","t3","s0","s1","s2","s3","inputWords0","inputWords1","inputWords2","inputWords3","swapWord","Decrypter","removePKCS7Padding","logEnabled","softwareDecrypter","fastAesKey","remainderData","currentIV","currentResult","useSoftware","enableSoftwareAES","browserCrypto","crypto","webkitSubtle","isSync","removePadding","outputBytes","paddingBytes","getUint8","softwareDecrypt","decryptResult","webCryptoDecrypt","logOnce","currentChunk","getValidChunk","aesKey","onWebCryptoError","splitPoint","msg","BaseStreamController","fragmentTracker","fragCurrent","transmuxer","mediaBuffer","lastCurrentTime","nextLoadPosition","loadedmetadata","retryDate","fragmentLoader","levelLastLoaded","startFragRequested","decrypter","initPTS","onvseeking","onvended","onTickEnd","resetTransmuxer","_streamEnded","isBuffered","getLevelDetails","_this$levels$this$lev","onMediaSeeking","onMediaEnded","ended","maxBufferHole","resetLoadingState","tolerance","fragStartOffset","fragEndOffset","pastFragment","loadFragment","targetBufferTime","_loadFragForPlayback","_doFragLoad","fragContextChanged","_handleFragmentLoadProgress","_handleFragmentLoadComplete","resetFragmentLoading","clearTrackerIfNeeded","APPENDING","getFwdBufferInfo","minForwardBufferLength","maxBufferLength","reduceMaxBufferLength","_this$mediaBuffer","flushMainBuffer","_loadInitSegment","decryptData","decryptedData","tstart","tdecrypt","fragBufferedComplete","_frag$startPTS","NaN","_frag$endPTS","TimeRanges","_this$fragCurrent","_this$fragPrevious","seekToStartPos","fragLoadedEndData","partsLoaded","fragLoaded","chunkMeta","progressCallback","keyLoadingPromise","getNextPart","doFragPartsLoad","handleFragLoadError","loadedEndOfParts","dataOnProgress","progressive","fragLoadedData","fromPart","initialPartList","loadedPart","nextPart","handleFragLoadAborted","_handleTransmuxerFlush","getCurrentContext","updateLevelTiming","getFragmentWithSN","bufferFragmentData","_buffer","dropped","flushBufferGap","segmentFraction","bufferable","getLoadPosition","getFwdBufferInfoAtPos","bufferedFragAtPos","getMaxBufferLength","levelBitrate","maxBufLen","maxBufferSize","maxMaxBufferLength","threshold","fragOrPart","getNextFragment","fragLen","initialLiveManifestSize","getInitialLiveFragment","getFragmentAtPosition","mapToInitFragWhenRequired","isLoopLoading","trackerState","OK","getNextFragmentLoopLoading","gapStart","nextFragment","nextbufferInfo","contiguous","independentAttrOmitted","findFragmentByPDT","PDTValue","seg","targetSN","findFragWithCC","liveStart","loadingParts","curSNIdx","fragState","nextFrag","synchronizeToLiveEdge","withinSlidingWindow","readyState","alignPlaylists","slidingStart","firstLevelLoad","aligned","alignStream","lastFrag","alignDiscontinuities","shouldAlignOnDiscontinuities","referenceFrag","findDiscontinuousReferenceFrag","prevDetails","curDetails","prevFrags","curFrags","prevStartFrag","alignPDT","lastDetails","lastPDT","newPDT","alignedSlidingStart","waitForCdnTuneIn","advancePartLimit","setStartPosition","offsetInMultivariantPlaylist","onFragmentOrKeyLoadError","filterType","_this$fragCurrent2","gapTagEncountered","FRAG_LOADING_WAITING_RETRY","resetFragmentErrors","reduceLengthAndFlushBuffer","flushBuffer","afterBufferFlushed","bufferType","bufferedTimeRanges","resetStartWhenNotLoaded","resetWhenMissingContext","removeUnbufferedFrags","parsedDuration","_this$transmuxer","recoverWorkerError","previousState","getSourceBuffer","SourceBuffer","WebKitSourceBuffer","dummyTrack","inputTimeScale","pid","sequenceNumber","BaseAudioDemuxer","_audioTrack","_id3Track","frameIndex","cachedData","basePTS","lastPTS","resetInitSegment","trackDuration","resetTimeStamp","deaultTimestamp","resetContiguity","appendFrame","demux","lastDataIndex","initPTSFn","dts","sample","partialData","videoTrack","demuxSampleAes","isHeaderPattern","getHeaderLength","getFullFrameLength","probe","headerLength","frameLength","newOffset","initTrackConfig","observer","samplerate","getAudioConfig","adtsObjectType","adtsExtensionSamplingIndex","adtsChannelConfig","manifestCodec","adtsSamplingRates","adtsSamplingIndex","channelCount","getFrameDuration","stamp","parseFrameHeader","missing","emsgSchemePattern","chromeVersion","BitratesMap","SamplingRateMap","SamplesCoefficients","BytesInSlot","parseHeader","samplesPerFrame","sampleRate","mpegVersion","mpegLayer","bitRateIndex","sampleRateIndex","channelMode","bitRate","sampleCoefficient","bytesInSlot","ExpGolomb","bytesAvailable","bitsAvailable","loadWord","workingBytes","availableBytes","skipBits","skipBytes","readBits","bits","valu","skipLZ","leadingZeroCount","skipUEG","skipEG","readUEG","clz","readEG","readBoolean","readUByte","readUShort","readUInt","skipScalingList","deltaScale","lastScale","nextScale","readSPS","numRefFramesInPicOrderCntCycle","scalingListCount","frameCropLeftOffset","frameCropRightOffset","frameCropTopOffset","frameCropBottomOffset","profileIdc","chromaFormatIdc","picOrderCntType","picWidthInMbsMinus1","picHeightInMapUnitsMinus1","frameMbsOnlyFlag","pixelRatio","ceil","readSliceType","SampleAesDecrypter","decryptBuffer","encryptedData","decryptAacSample","sampleIndex","curUnit","encryptedBuffer","decryptedBuffer","decryptAacSamples","getAvcEncryptedData","decodedData","encryptedDataLen","Int8Array","outputPos","inputPos","getAvcDecryptedUnit","uint8DecryptedData","decryptAvcSample","unitIndex","decryptAvcSamples","curUnits","units","PACKET_LENGTH","TSDemuxer","typeSupported","sampleAes","pmtParsed","_pmtId","_avcTrack","_txtTrack","aacOverFlow","avcSample","syncOffset","scanwindow","foundPat","packetStart","tsPackets","parsePID","segmentCodec","pesData","isSampleAes","pes","avcId","avcData","audioId","id3Id","audioData","unknownPID","pmtId","tsPacketErrors","stt","parsePES","parseAVCPES","parseAACPES","parseMPEGPES","parseID3PES","parsePAT","parsedPIDs","parsePMT","avc","demuxResult","extractRemainingSamples","last","parseAVCNALu","spsfound","audFound","pushAccessUnit","createAVCSample","sliceType","sps","codecarray","codecstring","pps","getLastNalUnit","lastUnit","_avcSample","naluState","lastState","unitType","lastUnitStart","lastUnitType","tmp","frameMissingBytes","sampleLength","frameOverflowBytes","ADTS","recoverable","frameDuration","MpegAudio","id3Sample","tableEnd","mpeg","mp3","stream","pesLen","pesHdrLen","pesPts","pesDts","pesFlags","payloadStartOffset","dataLen","avcTrack","nbSamples","lastSample","AAC","MP4","avcC","btrt","dinf","dref","esds","ftyp","mdat","mdia","mfhd","minf","moov","mvex","mvhd","pasp","sdtp","stbl","stco","stsc","stsz","stts","vmhd","smhd","videoHdlr","audioHdlr","HDLR_TYPES","STTS","STSC","STCO","STSZ","VMHD","SMHD","STSD","majorBrand","avc1Brand","minorVersion","FTYP","box","DINF","upperWordDuration","lowerWordDuration","baseMediaDecodeTime","boxes","dependsOn","isDependedOn","hasRedundancy","avcc","hSpacing","vSpacing","configlen","sampleDependencyTable","upperWordBaseMediaDecodeTime","lowerWordBaseMediaDecodeTime","arraylen","cts","isLeading","paddingValue","isNonSync","degradPrio","movie","MPEG_TS_CLOCK_FREQ_HZ","toTimescaleFromBase","destScale","srcBase","toMsFromMpegTsClock","safariWebkitVersion","MP4Remuxer","vendor","ISGenerated","_initPTS","_initDTS","nextAvcDts","nextAudioPts","videoSampleDuration","isAudioContiguous","isVideoContiguous","defaultTimeStamp","resetNextTimestamp","getVideoStartPts","videoSamples","rolloverDetected","minPTS","normalizePts","remux","accurateTimeOffset","audioTimeOffset","videoTimeOffset","hasVideo","enoughAudioSamples","enoughVideoSamples","generateIS","firstKeyFramePTS","firstKeyFrameIndex","findKeyframeIndex","forceKeyFrameOnDiscontinuity","audiovideoTimestampDelta","remuxAudio","audioTrackLength","remuxVideo","firstKeyFrame","flushTextTrackMetadataCueSamples","flushTextTrackUserdataCueSamples","audioSamples","initDTS","computePTSDTS","timeScale","inputSamples","outputSamples","firstDTS","lastDTS","mp4SampleDuration","maxPTS","NEGATIVE_INFINITY","sortSamples","initTime","inputDuration","averageSampleDuration","foundHole","foundOverlap","firstPTS","nbNalu","naluLen","nbUnits","sampleLen","mdatSize","stretchedLastFrame","minDtsDelta","minPtsDelta","maxDtsDelta","maxPtsDelta","avcSampleUnits","ptsDelta","mp4SampleLength","unitData","unitDataLen","lastFrameDuration","stretchShortVideoTrack","gapTolerance","deltaToFrameEnd","compositionTimeOffset","Mp4Sample","nextDts","hasAudio","nb","scaleFactor","inputSampleDuration","rawMPEG","alignedWithVideo","timeOffsetMpegTS","maxAudioFramesDrift","nextPts","newStamp","fillFrame","getSilentFrame","audioSample","unitLen","remuxEmptyAudio","init90kHz","silentFrame","reference","isKeyframe","Mp4SampleFlags","getParsedTrackCodec","parsedCodec","muxConfig","MP4Demuxer","txtTrack","captionTrack","initData","segmentedData","segmentValidRange","segmentedRange","valid","remainder","extractID3Track","emsgs","emsgInfo","parseEmsg","schemeIdUri","presentationTimeDelta","presentationTime","eventDuration","leftPresentationTime","rightPresentationTime","isSafeInteger","PassThroughRemuxer","emitInitSegment","initTracks","lastEndTime","defaultInitPTS","generateInitSegment","patchEncyptionData","sampleEntries","encBoxes","isAudio","enc","tenc","tencKeyId","_initData","_initData2","getDuration","rawDuration","videoDuration","audioDuration","trafs","trackDefault","truns","sidxDuration","sidxs","dur","ref","getStartDTS","fmp4","decodeTime","isInvalidInitPts","minDuration","offsetStartDTS","upper","lower","AACDemuxer","canGetFrameLength","MP3Demuxer","Transmuxer","async","demuxer","remuxer","decryptionPromise","transmuxConfig","currentTransmuxState","configure","uintData","discontinuity","trackSwitch","initSegmentChange","defaultInitPts","initSegmentData","getEncryptionType","encryptionType","getDecrypter","emptyResult","resetMuxers","needsProbing","configureTransmuxer","resetInitialTimestamp","transmux","transmuxResults","demuxResultOrPromise","isPromise","flushRemux","remuxResult","transmuxSampleAes","transmuxUnencrypted","mux","Remuxer","Demuxer","Function","TransmuxConfig","TransmuxState","EE","once","addListener","emitter","TypeError","evt","_events","_eventsCount","clearEvent","__proto__","eventNames","names","getOwnPropertySymbols","handlers","ee","listenerCount","a1","a2","a3","a4","a5","arguments","removeListener","removeAllListeners","prefixed","TransmuxerInterface","onTransmuxComplete","onFlush","useWorker","workerContext","onwmsg","enableWorker","forwardMessage","ev","mp4","Worker","workerPath","hasUMDWorker","__HLS_WORKER_BUNDLE__","loadWorker","scriptURL","worker","injectWorker","blob","Blob","objectURL","createObjectURL","onWorkerMessage","filename","lineno","postMessage","cmd","resetWorker","revokeObjectURL","terminate","snDiff","partDiff","_frag$initSegment","_lastFrag$initSegment","ArrayBuffer","transmuxResult","handleTransmuxComplete","transmuxerError","handleFlushResult","_this$workerContext","logType","GapController","nudgeRetry","stallReported","stalled","moved","seeking","poll","activeFrag","seeked","beginSeek","stalledDuration","paused","hasEnoughBuffer","noBufferGap","startJump","maxStartGapJump","partialOrGap","_trySkipBufferHole","tnow","_reportStall","bufferedWithHoles","_tryFixBufferStall","stalledDurationMs","highBufferWatchdogPeriod","_tryNudgeBuffer","gapLength","startGap","startFrag","startProvisioned","moreToLoad","provisioned","targetTime","nudgeMaxRetry","nudgeOffset","StreamController","audioCodecSwap","gapController","_forceStartLoad","audioOnly","fragPlaying","onvplaying","onvseeked","fragLastKbps","couldBacktrack","backtrackFragment","audioCodecSwitch","videoBuffer","onManifestParsed","onFragLoadEmergencyAborted","onAudioTrackSwitching","onBufferCreated","onBufferFlushed","testBandwidth","_levels$level","_this$media","doTickIdle","checkBuffer","checkFragmentChanged","startFragPrefetch","levelInfo","getMainFwdBufferInfo","loadLevel","_this$backtrackFragme","backtrackFrag","NOT_LOADED","_loadBitrateTestFrag","followingBufferedFrag","immediateLevelSwitch","abortCurrentFrag","nextLevelSwitch","fetchdelay","fragPlayingCurrent","bufferedFrag","nextBufferedFrag","fragDuration","startPts","onMediaPlaying","onMediaSeeked","aac","heaac","changeTypeSupported","sourceBuffer","_sourceBuffer$prototy","changeType","newLevelId","_curLevel$details","IDLE","_getAudioCodec","_handleTransmuxComplete","fromAltAudio","mediaTrack","alternate","_data$context","swapAudioCodec","defaultAudioCodec","mapFragment","_bufferInitSegment","backtrack","_id3$samples","ua","levelCodec","trackName","fragCurrentLevel","currentProgramDateTime","EWMA","halfLife","estimate","weight","alpha_","estimate_","totalWeight_","adjAlpha","getTotalWeight","getEstimate","zeroFactor","EwmaBandWidthEstimator","slow","fast","defaultEstimate","defaultTTFB","defaultEstimate_","minWeight_","minDelayMs_","slow_","fast_","defaultTTFB_","ttfb_","update","durationMs","numBytes","durationS","bandwidthInBps","sampleTTFB","ttfb","sqrt","canEstimate","getEstimateTTFB","ChunkCache","chunks","dataLength","chunk","concatUint8Arrays","subtitleOptionsIdentical","trackList1","trackList2","subtitleAttributesIdentical","attrs1","attrs2","stableRenditionId","subtitleAttribute","BufferableInstance","timeranges","getRange","DOMException","filterSubtitleTracks","textTrackList","BufferOperationQueue","sourceBufferReference","buffers","queues","operation","queue","executeNext","insertAbort","appendBlocker","execute","onComplete","sb","updating","shiftAndExecuteNext","VIDEO_CODEC_PROFILE_REPACE","specialCea608CharsCodes","getCharForByte","byte","charCode","NR_COLS","rowsLowCh1","rowsHighCh1","rowsLowCh2","rowsHighCh2","backgroundColors","CaptionsLogger","verboseLevel","severity","numArrayToHexArray","numArray","hexArray","PenState","foreground","underline","italics","background","flash","attribs","isDefault","equals","other","copy","newPenState","StyledUnicodeChar","uchar","penState","setChar","setPenState","newChar","Row","chars","currPenState","cueStartTime","equal","setCursor","absPos","moveCursor","relPos","newPos","backSpace","insertChar","clearFromPos","startPos","clearToEndOfRow","getTextString","setPenStyles","CaptionScreen","currRow","nrRollUpRows","lastOutputScreen","NR_ROWS","setPen","setPAC","pacData","newRow","topRowIndex","prevLineTime","indent","prevPos","setBkgData","bkgData","setRollUpRows","nrRows","rollUp","getDisplayText","topRow","asOneRow","displayText","rowNr","rowText","getTextAndFormat","Cea608Channel","channelNumber","outputFilter","chNr","verbose","displayedMemory","nonDisplayedMemory","currRollUpRow","writeScreen","getHandler","setHandler","newHandler","setMode","newMode","insertChars","outputDataUpdate","ccRCL","ccBS","ccAOF","ccAON","ccDER","ccRU","ccFON","ccRDC","ccTR","ccRTD","ccEDM","ccCR","ccENM","ccEOC","ccTO","nrCols","ccMIDROW","secondByte","colorIndex","newCue","dispatchCue","cueSplitAtTime","Cea608Parser","field","out1","out2","channels","currentChannel","cmdHistory","channel","addData","byteList","cmdFound","charsFound","parseCmd","parseMidrow","parsePAC","parseBackgroundAttributes","parseChars","currChNr","hasCmdRepeated","setLastCmd","interpretPAC","pacIndex","channelNr","charCodes","charCode1","oneCode","hexCodes","OutputFilter","timelineController","cueRanges","addCues","createCaptionsTrack","AllowedDirections","AllowedAlignments","isAllowedValue","allowed","lcValue","findAlignSetting","extend","rest","cobj","baseObj","enumerable","hasBeenReset","_pauseOnExit","_startTime","_endTime","_text","_region","_vertical","_snapToLines","_line","_lineAlign","_position","_positionAlign","_size","_align","defineProperty","findDirectionSetting","SyntaxError","displayState","getCueAsHTML","WebVTT","convertCueToDOMTree","StringDecoder","parseTimeStamp","computeSeconds","Settings","dflt","defaultKey","alt","integer","parseOptions","keyValueDelim","groupDelim","kv","center","parseCue","regionList","oInput","consumeTimeStamp","ts","skipWhitespace","consumeCueSettings","vals","region","vertical","line","lineAlign","snapToLines","fixLineBreaks","VTTParser","oncue","onparsingerror","onflush","collectNextLine","alreadyCollectedLine","hasSubstring","LINEBREAKS","inputString","searchString","cueString2millis","timeString","secs","mins","hash","generateCueId","calculateOffset","vttCCs","currCC","prevCC","new","presentationOffset","_prevCC","IMSC1_CODEC","HMSF_REGEX","TIME_UNIT_REGEX","textAlignToLineAlign","parseIMSC1","callBack","errorCallBack","ttmlList","syncTime","toTimescaleFromScale","srcScale","ttml","parseTTML","tt","defaultRateInfo","frameRate","subFrameRate","frameRateMultiplier","tickRate","rateInfo","styleElements","collectionToDictionary","getElementCollection","regionElements","cueElements","cueElement","cueText","getTextContent","hasAttribute","parseTtmlTime","timestampParsingError","getTtmlStyles","ttsNs","regionStyle","regionStyleName","getAttributeNS","fromElement","parentName","childName","elementsWithId","dict","_node$childNodes","hasAttributeNS","timeAttributeValue","parseHoursMinutesSecondsFrames","parseTimeUnits","canReuseVttTextTrack","inUseTrack","manifestTrack","textTrack1","textTrack2","intersection","x1","y1","y2","CapLevelController","autoLevelCapping","restrictedLevels","clientRect","streamController","setStreamController","unregisterListener","capLevelToPlayerSize","stopCapping","onFpsDropLevelCapping","onMediaAttaching","onBufferCodecs","droppedLevel","isLevelAllowed","HTMLVideoElement","startCapping","detectPlayerSize","mediaHeight","mediaWidth","getMaxLevel","capLevelIndex","validLevels","getMaxLevelByMediaSize","getDimensions","boundsRect","bottom","contentScaleFactor","ignoreDevicePixelRatio","devicePixelRatio","restrictedLevel","atGreatestBandwidth","maxLevelIndex","LOGGER_PREFIX","EMEController","keyFormatPromise","keySystemAccessPromises","_requestLicenseFailureCount","mediaKeySessions","keyIdToKeySessionPromise","setMediaKeysQueue","CDMCleanupPromise","onMediaEncrypted","_onMediaEncrypted","onWaitingForKey","_onWaitingForKey","onMediaDetached","requestMediaKeySystemAccessFunc","licenseXhrSetup","licenseResponseCallback","drmSystemOptions","getLicenseServerUrl","keySystemConfiguration","licenseUrl","getServerCertificateUrl","serverCertificateUrl","attemptKeySystemAccess","uniqueCodec","audioCodecs","videoCodecs","attempt","keySystems","getMediaKeysPromise","mediaKeys","EMEKeyError","supportedConfigurations","errMessage","mediaKeySystemConfigs","getSupportedMediaKeySystemConfigurations","initDataTypes","createMediaKeySystemConfigurations","persistentState","distinctiveIdentifier","sessionTypes","sessionType","audioCapabilities","robustness","audioRobustness","encryptionScheme","audioEncryptionScheme","videoCapabilities","videoRobustness","videoEncryptionScheme","keySystemAccess","mediaKeySystemAccess","certificateRequest","fetchServerCertificate","createMediaKeys","certificate","setMediaKeysServerCertificate","createMediaKeySessionContext","mediaKeysSession","createSession","renewKeySession","getKeyIdString","generateRequestWithPreferredKeySession","removeSession","updateKeySession","keySession","sessionId","_mediaKeySessionConte","getKeyFormatPromise","keySystemsInConfig","getKeySystemSelectionPromise","keySystemToKeySystemFormat","keyDetails","getKeySystemForKeyPromise","throwIfDestroyed","attemptSetMediaKeys","handleError","initDataType","keySystemDomain","json","psshInfo","parsePssh","boxSize","dataSizeOrKidCount","keySystemIdToKeySystemDomain","keyIdHex","keyContext","oldKeyIdHex","_keySystemToKeySystem","setMediaKeysPromise","setMediaKeys","generateRequestFilter","_this$config$drmSyste","_this$config$drmSyste2","generateRequest","mappedInitData","_this$hls","licenseStatus","onmessage","messageType","renewLicense","onkeystatuseschange","onKeyStatusChange","keyUsablePromise","_context$mediaKeysSes","keyStatuses","certLoader","certLoadPolicy","contex","cert","setServerCertificate","keyMessage","requestLicense","setupLicenseXHR","xhr","keysListItem","licenseChallenge","licenseXhrSetupResult","XMLHttpRequest","onreadystatechange","statusText","attemptsLeft","licenseXhr","DONE","send","mediaKeysList","clearKeyUriToKeyIdMap","keySessionCount","formats","CMCDController","sid","cid","useHeaders","initialized","starved","audioBuffer","onWaiting","onPlaying","applyPlaylistData","ot","su","applyFragmentData","getObjectType","MUXED","br","tb","getTopBandwidth","bl","getBufferLength","cmcd","createPlaylistLoader","createFragmentLoader","_data$tracks$audio","_data$tracks$video","createData","sf","pr","mtp","bandwidthEstimate","INIT","bs","toHeaders","toQuery","appendQueryToUri","TIMED_TEXT","maxAutoLevel","Ctor","toRounded","toHundred","formatters","dl","nor","rtp","formatter","headerNames","headerGroups","headerMap","nrr","st","serialize","cloneRenditionGroups","groupCloneMap","uriReplacement","cloneId","clonedTracks","clonedTrack","performUriReplacement","stableId","perOptionKey","HOST","PARAMS","perOptionUris","perVariantUri","AGE_HEADER_LINE_REGEX","XhrLoader","xhrSetup","requestTimeout","retryTimeout","abortInternal","onprogress","_this$callbacks","openAndSendXhr","setRequestHeader","readystatechange","loadprogress","loadtimeout","useResponse","responseText","responseURL","_this$config","lengthComputable","getAllResponseHeaders","getResponseHeader","FetchLoader","fetchSetup","request","controller","getRequest","AbortController","ok","initParams","getRequestParameters","signal","credentials","Headers","isArrayBuffer","LENGTH","FetchError","getContentLength","contentRange","byteRangeLength","getByteRangeLength","byteRangeHeader","contentLength","loadProgressively","responseData","loaderResponse","chunkCache","reader","getReader","pump","read","Request","WHITESPACE_CHAR","Cues","captionScreen","indenting","_track$cues","cueA","cueB","hlsDefaultConfig","capLevelOnFPSDrop","backBufferLength","liveDurationInfinity","liveBackBufferLength","fpsDroppedMonitoringPeriod","fpsDroppedMonitoringThreshold","appendErrorMaxRetry","abrController","AbrController","lastLevelLoadSec","lastLoadedFragLevel","_nextAutoLevel","onCheck","_abandonRulesCheck","partCurrent","bitrateTestDelay","bwEstimator","abrEwmaSlowVoD","abrEwmaFastVoD","abrEwmaDefaultEstimate","onFragLoading","onLevelSwitching","ignoreFragment","_data$part","getTimeToLoadFrag","timeToFirstByteSec","bandwidth","fragSizeBits","isSwitch","abrEwmaSlowLive","abrEwmaFastLive","autoLevelEnabled","timeLoading","ttfbEstimate","bufferStarvationDelay","loadedFirstByte","minAutoLevel","expectedLen","timeStreaming","loadRate","fragLoadedDelay","bwe","fragLevelNextLoadedDelay","abrMaxWithRealBitrate","loadedBytes","loadedDuration","processingMs","forcedAutoLevel","nextABRAutoLevel","getNextABRAutoLevel","currentFragDuration","avgbw","bestLevel","findBestLevel","abrBandWidthFactor","abrBandWidthUpFactor","maxStarvationDelay","bwFactor","bwUpFactor","maxLoadingDelay","currentBw","maxFetchDuration","currentCodecSet","ttfbEstimateSec","levelSkippedMin","levelSkippedMax","avgDuration","adjustedbw","fetchDuration","bufferController","BufferController","_objectUrl","operationQueue","bufferCodecEventsExpected","_bufferCodecEventsTotal","mediaSource","lastMpegAudioChunk","appendError","pendingTracks","_onMediaSourceOpen","_onMediaEmptied","updateMediaElementDuration","checkPendingTracks","_onMediaSourceClose","_onMediaSourceEnded","_initSourceBuffer","hasSourceTypes","getSourceBufferTypes","onBufferReset","onBufferAppending","onBufferEos","onFragParsed","onFragChanged","codecEvents","ms","endOfStream","removeBufferListeners","removeSourceBuffer","sourceBufferCount","currentCodec","nextCodec","appendChangeType","mimeType","eventData","chunkStats","bufferAppendingStart","fragBuffering","partBuffering","checkTimestampOffset","fragStart","timestampOffset","appendExecutor","QUOTA_EXCEEDED_ERR","flushOperation","removeExecutor","buffersAppendedTo","blockBuffers","onUnblocked","flushBackBuffer","acc","ending","sourceBufferTypes","maxBackBufferLength","targetBackBufferPosition","levelDuration","mediaDuration","msDuration","updateSeekableRange","setLiveSeekableRange","pendingTracksCount","createSourceBuffers","addSourceBuffer","sbName","addBufferListener","_onSBUpdateStart","_onSBUpdateEnd","_onSBUpdateError","removeStart","removeEnd","appendBuffer","blockingOperations","capLevelController","errorController","ErrorController","playlistError","penalizedRenditions","onErrorOut","getVariantLevelIndex","getFragRetryOrSwitchAction","_data$context$levelDe","getPlaylistRetryOrSwitchAction","getLevelSwitchAction","MoveAllAlternatesMatchingHost","restrictedHdcpLevel","MoveAllAlternatesMatchingHDCP","hdcpLevel","_data$level","DoNothing","None","_data$response","variantLevelIndex","fragmentErrors","_data$response2","fragErrorType","_data$frag","playlistErrorType","playlistErrorGroupId","_data$context2","levelCandidate","fragCandidate","_data$errorAction","sendAlternateToPenaltyBox","switchLevel","redundantFailover","maxHdcpLevel","redundantLevels","errorUrlId","penalizeRendition","newUrlId","lv","fpsController","FPSController","isVideoPlaybackQualityAvailable","lastTime","lastDroppedFrames","lastDecodedFrames","getVideoPlaybackQuality","checkFPSInterval","checkFPS","decodedFrames","droppedFrames","currentDropped","currentDecoded","droppedFPS","totalDroppedFrames","videoPlaybackQuality","totalVideoFrames","droppedVideoFrames","webkitDecodedFrameCount","webkitDroppedFrameCount","minAutoBitrate","steeringManifestLoadPolicy","manifestLoadingTimeOut","manifestLoadingMaxRetry","manifestLoadingRetryDelay","manifestLoadingMaxRetryTimeout","levelLoadingTimeOut","levelLoadingMaxRetry","levelLoadingRetryDelay","levelLoadingMaxRetryTimeout","fragLoadingTimeOut","fragLoadingMaxRetry","fragLoadingRetryDelay","fragLoadingMaxRetryTimeout","timelineConfig","cueHandler","enableWebVTT","enableIMSC1","enableCEA708Captions","captionsTextTrack1Label","captionsTextTrack1LanguageCode","captionsTextTrack2Label","captionsTextTrack2LanguageCode","captionsTextTrack3Label","captionsTextTrack3LanguageCode","captionsTextTrack4Label","captionsTextTrack4LanguageCode","renderTextTracksNatively","subtitleStreamController","SubtitleStreamController","currentTrackId","tracksBuffered","mainDetails","onSubtitleTracksUpdated","onSubtitleTrackSwitch","onSubtitleTrackLoaded","onSubtitleFragProcessed","fragEnd","endOffsetSubtitles","mediaPlaylist","currentTrack","mediaBufferTimeRanges","_track$details","mainSlidingStartFragment","trackDetails","mainBufferInfo","foundFrag","mainBufferLength","maxConfigBuffer","subtitleTrackController","SubtitleTrackController","tracksInGroup","selectDefaultTrack","queuedDefaultTrack","trackChangeListener","onTextTracksChanged","asyncPollTrackChange","pollTrackChange","useTextTrackPolling","subtitlePollingInterval","_subtitleDisplay","subtitleDisplay","toggleTrackModes","subtitleTrack","lastTrack","initialTrackId","findTrackId","subtitleTracksUpdated","setSubtitleTrack","newId","groupTracks","oldTrack","nextTrack","_tracks$newId","TimelineController","unparsedVttFrags","captionsTracks","nonNativeCaptionsTracks","cea608Parser1","cea608Parser2","captionsProperties","languageCode","textTrack3","textTrack4","channel1","channel2","channel3","channel4","onFragParsingUserdata","onFragDecrypted","onInitPtsFound","onSubtitleTracksCleared","merged","cueRange","overlap","getExistingTrack","createNativeTrack","createNonNativeTrack","existingTrack","createTextTrack","trackProperties","closedCaptions","_cleanTracks","hasIMSC1","inUseTracks","textTrackKind","_captionsOrSubtitlesFromCharacteristics","tracksList","CHARACTERISTICS","transcribesSpokenDialog","describesMusicAndSound","captionsTrack","instreamIdMatch","closedCaptionsForLevel","_data$part$index","trackPlaylistMedia","_parseIMSC1","_parseVTTs","_appendCues","parseWebVTT","vttByteArray","parser","vttLines","toMpegTsClockFromTimescale","parsingError","cueTime","timestampMapMPEGTS","timestampMapLOCAL","inHeader","cueOffset","webVttMpegTsMapOffset","_fallbackToIMSC1","fragLevel","ccBytes","ccdatas","extractCea608Data","actualCCBytes","tmpByte","ccbyte1","ccbyte2","ccType","audioStreamController","AudioStreamController","videoTrackCC","waitingVideoCC","bufferedTrack","switchingTrack","waitingData","bufferFlushed","cachedTrackLoadedData","onAudioTracksUpdated","onAudioTrackLoaded","_levels$trackId","WAITING_INIT_PTS","cache","clearWaitingFragment","atGap","atBufferSyncLimit","mainFrag","completeAudioSwitch","emittedID3","emittedText","_track$details2","bufferedAttributes","switchAttributes","CHANNELS","audioTrackController","AudioTrackController","trackInActiveGroup","audioTracksUpdated","selectInitialTrack","setAudioTrack","cmcdController","ContentSteeringController","pathwayPriority","timeToLoad","reloadTimer","started","penalizedPathways","ttl","scheduleRefresh","loadSteeringManifest","levelToRemove","pathways","updatePathwayPriority","pathwayLevels","getLevelsForPathway","selectedIndex","selectedLevel","levelAfterChange","clonePathways","pathwayClones","audioGroupCloneMap","subtitleGroupCloneMap","pathwayClone","baseId","clonedVariants","baseLevel","clonedAudioGroupId","clonedSubtitleGroupId","clonedLevel","throughput","steeringData","VERSION","TTL","reloadUri","retryAfter","ttlMs","deepCpy","Hls","DefaultConfig","defaultConfig","coreComponents","networkControllers","_emitter","_autoLevelCapping","_maxHdcpLevel","latencyController","levelController","_media","enableLogs","debugConfig","exportLoggerFunctions","functions","consolePrintFn","func","mergeConfig","defaultsCopy","deprecatedSettings","deprecatedSettingTypes","policyName","policyNotSet","report","deprecatedSetting","enableStreamingMode","currentLoader","fetchSupported","ReadableStream","ConfigAbrController","ConfigBufferController","ConfigCapLevelController","ConfigErrorController","ConfigFpsController","playListLoader","id3TrackController","ConfigContentSteeringController","createController","AudioStreamControllerClass","SubtitleStreamControllerClass","ControllerClass","components","controllerInstance","eventObject","detachMedia","component","attachMedia","loadSource","loadedSource","loadingSource","recoverMediaError","shouldStartCapping","newCapLevelToPlayerSize","playingDate","audioTrackId","subtitleTrackId","HlsjsPlyrDriver","autoload","videoElement","Plyr","updateSource","sources","poster","AudioHlsPlayerComponent","active","useHls","ngAfterViewInit","hlsDriver","plyrSeeked","pushDebouncedTagWithUserType","onClickRewindSeconds","onClickForwardSeconds","LayoutAudioRecordedComponent","LayoutAudioPartialComponent","HeaderBookComponent","HeaderCourseComponent","HeaderComponent","headerService","modalService","displayOverlay$","visible","domHeader","DropdownOverlayComponent","LoaderComponent","loaderService","zIndexService","uuidv4","item$","setItem","AppComponent","mouseAndKeyboardService","dropdownServiceOld","behind$","paddingRight","NavigationStart","NavigationEnd","NavigationCancel","NavigationError","headerType","contentPage$","GlobalErrorHandler","ErrorHandler","HttpErrorResponse","shouldHandleError","_errorMessage","showToastr","HeaderModule","MESSAGE_FORMAT_CONFIG","InjectionToken","biDiSupport","strictNumberSign","currency","TranslateMessageFormatCompiler","TranslateCompiler","customFormatters","strict","compile","getMessageFormatInstance","compileTranslations","translations","u","locale","mfCache","MessageFormat","RefreshTokenInterceptor","startRefresh","doNotTrack","expired","expiresAt","expiresAtDate","contextIdentifier","setToken","intercept","req","HttpLoaderFactory","AppModule","bootstrap","HTTP_INTERCEPTORS","AuthInterceptor","APP_INITIALIZER","initializeApp","InitService","ApiService","compiler","TranslateLoader","HttpClient","ModalModule","useTransition","DropdownModule","NgResizeObserverPonyfillModule","HttpClientModule","MatDialogModule","ToastrModule","positionClass","onActivateTick","enableHtml","progressBar","timeOut","extendedTimeOut","StoreModule","EffectsModule","StoreDevtoolsModule","NgbModule","CoreModule","apiConfig","apiUmbracoBaseUrl","localHostname","ToastModule","ZIndexModule","initializeLogin","enableProdMode","__NgCli_bootstrap_1","bootstrapModule","exports","__assign","assign","__values","o","__read","ar","return","__spreadArray","pack","DateFormatError","numeric","monthStyle","desc","dayStyle","weekdayStyle","WARNING","timeZoneNameStyle","compileOptions","era","yearOptions","calendar","weekday","hourOptions","hour","hourCycle","minute","second","timeZoneName","getDateFormatOptions","tokens","fields","dte","stack","opt","isWarning","G","U","Q","q","M","L","W","D","F","E","B","H","K","J","C","S","A","z","Z","O","V","isLetter","readToken","readFieldToken","readQuotedToken","parseDateTokens","NumberFormatError","BadOptionError","stem","option","BadStemError","MaskedValueError","MissingOptionError","PatternError","TooManyOptionsError","maxOpt","UnsupportedError","getNumberFormatLocales","locales","_ref","numberingSystem","lc","ext","getNumberFormatMultiplier","scale","getNumberFormatOptions","skeleton","onUnsupported","decimal","integerWidth","notation","precision","roundingMode","sign","unitPer","unitWidth","fail","currencyDisplay","unitDisplay","useGrouping","minFraction","minF","maxFraction","maxF","minSignificant","minS","maxSignificant","maxS","minimumFractionDigits","maximumFractionDigits","minimumSignificantDigits","maximumSignificantDigits","compactDisplay","expDigits","expSign","minimumIntegerDigits","signDisplay","currencySign","parseAffixToken","isDigit","parseNumberToken","digits","plus","parseSubpattern","State","Prefix","Suffix","pattern","handleAffix","affixTokens","isPrefix","inFmt","getNegativeAffix","parseNumberPattern","negative","parseTokens","parseNumberAsSkeleton","hasGroups","hasExponent","intOptional","intDigits","decimalPos","fracDigits","fracOptional","increment","dc","negPrefix","negSuffix","affix","neg","isUnit","maxOptions","scientific","engineering","permille","latin","minOptions","validOptions","hasMaxOption","hasMinOption","parseBlueprintDigits","TokenParser","badOption","assertEmpty","parseToken","isNumberingSystem","parsePrecisionBlueprint","fd","sd","parseNumberSkeleton","getNumberFormatter","mod","getNumberFormatModifier","nf","Intl","NumberFormat","p0","p1","n0","n1","getNumberFormatterSource","modSrc","getNumberFormatModifierSource","lines","commonjsGlobal","globalThis","global","lexer","mooExports","hasSticky","sticky","isRegExp","isObject","reGroups","reCapture","reUnion","regexps","regexpOrLiteral","reEscape","ignoreCase","multiline","ruleOptions","include","defaultType","lineBreaks","shouldThrow","toRules","spec","arrayToRules","objectToRules","object","getOwnPropertyNames","rules","rule","defaultErrorRule","compileRules","hasStates","errorRule","fastAllowed","unicodeFlag","unicode","pat","regexp","fallbackRule","checkStateGroup","Lexer","startState","col","queuedToken","queuedText","queuedThrow","setState","save","re","popState","pushState","eat","tokenToString","_getGroup","groupCount","queuedGroup","_token","matchNL","nl","formatError","LexerIterator","firstDisplayedLine","lastLineDigits","displayedLines","lastNLines","numLines","errorLines","lineNo","clone","tokenType","compileStates","$all","ruleMap","included","newRules","newRule","fastKeys","freeze","keywordTransform","isMap","reverseMap","keyword","moo","__importDefault","__esModule","moo_1","doubleapos","quoted","argument","octothorpe","arg","case","parse_1","ParseError","lexer_js_1","lt","isSelectType","strictArgTypes","defaultPluralKeys","Parser","cardinalKeys","cardinal","ordinalKeys","ordinal","parseBody","checkSelectKey","parseSelect","inPlural","cases","pluralOffset","parseArgToken","argType","strictArgStyleParam","pText","atRoot","_nf$1","Runtime","_nf","plural","lcfunc","isOrdinal","reqArgs","strictNumber","Formatters","sec","numberCurrency","numberFmt","defaultCurrency","_a","numberInteger","numberPercent","toLocaleTimeString","reserved$1","ES3","break","continue","else","for","function","if","in","typeof","var","void","while","with","do","finally","instanceof","switch","throw","try","ESnext","await","debugger","enum","extends","const","export","import","null","true","false","implements","let","private","public","yield","interface","package","protected","identifier","unique","hashCode","jkey","rtlRegExp","PLURAL_MODULE","Compiler","runtime","plurals","e_1","_b","localeCodeFromKey","requireAllArguments","_c","_d","e_1_1","parserOptions","cardinals","ordinals","hasArgs","concatenate","setRuntimeFn","pluralToken","needOther","tok","returnType","biDiMarkText","isLocaleRTL","setLocale","setDateFormatter","setNumberFormatter","getFormatterArg","setFormatter","runtimeIncludes","ord","pf","getCardinal","getPlural","e_2","e_3","fmt","isFormatterKey","argShape","param_1","param_1_1","e_2_1","_e","pair","keyEnd","e_3_1","cf","argStyle","argSkeletonText_1","substr","getDateFormatter","dtf","DateTimeFormat","getDateFormatterSource","fmtArg_1","cm","currency_1","a$2","b$2","c$2","d$2","e$1","f$2","Cardinals","af","ak","am","an","n100","ars","as","asa","az","bal","be","n10","bem","bez","bg","bho","bm","bn","bo","n1000000","brx","v0","i10","i100","f10","f100","ca","i1000000","ce","ceb","cgg","chr","ckb","cs","cy","de","doi","dsb","dv","dz","eo","es","et","eu","fa","ff","fi","fil","fo","fr","fur","fy","ga","gd","gl","gsw","gu","guw","gv","ha","haw","he","hi","hnj","hr","hsb","hu","hy","ia","ig","ii","io","is","it","iu","ja","jbo","jgo","jmc","jv","jw","ka","kab","kaj","kcg","kde","kea","kk","kkj","kl","km","kn","ko","ks","ksb","ksh","ku","kw","n1000","n100000","ky","lag","lb","lg","lij","lkt","ln","lo","mas","mg","mgo","mk","ml","mn","mo","mr","mt","my","nah","naq","nd","ne","nn","nnh","no","nqo","nr","nso","ny","nyn","om","or","osa","pa","pap","pcm","pl","prg","ps","pt","pt_PT","rm","ro","rof","ru","rwk","sah","saq","sat","sc","scn","sdh","se","seh","ses","sg","sh","shi","si","sk","sl","sma","smi","smj","smn","sms","so","sq","sr","ss","ssy","sv","sw","syr","ta","te","teo","th","ti","tig","tk","tn","tpi","tr","tzm","ug","uk","und","ur","uz","ve","vec","vi","vo","vun","wa","wae","wo","xh","xog","yi","yo","yue","zh","zu","f$1","a$1","b$1","c$1","d$1","PluralCategories","Plurals","i1000","normalize","lc_1","isPluralId","hasPlural","getAllPlurals","firstLocale","defaultLocale","Boolean","escape","esc","supportedLocalesOf","resolvedOptions","fnBody","nfArgs","fnArgs","InlineSVGConfig","InlineSVGService","rendererFactory","_ranScripts","insertEl","dir","parentEl","replaceContents","prepend","_prevSVG","evalScripts","evalMode","scriptsToEval","scriptType","innerText","ɵfac","ɵprov","providedIn","InlineSVGComponent","_inlineSVGService","_el","_updateContent","changes","ɵcmp","inputs","features","decls","vars","template","rf","changeDetection","SVGCacheService","_appBase","_location","_config","httpBackend","_http","bypassHttpClientInterceptorChain","setBaseUrl","_cache","_inProgressReqs","getSVG","resolveSVGUrl","svgUrl","getAbsoluteUrl","_cloneSVG","throwError","svgText","svgEl","_svgElementFromString","_baseUrl","getBaseHrefFromDOM","base","div","cloneNode","APP_BASE_HREF","i2","i3","removeAttributes","innerEls","InlineSVGDirective","_viewContainerRef","_resolver","_svgCache","injectComponent","cacheSVG","forceEvalStyles","onSVGInserted","onSVGFailed","_supportsSVG","isSvgSupported","SVGRect","SvgUtil","isPlatformServer","_fail","_isValidPlatform","_isSSRDisabled","_insertSVG","setSVGAttributesChanged","setSVGAttributes","inlineSVG","_subscription","_prevUrl","isUrlSymbol","symbolId","createSymbolSvg","symbol","elSvg","elSvgUse","_processSvg","removeSVGAttributes","setAttributes","onSVGLoaded","_insertEl","styleTags","_svgComp","resolveComponentFactory","createComponent","fallbackImgUrl","elImg","fallbackSVG","clientOnly","ɵdir","outputs","forRoot","ɵmod","ɵinj","_defineProperty$1","hint","prim","toPrimitive","configurable","writable","_defineProperties","_defineProperty","ownKeys","getOwnPropertyDescriptor","getOwnPropertyDescriptors","defineProperties","addCSS","thumbWidth","watch","getConstructor","instanceOf","isNullOrUndefined","isString","isNodeList","NodeList","nullOrUndefined","boolean","nodeList","RangeTouch","rangeTouch","userSelect","webKitUserSelect","touchAction","changedTouches","clientX","bubbles","MutationObserver","addedNodes","childList","subtree","isFunction","weakMap","keyboardEvent","KeyboardEvent","TextTrack","transitionEndEvent","WebkitTransition","MozTransition","OTransition","repaint","hidden","isIE","documentMode","isEdge","isWebKit","isIPhone","isIPadOS","isIos","getDeep","wrap","wrapper","sibling","insertElement","removeElement","emptyElement","lastChild","replaceElement","getAttributesFromSelector","existingAttributes","existing","toggleHidden","hide","toggleClass","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","getElements","setFocus","focusVisible","preventScroll","defaultCodecs","support","check","provider","ui","rangeInput","pip","browser","webkitSetPresentationMode","pictureInPictureEnabled","disablePictureInPicture","airplay","WebKitPlaybackTargetAvailabilityEvent","playsinline","mime","mediaType","isHTML5","canPlayType","touch","reducedMotion","supportsPassiveListeners","supported","toggleListener","toggle","passive","capture","eventListeners","onceCallback","triggerEvent","CustomEvent","unbindListeners","ready","silencePromise","dedupe","curr","supportsCSS","declaration","CSS","supports","standardRatios","validateAspectRatio","reduceAspectRatio","ratio","getDivider","divider","getAspectRatio","embed","videoWidth","videoHeight","setAspectRatio","isVideo","padding","aspectRatio","paddingBottom","isVimeo","vimeo","premium","fullscreen","classNames","videoFixedRatio","roundAspectRatio","html5","getSources","getQualityOptions","setup","speed","preload","cancelRequests","blankVideo","replaceAll","toTitleCase","getHTML","resources","youtube","i18n","seekTime","Storage","storage","loadSprite","hasId","isCached","exists","insertAdjacentElement","useStorage","cached","getHours","trunc","getMinutes","getSeconds","formatTime","displayHours","inverted","getIconUrl","cors","svg4everybody","findElements","buttons","rewind","fastForward","mute","seek","volume","seekTooltip","tooltip","toggleNativeControls","createIcon","iconPath","iconPrefix","createElementNS","focusable","setAttributeNS","createLabel","createBadge","badge","menu","createButton","buttonType","toCamelCase","labelPressed","iconPressed","control","role","updateRangeFill","createProgress","suffixKey","played","createTime","bindMenuItemShortcuts","menuItem","isRadioButton","showMenuPanel","nextElementSibling","firstElementChild","previousElementSibling","lastElementChild","focusFirstMenuItem","createMenuItem","flex","updateTimeDisplay","updateVolume","setRange","muted","pressed","updateProgress","setProgress","updateSeekTooltip","tooltips","tipElement","pageX","point","_this$config$markers","markers","_this$config$markers$","points","insertAdjacentHTML","timeUpdate","invert","durationUpdate","hasDuration","displayDuration","setMarkers","toggleMenuButton","updateSetting","pane","panels","getLabel","setQualityMenu","checkMenu","getBadge","sorting","setCaptionsMenu","getTracks","toggled","setSpeedMenu","minimumSpeed","maximumSpeed","popup","firstItem","toggleMenu","composedPath","isMenuItem","getMenuSize","opacity","scrollWidth","scrollHeight","restore","setDownloadUrl","download","defaultAttributes","progressContainer","home","backButton","isEmbed","inject","seektime","addProperty","controlPressed","labels","setMediaMetadata","mediaSession","MediaMetadata","mediaMetadata","artist","album","artwork","_this$config$markers2","_this$config$markers3","containerFragment","createDocumentFragment","pointsFragment","tipVisible","toggleTip","markerElement","marker","tip","parseUrl","safe","buildUrlParams","isYouTube","userLanguage","currentTrackNode","languageExists","updateCues","setLanguage","activeClass","findTrack","enableTextTrack","sortIsDefault","sorted","getCurrentTrack","activeCues","autopause","toggleInvert","clickToPlay","hideControls","resetOnEnd","loop","keyboard","focused","iosNative","seekLabel","unmute","enableCaptions","disableCaptions","enterFullscreen","exitFullscreen","frameTitle","menuBack","normal","advertisement","qualityBadge","sdk","iframe","googleIMA","editable","embedContainer","posterEnabled","ads","stopped","isTouch","uiSupported","noTransition","previewThumbnails","thumbContainer","thumbContainerShown","imageContainer","timeContainer","scrubbingContainer","scrubbingContainerShown","publisherId","tagUrl","byline","transparent","customControls","referrerPolicy","showinfo","iv_load_policy","modestbranding","noCookie","Console","Fullscreen","scrollPosition","scrollX","scrollTo","viewport","hasProperty","cleanupViewport","activeElement","shiftKey","forceFallback","nativeSupported","requestFullscreen","webkitEnterFullscreen","toggleFallback","navigationUI","cancelFullScreen","exit","enter","proxy","trapFocus","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","msFullscreenEnabled","useNative","getRootNode","fullscreenElement","shadowRoot","loadImage","minWidth","handler","naturalWidth","addStyleHook","checkPlaying","setPoster","togglePoster","enable","backgroundImage","backgroundSize","toggleControls","checkLoading","timers","controlsElement","recentTouchSeek","lastSeekTime","migrateStyles","removeProperty","Listeners","handleKey","firstTouch","setGutter","useNativeAspectRatio","maxWidth","margin","viewportWidth","viewportHeight","clientWidth","resized","togglePlay","proxyEvents","defaultHandler","customHandlerKey","customHandler","returned","hasCustomHandler","inputEvent","forward","toggleCaptions","currentTarget","attribute","seekTo","startMove","endMove","startScrubbing","endScrubbing","webkitDirectionInvertedFromDevice","deltaX","deltaY","direction","increaseVolume","lastKey","focusTimer","lastKeyDown","altKey","metaKey","repeat","decreaseVolume","usingNative","loadjs_umd","devnull","bundleIdCache","bundleResultCache","bundleCallbackQueue","publish","bundleId","pathsNotFound","executeCallbacks","depsNotFound","loadFile","callbackFn","numTries","isLegacyIECss","maxTries","numRetries","beforeCallbackFn","before","pathStripped","relList","onbeforeload","sheet","cssText","defaultPrevented","loadjs","paths","arg1","arg2","loadFn","loadFiles","numWaiting","returnPromise","bundleIds","isDefined","assurePlaybackState","hasPlayed","Vimeo","frameParams","hashParam","sidedock","gesture","$2","thumbnail_url","Player","disableTextTrack","restorePause","setVolume","setCurrentTime","setPlaybackRate","setMuted","currentSrc","setLoop","getVideoUrl","getVideoWidth","getVideoHeight","setAutopause","getVideoTitle","getCurrentTime","getTextTracks","strippedCues","getPaused","getHost","YT","onYouTubeIframeAPIReady","getTitle","videoId","currentId","posterSrc","playerVars","hl","disablekb","cc_load_policy","cc_lang_pref","widget_referrer","onPlaybackRateChange","getPlaybackRate","onReady","playVideo","pauseVideo","stopVideo","speeds","getAvailablePlaybackRates","getVideoLoadedFraction","lastBuffered","onStateChange","unMute","Ads","google","ima","manager","displayContainer","startSafetyTimer","managerPromise","clearSafetyTimer","setupIMA","setVpaidMode","ImaSdkSettings","VpaidMode","ENABLED","setDisableCustomPlaybackForIOS10Plus","AdDisplayContainer","AdsLoader","AdsManagerLoadedEvent","ADS_MANAGER_LOADED","onAdsManagerLoaded","AdErrorEvent","AD_ERROR","onAdError","requestAds","AdsRequest","adTagUrl","linearAdSlotWidth","linearAdSlotHeight","offsetHeight","nonLinearAdSlotWidth","nonLinearAdSlotHeight","forceNonLinearFullSlot","setAdWillPlayMuted","countdownTimer","getRemainingTime","AdsRenderingSettings","restoreCustomPlaybackStateOnAdBreakComplete","enablePreloading","getAdsManager","cuePoints","getCuePoints","AdEvent","onAdEvent","cuePoint","seekElement","cuePercentage","ad","getAd","adData","getAdData","LOADED","pollCountdown","isLinear","STARTED","ALL_ADS_COMPLETED","loadAds","contentComplete","CONTENT_PAUSE_REQUESTED","pauseContent","CONTENT_RESUME_REQUESTED","resumeContent","LOG","adError","getMessage","addCuePoints","seekedTime","discardAdBreak","resize","ViewMode","NORMAL","safetyTimer","AV_PUBLISHERID","AV_CHANNELID","AV_URL","AV_WIDTH","AV_HEIGHT","AV_CDIM2","clamp","parseVtt","vttDataString","processedList","lineSplit","matchTimes","fitRatio","PreviewThumbnails","getThumbnails","render","determineContainerAutoSizing","sortAndResolve","thumbnails","getThumbnail","urlPrefix","tempImage","naturalHeight","mousePosX","thumb","_this$player$config$m","_this$player$config$m2","showImageAtCurrentTime","toggleThumbContainer","mouseDown","toggleScrubbingContainer","scrubbing","setScrubbingContainerSize","setThumbContainerSizeAndPos","thumbNum","hasThumb","qualityIndex","loadedImages","showingThumb","thumbFilename","thumbUrl","currentImageElement","dataset","showImage","removeOldImages","loadingImage","usingSprites","previewImage","showingThumbFilename","newImage","setImageSizeAndOffset","currentImageContainer","preloadNearby","getHigherQuality","currentImage","removeDelay","deleting","oldThumbFilename","thumbnailsClone","foundOne","newThumbFilename","thumbURL","currentQualityIndex","previewImageHeight","thumbContainerHeight","clearShowing","sizeSpecifiedInCSS","thumbAspectRatio","thumbHeight","setThumbContainerPos","scrubberRect","containerRect","clamped","multiplier","lastMouseMoveTime","currentScrubbingImageElement","currentThumbnailImageElement","insertElements","change","crossorigin","webkitShowPlaybackTargetPicker","hiding","soft","unload","failed","jQuery","truthy","inputIsValid","fauxDuration","realDuration","mozHasAudio","webkitAudioDecodedByteCount","updateStorage","requestPictureInPicture","exitPictureInPicture","webkitPresentationMode","pictureInPictureElement","setPreviewThumbnails","thumbnailSource","targets","_value","getValue","_subscribe","subscription","closed","hasError","thrownError","_throwIfClosed","Observable","lift","operator","observerOrNext","isSubscriber","Subscriber","isObserver","isSubscription","SafeSubscriber","errorContext","_trySubscribe","sink","promiseCtor","getPromiseCtor","Symbol_observable","operations","pipeFromArray","toPromise","_bufferSize","_windowTime","_timestampProvider","dateTimestampProvider","_infiniteTimeWindow","isStopped","_trimBuffer","_innerSubscribe","_checkFinalizedStatuses","adjustedBufferSize","ObjectUnsubscribedError","createErrorClass","_super","AnonymousSubject","currentObservers","observers","observed","EMPTY_SUBSCRIPTION","Subscription","arrRemove","COMPLETE_NOTIFICATION","createNotification","EMPTY_OBSERVER","handleStoppedNotification","nextNotification","_next","errorNotification","_error","_complete","_bind","thisArg","ConsumerObserver","partialObserver","handleUnhandledError","captureError","reportUnhandledError","notification","onStoppedNotification","timeoutProvider","defaultErrorHandler","UnsubscriptionError","initialTeardown","_parentage","initialFinalizer","_finalizers","finalizer","execFinalizer","teardown","_hasParent","_addParent","_removeParent","onUnhandledError","useDeprecatedSynchronousErrorHandling","useDeprecatedNextContext","hasConfig","EmptyError","combineLatest","scheduler","popScheduler","resultSelector","popResultSelector","observables","argsArgArrayOrObject","combineLatestInit","valueTransform","maybeSchedule","remainingFirstValues","hasFirstValue","createObject","mapOneOrManyArgs","executeSchedule","concatAll","mergeAll","defer","observableFactory","forkJoin","remainingCompletions","remainingEmissions","hasValue","subscribeOn","schedule","scheduleAsyncIterable","asyncIterator","scheduled","isInteropObservable","scheduleObservable","observeOn","isArrayLike","scheduleArray","schedulePromise","isAsyncIterable","isIterable","scheduleIterable","Symbol_iterator","isReadableStreamLike","scheduleReadableStreamLike","readableStreamLikeToAsyncGenerator","createInvalidObservableTypeError","nodeEventEmitterMethods","eventTargetMethods","jqueryMethods","isEventTarget","methodName","isNodeStyleEventEmitter","toCommonHandlerRegistry","isJQueryStyleEventEmitter","subTarget","condition","trueResult","falseResult","fromInteropObservable","obs","fromArrayLike","fromPromise","fromAsyncIterable","fromIterable","iterable","fromReadableStreamLike","readableStream","asyncIterable","asyncIterable_1","asyncIterable_1_1","merge","concurrent","popNumber","NEVER","never","errorOrErrorFactory","errorFactory","dueTime","intervalOrScheduler","asyncScheduler","intervalDuration","isScheduler","due","isValidDate","zip","argsOrArgArray","completed","onNext","onFinalize","OperatorSubscriber","shouldUnsubscribe","handledResult","concatMap","project","activeTask","lastValue","emitWhenIdle","defaultIfEmpty","delayWhen","delayDurationSelector","subscriptionDelay","ignoreElements","mapTo","distinctUntilChanged","comparator","keySelector","defaultCompare","previousKey","currentKey","exhaustMap","isComplete","outerValue","finalize","hasDefaultValue","throwIfEmpty","mergeInternals","onBeforeNext","expand","innerSubScheduler","additionalFinalizer","checkComplete","outerNext","doInnerSub","innerComplete","innerValue","bufferedValue","scan","seed","scanInternals","hasSeed","emitOnNext","emitBeforeComplete","hasState","connector","resetOnError","resetOnComplete","resetOnRefCountZero","wrapperSource","connection","resetConnection","refCount","hasCompleted","hasErrored","cancelReset","resetAndUnsubscribe","conn","dest","handleReset","onSubscriber","shareReplay","configOrBufferSize","windowTime","bufferSize","innerSubscriber","innerIndex","outerIndex","seen","takeUntil","tapObserver","isUnsub","defaultErrorFactory","TimeoutError","schedulerArg","each","_with","timeoutErrorFactory","originalSourceSubscription","timerSubscription","startTimer","otherValues","Action","work","intervalProvider","AsyncAction","recycleAsyncId","pending","requestAsyncId","_scheduler","_execute","errorValue","errored","actions","Scheduler","schedulerActionCtor","AsyncScheduler","SchedulerAction","_active","nextHandle","activeHandles","findAndClearHandle","Immediate","setImmediate","clearImmediate","immediateProvider","asapScheduler","AsapScheduler","flushId","_scheduled","AsapAction","queueScheduler","QueueScheduler","QueueAction","getSymbolIterator","getPrototypeOf","objectProto","getKeys","isPOJO","createImpl","ctorFunc","isRoot","errorThrown","parentSubscription","scheduleSubscription","releaseLock","hasLift","liftedSource","callOrApply","fns","randomUUID","getRandomValues","rnds8","rng","byteToHex","v4","buf","native","rnds","unsafeStringify","stateChangeExpr","scheduleMicroTask","_onStart","triggerMicrotask","_players","doneCount","destroyCount","startCount","timeAtPosition","longestPlayer","longestSoFar","ɵPRE_STYLE","ListKeyManager","_items","_activeItemIndex","_activeItem","_wrap","_allowedModifierKeys","_homeAndEnd","_pageUpAndDown","_skipPredicateFn","_pressedLetters","QueryList","_itemChangesSubscription","newItems","newIndex","toArray","skipPredicate","withWrap","shouldWrap","withVerticalOrientation","withHorizontalOrientation","_horizontal","withAllowedModifierKeys","withTypeAhead","debounceInterval","_typeaheadSubscription","_letterKeyStream","letter","_getItemsArray","setActiveItem","cancelTypeahead","withHomeAndEnd","withPageUpDown","previousActiveItem","updateActiveItem","onKeydown","isModifierAllowed","modifier","TAB","tabOut","DOWN_ARROW","setNextItemActive","UP_ARROW","setPreviousItemActive","RIGHT_ARROW","LEFT_ARROW","HOME","setFirstItemActive","END","setLastItemActive","PAGE_UP","targetIndex","_setActiveItemByIndex","PAGE_DOWN","itemsLength","hasModifierKey","toLocaleUpperCase","ZERO","NINE","activeItemIndex","activeItem","isTyping","_setActiveItemByDelta","itemArray","_setActiveInWrapMode","_setActiveInDefaultMode","fallbackDelta","FocusKeyManager","_origin","setFocusOrigin","InteractivityChecker","_platform","isDisabled","isVisible","hasGeometry","getClientRects","isTabbable","getFrameElement","getWindow","getTabIndexValue","tabIndexValue","WEBKIT","IOS","isPotentiallyTabbableIOS","inputType","FIREFOX","tabIndex","isFocusable","isPotentiallyFocusable","isHiddenInput","isInputElement","isNativeFormElement","isAnchorWithHref","isAnchorElement","hasValidTabIndex","ignoreVisibility","FocusTrap","_enabled","_startAnchor","_endAnchor","_toggleAnchorTabIndex","_checker","_ngZone","_document","deferAnchors","_hasAttached","startAnchorListener","focusLastTabbableElement","endAnchorListener","focusFirstTabbableElement","attachAnchors","startAnchor","endAnchor","_createAnchor","focusInitialElementWhenReady","_executeOnStable","focusInitialElement","focusFirstTabbableElementWhenReady","focusLastTabbableElementWhenReady","_getRegionBoundary","bound","_getFirstTabbableElement","_getLastTabbableElement","redirectToElement","focusableChild","hasAttached","tabbableChild","ELEMENT_NODE","anchor","isEnabled","toggleAnchors","isStable","onStable","FocusTrapFactory","deferCaptureElements","isFakeMousedownFromScreenReader","offsetX","offsetY","isFakeTouchstartFromScreenReader","touches","radiusX","radiusY","INPUT_MODALITY_DETECTOR_OPTIONS","INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS","ignoreKeys","ALT","CONTROL","MAC_META","META","SHIFT","modalityEventListenerOptions","normalizePassiveListenerOptions","InputModalityDetector","mostRecentModality","_modality","ngZone","_mostRecentTarget","_lastTouchMs","_options","_getEventTarget","modalityDetected","modalityChanged","_onKeydown","_onMousedown","_onTouchstart","FOCUS_MONITOR_DEFAULT_OPTIONS","captureEventListenerOptions","FocusMonitor","_inputModalityDetector","_windowFocused","_originFromTouchInteraction","_monitoredElementCount","_windowFocusListener","_windowFocusTimeoutId","_onFocus","_onBlur","_detectionMode","detectionMode","monitor","checkChildren","coerceElement","observableOf","rootNode","_getShadowRoot","_getDocument","cachedInfo","_elementInfo","_registerGlobalListeners","stopMonitoring","elementInfo","_setClasses","_removeGlobalListeners","focusVia","_getClosestElementsInfo","_originChanged","_setOrigin","_info","_getWindow","_getFocusOrigin","focusEventTarget","_shouldBeAttributedToTouch","_lastFocusOrigin","_isLastInteractionFromInputLabel","isFromInteraction","_originTimeoutId","relatedTarget","Node","_emitOrigin","rootNodeFocusListeners","_rootNodeFocusListenerCount","_rootNodeFocusAndBlurListener","_stopInputModalityDetector","modality","mostRecentTarget","i2.InputModalityDetector","BLACK_ON_WHITE_CSS_CLASS","WHITE_ON_BLACK_CSS_CLASS","HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS","HighContrastModeDetector","_breakpointSubscription","BreakpointObserver","_hasCheckedHighContrastMode","_applyBodyHighContrastModeCssClasses","getHighContrastMode","testElement","documentWindow","computedStyle","computedColor","bodyClasses","A11yModule","highContrastModeDetector","i1.HighContrastModeDetector","ObserversModule","DIR_DOCUMENT","DIR_DOCUMENT_FACTORY","RTL_LOCALE_PATTERN","Directionality","_resolveDirectionality","rawValue","BidiModule","coerceBooleanProperty","coerceNumberProperty","fallbackValue","_isNumberValue","coerceArray","coerceCssPixelValue","elementOrRef","ElementRef","ENTER","ESCAPE","SPACE","modifiers","mediaQueriesForWebkitCompatibility","mediaQueryStyleNode","MediaMatcher","_matchMedia","noopMatchMedia","BLINK","createEmptyStyleRule","insertRule","_mediaMatcher","_destroySubject","isMatched","splitQueries","mediaQuery","_registerQuery","mql","stateObservable","breakpointStates","_queries","output","queries","MutationObserverFactory","ContentObserver","_mutationObserverFactory","_observedElements","_cleanupObserver","_observeElement","_unobserveElement","mutations","characterData","disconnect","CdkObserveContent","_disabled","_unsubscribe","debounce","_debounce","_contentObserver","_elementRef","_currentSubscription","ngAfterContentInit","scrollBehaviorSupported","supportsScrollBehavior","BlockScrollStrategy","_viewportRuler","_previousHTMLStyles","_isEnabled","attach","_canBeEnabled","_previousScrollPosition","getViewportScrollPosition","htmlStyle","bodyStyle","previousHtmlScrollBehavior","scrollBehavior","previousBodyScrollBehavior","getViewportSize","CloseScrollStrategy","_scrollDispatcher","_scrollSubscription","_detach","_overlayRef","overlayRef","scrollable","overlayElement","getElementRef","_initialScrollPosition","updatePosition","NoopScrollStrategy","scrollContainers","containerBounds","scrollContainerRect","RepositionScrollStrategy","scrollThrottle","autoClose","overlayRect","isElementScrolledOutsideView","ScrollStrategyOptions","reposition","OverlayConfig","panelClass","hasBackdrop","backdropClass","disposeOnNavigation","configKeys","ConnectedOverlayPositionChange","connectionPair","scrollableViewProperties","BaseOverlayDispatcher","_attachedOverlays","OverlayKeyboardDispatcher","overlays","_keydownEvents","keydownEvents","_isAttached","_keydownListener","OverlayOutsideClickDispatcher","_cursorStyleIsSet","_pointerDownEventTarget","_outsidePointerEvents","outsidePointerEvents","_addEventListeners","_cursorOriginalValue","cursor","_pointerDownListener","_clickListener","OverlayContainer","_containerElement","getContainerElement","_createContainer","containerClass","_isTestEnvironment","oppositePlatformContainers","OverlayRef","_portalOutlet","_host","_pane","_keyboardDispatcher","_outsideClickDispatcher","_animationsDisabled","_backdropElement","_backdropClick","_disposeBackdrop","scrollStrategy","_scrollStrategy","_positionStrategy","positionStrategy","backdropElement","portal","_previousHostParent","attachResult","_updateStackingOrder","_updateElementSize","_updateElementDirection","_togglePointerEvents","_attachBackdrop","_toggleClasses","_attachments","_locationChanges","dispose","detachBackdrop","detachmentResult","_detachments","_detachContentWhenStable","isAttached","_disposeScrollStrategy","backdropClick","attachments","detachments","getConfig","updatePositionStrategy","strategy","updateSize","sizeConfig","setDirection","addPanelClass","classes","removePanelClass","getDirection","updateScrollStrategy","minHeight","maxHeight","enablePointer","pointerEvents","showingClass","_backdropClickHandler","requestAnimationFrame","backdropToDetach","_backdropTransitionendHandler","_backdropTimeout","cssClasses","isAdd","backdrop","boundingBoxClass","cssUnitPattern","FlexibleConnectedPositionStrategy","_preferredPositions","connectedTo","_overlayContainer","_lastBoundingBoxSize","_isPushed","_canPush","_growAfterOpen","_hasFlexibleDimensions","_positionLocked","_viewportMargin","_scrollables","_offsetX","_offsetY","_appliedPanelClasses","_positionChanges","setOrigin","_validatePositions","_boundingBox","_isDisposed","_isInitialRender","_lastPosition","_resizeSubscription","reapplyLastPosition","_clearPanelClasses","_resetOverlayElementStyles","_resetBoundingBoxStyles","_viewportRect","_getNarrowedViewportRect","_originRect","_getOriginRect","_overlayRect","_containerRect","originRect","viewportRect","flexibleFits","originPoint","_getOriginPoint","overlayPoint","_getOverlayPoint","overlayFit","_getOverlayFit","isCompletelyWithinViewport","_applyPosition","_canFitWithFlexibleDimensions","boundingBoxRect","_calculateBoundingBoxRect","visibleArea","bestFit","bestScore","fit","score","_previousPushAmount","extendStyles","alignItems","justifyContent","lastPosition","withScrollableContainers","scrollables","withPositions","withViewportMargin","withFlexibleDimensions","flexibleDimensions","withGrowAfterOpen","growAfterOpen","withPush","canPush","withLockedPosition","isLocked","withDefaultOffsetX","withDefaultOffsetY","withTransformOriginOn","_transformOriginSelector","originX","startX","_isRtl","endX","originY","overlayStartX","overlayStartY","overlayX","overlayY","rawOverlayRect","overlay","getRoundedBoundingClientRect","_getOffset","topOverflow","bottomOverflow","visibleWidth","_subtractOverflows","visibleHeight","fitsInViewportVertically","fitsInViewportHorizontally","availableHeight","availableWidth","getPixelValue","horizontalFit","_pushOverlayOnScreen","overflowRight","overflowBottom","overflowTop","overflowLeft","pushX","pushY","_setTransformOrigin","_setOverlayElementStyles","_setBoundingBoxStyles","_addPanelClasses","_getScrollVisibility","changeEvent","xOrigin","yOrigin","transformOrigin","isRtl","smallestDistanceToViewportEdge","previousHeight","previousWidth","_hasExactPosition","hasExactPosition","hasFlexibleDimensions","_getExactOverlayY","_getExactOverlayX","transformString","horizontalStyleProperty","originBounds","overlayBounds","scrollContainerBounds","isOriginClipped","isElementClippedByScrolling","isOriginOutsideView","isOverlayClipped","isOverlayOutsideView","overflows","currentOverflow","axis","cssClass","wrapperClass","GlobalPositionStrategy","_cssPosition","_topOffset","_bottomOffset","_alignItems","_xPosition","_xOffset","_width","_height","centerHorizontally","centerVertically","parentStyles","shouldBeFlushHorizontally","shouldBeFlushVertically","xPosition","xOffset","marginLeft","marginRight","marginTop","marginBottom","OverlayPositionBuilder","flexibleConnectedTo","i3.OverlayContainer","nextUniqueId","Overlay","scrollStrategies","_componentFactoryResolver","_positionBuilder","_injector","_directionality","_animationsModuleType","_createHostElement","_createPaneElement","portalOutlet","_createPortalOutlet","overlayConfig","_appRef","ApplicationRef","DomPortalOutlet","i1.ScrollStrategyOptions","i2.OverlayContainer","i3.OverlayPositionBuilder","i4.OverlayKeyboardDispatcher","i5","i6","i7.OverlayOutsideClickDispatcher","CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER","CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY","OverlayModule","PortalModule","ScrollingModule","hasV8BreakIterator","v8BreakIterator","supportsPassiveEvents","rtlScrollAxisType","shadowDomIsSupported","Platform","_platformId","chrome","EDGE","TRIDENT","supportsPassiveEventListeners","scrollToFunction","getRtlScrollAxisType","scrollContainer","containerStyle","contentStyle","scrollLeft","_supportsShadowDom","createShadowRoot","attachShadow","ShadowRoot","_getFocusedElementPierceShadowDom","newActiveElement","__karma__","jasmine","jest","Mocha","Portal","_attachedHost","setAttachedHost","ComponentPortal","viewContainerRef","componentFactoryResolver","projectableNodes","TemplatePortal","templateRef","DomPortal","BasePortalOutlet","attachDomPortal","_attachedPortal","attachComponentPortal","attachTemplatePortal","_invokeDisposeFn","setDisposeFn","_disposeFn","outletElement","_defaultInjector","componentFactory","componentRef","attachView","hostView","viewCount","detachView","_getComponentRootNode","viewContainer","viewRef","createEmbeddedView","rootNodes","detectChanges","CdkPortal","TemplatePortalDirective","useExisting","CdkPortalOutlet","_isInitialized","_getRootNode","attachedRef","_attachedRef","attached","animationFrameProvider","cancelAnimationFrame","animationFrameScheduler","AnimationFrameScheduler","AnimationFrameAction","auditTime","audit","durationSelector","durationSubscriber","endDuration","cleanupDuration","VIRTUAL_SCROLL_STRATEGY","ScrollDispatcher","_globalSubscription","_scrolledCount","elementScrolled","_scrolled","scrollableReference","auditTimeInMs","_addGlobalListener","_removeGlobalListener","ancestorScrolled","elementOrElementRef","ancestors","getAncestorScrollContainers","scrollingContainers","_scrollableContainsElement","scrollableElement","CdkScrollable","scrollDispatcher","_elementScrolled","_applyScrollToOptions","measureScrollOffset","LEFT","ViewportRuler","_change","_changeListener","_viewportSize","_updateViewportSize","getViewportRect","documentRect","throttleTime","VIRTUAL_SCROLLABLE","CdkVirtualScrollable","measureViewportSize","viewportEl","SCROLL_SCHEDULER","CdkVirtualScrollViewport","_orientation","_calculateSpacerSize","appendOnly","_appendOnly","_changeDetectorRef","viewportRuler","scrolledIndexChange","_renderedRangeSubject","_totalContentSize","_totalContentWidth","_totalContentHeight","_renderedRange","_dataLength","_renderedContentOffset","_renderedContentOffsetNeedsRewrite","_isChangeDetectionPending","_runAfterChangeDetection","_viewportChanges","checkViewportSize","_measureViewportSize","onContentScrolled","_markChangeDetectionNeeded","_detachedSubject","forOf","_forOf","dataStream","onDataLengthChanged","_doChangeDetection","getDataLength","getRenderedRange","measureBoundingClientRectWithScrollOffset","setTotalContentSize","setRenderedRange","rangesEqual","r1","r2","onContentRendered","getOffsetToRenderedContentStart","setRenderedContentOffset","isHorizontal","_renderedContentTransform","measureRenderedContentSize","onRenderedOffsetChanged","scrollToOffset","behavior","scrollToIndex","_from","measureViewportOffset","fromRect","scrollerClientRect","contentEl","_contentWrapper","measureRangeSize","runAfter","markForCheck","runAfterChangeDetection","virtualScrollable","Optional","Inject","CdkScrollableModule","_DOM","getDOM","setRootDomAdapter","adapter","DomAdapter","PlatformLocation","historyGo","relativePosition","useBrowserPlatformLocation","ɵɵinject","BrowserPlatformLocation","LOCATION_INITIALIZED","_doc","_history","history","getBaseHref","getGlobalEventTarget","onHashChange","port","supportsState","back","createBrowserPlatformLocation","slashes","stripTrailingSlash","pathEndIdx","normalizeQueryParams","LocationStrategy","PathLocationStrategy","_platformLocation","_removeListenerFns","_baseHref","prepareExternalUrl","internal","joinWithSlash","includeHash","externalUrl","HashLocationStrategy","Location","locationStrategy","_urlChangeListeners","_urlChangeSubscription","_locationStrategy","baseHref","_basePath","_stripOrigin","_stripIndexHtml","_subject","isCurrentPathEqualTo","_stripBasePath","strippedUrl","_notifyUrlChangeListeners","onUrlChange","fnIndex","onThrow","onReturn","createLocation","NumberFormatStyle","FormStyle","TranslationWidth","FormatWidth","NumberSymbol","getLocaleDayPeriods","formStyle","ɵfindLocaleData","amPm","getLastDefinedValue","ɵLocaleDataIndex","getLocaleDayNames","days","getLocaleMonthNames","months","dateTimeFormatData","CurrencyDecimal","Decimal","CurrencyGroup","Group","checkFullData","extractTime","ISO8601_DATE_REGEX","NAMED_FORMATS","DATE_FORMATS_SPLIT","ZoneWidth","DateType","TranslationType","formatDate","timezone","toDate","isDate","createDate","parsedNb","isoStringToDate","tzHour","tzMin","dateSetter","setUTCFullYear","setFullYear","timeSetter","setUTCHours","setHours","getNamedFormat","dateTimezoneOffset","getTimezoneOffset","timezoneToOffset","convertTimezoneToLocal","reverseValue","addDateMinutes","setMinutes","dateFormatter","DATE_FORMATS","dateStrGetter","Eras","Abbreviated","Wide","Narrow","dateGetter","FullYear","weekNumberingYearGetter","Month","Months","Standalone","weekGetter","Day","Days","Short","DayPeriods","Format","Seconds","FractionalSeconds","timeZoneGetter","Extended","ShortGMT","Long","localeId","getLocaleId","formatValue","getLocaleDateFormat","Medium","getLocaleTimeFormat","shortTime","shortDate","formatDateTime","getLocaleDateTimeFormat","mediumTime","mediumDate","longTime","longDate","fullTime","fullDate","opt_values","padNumber","minusSign","negWrap","strNum","getDatePart","getFullYear","getMonth","getDate","getMilliseconds","getDay","formatFractionalSeconds","milliseconds","localeMinus","getLocaleNumberSymbol","MinusSign","form","extended","getDateTranslation","currentHours","currentMinutes","getLocaleExtraDayPeriodRules","dayPeriods","getLocaleExtraDayPeriods","afterFrom","beforeTo","erasData","getLocaleEraNames","JANUARY","THURSDAY","getThursdayThisWeek","datetime","monthBased","nbDaysBefore1stDayOfMonth","thisThurs","firstThurs","getFirstThursdayOfYear","firstDayOfYear","diff","requestedTimezoneOffset","valueOf","NUMBER_FORMAT_REGEXP","MAX_DIGITS","DECIMAL_SEP","ZERO_CHAR","PATTERN_SEP","GROUP_SEP","DIGIT_CHAR","parseIntAutoRadix","cookieStr","eqIndex","cookieName","cookieValue","WS_REGEXP","EMPTY_ARRAY","NgClass","_iterableDiffers","_keyValueDiffers","_ngEl","initialClasses","klass","ngClass","rawClass","ngDoCheck","_updateState","_applyStateDiff","nextEnabled","touched","stateEntry","_toggleClass","NgForOfContext","$implicit","ngForOf","even","odd","NgForOf","_ngForOf","_ngForOfDirty","ngForTrackBy","_trackByFn","_viewContainer","_template","_differs","_differ","ngForTemplate","_applyChanges","forEachOperation","adjustedPreviousIndex","previousIndex","move","applyViewChange","ilen","forEachIdentityChange","record","NgIf","NgIfContext","_thenTemplateRef","_elseTemplateRef","_thenViewRef","_elseViewRef","ngIf","_context","_updateView","ngIfThen","assertTemplate","ngIfElse","NgStyle","_ngStyle","ngStyle","_setStyle","nameAndUnit","RendererStyleFlags2","forEachRemovedItem","forEachAddedItem","forEachChangedItem","NgTemplateOutlet","_viewRef","ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector","SubscribableStrategy","createSubscription","updateLatestValue","PromiseStrategy","_promiseStrategy","_subscribableStrategy","AsyncPipe","_latestValue","_obj","_strategy","_dispose","_selectStrategy","_updateLatestValue","ɵisPromise","ɵisSubscribable","invalidPipeArgumentError","LowerCasePipe","DATE_PIPE_DEFAULT_TIMEZONE","DATE_PIPE_DEFAULT_OPTIONS","DatePipe","defaultTimezone","defaultOptions","dateFormat","LOCALE_ID","JsonPipe","KeyValuePipe","differs","keyValues","compareFn","defaultComparator","differ","differChanges","compareFnChanged","forEachItem","makeKeyValuePair","keyValueA","keyValueB","aString","bString","PercentPipe","_locale","digitsInfo","isValue","formatPercent","formatNumberToLocaleString","groupSymbol","decimalSymbol","isPercent","formattedText","isZero","parsedNumber","parseNumber","integerLen","zeros","numStr","exponent","toPercent","fractionLen","minInt","minFrac","maxFrac","minIntPart","minFractionPart","maxFractionPart","roundNumber","fractionSize","roundAt","digit","dropTrailingZeros","minLen","carry","reduceRight","decimals","lgSize","gSize","Exponential","negPre","negSuf","posPre","posSuf","parseNumberFormat","patternParts","positive","positiveParts","fraction","ch","trunkLen","getLocaleNumberFormat","Percent","PercentSign","strToNumber","PLATFORM_BROWSER_ID","PLATFORM_SERVER_ID","ViewportScroller","ɵɵdefineInjectable","BrowserViewportScroller","setOffset","getScrollPosition","supportsScrolling","pageXOffset","pageYOffset","scrollToPosition","scrollToAnchor","elSelected","findAnchorFromDocument","documentResult","getElementsByName","createTreeWalker","treeWalker","NodeFilter","SHOW_ELEMENT","currentNode","nextNode","scrollToElement","setHistoryScrollRestoration","scrollRestoration","supportScrollRestoration","scrollRestorationDescriptor","getScrollRestorationProperty","XhrFactory","HttpHandler","HttpBackend","HttpHeaders","lazyUpdate","lazyInit","maybeSetNormalizedName","headerValues","normalizedNames","getAll","op","lcName","copyFrom","applyUpdate","toDelete","HttpUrlEncodingCodec","encodeKey","standardEncoding","encodeValue","decodeKey","decodeValue","STANDARD_ENCODING_REGEX","STANDARD_ENCODING_REPLACEMENTS","valueToString","updates","cloneFrom","encoder","fromString","fromObject","paramParser","rawParams","eqIdx","appendAll","eKey","HttpContextToken","HttpContext","isBlob","isFormData","FormData","HttpRequest","third","fourth","reportProgress","mightHaveBody","urlWithParams","qIdx","serializeBody","isUrlSearchParams","detectContentTypeHeader","setHeaders","setParams","HttpEventType","HttpResponseBase","defaultStatus","defaultStatusText","HttpHeaderResponse","ResponseHeader","HttpResponse","Response","addBody","events$","res$","jsonp","callbackParam","patch","put","interceptorChainEndFn","finalHandlerFn","adaptLegacyInterceptorToChain","chainTailFn","interceptor","initialRequest","downstreamRequest","HTTP_INTERCEPTOR_FNS","legacyInterceptorFnFactory","chain","HttpInterceptorHandler","backend","dedupedInterceptorFns","nextSequencedFn","interceptorFn","chainedInterceptorFn","runInContext","XSSI_PREFIX","HttpXhrBackend","xhrFactory","detectedType","reqBody","headerResponse","partialFromXhr","onLoad","originalBody","sentHeaders","onDownProgress","progressEvent","DownloadProgress","partialText","onUpProgress","UploadProgress","upload","Sent","XSRF_ENABLED","XSRF_COOKIE_NAME","XSRF_HEADER_NAME","HttpXsrfTokenExtractor","HttpXsrfCookieExtractor","lastCookieString","lastToken","parseCount","getToken","cookieString","parseCookieValue","lcUrl","headerName","HttpFeatureKind","makeHttpFeature","ɵkind","ɵproviders","xsrfInterceptorFn","feature","makeEnvironmentProviders","LEGACY_INTERCEPTOR_FN","provideHttpClient","LegacyInterceptors","getClosureSafeProperty","objWithPropertyToExtract","overriddenName","newLineIndex","after","__forward_ref__","forwardRef","forwardRefFn","resolveForwardRef","isForwardRef","isEnvironmentProviders","XSS_SECURITY_URL","formatRuntimeError","renderStringify","injectorName","actual","expected","comparison","ɵɵdefineInjector","getInjectableDef","getOwnDefinition","NG_PROV_DEF","NG_INJECTABLE_DEF","isInjectable","getInjectorDef","NG_INJ_DEF","NG_INJECTOR_DEF","ngInjectableDef","ngInjectorDef","InjectFlags","_injectImplementation","setInjectImplementation","impl","injectRootLimpMode","notFoundValue","injectableDef","throwProviderNotFoundError","_global","WorkerGlobalScope","THROW_IF_NOT_FOUND","DI_DECORATOR_FLAG","NG_TEMP_TOKEN_PATH","NG_TOKEN_PATH","NEW_LINE","NO_NEW_LINE","SOURCE","_currentInjector","setCurrentInjector","former","injectInjectorOnly","Default","getInjectImplementation","convertToBitFlags","skipSelf","injectArgs","flag","getInjectFlag","decorator","noSideEffects","ChangeDetectionStrategy","EMPTY_OBJ","NG_COMP_DEF","NG_DIR_DEF","NG_PIPE_DEF","ɵpipe","NG_MOD_DEF","NG_FACTORY_DEF","NG_ELEMENT_ID","__NG_ELEMENT_ID__","componentDefCount","ɵɵdefineComponent","componentDefinition","baseDef","getNgDirectiveDef","consts","ngContentSelectors","onPush","OnPush","directiveDefs","pipeDefs","dependencies","standalone","getStandaloneInjector","Emulated","schemas","tView","initFeatures","extractDefListOrFactory","extractDirectiveDef","getComponentDef","getDirectiveDef","nonNull","ɵɵdefineNgModule","declarations","transitiveCompileScopes","scope","ngModuleDef","getNgModuleDef","invertObject","secondary","newLookup","minifiedKey","publicName","declaredName","ɵɵdefineDirective","directiveDefinition","ɵɵdefinePipe","pipeDef","getPipeDef","isStandalone","throwNotFound","declaredInputs","providersResolver","hostBindings","hostVars","hostAttrs","contentQueries","exportAs","viewQuery","setInput","findHostDirectiveDefs","hostDirectives","definition","defExtractor","dep","TVIEW","FLAGS","PARENT","NEXT","TRANSPLANTED_VIEWS_TO_REFRESH","T_HOST","CLEANUP","CONTEXT","INJECTOR","RENDERER_FACTORY","RENDERER","SANITIZER","CHILD_HEAD","CHILD_TAIL","DECLARATION_VIEW","DECLARATION_COMPONENT_VIEW","DECLARATION_LCONTAINER","PREORDER_HOOK_FLAGS","QUERIES","EMBEDDED_VIEW_INJECTOR","HEADER_OFFSET","HAS_TRANSPLANTED_VIEWS","NATIVE","VIEW_REFS","MOVED_VIEWS","CONTAINER_HEADER_OFFSET","isLView","isLContainer","isContentQueryHost","tNode","isComponentHost","componentOffset","isDirectiveHost","isComponentDef","isRootView","SimpleChange","firstChange","isFirstChange","ɵɵNgOnChangesFeature","NgOnChangesFeatureImpl","ngOnChangesSetInput","rememberChangeHistoryAndInvokeOnChangesHook","simpleChangesStore","getSimpleChangesStore","privateName","setSimpleChangesStore","SIMPLE_CHANGES_STORE","previousChange","ngInherit","profiler","hookOrListener","SVG_NAMESPACE","unwrapRNode","lView","nodeIndex","slotValue","viewAttachedToChangeDetector","resetPreOrderHookFlags","lContainer","viewOrContainer","instructionState","lFrame","createLFrame","bindingsEnabled","getBindingsEnabled","getLView","getTView","ɵɵrestoreView","viewToRestore","contextLView","ɵɵresetView","getCurrentTNode","currentTNode","getCurrentTNodePlaceholderOk","getCurrentParentTNode","isParent","isCurrentTNodeParent","setCurrentTNodeAsNotParent","getBindingRoot","bindingRootIndex","bindingStartIndex","getBindingIndex","bindingIndex","nextBindingIndex","incrementBindingIndex","setInI18nBlock","isInI18nBlock","inI18n","currentDirectiveIndex","setCurrentDirectiveIndex","getCurrentDirectiveDef","tData","getCurrentQueryIndex","setCurrentQueryIndex","getDeclarationTNode","declTNode","enterDI","SkipSelf","parentTNode","parentLView","Host","allocLFrame","enterView","newView","newLFrame","currentLFrame","childLFrame","elementDepthCount","currentNamespace","leaveViewLight","oldLFrame","leaveDI","leaveView","getSelectedIndex","setSelectedIndex","getSelectedTNode","getTNode","ɵɵnamespaceSVG","ɵɵnamespaceHTML","namespaceHTMLInternal","directiveStart","directiveEnd","lifecycleHooks","ngAfterContentChecked","ngAfterViewChecked","contentHooks","contentCheckHooks","viewHooks","viewCheckHooks","destroyHooks","executeCheckHooks","hooks","callHooks","executeInitAndCheckHooks","initPhase","currentView","currentNodeIndex","nodeIndexLimit","lastNodeIndexFound","callHook","isInitHook","hook","directive","NO_PARENT_INJECTOR","NodeInjectorFactory","isViewProvider","injectImplementation","resolving","canSeeViewProviders","injectImpl","setUpAttributes","namespaceURI","attrVal","isAnimationProp","isNameOnlyAttributeMarker","dst","srcMarker","mergeHostAttribute","markerInsertPosition","dstValue","hasParentInjector","parentLocation","getParentInjectorIndex","startView","viewOffset","getParentInjectorViewOffset","parentView","includeViewProviders","setIncludeViewProviders","BLOOM_MASK","BLOOM_BUCKET_BITS","nextNgElementId","NOT_FOUND","existingInjectorIndex","getInjectorIndex","firstCreatePass","injectorIndex","insertBloom","blueprint","parentLoc","getParentInjectorLocation","parentIndex","getParentInjectorView","parentData","footer","declarationViewOffset","lViewCursor","getTNodeFromLView","diPublicInInjector","bloomAdd","bloomHash","notFoundValueOrThrow","lookupTokenUsingModuleInjector","Self","moduleInjector","previousInjectImplementation","embeddedInjectorValue","lookupTokenUsingEmbeddedInjector","currentLView","nodeInjectorValue","lookupTokenUsingNodeInjector","embeddedViewInjector","embeddedViewInjectorValue","bloomHashBitOrFactory","tokenId","createNodeInjector","previousTView","hostTElementNode","shouldSearchParent","bloomHasToken","searchTokensOnInjector","currentTView","injectableIdx","locateDirectiveOrProvider","getNodeInjectable","canAccessViewProviders","isHostSpecialCase","nodeProviderIndexes","providerIndexes","tInjectables","injectablesStart","directivesStart","cptViewProvidersCount","endIndex","providerTokenOrDef","dirDef","isFactory","depPath","throwCyclicDependencyError","stringifyForError","previousIncludeViewProviders","registerPreOrderHooks","directiveIndex","directiveDef","wrappedOnChanges","preOrderHooks","preOrderCheckHooks","injectorView","isFirstHostTNode","NodeInjector","_tNode","_lView","getOrCreateInjectable","ɵɵgetInheritedFactory","ownConstructor","ownFactory","getFactoryOf","objectPrototype","getFactoryDef","tViewType","ɵɵinjectAttribute","attrNameToInject","attrsLength","injectAttributeImpl","PARAMETERS","makeParamDecorator","parentClass","metaCtor","makeMetadataCtor","propName","ParamDecoratorFactory","annotationInstance","ParamDecorator","annotation","cls","unusedKey","ngMetadataName","annotationCls","_desc","deepForEach","addToArray","keyValueArraySet","keyValueArray","keyValueArrayIndexOf","arrayInsert2","_arrayIndexOfSorted","middle","attachInjectFlag","COMMENT_DISALLOWED","COMMENT_DELIMITER","COMMENT_DELIMITER_ESCAPED","TRACKED_LVIEWS","uniqueIdCounter","getLViewById","LContext","lViewId","getLContext","mpValue","readPatchedData","directives","isComponentInstance","findViaComponent","componentInstance","componentIndices","elementComponentIndex","getComponentLViewByIndex","isDirectiveInstance","findViaDirective","directiveInstance","directiveIndexEnd","traverseNextElement","getDirectivesAtNodeIndex","findViaNativeElement","existingCtx","createLContext","attachPatchData","rElement","MONKEY_PATCH_KEY_NAME","registerLView","_icuContainerIterate","tIcuContainerNode","getLViewParent","getFirstLContainer","getNearestLContainer","getNextLContainer","applyToElementOrContainer","lNodeToHandle","beforeNode","isComponent","rNode","nativeAppendChild","nativeInsertBefore","nativeRemoveNode","applyContainer","parentRElement","applyView","updateTextNode","escapeCommentText","createElementNode","detachMovedView","declarationContainer","movedViews","declarationViewIndex","insertionLContainer","updateTransplantedViewCount","removeIndex","indexInContainer","viewToDetach","declarationLContainer","removedLView","removeFromArray","removeViewFromContainer","lQueries","destroyViewTree","rootView","lViewOrLContainer","cleanUpView","firstView","executeOnDestroys","toCall","callContext","processCleanups","tCleanup","cleanup","lCleanup","lastLCleanupIndex","targetIdx","instanceCleanupFn","unregisterLView","getParentRElement","getClosestRElement","getNativeByTNode","nativeAppendOrInsertBefore","getInsertInFrontOfRNode","_getInsertInFrontOfRNodeWithI18n","getInsertInFrontOfRNodeWithNoI18n","_processI18nInsertBefore","policy","getInsertInFrontOfRNodeWithI18n","processI18nInsertBefore","childRNode","childTNode","parentRNode","getFirstNativeNode","tNodeType","getBeforeNodeForView","elIcuContainerChild","rNodeOrLContainer","icuContainerIterate","projectionNodes","getProjectionNodes","projection","viewIndexInContainer","nextViewIndex","firstTNodeOfView","nativeParent","nativeParentNode","nativeRemoveChild","applyNodes","isProjection","rawSlotValue","nextRNode","applyProjectionRecursive","projectionNext","tProjectionNode","componentLView","nodeToProjectOrRNodes","writeDirectClass","setupStaticAttributes","mergedAttrs","writeDirectStyle","trustedHTMLFromString","getPolicy","trustedTypes","createPolicy","createHTML","createScript","createScriptURL","setDocument","getDocument","trustedHTMLFromStringBypass","trustedScriptURLFromStringBypass","SafeValueImpl","changingThisBreaksApplicationSecurity","SafeHtmlImpl","getTypeName","SafeStyleImpl","SafeScriptImpl","SafeUrlImpl","SafeResourceUrlImpl","unwrapSafeValue","actualType","getSanitizationBypassType","bypassSanitizationTrustHtml","trustedHtml","bypassSanitizationTrustStyle","trustedStyle","bypassSanitizationTrustScript","trustedScript","bypassSanitizationTrustUrl","trustedUrl","bypassSanitizationTrustResourceUrl","trustedResourceUrl","getInertBodyHelper","defaultDoc","inertDocumentHelper","InertDocumentHelper","isDOMParserAvailable","DOMParserHelper","getInertBodyElement","inertDocument","implementation","createHTMLDocument","templateEl","SAFE_URL_PATTERN","_sanitizeUrl","tagSet","tags","sets","VOID_ELEMENTS","OPTIONAL_END_TAG_BLOCK_ELEMENTS","OPTIONAL_END_TAG_INLINE_ELEMENTS","VALID_ELEMENTS","URI_ATTRS","VALID_ATTRS","SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS","SanitizingHtmlSerializer","sanitizedSomething","sanitizeChildren","traverseContent","startElement","TEXT_NODE","endElement","checkClobberedElement","elAttrs","elAttr","encodeEntities","compareDocumentPosition","DOCUMENT_POSITION_CONTAINED_BY","SURROGATE_PAIR_REGEXP","NON_ALPHANUMERIC_REGEXP","inertBodyHelper","unsafeHtmlInput","inertBodyElement","unsafeHtml","mXSSAttempts","parsedHtml","getTemplateContent","isTemplateElement","SecurityContext","ɵɵsanitizeHtml","getSanitizer","sanitize","HTML","allowSanitizationBypassAndThrow","_sanitizeHtml","ɵɵsanitizeUrl","unsafeUrl","ɵɵsanitizeResourceUrl","unsafeResourceUrl","RESOURCE_URL","ɵɵsanitizeUrlOrResourceUrl","getUrlSanitizer","ENVIRONMENT_INITIALIZER","INJECTOR_DEF_TYPES","NullInjector","internalImportProvidersFrom","ɵfromNgModule","checkForStandaloneCmp","providersOut","dedup","injectorTypesWithProviders","internalSource","walkProviderTree","processInjectorTypesWithProviders","typesWithProviders","deepForEachProvider","parents","defType","injDef","cmpDef","isDuplicate","importTypesWithProviders","imported","defProviders","USE_VALUE","isValueProvider","isTypeProvider","INJECTOR_SCOPE","NOT_YET","CIRCULAR","NULL_INJECTOR","getNullInjector","EnvironmentInjector","R3Injector","scopes","_onDestroyHooks","forEachSingleProvider","processProvider","records","makeRecord","injectorDefTypes","assertNotDestroyed","service","_ngOnDestroyHooks","previousInjector","couldBeInjectableType","injectableDefInScope","injectableDefOrInjectorDefFactory","hydrate","catchInjectorError","injectorErrorName","tokenPath","resolveInjectorInitializers","initializers","initializer","providerToRecord","providerToFactory","multiRecord","hasOnDestroy","getUndecoratedInjectableFactory","paramLength","inheritedInjectableDef","getInheritedInjectableDef","ngModuleType","unwrappedProvider","isFactoryProvider","isExistingProvider","classRef","hasDeps","ComponentRef","ComponentFactory","_NullComponentFactoryResolver","noComponentFactoryError","ComponentFactoryResolver","injectElementRef","createElementRef","unwrapElementRef","Renderer2","injectRenderer2","nodeAtIndex","Sanitizer","Version","full","major","minor","NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR","ERROR_ORIGINAL_ERROR","getOriginalError","_console","originalError","_findOriginalError","ɵɵresolveWindow","ɵɵresolveDocument","maybeUnwrapFn","classIndexOf","classToSearch","startingIndex","NG_TEMPLATE_SELECTOR","isCssClassMatching","cssClassToMatch","isProjectionMode","isImplicitAttrsSection","isInlineTemplate","hasTagAndTypeMatch","currentSelector","isNodeMatchingSelector","nodeAttrs","nameOnlyMarkerIdx","getNameOnlyMarkerIndex","skipToNextSelector","isPositive","selectorAttrValue","attrIndexInNode","findAttrIndexInNode","nodeAttrValue","compareAgainstClassName","bindingsMode","maybeAttrName","matchTemplateAttribute","isNodeMatchingSelectorList","selectorListLoop","currentSelectorInList","maybeWrapInNotSelector","isNegativeMode","stringifyCSSSelector","valueOrMarker","attrValue","ɵɵadvance","selectIndexInternal","checkNoChangesMode","createInjector","additionalProviders","createInjectorWithoutInjectorInstances","importProvidersFrom","ɵɵdirectiveInject","ɵɵinvalidFactory","refreshContentQueries","directiveDefIdx","createLView","tHostNode","getUniqueLViewId","getOrCreateTNode","createTNodeAtIndex","setCurrentTNode","tParent","insertBeforeIndex","directiveStylingLast","propertyBindings","localNames","initialInputs","stylesWithoutHost","residualStyles","classesWithoutHost","residualClasses","classBindings","styleBindings","createTNode","allocExpando","numSlotsToAlloc","initialValue","allocIdx","renderView","executeViewQueryFn","templateFn","executeTemplate","staticContentQueries","staticViewQueries","renderChildComponents","hostLView","renderComponent","incompleteFirstPass","refreshView","setBindingIndex","hooksInitPhaseCompleted","incrementInitPhaseFlags","markTransplantedViewsForRefresh","movedLView","refreshEmbeddedViews","embeddedLView","embeddedTView","hostBindingOpCodes","opCode","directiveIdx","bindingRootIndx","hostBindingFn","setBindingRootForHostBindings","processHostBindingOpCodes","refreshChildComponents","refreshComponent","firstUpdatePass","prevSelectedIndex","isUpdatePhase","executeContentQueries","createDirectivesInstances","instantiateAllDirectives","addComponentLogic","hostTNode","getOrCreateComponentTView","componentView","addToViewTree","getOrCreateNodeInjectorForNode","setInputsFromAttrs","invokeDirectivesHostBindings","saveResolvedLocalsInData","viewData","localRefExtractor","localIndex","createTView","pipes","constsOrFactory","initialViewLength","createViewBlueprint","NO_CHANGE","expandoStartIndex","directiveRegistry","pipeRegistry","storeCleanupWithContext","cleanupFn","getOrCreateLViewCleanup","getOrCreateTViewCleanup","generatePropertyAliases","aliasMap","propertyAliases","hostDirectiveAliasMap","internalName","addPropertyAlias","elementPropertyInternal","nativeOnly","dataValue","inputData","setInputsForProperty","viewIndex","childComponentLView","markDirtyIfOnPush","mapPropName","resolveDirectives","localRefs","exportsMap","matchResult","findDirectiveDefMatches","registry","hostDirectiveDefs","hostDirectiveMatches","markAsComponentHost","initializeDirectives","cacheMatchingLocalNames","mergeHostAttrs","initTNodeFlags","numberOfDirectives","preOrderHooksFound","preOrderCheckHooksFound","configureViewWithDirective","saveNameToExportMap","lifeCycleHooks","initializeInputAndOutputAliases","hostDirectiveDefinitionMap","tViewData","tNodeAttrs","inputsFromAttrs","inputsStore","outputsStore","aliasData","aliasedOutputs","generateInitialInputs","elementIndex","getCurrentDirectiveIndex","dirIndex","invokeHostBindingsInCreationMode","directiveFactory","nodeInjectorFactory","registerHostBindingOpCodes","directiveVarsIdx","elementIndx","lastSelectedElementIdx","initialInputData","inputsToStore","inputConfig","createLContainer","hostNative","componentHostIdx","refreshContainsDirtyView","componentTView","syncViewWithBlueprint","markViewDirty","detectChangesInternal","notifyErrorHandler","viewQueryFn","loadComponentRenderer","currentDef","unwrapLView","errorHandler","textBindingInternal","getNativeByIndex","computeStaticStyling","writeToHost","concatStringsWithSpace","lNode","lViewInAContainer","lViewFirstChildTNode","collectNativeNodes","nodesInSlot","ViewRef","_cdRefInjectingView","_attachedToViewContainer","viewRefs","destroyLView","reattach","checkNoChanges","attachToViewContainerRef","detachFromAppRef","renderDetachView","attachToAppRef","RootViewRef","_view","AbstractComponentFactoryResolver","componentDef","toRefArray","nonMinified","templateName","ChainedInjector","parentInjector","AbstractComponentFactory","componentType","stringifyCSSSelectorList","selectorList","isBoundToModule","rootSelectorOrNode","environmentInjector","realEnvironmentInjector","rootViewInjector","hostRenderer","elementName","hostRNode","locateHostElement","elementOrSelector","ShadowDom","getNamespace","rootFlags","rootTView","rootLView","tElementNode","rootComponentDef","rootDirectives","createRootComponentTNode","createRootComponentView","applyRootComponentStyling","viewRenderer","setRootNodeAttributes","extractAttrsAndClassesFromSelector","projectNodes","nodesforSlot","createRootComponent","hostFeatures","rootTNode","LifecycleHooksFeature","AbstractComponentRef","_rootLView","changeDetectorRef","registerPostOrderHooks","ɵɵInheritDefinitionFeature","superType","getSuperType","shouldInheritFields","inheritanceChain","superDef","writeableDef","maybeUnwrapEmpty","superHostBindings","inheritHostBindings","superViewQuery","superContentQueries","inheritViewQuery","inheritContentQueries","fillProperties","defData","mergeHostAttrsAcrossInheritance","prevViewQuery","prevContentQueries","prevHostBindings","ɵɵHostDirectivesFeature","rawHostDirectives","bindingArrayToMap","matchedDefs","hostDirectiveConfig","hostDirectiveDef","patchDeclaredInputs","bindings","exposedInputs","isListLikeIterable","isJsObject","updateBinding","bindingUpdated","bindingUpdated2","exp1","exp2","different","bindingUpdated3","exp3","exp4","ɵɵattribute","setElementAttribute","elementAttributeInternal","interpolation1","v1","ɵɵtemplate","attrsIndex","localRefsIndex","adjustedIndex","templateFirstCreatePass","tViewConsts","getConstant","comment","ɵɵreference","getContextLView","ɵɵproperty","setDirectiveInputsWhichShadowsStyling","isClassBased","ɵɵelementStart","elementStartFirstCreatePass","elementStart","hasDirectives","getElementDepthCount","increaseElementDepthCount","ɵɵelementEnd","decreaseElementDepthCount","elementEnd","hasClassInput","hasStyleInput","ɵɵelement","ɵɵelementContainerStart","elementContainerStartFirstCreatePass","ɵɵelementContainerEnd","ɵɵelementContainer","ɵɵgetCurrentView","isSubscribable","isObservable","ɵɵlistener","listenerFn","useCapture","eventTargetResolver","listenerInternal","ɵɵsyntheticHostListener","isTNodeDirectiveHost","processOutputs","lCleanupIndex","idxOrTargetGetter","existingListener","findExistingListener","tNodeIdx","cleanupEventName","listenerIdxInLCleanup","__ngLastListenerFn__","__ngNextListenerFn__","wrapListener","propsLength","executeListenerWithErrorHandling","wrapWithPreventDefault","wrapListenerIn_markDirtyAndPreventDefault","nextListenerFn","returnValue","nextContextImpl","walkUpViews","nestingLevel","projectionSlots","wildcardNgContentIndex","ngProjectAsAttrVal","getProjectAsAttrValue","ngProjectAsAttrIdx","isSelectorInSelectorList","ɵɵprojectionDef","componentNode","projectionHeads","tails","componentChild","slotIndex","matchingProjectionSlotIndex","ɵɵprojection","selectorIndex","applyProjection","ɵɵpropertyInterpolate","ɵɵpropertyInterpolate1","interpolatedValue","interpolation2","ɵɵpropertyInterpolate2","getTStylingRangePrev","tStylingRange","setTStylingRangePrevDuplicate","getTStylingRangeNext","setTStylingRangeNextDuplicate","markDuplicates","tStylingKey","isPrevDir","isClassBinding","tStylingAtIndex","foundDuplicate","tStyleRangeAtCursor","isStylingMatch","tStylingKeyCursor","parserState","textEnd","valueEnd","getLastParsedKey","getLastParsedValue","consumeClassToken","consumeWhitespace","consumeStyleKey","consumeSeparator","consumeStyleValue","ch1","ch2","ch3","lastChIndex","consumeQuotedText","resetParserState","quoteCharCode","ɵɵstyleProp","checkStylingProperty","ɵɵclassProp","ɵɵstyleMap","checkStylingMap","styleKeyValueArraySet","styleStringParser","parseStyle","parseStyleNext","ɵɵclassMap","classKeyValueArraySet","classStringParser","parseClassName","parseClassNameNext","stylingFirstUpdatePass","updateStyling","normalizeSuffix","stringParser","hasStylingInputShadow","isInHostBindings","staticPrefix","updateStylingMap","oldKeyValueArray","newKeyValueArray","oldIndex","oldKey","newKey","setKey","toStylingKeyValueArray","styleKeyValueArray","unwrappedValue","isHostBindings","wrapInStaticStylingKey","stylingKey","residual","collectStylingFromTAttrs","collectStylingFromDirectives","templateStylingKey","getTemplateHeadTStylingKey","setTemplateHeadTStylingKey","collectResidual","tStylingKeyWithStatic","isHostBinding","tBindings","tmplHead","tmplTail","isKeyDuplicateOfStatic","toTStylingRange","setTStylingRangeNext","setTStylingRangePrev","markDuplicateOfResidualStyling","insertTStylingBinding","currentDirective","desiredMarker","currentMarker","stringKey","tRange","higherPriorityValue","getTStylingRangeNextDuplicate","findStylingValue","isStylingValuePresent","getTStylingRangePrevDuplicate","applyStyling","DashCase","Important","isPrevDirection","rawKey","containsStatics","isStylingMap","valueAtLViewIndex","keyValueArrayGet","ɵɵtext","textNative","ɵɵtextInterpolate","ɵɵtextInterpolate1","interpolated","ɵɵtextInterpolate2","interpolation3","ɵɵtextInterpolate3","ɵɵclassMapInterpolate1","ɵɵclassMapInterpolate2","ɵɵhostProperty","ɵɵsyntheticHostProperty","LOCALE_DATA","findLocaleData","normalizedLocale","normalizeLocale","getLocaleData","parentLocale","localeEn","getLocalePluralCase","LocaleDataIndex","PluralCase","ng","common","pluralMapping","DEFAULT_LOCALE_ID","ELEMENT_MARKER","ICU_MARKER","I18nCreateOpCode","setLocaleId","assertDefined","tNodeInsertBeforeIndex","i18nParent","anchorRNode","previousTNodes","newTNode","existingTNode","isI18nText","isNewTNodeCreatedBefore","getInsertBeforeIndex","setInsertBeforeIndex","setI18nHandling","createTNodePlaceholder","addTNodeAndUpdateInsertBeforeIndex","tIcu","currentCase","currentCaseLViewIndex","getParentFromIcuCreateOpCode","mergedCode","getRefFromIcuCreateOpCode","changeMask","changeMaskCounter","applyMutableOpCodes","mutableOpCodes","rootRNode","rootIdx","textNodeIndex","parentIdx","insertInFrontOf","refIdx","getTIcu","caseIndex","getCurrentICUCaseIndex","anchorIdx","commentValue","commentNodeIndex","createCommentNode","elementNodeIndex","applyUpdateOpCodes","updateOpCodes","bindingsStartIndex","checkBit","skipCodes","sanitizeFn","tNodeOrTagName","rText","applyIcuSwitchCase","applyIcuUpdateCase","activeCaseIndex","mask","getCaseIndex","icuExpression","bindingValue","resolvedCase","getPluralCase","applyIcuSwitchCaseRemove","removeCodes","nodeOrIcuIndex","loadIcuContainerVisitor","_stack","_removes","_index","enterIcu","icuContainerIteratorNext","removeOpCode","icuContainerIteratorStart","BINDING_REGEXP","NESTED_ICU","ICU_BLOCK_REGEXP","MARKER","SUBTEMPLATE_REGEXP","PH_REGEXP","NGSP_UNICODE_REGEXP","createTNodeAndAddOpCode","existingTNodes","createOpCodes","isICU","i18nNodeIdx","APPEND_EAGERLY","COMMENT","ensureIcuContainerVisitorLoaded","assertEqual","setTNodeInsertBeforeIndex","i18nStartFirstCreatePassProcessTextNode","hasBinding","generateBindingUpdateOpCodes","destinationNode","bindingStart","maskIndex","sizeIndex","textParts","textValue","toMaskBit","removeInnerTemplateTranslation","tagMatched","inTemplate","bindingMask","addUpdateIcuSwitch","mainBinding","setTIcu","valueArr","nestedIcus","icuIndex","parseIcuCase","addUpdateIcuUpdate","parseICUBlock","icuType","i18nParseTextIntoPartsAndICU","binding","blocks","braceStack","braces","block","caseName","unsafeCaseHtml","inertRootNode","walkIcuTree","sharedUpdateOpCodes","depth","addCreateNodeAndAppend","lowerAttrName","addCreateAttribute","addRemoveNode","COMMENT_NODE","isNestedIcu","icuStart","addRemoveNestedIcu","appendToParentIdx","createAtIdx","icuCreateOpCode","ɵɵi18nStart","messageIndex","subTemplateIndex","parentTNodeIndex","existingTNodeStack","isRootTemplateMessage","getTranslationForTemplate","msgParts","replaceNgsp","isClosing","i18nStartFirstCreatePass","tI18n","applyCreateOpCodes","appendNow","ɵɵi18n","ɵɵi18nEnd","ɵɵi18nExp","setMaskBit","hasChange","ɵɵi18nApply","applyI18n","resolveProvider","lInjectablesBlueprint","providerFactory","beginIndex","existingFactoryIndex","registerDestroyHooksIfSupported","existingProvidersFactoryIndex","existingViewProvidersFactoryIndex","doesViewProvidersFactoryExist","multiFactory","factoryFn","componentProviders","multiFactoryAdd","multiViewProvidersFactoryResolver","multiProvidersFactoryResolver","contextIndex","indexInFactory","providerIsTypeProvider","providerIsClassProvider","isClassProvider","existingCallbacksIndex","isComponentProvider","lData","multiResolve","factories","componentCount","multiProviders","ɵɵProvidersFeature","viewProviders","processProvidersFn","NgModuleRef","NgModuleFactory","viewEngine_NgModuleRef","_parent","_bootstrapComponents","destroyCbs","_r3Injector","viewEngine_ComponentFactoryResolver","viewEngine_NgModuleFactory","moduleType","EnvironmentNgModuleRefAdapter","createEnvironmentInjector","debugName","StandaloneService","getOrCreateStandaloneInjector","cachedInjectors","standaloneInjector","defineInjectable","ɵɵStandaloneFeature","ɵɵpureFunction0","slotOffset","pureFn","getBinding","ɵɵpureFunction1","pureFunction1Internal","ɵɵpureFunction2","pureFunction2Internal","pureFunction3Internal","pureFunction4Internal","ɵɵpureFunction5","exp5","bindingUpdated4","ɵɵpureFunction6","exp6","getPureFunctionReturnValue","returnValueIndex","lastReturnValue","bindingRoot","pipeName","pipeFactory","pipeInstance","ɵɵpipeBind1","isPure","ɵɵpipeBind2","ɵɵpipeBind3","v3","ɵɵpipeBindV","exps","pureFunctionVInternal","_wrapInTimeout","EventEmitter_","isAsync","__isAsync","nextFn","errorFn","completeFn","symbolIterator","_results","_changes","_emitDistinctChangesOnly","dirty","_changesDetected","proto","resultsTree","identityAccessor","newResultFlat","flatten","flat","arrayEquals","valueA","valueB","notifyOnChanges","setDirty","TemplateRef","injectTemplateRef","ViewEngineTemplateRef","R3TemplateRef","_declarationLView","_declarationTContainer","declarationViewLQueries","R3_ViewRef","createTemplateRef","ViewContainerRef","injectViewContainerRef","createContainerRef","VE_ViewContainerRef","R3ViewContainerRef","_lContainer","_hostTNode","_hostLView","getViewRefs","indexOrOptions","insert","componentFactoryOrType","isComponentFactory","isType","ngModuleRef","R3ComponentFactory","contextInjector","viewAttachedToContainer","prevIdx","prevLContainer","prevVCRef","adjustedIdx","_adjustIndex","insertView","containerLength","trackMovedView","parentNativeNode","addViewToContainer","getOrCreateViewRefs","viewRefsArr","detachedView","R3ViewRef","commentNode","nativeNextSibling","LQuery_","queryList","LQueries_","tQueries","noOfInheritedQueries","viewLQueries","tQuery","getByIndex","indexInDeclarationView","dirtyQueriesWithMatches","getTQuery","TQueryMetadata_","TQueries_","queriesForTemplateRef","childQueryIndex","tqueryClone","tquery","TQuery_","crossesNgTemplate","_appliesToNextNode","_declarationNodeIndex","isApplyingToNode","matchTNode","addMatch","declarationNodeIdx","matchTNodeWithReadOption","getIdxOfMatchingSelector","ViewEngine_TemplateRef","nodeMatchIdx","ViewEngine_ElementRef","directiveOrProviderIdx","matchIdx","createResultForNode","matchingIdx","createResultByTNodeType","createSpecialToken","materializeViewResults","queryIndex","lQuery","tQueryMatches","matchedNodeIdx","collectQueryResults","lViewResults","embeddedLViews","ɵɵqueryRefresh","isCreationMode","ɵɵviewQuery","createTQuery","createLQuery","ɵɵcontentQuery","saveContentQueryAndDirectiveIndex","tViewContentQueries","ɵɵloadQuery","loadQueryInternal","isNgModule","ApplicationInitStatus","appInits","donePromise","rej","runInitializers","asyncInitPromises","initResult","observableAsPromise","APP_ID","_appIdRandomProviderFactory","_randomChar","PLATFORM_INITIALIZER","getGlobalLocale","$localize","DEFAULT_CURRENCY_CODE","ModuleWithComponentFactories","ngModuleFactory","componentFactories","compileModuleSync","NgModuleFactoryR3","compileModuleAsync","compileModuleAndAllComponentsSync","ComponentFactoryR3","compileModuleAndAllComponentsAsync","clearCache","clearCacheFor","getModuleId","Zone","enableLongStackTrace","shouldCoalesceEventChangeDetection","shouldCoalesceRunChangeDetection","hasPendingMacrotasks","hasPendingMicrotasks","assertZonePatched","_nesting","_outer","_inner","TaskTrackingZoneSpec","longStackTraceZoneSpec","lastRequestAnimationFrameId","nativeRequestAnimationFrame","getNativeRequestAnimationFrame","nativeCancelAnimationFrame","unpatchedRequestAnimationFrame","__symbol__","unpatchedCancelAnimationFrame","forkInnerZoneWithAngularBehavior","delayChangeDetectionForEventsDelegate","delayChangeDetectionForEvents","isCheckStableRunning","fakeTopEventTask","scheduleEventTask","updateMicroTaskStatus","checkStable","invoke","isAngularZone","onInvokeTask","applyThis","applyArgs","onEnter","invokeTask","onLeave","onInvoke","onHasTask","hasTaskState","hasTask","_hasPendingMicrotasks","microTask","macroTask","onHandleError","isInAngularZone","runTask","EMPTY_PAYLOAD","cancelTask","runGuarded","onMicrotaskEmpty","onUnstable","NoopNgZone","TESTABILITY","TESTABILITY_GETTER","_testabilityGetter","Testability","testabilityGetter","_pendingCount","_isZoneStable","_didWork","_callbacks","taskTrackingZone","setTestabilityGetter","getter","addToWindow","_watchAngularEvents","assertNotInAngularZone","_runCallbacksIfReady","increasePendingRequestCount","decreasePendingRequestCount","timeoutId","doneCb","getPendingTasks","updateCb","macroTasks","creationLocation","addCallback","whenStable","getPendingRequestCount","registerApplication","unregisterApplication","findProviders","using","exactMatch","TestabilityRegistry","testability","_applications","unregisterAllApplications","getTestability","getAllTestabilities","getAllRootElements","findTestabilityInTree","findInAncestors","NG_DEV_MODE","_platformInjector","ALLOW_MULTIPLE_PLATFORMS","PLATFORM_DESTROY_LISTENERS","APP_BOOTSTRAP_LISTENER","NgProbeToken","createPlatformFactory","parentPlatformFactory","extraProviders","getPlatform","platformProviders","createPlatform","PlatformRef","runPlatformInitializers","inits","createPlatformInjector","assertPlatform","requiredToken","_modules","_destroyListeners","bootstrapModuleFactory","moduleFactory","getNgZone","ngZoneToUse","getNgZoneOptions","ngZoneEventCoalescing","ngZoneRunCoalescing","ngZoneInjector","moduleRef","exceptionHandler","_callAndReportToErrorHandler","initStatus","_moduleDoBootstrap","compilerOptions","optionsReducer","compileNgModuleFactory","R3NgModuleFactory","ngDoBootstrap","destroyListeners","objs","_exceptionHandler","_bootstrapListeners","_views","_runningTick","_stable","componentTypes","_onMicrotaskEmptySubscription","isCurrentlyStable","stableSub","unstableSub","assertInAngularZone","componentOrFactory","compRef","NULL","_loadComponent","warnIfDestroyed","isDevMode","ChangeDetectorRef","injectChangeDetectorRef","createViewRef","isPipe","DefaultIterableDifferFactory","trackByFn","DefaultIterableDiffer","trackByIdentity","_linkedRecords","_unlinkedRecords","_previousItHead","_itHead","_itTail","_additionsHead","_additionsTail","_movesHead","_movesTail","_removalsHead","_removalsTail","_identityChangesHead","_identityChangesTail","nextIt","nextRemove","addRemoveOffset","moveOffsets","getPreviousIndex","adjPreviousIndex","_nextRemoved","localMovePreviousIndex","localCurrentIndex","forEachPreviousItem","_nextPrevious","_nextAdded","forEachMovedItem","_nextMoved","_nextIdentityChange","_reset","itemTrackBy","mayBeDirty","trackById","_verifyReinsertion","_addIdentityChange","_mismatch","iterateListLike","_truncate","isDirty","previousRecord","_prev","_remove","_reinsertAfter","_moveAfter","_addAfter","IterableChangeRecord_","reinsertRecord","_addToMoves","nextRecord","_addToRemovals","_unlink","prevRecord","_prevRemoved","_insertAfter","_DuplicateMap","toIndex","_prevDup","_nextDup","_DuplicateItemRecordList","_head","_tail","atOrAfterIndex","duplicates","recordList","moveOffset","DefaultKeyValueDifferFactory","DefaultKeyValueDiffer","_mapHead","_appendAfter","_previousMapHead","_changesHead","_changesTail","_nextChanged","_forEach","_maybeAddToChanges","_getOrCreateRecordForKey","_insertBeforeOrAppend","_records","KeyValueChangeRecord_","_addToAdditions","_addToChanges","defaultIterableDiffersFactory","IterableDiffers","copied","defaultKeyValueDiffersFactory","KeyValueDiffers","platformCore","ApplicationModule","coerceToBoolean","elementInjector","BaseControlValueAccessor","registerOnTouched","onTouched","registerOnChange","setDisabledState","BuiltInControlValueAccessor","NG_VALUE_ACCESSOR","CHECKBOX_VALUE_ACCESSOR","CheckboxControlValueAccessor","writeValue","DEFAULT_VALUE_ACCESSOR","DefaultValueAccessor","COMPOSITION_BUFFER_MODE","_compositionMode","_composing","_isAndroid","getUserAgent","_handleInput","_compositionStart","_compositionEnd","isEmptyInputValue","hasValidLength","NG_VALIDATORS","NG_ASYNC_VALIDATORS","EMAIL_REGEXP","Validators","minValidator","maxValidator","requiredValidator","requiredTrueValidator","emailValidator","email","minLength","minLengthValidator","minlength","requiredLength","actualLength","maxLength","maxLengthValidator","patternValidator","nullValidator","regex","regexStr","requiredPattern","actualValue","validators","compose","composeAsync","required","maxlength","isPresent","toObservable","errorMessage","mergeErrors","arrayOfErrors","executeValidators","validator","normalizeValidators","isValidatorFn","validate","presentValidators","composeValidators","composeAsyncValidators","controlValidators","dirValidator","getControlValidators","_rawValidators","getControlAsyncValidators","_rawAsyncValidators","makeValidatorsArray","currentValidators","validatorsToAdd","hasValidator","AbstractControlDirective","_onDestroyCallbacks","invalid","pristine","untouched","statusChanges","valueChanges","_setValidators","_composedValidatorFn","_setAsyncValidators","_composedAsyncValidatorFn","asyncValidator","_registerOnDestroy","_invokeOnDestroyCallbacks","errorCode","getError","ControlContainer","formDirective","NgControl","valueAccessor","AbstractControlStatus","cd","_cd","isTouched","isUntouched","isPristine","isInvalid","isPending","isSubmitted","submitted","NgControlStatus","NgControlStatusGroup","describeKey","isFormGroup","VALID","INVALID","PENDING","DISABLED","pickValidators","validatorOrOpts","isOptionsObj","asyncValidators","AbstractControl","_pendingDirty","_hasOwnPendingAsyncValidator","_pendingTouched","_onDisabledChange","_assignValidators","_assignAsyncValidators","validatorFn","asyncValidatorFn","updateOn","_updateOn","setValidators","setAsyncValidators","addValidators","addAsyncValidators","removeValidators","removeAsyncValidators","hasAsyncValidator","clearValidators","clearAsyncValidators","markAsTouched","onlySelf","markAllAsTouched","_forEachChild","markAsUntouched","_updateTouched","markAsDirty","markAsPristine","_updatePristine","markAsPending","emitEvent","skipPristineCheck","_parentMarkedDirty","_updateValue","_updateAncestors","changeFn","updateValueAndValidity","setParent","getRawValue","_setInitialStatus","_cancelExistingSubscription","_runValidator","_calculateStatus","_runAsyncValidator","_updateTreeValidity","ctrl","_allControlsDisabled","_asyncValidationSubscription","setErrors","_updateControlsErrors","currPath","_find","_initObservables","_anyControlsHaveStatus","_anyControls","_anyControlsDirty","_anyControlsTouched","_registerOnCollectionChange","_onCollectionChange","_setUpdateStrategy","coerceToValidator","coerceToAsyncValidator","FormGroup","pickAsyncValidators","_setUpControls","registerControl","addControl","removeControl","setControl","controlName","assertAllValuesPresent","isGroup","missingControlValueError","assertControlPresent","noControlsError","missingControlError","patchValue","_reduceChildren","_syncPendingControls","subtreeUpdated","_reduceValue","initValue","CALL_SET_DISABLED_STATE","setDisabledStateDefault","setUpControl","callSetDisabledState","setUpValidators","setUpViewChangePipeline","_pendingValue","_pendingChange","updateControl","setUpModelChangePipeline","emitModelEvent","viewToModelUpdate","_unregisterOnChange","setUpBlurPipeline","onDisabledChange","registerOnDisabledChange","_unregisterOnDisabledChange","setUpDisabledChangeHandler","cleanUpControl","validateControlPresenceOnChange","cleanUpValidators","registerOnValidatorChange","mergeValidators","onValidatorChange","isControlUpdated","updatedValidators","updatedAsyncValidators","emitModelToViewChange","viewModel","model","valueAccessors","defaultAccessor","builtinAccessor","customAccessor","isBuiltInAccessor","formDirectiveProvider","NgForm","resolvedPromise","_findContainer","_directives","getControl","addFormGroup","setUpFormContainer","removeFormGroup","getFormGroup","updateModel","onSubmit","$event","syncPendingControls","ngSubmit","onReset","resetForm","isFormControlState","formState","FormControl","_onChange","_applyFormState","nonNullable","initialValueIsDefault","emitViewToModelChange","removeListItem","formControlBinding","NgModel","_registered","selectValueAccessor","_checkForErrors","_checkName","oldName","_getPath","_setUpControl","_updateDisabled","isPropertyUpdated","_isStandalone","_setUpStandalone","_checkParentType","disabledValue","controlPath","ɵNgNoValidate","RadioControlRegistryModule","NG_MODEL_WITH_FORM_CONTROL_WARNING","FormGroupDirective","_updateDomValue","_checkFormPresent","_updateValidators","_updateRegistrations","_oldForm","_setUpFormContainer","_cleanUpFormContainer","addFormArray","removeFormArray","getFormArray","oldCtrl","newCtrl","isFormControl","cleanUpFormContainer","controlNameBinding","FormControlName","_ngModelWarningConfig","_added","_ngModelWarningSent","_ngModelWarningSentOnce","AbstractValidatorDirective","_validator","inputName","normalizeInput","createValidator","REQUIRED_VALIDATOR","RequiredValidator","CHECKBOX_REQUIRED_VALIDATOR","CheckboxRequiredValidator","MAX_LENGTH_VALIDATOR","MaxLengthValidator","toInteger","ɵInternalFormsSharedModule","warnOnNgModelWithFormControl","MATERIAL_SANITY_CHECKS","MATERIAL_SANITY_CHECKS_FACTORY","MatCommonModule","_sanityChecks","_hasDoneGlobalChecks","_checkIsEnabled","mixinDisabled","defaultColor","_color","colorPalette","mixinDisableRipple","disableRipple","_disableRipple","mixinTabIndex","defaultTabIndex","_tabIndex","RippleRef","_animationForciblyDisabledThroughCss","fadeOut","fadeOutRipple","passiveCapturingEventOptions","RippleEventManager","handleEvent","addHandler","handlersForEvent","handlersForElement","_delegateEventHandler","removeHandler","enterDuration","exitDuration","pointerDownEvents","pointerUpEvents","RippleRenderer","_target","_isPointerDown","_pointerUpEventsRegistered","fadeInRipple","animationConfig","defaultRippleAnimationConfig","centered","radius","distanceToFurthestCorner","distX","distY","ripple","transitionDuration","computedStyles","userTransitionDuration","animationForciblyDisabledThroughCss","transitionProperty","rippleRef","persistent","_mostRecentTransientRipple","onTransitionEnd","_finishRippleTransition","onTransitionCancel","_destroyRipple","_activeRipples","rippleEl","fadeOutAll","_getActiveRipples","fadeOutAllNonPersistent","setupTriggerEvents","_triggerElement","_removeTriggerEvents","_eventManager","_onTouchStart","_onPointerUp","_startFadeOutTransition","isMostRecentTransientRipple","isFakeMousedown","isSyntheticEvent","_lastTouchStartEvent","rippleDisabled","clientY","rippleConfig","terminateOnPointerUp","MAT_RIPPLE_GLOBAL_OPTIONS","MatRipple","_setupTriggerEventsIfEnabled","_trigger","globalOptions","_animationMode","_globalOptions","_rippleRenderer","launch","configOrX","MatRippleModule","MatPseudoCheckboxModule","DialogConfig","ariaDescribedBy","ariaLabelledBy","ariaLabel","ariaModal","closeOnNavigation","closeOnDestroy","closeOnOverlayDetachments","CdkDialogContainer","_focusTrapFactory","_interactivityChecker","_focusMonitor","_elementFocusedBeforeDialogWasOpened","_closeInteractionType","_contentAttached","_ariaLabelledBy","_initializeFocusTrap","_handleBackdropClicks","_captureInitialFocus","_trapFocus","_restoreFocus","_recaptureFocus","_containsFocus","_forceFocus","_focusByCssSelector","elementToFocus","_focusTrap","focusedSuccessfully","_focusDialogContainer","focusConfig","focusTargetElement","DialogRef","focusOrigin","_detachSubscription","containerInstance","closedSubject","DIALOG_SCROLL_STRATEGY","DIALOG_DATA","DEFAULT_DIALOG_CONFIG","DIALOG_SCROLL_STRATEGY_PROVIDER","DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY","uniqueId","Dialog","openDialogs","_parentDialog","_openDialogsAtThisLevel","_afterOpenedAtThisLevel","_overlay","_defaultOptions","afterAllClosed","_getAfterAllClosed","getDialogById","_getOverlayConfig","dialogContainer","_attachContainer","_attachDialogContent","_hideNonDialogContentFromAssistiveTechnology","_removeOpenDialog","reverseForEach","_afterAllClosedAtThisLevel","userInjector","containerType","containerPortal","_createInjector","templateContext","contentRef","fallbackInjector","_ariaHiddenElements","overlayContainer","siblings","DialogModule","delayFocusTrap","_MatDialogContainerBase","focusTrapFactory","interactivityChecker","focusMonitor","_openAnimationDone","_animationStateChanged","i2.MatDialogConfig","MatDialogRef","_containerInstance","_afterOpened","_closeFallbackTimeout","_finishDialogClose","_beforeClosed","_result","_closeDialogVia","interactionType","dialogResult","_startExitAnimation","beforeClosed","_MatDialogBase","_dialogRefConstructor","_dialogContainerType","_dialogDataToken","_idPrefix","dialogConfigClass","_dialog","cdkRef","cdkConfig","_closeDialogs","dialogs","enterAnimationDuration","exitAnimationDuration","matDialogAnimations","animateChild","_defaultParams","MatLegacyDialogConfig","DialogConfigBase","MatLegacyDialogContainer","_onAnimationDone","_onAnimationStart","checker","_getAnimationState","i2.MatLegacyDialogConfig","i4","MatLegacyDialogRef","NewDialogRef","MAT_LEGACY_DIALOG_DATA","MAT_LEGACY_DIALOG_DEFAULT_OPTIONS","MAT_LEGACY_DIALOG_SCROLL_STRATEGY","MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER","MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY","MatLegacyDialog","parentDialog","animationMode","i1$1","MatLegacyDialogModule","MAT_MENU_PANEL","_MatMenuItemBase","MatMenuItem","_parentMenu","_highlighted","_triggersSubmenu","addItem","_getHostElement","_focused","_hovered","_getTabIndex","_checkDisabled","_handleMouseEnter","icons","_setHighlighted","isHighlighted","_setTriggersSubmenu","triggersSubmenu","_hasFocus","MAT_MENU_CONTENT","_MatMenuContentBase","_portal","_outlet","_attached","transformMenu","fadeInItems","menuPanelUid","MAT_MENU_DEFAULT_OPTIONS","MAT_MENU_DEFAULT_OPTIONS_FACTORY","overlapTrigger","yPosition","_MatMenuBase","setPositionClasses","_yPosition","_overlapTrigger","_hasBackdrop","previousPanelClass","_previousPanelClass","_classList","_panelAnimationState","overlayPanelClass","_updateDirectDescendants","_keyManager","_directDescendantItems","focusedItem","itemsList","_firstItemFocusSubscription","_item","_handleKeydown","parentMenu","focusFirstItem","menuPanel","resetActiveItem","setElevation","elevation","_baseElevation","newElevation","_elevationPrefix","customElevation","_previousElevation","posX","posY","_startAnimation","_resetAnimation","_animationDone","_isAnimating","_allItems","MAT_MENU_SCROLL_STRATEGY","MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER","MAT_MENU_SCROLL_STRATEGY_FACTORY","passiveEventListenerOptions","_MatMenuTriggerBase","_deprecatedMatMenuTriggerFor","_menu","_menuCloseSubscription","_destroyMenu","_parentMaterialMenu","_menuItemInstance","_dir","_menuOpen","_openedBy","_handleTouchStart","_handleHover","_closingActionsSubscription","_hoverSubscription","menuOpen","closeMenu","openMenu","_createOverlay","_setPosition","_getPortal","lazyContent","menuData","_menuClosingActions","_initMenu","_setIsMenuOpen","_setMenuElevation","isOpen","_subscribeToPositions","positionChanges","originFallbackX","overlayFallbackY","originFallbackY","overlayFallbackX","_parentInnerPadding","offsetTop","parentClose","_handleMousedown","_handleClick","ctx_r1","ctx_r3","ctx_r4","MatLegacyMenu","matMenuAnimations","MatLegacyMenuTrigger","MatLegacyMenuContent","MatLegacyMenuModule","GenericBrowserDomAdapter","supportsDOMEvents","BrowserDomAdapter","onAndCancel","getDefaultDocument","createHtmlDocument","isShadowRoot","DocumentFragment","getBaseElementHref","baseElement","relativePath","urlParsingNode","pathName","resetBaseElement","TRANSITION_ID","SERVER_TRANSITION_PROVIDERS","appInitializerFactory","transitionId","dom","BrowserXhr","EVENT_MANAGER_PLUGINS","EventManager","plugins","plugin","_plugins","_findPluginFor","addGlobalEventListener","getZone","_eventNameToPlugin","EventManagerPlugin","SharedStylesHost","addStyles","changeUsageCount","onStyleAdded","removeStyles","onStyleRemoved","getAllStyles","usageCount","usage","DomSharedStylesHost","resetHostNodes","hostNodes","addStyleToHost","styleRef","addHost","hostNode","removeHost","styleEl","styleElRef","xhtml","xlink","xml","xmlns","math","COMPONENT_REGEX","COMPONENT_VARIABLE","HOST_ATTR","CONTENT_ATTR","REMOVE_STYLES_ON_COMPONENT_DESTROY","compId","decoratePreventDefault","eventHandler","eventManager","sharedStylesHost","appId","removeStylesOnCompDestory","defaultRenderer","DefaultDomRenderer2","getOrCreateRenderer","EmulatedEncapsulationDomRenderer2","applyToHost","NoneEncapsulationDomRenderer","applyStyles","rendererByCompId","ShadowDomRenderer","NAMESPACE_URIS","isTemplateNode","namespaceUri","removeAttributeNS","hostEl","nodeOrShadowRoot","rendererUsageCount","contentAttr","shimContentAttribute","componentShortId","hostAttr","shimHostAttribute","DomEventsPlugin","MODIFIER_KEYS","_keyMap","Del","Esc","Left","Right","Up","Down","Menu","Scroll","Win","MODIFIER_KEY_GETTERS","KeyEventsPlugin","parseEventName","parsedEvent","outsideHandler","eventCallback","fullKey","domEventName","_normalizeKey","codeIX","modifierName","fullKeyCode","keycode","modifierGetter","matchEventFullKeyCode","keyName","platformBrowser","initDomAdapter","makeCurrent","ɵsetDocument","BROWSER_MODULE_PROVIDERS_MARKER","TESTABILITY_PROVIDERS","BrowserGetTestability","testabilities","didWork","decrement","didWork_","BROWSER_MODULE_PROVIDERS","providersAlreadyPresent","Meta","_dom","addTag","forceCreation","_getOrCreateElement","addTags","getTag","attrSelector","getTags","_parseSelector","_setMetaElementAttributes","removeTag","removeTagElement","_containsAttributes","_getMetaKeyMap","META_KEYS_MAP","createMeta","httpEquiv","newTitle","createTitle","DomSanitizer","DomSanitizerImpl","allowSanitizationBypassOrThrow","bypassSecurityTrustStyle","bypassSecurityTrustScript","bypassSecurityTrustUrl","bypassSecurityTrustResourceUrl","domSanitizerImplFactory","_refCount","refCounter","sharedConnection","_connection","connect","ConnectableObservable","subjectFactory","getSubject","_teardown","higherOrderRefCount","takeLast","PRIMARY_OUTLET","RouteTitleKey","ParamsAsMap","convertToParamMap","defaultUrlMatcher","segmentGroup","pathMatch","hasChildren","posParams","consumed","equalArraysOrString","aSorted","bSorted","wrapIntoObservable","pathCompareMap","exact","equalSegmentGroups","containee","matrixParams","equalPath","matrixParamsMatch","numberOfChildren","subset","containsSegmentGroup","paramCompareMap","equalParams","shallowEqual","containsParams","ignored","containsTree","containsSegmentGroupHelper","containeePaths","containerPaths","containeeSegment","UrlTree","UrlSegmentGroup","queryParamMap","_queryParamMap","DEFAULT_SERIALIZER","serializePaths","UrlSegment","parameterMap","_parameterMap","serializePath","UrlSerializer","DefaultUrlSerializer","UrlParser","parseRootSegment","parseQueryParams","parseFragment","tree","serializeQueryParams","strParams","encodeUriQuery","encodeUriFragment","encodeURI","serializeSegment","primary","childOutlet","mapChildrenIntoArray","encodeUriString","encodeUriSegment","decodeQuery","serializeMatrixParams","SEGMENT_RE","matchSegments","QUERY_PARAM_RE","QUERY_PARAM_VALUE_RE","consumeOptional","peekStartsWith","parseChildren","parseQueryParam","parseSegment","parseParens","parseMatrixParams","parseParam","valueMatch","matchQueryParams","matchUrlQueryParamValue","decodedKey","decodedVal","currentVal","allowPrimary","outletName","createRoot","rootCandidate","De","squashSegmentGroup","newChildren","childCandidate","mergeTrivialChildren","isUrlTree","createUrlTree","urlTree","commands","nav","computeNavigation","Navigation","numberOfDoubleDots","isAbsolute","cmdIdx","outlets","segmentPath","urlPart","toRoot","createTreeUsingPathIndex","lastPathIndex","startingPosition","findStartingPosition","Position","createPositionApplyingDoubleDots","ci","dd","isMatrixParams","snapshot","_urlSegment","processChildren","updateSegmentGroupChildren","updateSegmentGroup","_lastPathIndex","isCommandWithOutlets","oldRoot","oldSegmentGroup","newSegmentGroup","qp","replaceSegment","newRoot","oldSegment","newSegment","cmdWithOutlet","prefixedWith","currentCommandIndex","currentPathIndex","noMatch","pathIndex","commandIndex","slicedCommands","createNewSegmentGroup","getOutlets","childrenOfEmptyChild","outlet","createNewSegmentChildren","IMPERATIVE_NAVIGATION","RouterEvent","navigationTrigger","restoredState","urlAfterRedirects","NavigationSkipped","GuardsCheckStart","GuardsCheckEnd","shouldActivate","ResolveStart","ResolveEnd","RouteConfigLoadStart","RouteConfigLoadEnd","ChildActivationStart","routeConfig","ChildActivationEnd","ActivationStart","ActivationEnd","routerEvent","LegacyCreateUrlTree","relativeTo","currentUrlTree","CreateUrlTreeStrategy","Tree","_root","pathFromRoot","findNode","findPath","TreeNode","nodeChildrenAsMap","RouterState","setRouterState","rootComponent","activated","ActivatedRouteSnapshot","RouterStateSnapshot","createEmptyStateSnapshot","emptyUrl","emptyParams","emptyData","emptyQueryParams","ActivatedRoute","futureSnapshot","_futureSnapshot","_routerState","paramMap","_paramMap","inheritedParamsDataResolve","paramsInheritanceStrategy","inheritingStartingFrom","flattenInherited","_resolvedData","urlSegment","_resolve","serializeNode","advanceActivatedRoute","nextSnapshot","shallowEqualArrays","equalUrlParams","equalSegments","equalParamsAndUrlSegments","createNode","routeReuseStrategy","prevState","shouldReuseRoute","createOrReuseChildren","shouldAttach","detachedRouteHandle","retrieve","createActivatedRoute","NAVIGATION_CANCELING_ERROR","urlSerializer","redirect","redirectTo","navigationBehaviorOptions","navigationCancelingError","redirectUrl","cancellationCode","isRedirectingNavigationCancelingError","isNavigationCancelingError","OutletContext","resolver","ChildrenOutletContexts","attachRef","onChildOutletCreated","getOrCreateContext","contexts","onChildOutletDestroyed","onOutletDeactivated","onOutletReAttached","RouterOutlet","_activatedRoute","isTrackedInParentContexts","deactivate","parentContexts","initializeOutletWithName","activateWith","isActivated","activatedRoute","activatedRouteData","cmp","detachEvents","attachEvents","deactivateEvents","resolverOrInjector","childContexts","OutletInjector","isComponentFactoryResolver","changeDetector","activateEvents","ɵEmptyOutletComponent","currentInjector","standardizeConfig","loadComponent","EmptyOutletComponent","getOutlet","sortedConfig","getClosestRouteInjector","_loadedInjector","ActivateRoutes","futureState","currState","forwardEvent","activate","futureRoot","currRoot","deactivateChildRoutes","activateChildRoutes","futureNode","currNode","futureChild","childOutletName","deactivateRoutes","deactivateRouteAndItsChildren","future","shouldDetach","detachAndStoreRouteSubtree","deactivateRouteAndOutlet","activateRoutes","stored","cmpFactoryResolver","CanActivate","CanDeactivate","getAllRouteGuards","getChildRouteGuards","tokenOrFunction","futurePath","checks","canDeactivateChecks","canActivateChecks","prevChildren","getRouteGuards","shouldRun","shouldRunGuardsAndResolvers","runGuardsAndResolvers","isEmptyError","INITIAL_VALUE","prioritizedGuardValue","redirectIfUrlTree","redirectingNavigationError","matched","consumedSegments","remainingSegments","positionalParamSegments","matchWithChecks","runCanMatchGuards","canMatch","canMatchObservables","injectionToken","guard","getTokenOrFunctionIdentity","isCanMatch","getOrCreateRouteInjectorIfNeeded","matcher","slicedSegments","containsEmptyPathMatchesWithNamedOutlets","emptyPathMatch","createChildrenForEmptyPaths","primarySegment","_sourceSegment","_segmentIndexShift","containsEmptyPathMatches","addEmptyPathsToChildrenIfNeeded","isImmediateMatch","rawSegment","noLeftoversInUrl","NoMatch","AbsoluteRedirect","absoluteRedirect","newTree","ApplyRedirects","configLoader","allowRedirects","splitGroup","rootSegmentGroup","expandSegmentGroup","noMatchError","expandChildren","expandSegment","childOutlets","sortedRoutes","sortByMatchingOutlets","expandedChild","expandSegmentAgainstRoute","matchSegmentAgainstRoute","expandSegmentAgainstRouteUsingRedirect","expandWildCardWithParamsAgainstRouteUsingRedirect","expandRegularSegmentAgainstRouteUsingRedirect","applyRedirectCommands","lineralizeSegments","newSegments","rawSegmentGroup","_loadedRoutes","cfg","getChildConfig","routerConfig","childInjector","childConfig","splitSegmentGroup","matchedOnOutlet","runCanLoadGuards","canLoadObservables","isCanLoad","shouldLoadResult","canLoadFails","applyRedirectCreateUrlTree","createSegmentGroup","createQueryParams","redirectToParams","actualParams","sourceName","updatedSegments","createSegments","redirectToSegments","actualSegments","findPosParam","findOrReturn","redirectToUrlSegment","Recognizer","rootComponentType","recognize","processSegmentGroup","routeState","inheritParamsAndData","routeNode","processSegment","outletChildren","takeWhile","inclusive","rxjsLast","mergedChildren","mergeEmptyPathMatches","sortActivatedRouteSnapshots","processSegmentAgainstRoute","pathIndexShift","getPathIndexShift","getData","_loadedComponent","getSourceSegmentGroup","getResolve","hasEmptyPathConfig","mergedNodes","duplicateEmptyPathNode","resultNode","mergedNode","hasStaticTitle","switchTap","nextResult","ROUTES","RouterConfigLoader","componentLoaders","onLoadStartListener","loadRunner","maybeUnwrapDefaultExport","onLoadEndListener","childrenLoaders","loadModuleFactoryOrRoutes","factoryOrRoutes","rawRoutes","requireStandaloneComponents","isWrappedDefaultExport","NavigationTransitions","hasRequestedNavigation","navigationId","currentNavigation","lastSuccessfulNavigation","afterPreactivation","handleNavigationRequest","setupNavigations","targetPageId","currentRawUrl","extractedUrl","urlHandlingStrategy","extract","rawUrl","extras","routerState","targetSnapshot","currentRouterState","targetRouterState","guards","guardsResult","overallTransitionState","initialUrl","previousNavigation","browserUrlTree","urlTransition","navigated","onSameUrlNavigation","serializeUrl","rawUrlTree","shouldProcessUrl","isBrowserTriggeredNavigation","applyRedirects","applyRedirectsFn","finalUrl","serializer","newObservableError","recognizeFn","urlUpdateStrategy","setBrowserUrl","routesRecognized","navStart","createEmptyState","replaceUrl","guardsStart","rootContexts","runCanDeactivateChecks","futureRSS","currRSS","runCanDeactivate","currARS","canDeactivate","canDeactivateObservables","closestInjector","isCanDeactivate","isBoolean","runCanActivateChecks","fireChildActivationStart","fireActivationStart","runCanActivateChild","futureARS","canActivateChildGuardsMapped","getCanActivateChild","canActivateChild","guardsMapped","isCanActivateChild","runCanActivate","canActivateObservables","isCanActivate","checkGuards","guardsEnd","restoreHistory","cancelNavigationTransition","resolveStart","dataResolved","canActivateChecksResolved","runResolve","resolveNode","getDataKeys","getResolver","resolvedData","resolveData","resolveEnd","loadComponents","loadedComponent","createRouterState","titleStrategy","updateTitle","navCancel","mergedTree","scheduleNavigation","navError","TitleStrategy","buildTitle","pageTitle","getResolvedTitleForRoute","DefaultTitleStrategy","RouteReuseStrategy","DefaultRouteReuseStrategy","BaseRouteReuseStrategy","detachedTree","ROUTER_CONFIGURATION","UrlHandlingStrategy","DefaultUrlHandlingStrategy","newUrlPart","wholeUrl","defaultMalformedUriErrorHandler","exactMatchOptions","subsetMatchOptions","Router","navigationTransitions","browserPageId","canceledNavigationResolution","ɵrouterPageId","disposed","currentPageId","isNgZoneEnabled","malformedUriErrorHandler","lastSuccessfulId","resetConfig","resetRootComponentType","initialNavigation","setUpLocationChangeListener","navigateToSyncWithBrowser","locationSubscription","stateCopy","getCurrentNavigation","navigationExtras","queryParamsHandling","preserveFragment","removeEmptyProps","urlCreationStrategy","validateCommands","matchOptions","priorPromise","generateNgRouterState","restoringFromCaughtError","targetPagePosition","resetState","resetUrlToCurrentUrlTree","routerPageId","RouterLink","tabIndexAttribute","_preserveFragment","_skipLocationChange","_replaceUrl","updateHref","setTabIndexIfNotOnNativeEl","newTabIndex","applyAttributeValue","onChanges","routerLink","onClick","sanitizedValue","PreloadingStrategy","RouterPreloader","preloadingStrategy","setUpPreloading","processRoutes","injectorForCurrentRoute","injectorForChildren","preloadConfig","loadedChildren$","recursiveLoadChildren$","loadComponent$","ROUTER_SCROLLER","RouterScroller","viewportScroller","lastId","lastSource","restoredId","anchorScrolling","routerEventsSubscription","createScrollEvents","scrollEventsSubscription","consumeScrollEvents","scheduleScrollEvent","NavigationResult","routerFeature","ROUTER_IS_PROVIDED","getBootstrapListener","bootstrappedComponentRef","bootstrapDone","BOOTSTRAP_DONE","INITIAL_NAVIGATION","ROUTER_PRELOADER","withDebugTracing","stringifyEvent","groupEnd","withPreloading","ROUTER_FORROOT_GUARD","ROUTER_PROVIDERS","rootRoute","routerNgProbeToken","provideForRootGuard","useHash","scrollOffset","provideInitialNavigation","ROUTER_INITIALIZER","locationInitialized","COMPLETE","REDIRECTING","FAILED","afterNextNavigation","UniqueSelectionDispatcher","_listeners","notify","registered","nextId","CDK_ACCORDION","CdkAccordion","_multi","openAll","_openCloseAllActions","_stateChanges","CdkAccordionItem","_expanded","expandedChange","opened","_expansionDispatcher","accordion","_removeUniqueSelectionListener","accordionId","_openCloseAllSubscription","_subscribeToOpenCloseAllActions","CdkAccordionModule","MAT_ACCORDION","EXPANSION_PANEL_ANIMATION_TIMING","matExpansionAnimations","indicatorRotate","bodyExpansion","MAT_EXPANSION_PANEL","MatExpansionPanelContent","_expansionPanel","MAT_EXPANSION_PANEL_DEFAULT_OPTIONS","MatExpansionPanel","hideToggle","_hideToggle","togglePosition","_togglePosition","_uniqueSelectionDispatcher","_bodyAnimationDone","afterExpand","afterCollapse","_hasSpacing","displayMode","_getExpandedState","_lazyContent","_inputChanges","_body","focusedElement","bodyElement","MatExpansionPanelHeaderBase","_MatExpansionPanelHeaderMixinBase","MatExpansionPanelHeader","panel","accordionHideToggleChange","_parentChangeSubscription","expandedHeight","collapsedHeight","_toggle","_isExpanded","_getPanelId","_getTogglePosition","_showToggle","_getHeaderHeight","isExpanded","_keydown","_handleHeaderKeydown","_handleHeaderFocus","i1.MatExpansionPanel","MatExpansionPanelTitle","MatAccordion","_headers","_ownHeaders","MatExpansionModule","MatIconModule","MatLegacyFormFieldModule","MatLegacyOptionModule","MAT_SELECT_SCROLL_STRATEGY_PROVIDER","MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY","MatLegacySelectModule","ctx_r6","softBezier","LoadingAnimationVariant","LoadingAnimationComponent","variant","BLOCK","strokeWidth","circleCutout","PI","LoadingAnimationModule","ButtonComponent","theme","hollow","paddingPX","ButtonModule","LoungeConfig","replaceSvgs","IconComponent","loungeConfig","old","styleColor","colors","styleColorForeground","styleColorBackground","dataRotate","rotate","onEnterKeydown","IconModule","CheckboxModule","MouseKeyboardService","keyUpSubscription","keyUp$","keyDown$","touchStart","clickOrTouchSubscription","clickOrTouch$","keyDownSubscription","scrollIntoView","wrapAround","zIndex$","prevEvent","_2","targetItems","elementToSetFocusTo","setZIndex","zindex","setPortalOutlet","detachCurrentDropdown","attachDropdown","handleFocus","DropdownOutletComponent","setUpFocusHandler","destroyFocusHandler","focusHandler","dropdownSubscription","getLastItemFromArray","focusableElements","DropdownConfig","openFunc","closeFunc","sameWidth","sameHeight","horizontalDirection","verticalDirection","toleranceWidth","toleranceHeight","spacingFromButton","spacingFromWindow","popOver","fillWidth","fillHeight","setConfig","zIndexFeatureKey","zIndexReducer","currentZIndex","initialZIndexState","ZIndexActions.setConfig","ZIndexActions.setItem","selectZIndexState","selectConfig","selectCurrentZIndex","ZIndexConfig","ZIndexService","config$","ZIndexSelectors.selectConfig","ZIndexSelectors.getItemById","currentZIndex$","ZIndexSelectors.selectCurrentZIndex","appliedTop","appliedBottom","appliedLeft","appliedRight","appliedMaxWidth","appliedMaxHeight","appliedWidth","appliedHeight","appliedVisibility","appliedHorizontalDirection","appliedVerticalDirection","appliedFillWidth","appliedFillHeight","lastFocusEventTarget","listenForPositionChanges","positionChangeInterval","domOpenDropdownButton","currentRect","setDropdownStyling","focusOnDropdown","onCloseClick","eventTarget","domDropdownContent","HTMLElement","focusOnLastDescendant","focusOnFirstDescendant","dropdownElement","autofocusElement","lastElement","px","resetDropdownStyling","buttonOffsetTop","buttonOffsetBottom","buttonOffsetLeft","buttonOffsetRight","onClickToggleDropdown","onScroll","throttle","onResize","SharedLoadingKeys","levelLoadLevels","levelLoadLevelsSuccess","levelLoadLevelsFailure","markTeacherForSelection","markTeacherForSelectionSuccess","markClassForSelection","markClassForSelectionSuccess","markStudentForSelection","markStudentForSelectionSuccess","removeSelectionsFromStudents","removeSelectionsFromStudentsSuccess","removeSelectionsFromTeachers","removeSelectionsFromTeachersSuccess","dlpLoadTeachers","dlpLoadTeachersSuccess","dlpLoadTeachersFailure","dlpLoadClassesWithStudents","dlpLoadClassesWithStudentsSuccess","dlpLoadClassesWithStudentsFailure","teamLoadTeams","teamLoadTeamsSuccess","teamLoadTeamsFailure","teamCreateTeam","teamCreateTeamSuccess","teamCreateTeamFailure","teamEditTeam","teamEditTeamCancel","teamEditAssignTeachers","teamEditAssignTeachersSuccess","teamEditAssignStudents","teamEditAssignStudentsSuccess","teamLoadStudents","teamLoadStudentsSuccess","teamLoadStudentsFailure","teamSaveStudentsToTeam","teamSaveStudentsToTeamSuccess","teamSaveStudentsToTeamFailure","teamDeleteModal","teamDeleteTeam","teamDeleteTeamSuccess","teamDeleteTeamFailure","teamEditDetailsModal","teamEditDetailsFailure","teamEditDetails","teamEditDetailsSuccess","teamSaveDetailsToTeam","teamSaveDetailsToTeamSuccess","teamSaveDetailsToTeamFailure","teamRemoveTeacherSelfModal","teamRemoveTeacherSelf","teamRemoveTeacherSelfSuccess","teamRemoveTeacherSelfFailure","teamAddTeacher","teamAddTeacherSuccess","teamAddTeacherFailure","teamAddTeachers","teamAddTeachersSuccess","teamAddTeachersFailure","teamLoadSingleTeamForEdit","teamLoadSingleTeamForEditFailure","sortComparer","ascending","loungeFeatureKey","loungeReducer","fullLevel","dlpTeachersList","dlpClassWithStudentsList","teamWithTeachersList","teamEdit","initialLoungeState","LoungeActions.levelLoadLevelsSuccess","LoungeActions.markTeacherForSelectionSuccess","newlist","_teacher","teacherId","permission","canCreateSubTeam","canDeleteSubTeam","canDeleteTeam","canEditSubTeam","canEditTeam","canViewSubTeam","isOwner","LoungeActions.markClassForSelectionSuccess","classWithUsers","searchTerm","LoungeActions.markStudentForSelectionSuccess","notAllUsersSelected","LoungeActions.removeSelectionsFromStudentsSuccess","newList","LoungeActions.removeSelectionsFromTeachersSuccess","LoungeActions.dlpLoadTeachersSuccess","teachersSorted","teachers","LoungeActions.dlpLoadClassesWithStudentsSuccess","LoungeActions.teamLoadTeamsSuccess","teamList","LoungeActions.teamEditTeam","team","LoungeActions.teamEditTeamCancel","LoungeActions.teamEditAssignTeachersSuccess","LoungeActions.teamEditAssignStudentsSuccess","classWithSelectedUsersList","LoungeActions.teamLoadStudentsSuccess","studentList","LoungeActions.teamDeleteTeam","newTeamList","LoungeActions.teamRemoveTeacherSelfSuccess","newTeamWithTeachersList","selectLoungeState","selectFullLevel","selectDlpTeachersList","selectSelectedTeachersList","selectDlpClassWithUsersList","selectSelectedUsersList","selectTeamWithTeachersList","selectTeamEdit","getObservableValueSync","BackendUrlConfig","loginDotNet","ApiServiceConfig","apiBFFGatewayBaseUrl","UserTypeEnum","UserService","apiServiceConfig","_loginStatus","_user","defaultUserServiceConfig","_loginUsingMvcDotNet","_internalBackendUrl","internalBackendUrlFallBack","isbn","returnUrl","removeUser","setUser","accessToken","AccessToken","AccessTokenExpiresAt","user$","TEACHERS","STUDENTS","NOT_LOGGED_IN","isAlineaUser","authenticationToken","institutionNumber","displayName","institutionName","initials","institutionId","querystring","GoogleTagManagerService","isLoaded","debouncedFunc","windowRef","documentRef","browserGlobals","pushOnDataLayer","getDataLayer","dataLayer","LoungeService","loadingKey","loungeStore","LoungeActions.dlpLoadClassesWithStudents","LoungeActions.dlpLoadTeachers","studentId","LoungeActions.markStudentForSelection","LoungeActions.markClassForSelection","LoungeActions.markTeacherForSelection","removeStudentsFromSelection","LoungeActions.removeSelectionsFromStudents","removeTeachersFromSelection","LoungeActions.removeSelectionsFromTeachers","teamSaveTeachersToTeam","LoungeActions.teamAddTeachers","studentIds","LoungeActions.teamSaveStudentsToTeam","LoungeActions.teamSaveDetailsToTeam","LoungeActions.teamLoadTeams","teamEditNavigate","teamEditCancel","LoungeActions.teamEditAssignStudents","LoungeActions.teamEditAssignTeachers","LoungeActions.teamDeleteModal","teamDelete","teamCreate","LoungeActions.teamCreateTeam","LoungeActions.teamEditDetailsModal","LoungeActions.teamRemoveTeacherSelfModal","LoungeActions.teamRemoveTeacherSelf","teacher","LoungeActions.teamAddTeacher","LoungeActions.teamLoadSingleTeamForEdit","fullLevel$","LoungeSelectors.selectFullLevel","LoungeActions.levelLoadLevels","selectedTeachersList$","LoungeSelectors.selectSelectedTeachersList","dlpTeachersListWithoutCurrentUser$","LoungeSelectors.selectDlpTeachersList","selectedUsersList$","LoungeSelectors.selectSelectedUsersList","dlpClassWithStudentsList$","LoungeSelectors.selectDlpClassWithUsersList","dlpClasses","teamTeamWithTeachersList$","LoungeSelectors.selectTeamWithTeachersList","teams","teamEdit$","LoungeSelectors.selectTeamEdit","startLoading","finishLoading","loadFailed","loadingFeatureKey","actionsThatFinishLoad","actionsThatError","loadingReducer","callStates","initialLoadingState","assignCallStateToState","callState","newCallStates","selectLoadingState","selectLoadState","LoadingService","selectInit","selectLoading","selectLoaded","selectError","BoxComponent","LoungeModalPages","counter","addMessage","updateMessage","removeMessage","pauseMessageExpiration","continueMessageExpiration","initializeMessageTimeout","clearMessageTimeout","toastFeatureKey","toastReducer","messages","initialToastState","selectToastState","selectAllMessages","ToastConfig","horizontalPosition","verticalPosition","durationInMilliseconds","spacingBetweenToasts","ToastService","toastStore","messages$","ToastActions.setConfig","displayMessage","canDismiss","preparedMessage","prepareMessageForStore","createUniqueId","messageInstance","LoungeModalService","setPage","removeTeacherSelf","allowRemoveYourself","setPageToNone","none","loungeService","toastService","modalActive","modalHeight","pageToModalHeight","deleteTeam","detailsInput","ModalConfig","showBackgroundOverLay","transitionTiming","modalHiddenStyle","modalVisibleStyle","overlayHiddenStyle","overlayVisibleStyle","modalEnterLeaveAnimation","modalOverlayEnterLeaveAnimation","ModalService","visibleModals","displayOverlaySubject","currentlyVisibleModal","modalToAttachWhenReady","setModalVisible","modal","setVisibility","hideCurrentModal","storeModalVisibility","wasLatestVisible","attachModal","detachCurrentModal","isModalInVisibleStack","ModalComponent","cdr","overflowVisible","previouslyFocusedElement","lastReactionValue","reactOnVisibilityChange","onWrapperClick","wasAlreadyVisible","isVisibleChange","dropdownOutlet","modalContent","focusOnModal","animationDone","unlockScroll","animationEnded","scrolly","overflowY","inStack","focusOnPreviousElement","modalElement","SearchClassWithUsersPipe","searchLevels","classWithUsersList","classesToAdd","valuesToSearchIn","TeamPickerComponent","sharedLoadingKeys","selectedLevels","onClickUser","onClickClass","onClickLevel","getLevelsLabel","mediumForm","isLevelSelected","isClassSemiSelected","classTrackBy","i3.IconComponent","TeamHeaderComponent","onClickBack","backFunc","onClickClose","i1.IconComponent","TeamEditAssignStudentsComponent","loungeModalService","loadingAnimationVariants","onClickSave","selectedUsers","TeamEditDeleteComponent","onClickDelete","i3.ButtonComponent","TeamDetailsFormComponent","i2.IconComponent","TeamEditDetailsComponent","saveDetailsToTeam","TeamEditRemoveTeacherSelfComponent","onClickRemoveTeacherSelf","SearchUserPermissionWithSelectedListPipe","TeamPickerTeacherComponent","onClickTeacher","teacherTrackBy","TeamEditAssignTeachersComponent","selectedTeachers","currentUser","currentTeacher","alert","TeamEditDropdownComponent","onModalVisibilityChange","showModal","pageEnum","TeamEditComponent","editTeam","i5.IconComponent","SortMode","StorageService","localStorageChanged","getObject","jsonString","setObject","deleteAll","TeamBoxComponent","onClickEdit","UmbracoService","setConfiguration","_siteconfiguration","TeamCreationService","umbracoService","createTeam","isPublic","productIds","TeamCreationComponent","teamCreationService","page$","onClickCancel","studentPicker","goToDetailsPage","onClickSubmit","pageSubscription","TeamOverviewComponent","storageService","sortModeEnum","sortMode$","alphabetically","sortMode","teamOverviewSort","creationDate","onClickCreateTeam","onClickSort","models","created","updatedDate","i6.IconComponent","ModalOutletComponent","displayOverlay","lockScroll","dropdownFocus","ToastMessageComponent","toastType","onDismissClick","toastAnimateInOut","stagger","ToastMessageListComponent","appliedHorizontalPosition","appliedVerticalPosition","appliedSpacingBetweenToasts","appliedSpacingFromWindow","appliedVariant","onMouseenter","onMouseleave","toastConfigSubscription","ToastEffects","ignoreTiming","expirationTimestamp","newMessage","_apiLoungeBaseUrl","_apiNextBaseUrl","_apiBFFGatewayBaseUrl","_apiNextSearchBaseUrl","_apiUmbracoBaseUrl","httpParams","getNextSearch","getInternalBackend","getInternalBackendWithCredentials","postBFFGateway","wwwForm","postLounge","putLounge","putNextSearch","putUmbraco","putInternalBackend","patchLounge","patchNextSearch","patchUmbraco","patchInternalBackend","deleteLounge","deleteNextSearch","deleteInternalBackend","apiBaseUrl","LoungeApiService","dlpGetCurrentUser","dlpGetClasses","dlpGetStudentsInClass","dlpGetClassesWithStudents","dlpGetStudentsInClasses","classIds","dlpClassIds","dlpGetAllTeachersInInstitution","levelGetListOfLevelsLevelGroupsAndEducationGroups","subTeamGetSingleSubTeam","subTeamId","subTeamGetAllSubTeamsInTeam","subTeamCreateSubTeam","postBody","subTeamUpdateSubTeam","putBody","subTeamDeleteSubTeam","subTeamSaveStudentsToSubTeam","subTeamGetIconsAvailableToSubTeams","teamGetSingleTeam","teamUpdateTeam","teamGetTeamsAvailableToUser","teamGetTeamsAndDlpClassesAvailableToUser","teamGetTeamsWhereUserIsStudent","teamGetStudentsInTeam","teamGetStudentsInSubTeams","teamRemoveTeacher","teamRemoveSelf","contentSearchStatus","LoungeEffects","loungeApiService","levelLoadLevels$","LoungeActions.levelLoadLevelsFailure","teacherList","firstName","lastName","LoungeActions.dlpLoadTeachersFailure","LoungeActions.dlpLoadClassesWithStudentsFailure","markTeacherForSelection$","_currentTeacher","_permission","teamLoadTeams$","LoungeActions.teamLoadTeamsFailure","teamSaveStudentsToTeam$","LoungeActions.teamSaveStudentsToTeamSuccess","LoungeActions.teamSaveStudentsToTeamFailure","teamSaveStudentsToTeamSuccess$","LoungeActions.teamDeleteTeamSuccess","LoungeActions.teamDeleteTeamFailure","removeTeamSuccess$","LoungeActions.teamSaveDetailsToTeamSuccess","LoungeActions.teamSaveDetailsToTeamFailure","editTeamDetailsSuccess$","teamCreateTeam$","LoungeActions.teamCreateTeamSuccess","LoungeActions.teamCreateTeamFailure","teamCreateTeamSuccess$","teamEditTeam$","LoungeActions.teamLoadStudents","teamStudents","teamEditTeamCancel$","teamEditAssignTeachers$","shareWithTeachers","teachersList","selectedTeacher","selectedUser","teamEditAssignStudents$","classWithStudentsList","classDto","teamLoadStudents$","LoungeActions.teamLoadStudentsFailure","LoungeActions.teamRemoveTeacherSelfFailure","teamRemoveTeacherSelfSuccess$","teamAddTeachers$","LoungeActions.teamAddTeachersSuccess","LoungeActions.teamAddTeachersFailure","teamAddTeacher$","LoungeActions.teamAddTeacherSuccess","LoungeActions.teamAddTeacherFailure","teamAddTeacherSuccess$","LoungeActions.teamLoadSingleTeamForEditFailure","LoungeModule","MatFormFieldModule","MatSelectModule","addAuth","Authorization","AuthenticationToken","ContextIdentifier","InstitutionNumber","LoadingEffects","parentModule","LocalService","_localHostname","localService","retrieveUser","retrieveConfig","Initials","hasAccess","HasAccess","userName","UserName","IsTeacher","IsAlineaUser","buildKey","BuildKey","InstitutionName","InstitutionId","institutionShortId","InstitutionShortId","ExpiresAt","idToken","IdToken","DoNotTrack","CssColorService","rgb","variantHex","lightenDarkenHexColor","convertCssColorVariantToPercentage","variantRgb","race","raceInit","subscriptions","getOppositePlacement","placement","getBasePlacement","getOppositeVariationPlacement","auto","basePlacements","clippingParents","popper","variationPlacements","placements","modifierPhases","isElement","isHTMLElement","getDocumentElement","getUAString","uaData","userAgentData","brands","brand","isLayoutViewport","includeScale","isFixedStrategy","scaleX","scaleY","visualViewport","addVisualOffsets","offsetLeft","getWindowScroll","win","getWindowScrollBarX","getNodeName","getParentNode","assignedSlot","isScrollParent","_getComputedStyle","overflowX","getScrollParent","listScrollParents","_element$ownerDocumen","scrollParent","isBody","updatedList","isTableElement","getTrueOffsetParent","offsetParent","getOffsetParent","getContainingBlock","isFirefox","perspective","contain","willChange","isSameNode","rectToClientRect","getClientRectFromMixedType","clippingParent","layoutViewport","getInnerBoundingClientRect","clientTop","clientLeft","getDocumentRect","winScroll","getVariation","getMainAxisFromPlacement","computeOffsets","basePlacement","variation","commonX","commonY","mainAxis","mergePaddingObject","paddingObject","expandToHashMap","hashMap","detectOverflow","_options$placement","_options$strategy","_options$boundary","boundary","_options$rootBoundary","rootBoundary","_options$elementConte","elementContext","_options$altBoundary","altBoundary","_options$padding","popperRect","rects","clippingClientRect","getClippingRect","mainClippingParents","getClippingParents","clipperElement","clippingRect","accRect","contextElement","referenceClientRect","popperOffsets","popperClientRect","elementClientRect","overflowOffsets","offsetData","modifiersData","multiply","flip","_skip","_options$mainAxis","checkMainAxis","_options$altAxis","altAxis","checkAltAxis","specifiedFallbackPlacements","fallbackPlacements","_options$flipVariatio","flipVariations","allowedAutoPlacements","preferredPlacement","getExpandedFallbackPlacements","oppositePlacement","computeAutoPlacement","_options$allowedAutoP","allPlacements","allowedPlacements","referenceRect","checksMap","makeFallbackChecks","firstFittingPlacement","_basePlacement","isStartVariation","isVertical","mainVariationSide","altVariationSide","_loop","_i","fittingPlacement","requiresIfExists","within","mathMax","mathMin","getLayoutRect","preventOverflow","_options$tether","tether","_options$tetherOffset","tetherOffset","isBasePlacement","getAltAxis","tetherOffsetValue","normalizedTetherOffsetValue","offsetModifierState","_offsetModifierState$","mainSide","altSide","additive","maxLen","arrowElement","arrow","arrowRect","arrowPaddingObject","arrowPaddingMin","arrowPaddingMax","arrowLen","minOffset","maxOffset","arrowOffsetParent","offsetModifierValue","tetherMax","preventedOffset","_offsetModifierState$2","_offset","_len","_min","_max","isOriginSide","_offsetModifierValue","_tetherMin","_tetherMax","_preventedOffset","withinMaxClamp","_state$modifiersData$","toPaddingObject","minProp","maxProp","endDiff","startDiff","clientSize","centerOffset","effect","_ref2","_options$element","requires","getCompositeRect","elementOrVirtualElement","isFixed","isOffsetParentAnElement","offsetParentIsScaled","isElementScaled","getNodeScroll","getHTMLElementScroll","order","visited","depModifier","DEFAULT_OPTIONS","areValidElements","_key","popperGenerator","generatorOptions","_generatorOptions$def","defaultModifiers","_generatorOptions$def2","orderedModifiers","effectCleanupFns","isDestroyed","setOptions","setOptionsAction","cleanupModifierEffects","scrollParents","orderModifiers","mergeByName","runModifierEffects","_ref3","_ref3$options","forceUpdate","_state$elements","_state$orderedModifie","_state$orderedModifie2","onFirstUpdate","unsetSides","mapToStyles","_Object$assign2","gpuAcceleration","adaptive","roundOffsets","_offsets$x","_offsets$y","hasX","hasY","sideX","sideY","heightProp","widthProp","_Object$assign","commonStyles","_ref4","roundOffsetsByDPR","dpr","createPopper","_options$scroll","_options$resize","computeStyles","_ref5","_options$gpuAccelerat","_options$adaptive","_options$roundOffsets","getValueInRange","isNumber","isInteger","reflow","removeAccents","transitionTimerDelayMs","noopFn","runningTransitions","ngbRunTransition","startFn","running","runningTransition","transition$","endFn","runInZone","finishTransition$","stop$","endWith","transitionDurationMs","getTransitionDurationMs","transitionDelay","transitionEnd$","timer$","ngbCollapsingTransition","maxSize","dimension","setInitialClasses","measureCollapsingElementDimensionPx","hasShownClass","dimensionSize","NgbConfig","NgbAccordionConfig","_ngbConfig","closeOthers","_animation","NgbPanelHeader","NgbPanelTitle","NgbPanelContent","NgbPanel","initClassDone","transitionRunning","titleTpl","titleTpls","headerTpl","headerTpls","contentTpl","contentTpls","NgbRefDirective","_El","ngbRef","NgbPanelToggle","ngbPanelToggle","NgbAccordion","_changeDetector","activeIds","destroyOnHide","closeOtherPanels","panelId","_changeOpenState","_findPanelById","expandAll","collapse","collapseAll","_closeOthers","_updateActiveIds","panelElement","panelDiv","panelChange","_runTransitions","enableTransition","shown","NgFor","NgbAccordionModule","ngbAlertFadingTransition","NgbAlertConfig","dismissible","NgbAlert","typeChange","NgbAlertModule","NgbSlideEventDirection","isBeingAnimated","removeDirectionClasses","removeClasses","ngbCarouselTransitionIn","START","ngbCarouselTransitionOut","NgbCarouselConfig","pauseOnHover","pauseOnFocus","showNavigationArrows","showNavigationIndicators","NgbSlide","tplRef","NgbCarousel","_container","NgbSlideEventSource","_transitionIds","_interval$","_wrap$","_pauseOnHover$","_pauseOnFocus$","mouseHover","_mouseHover$","_focused$","arrowLeft","ARROW_LEFT","arrowRight","ARROW_RIGHT","hasNextSlide$","slide","slideEvent","activeId","slides","currentSlideId","slideArr","currentSlideIdx","_getSlideIdxById","_pause$","hasNextSlide","_destroy$","TIMER","ngbCompleteTransition","_getSlideElement","activeSlide","_getSlideById","slideId","_cycleToSelected","_getSlideEventDirection","_getPrevSlide","_getNextSlide","cycle","slideIdx","transitionIds","selectedSlide","activeSlideTransition","slid","isShown","previousId","nextSlide","currentActiveSlideId","nextActiveSlideId","NgbCarouselModule","NgbCollapseModule","NgbDate","dateComparator","checkDateInRange","minDate","maxDate","markDisabled","fromJSDate","jsDate","toJSDate","NgbCalendar","NGB_DATEPICKER_CALENDAR_FACTORY","NgbCalendarGregorian","getDaysPerWeek","getMonths","getWeeksPerMonth","checkMonth","expectedMonth","setMonth","setDate","getPrev","getWeekday","getWeekNumber","week","firstDayOfWeek","getToday","NgbDatepickerI18n","getMonthLabel","getMonthFullName","getYearNumerals","getDayNumerals","getWeekNumerals","weekNumber","getWeekLabel","NGB_DATEPICKER_18N_FACTORY","NgbDatepickerI18nDefault","_monthsShort","_monthsFull","getWeekdayLabel","weekdaysStartingOnSunday","getMonthShortName","getDayAriaLabel","NgbDatepickerService","_calendar","_i18n","dayTemplateData","displayMonths","toValidDate","isChangedDate","navigation","outsideDays","weekdays","weekdayWidth","weekdaysVisible","firstDate","lastDate","focusDate","prevDisabled","nextDisabled","selectedDate","selectBoxes","years","model$","_model$","dateSelect$","_dateSelect$","_VALIDATORS","_nextState","focusedDate","focusSelect","isDateSelectable","isChangedMonth","ngbDate","struct","newState","_patchContexts","weeks","tabindex","checkMinBeforeMax","buildMonths","monthsToReuse","firstDates","reusedIndex","calendarToday","getFirstViewDate","daysPerWeek","firstMonthDate","dayOfWeek","weekObject","nextDate","contextUserData","dayObject","currentMonth","currentYear","buildMonth","yearChanged","monthChanged","generateSelectBoxYears","numbers","generateSelectBoxMonths","prevMonthDisabled","prevDate","nextMonthDisabled","NavigationEvent","NgbDatepickerDayView","isMuted","NgbDatepickerNavigationSelect","_month","_year","changeMonth","changeYear","monthSelect","yearSelect","NgbDatepickerNavigation","onClickPrev","PREV","onClickNext","Key","NgbDatepickerKeyboardService","processKey","datepicker","PageUp","PageDown","End","Home","ArrowLeft","ArrowUp","ArrowRight","ArrowDown","Enter","Space","NgbDatepickerConfig","showWeekNumbers","NgbDateAdapter","NGB_DATEPICKER_DATE_ADAPTER_FACTORY","NgbDateStructAdapter","fromModel","toModel","NgbDatepickerContent","NgbDatepickerMonth","_keyboardService","_service","onKeyDown","doSelect","onDateSelect","NgbDatepicker","_ngbDateAdapter","_controlValue","_publicState","_destroyed$","dateSelect","oldDate","navigationPrevented","newSelectedDate","newFocusedDate","oldFocusedDate","navigateTo","focusIns$","_contentEl","focusOuts$","hasClassName","dayTemplate","_defaultDayTemplate","onNavigateDateSelect","onNavigateEvent","isContainedIn","matchesSelectorIfAny","isMobile","wrapAsyncForMobile","FOCUSABLE_ELEMENTS_SELECTOR","getFocusableBoundaryElements","NgbRTL","isRTL","placementSeparator","spacesRegExp","bootstrapPopperMatches","popperStartPrimaryPlacement","popperEndPrimaryPlacement","popperStartSecondaryPlacement","popperEndSecondaryPlacement","getPopperOptions","baseClass","rtl","placementVals","hasAuto","popperPlacements","_placement","leftClass","rightClass","getPopperClassPlacement","bsClassRegExp","popperElement","popperPlacement","newPrimary","classnames","newSecondary","classname","getBootstrapBaseClassPlacement","NgbDatepickerModule","NgbDropdownModule","ContentRef","PopupService","_componentType","_applicationRef","_windowRef","_contentRef","_getContentRef","NgbModalBackdrop","NgbActiveModal","dismiss","WINDOW_ATTRIBUTES","BACKDROP_ATTRIBUTES","NgbModalRef","_windowCmptRef","_backdropCmptRef","_beforeDismiss","dismissEvent","_reject","_applyWindowOptions","windowInstance","optionName","_applyBackdropOptions","backdropInstance","_closed","_hidden","dismissed","_dismissed","_removeModalElements","_dismiss","windowTransition$","backdropTransition$","ModalDismissReasons","NgbModalWindow","_elRef","fullscreenClass","_elWithFocus","_show","_disableEventHandling","dialogTransition$","_dialogEl","transitions$","_enableEventHandling","_setFocus","_closed$","Escape","ESC","_bumpBackdrop","preventClose","BACKDROP_CLICK","autoFocusable","firstFocusable","elWithFocus","ScrollBar","actualPadding","NgbModalStack","_environmentInjector","_scrollBar","_rendererFactory","_scrollBarRestoreFn","_modalRefs","_windowCmpts","_activeWindowCmptHasChanged","activeWindowCmpt","stopFocusTrap$","refocusOnClick","lastFocusedElement$","tabEvent","lastFocusedElement","ngbFocusTrap","_revertAriaHidden","_setAriaHidden","_restoreScrollBar","scrollBarRestoreFn","_hideScrollBar","contentInjector","containerEl","activeModal","backdropCmptRef","windowCmptRef","_attachWindowComponent","ngbModalRef","beforeDismiss","_registerModalRef","_registerWindowCmpt","activeInstances","_activeInstances","dismissAll","hasOpenModals","_createFromTemplateRef","_createFromString","_createFromComponent","componentNativeEl","_ariaHiddenValues","unregisterModalRef","ngbWindowCmpt","NgbModalConfig","NgbModal","_modalStack","combinedOptions","NgbModalModule","ngbNavFadeOutTransition","ngbNavFadeInTransition","NgbNavPane","elRef","NgbNavOutlet","_activePane","isPanelTransitioning","_updateActivePane","navItemChange$","destroy$","nextItem","_getPaneForItem","_getActivePane","_panes","NgbNavModule","NgbPaginationConfig","boundaryLinks","directionLinks","ellipses","NgbPaginationEllipsis","NgbPaginationFirst","NgbPaginationLast","NgbPaginationNext","NgbPaginationNumber","NgbPaginationPrevious","NgbPaginationPages","NgbPagination","pageCount","hasPrevious","hasNext","previousDisabled","selectPage","pageNumber","_updatePages","isEllipsis","_applyEllipses","_applyRotation","leftOffset","_applyPagination","_setPageInRange","newPageNo","prevPageNo","pageChange","newPage","Trigger","isManual","DEFAULT_ALIASES","delayOrNoop","NgbPopoverModule","NgbProgressbarConfig","animated","striped","showValue","NgbProgressbar","textType","getPercentValue","NgbProgressbarModule","NgbRatingConfig","readonly","resettable","NgbRating","ariaValueText","isInteractive","handleBlur","handleClick","handleKeyDown","_updateMax","_setupContexts","leave","nextRate","internalChange","newRate","rateChange","nextValue","NgbRatingModule","NgbTime","changeHour","updateHour","changeMinute","updateMinute","changeSecond","updateSecond","checkSecs","NgbTimepickerConfig","meridian","spinners","hourStep","minuteStep","secondStep","readonlyInputs","NgbTimeAdapter","NGB_DATEPICKER_TIME_ADAPTER_FACTORY","NgbTimeStructAdapter","NgbTimepickerI18n","NGB_TIMEPICKER_I18N_FACTORY","NgbTimepickerI18nDefault","_periods","getMorningPeriod","getAfternoonPeriod","FILTER_REGEX","NgbTimepicker","_ngbTimeAdapter","_hourStep","_minuteStep","_secondStep","structValue","propagateModelChange","newVal","isPM","enteredHour","toggleMeridian","formatInput","formatHour","formatMinSec","isSmallSize","isLargeSize","NgbTimepickerModule","ngbToastFadeInTransition","ngbToastFadeOutTransition","NgbToastConfig","autohide","ariaLive","NgbToastHeader","NgbToast","contentHeaderTpl","_init","_clearTimeout","_timeoutID","NgbToastModule","NgbTooltipConfig","triggers","disableTooltip","openDelay","closeDelay","NgbTooltipWindow","NgbTooltip","applicationRef","popperOptions","tooltipClass","_popupService","_positioning","ngbPositioning","popperInstance","positioningOption","updatePopperOptions","createPopperLite","targetElement","ngbTooltip","_ngbTooltip","_ngbTooltipWindowId","_getPositionTargetElement","appendToBody","_zoneSubscription","ngbAutoClose","closed$","insideElements","insideSelector","escapes$","mouseDowns$","closeableClicks$","shouldClose","_unregisterListenersFn","listenToTriggers","isOpenedFn","openFn","closeFn","parsedTriggers","parseTriggers","aliases","trimmedTriggers","triggerPair","manualTriggers","observeTriggers","toggleFn","unsubscribeFn","triggerDelay","input$","filteredInput$","currentlyOpen","delayedOpen$","delayedClose$","positionTarget","NgbTooltipModule","NgbHighlight","highlightClass","accentSensitive","terms","term","prepareTerm","escapedTerms","regExpEscape","toSplit","ARIA_LIVE_DELAY_FACTORY","NgbTypeaheadModule","NgbOffcanvasModule","NGB_MODULES","Notification","observeNotification","nextHandler","completeHandler","accept","nextOrObserver","completeNotification","groupBy","elementOrOptions","consumer","activeGroups","teardownAttempted","groupBySourceSubscriber","grouped","createGroupedObservable","groupSubject","groupSubscriber","DEFAULT_EFFECT_CONFIG","functional","useEffectsErrorHandler","CREATE_EFFECT_METADATA_KEY","getSourceForInstance","isClass","classOrRecord","getClasses","classesAndRecords","mergeEffects","sourceInstance","globalErrorHandler","effectsErrorHandler","observables$","getSourceMetadata","getCreateEffectMetadata","observable$","effectAction$","materialize","MAX_NUMBER_OF_RETRY_ATTEMPTS","defaultEffectsErrorHandler","retryAttemptLeft","Actions","ScannedActionsSubject","allowedTypes","typeOrActionCreator","_ROOT_EFFECTS_GUARD","USER_PROVIDED_EFFECTS","_ROOT_EFFECTS","_ROOT_EFFECTS_INSTANCES","_FEATURE_EFFECTS","_FEATURE_EFFECTS_INSTANCE_GROUPS","EFFECTS_ERROR_HANDLER","ROOT_EFFECTS_INIT","rootEffectsInit","onIdentifyEffectsKey","onInitEffects","isOnInitEffects","functionName","EffectSources","addEffects","effectSourceInstance","toActions","effectsInstance","isClassInstance","source$","effect$","resolveEffectSource","mergedEffects$","isOnRunEffects","ngrxOnRunEffects","reporter","isAction","getEffectName","isMethod","reportInvalidActions","dematerialize","init$","ngrxOnInitEffects","isOnIdentifyEffects","ngrxOnIdentifyEffects","EffectsRunner","effectSources","effectsSubscription","isStarted","i1.EffectSources","EffectsRootModule","runner","rootEffectsInstances","storeRootModule","storeFeatureModule","i2.EffectsRunner","EffectsFeatureModule","effectsRootModule","effectsInstanceGroups","effectsInstances","featureEffects","effects","effectsClasses","createEffectsInstances","rootEffects","_provideForRootGuard","effectsGroups","userProvidedEffectsGroups","effectsGroup","userProvidedEffectsGroup","effectsClassOrRecord","observablesFactory","observablesAsArray","PERFORM_ACTION","REFRESH","RESET","ROLLBACK","COMMIT","SWEEP","TOGGLE_ACTION","SET_ACTIONS_ACTIVE","JUMP_TO_STATE","JUMP_TO_ACTION","IMPORT_STATE","LOCK_CHANGES","PAUSE_RECORDING","PerformAction","Refresh","Reset","Rollback","Commit","Sweep","ToggleAction","SetActionsActive","JumpToState","JumpToAction","actionId","ImportState","nextLiftedState","LockChanges","PauseRecording","StoreDevtoolsConfig","maxAge","STORE_DEVTOOLS_CONFIG","INITIAL_OPTIONS","noMonitor","DEFAULT_NAME","createConfig","optionsInput","actionSanitizer","stateSanitizer","logOnly","autoPause","traceLimit","lock","persist","jump","reorder","unliftState","liftedState","computedStates","currentStateIndex","unliftAction","actionsById","nextActionId","liftAction","Actions.PerformAction","sanitizedActions","actionIdx","sanitizeAction","computedState","sanitizeState","stateIdx","shouldFilterActions","actionsSafelist","actionsBlocklist","filterLiftedState","safelist","blocklist","filteredStagedActionIds","filteredActionsById","filteredComputedStates","stagedActionIds","liftedAction","isActionFiltered","blockedlist","predicateMatch","safelistMatch","escapeRegExp","blocklistMatch","DevtoolsDispatcher","ActionsSubject","ExtensionActionTypes","DISPATCH","STOP","ACTION","REDUX_DEVTOOLS_EXTENSION","DevtoolsExtension","devtoolsExtension","dispatcher","createActionStreams","isPaused","sanitizedState","sanitizedAction","sendToReduxDevtools","extensionConnection","sanitizedLiftedState","sanitizeActions","sanitizeStates","getExtensionConfig","createChangesObservable","changes$","start$","liftedActions$","unwrapAction","UPDATE","actionsUntilStop$","liftedUntilStop$","extensionOptions","INIT_ACTION","RECOMPUTE","RECOMPUTE_ACTION","computeNextEntry","nextError","recomputeStates","minInvalidatedStateIndex","committedState","skippedActionIds","nextComputedStates","lastIncludedActionId","previousEntry","previousError","initialCommittedState","monitorReducer","monitorState","initialLiftedState","commitExcessActions","excess","idsToDelete","commitChanges","DevtoolsActions.LOCK_CHANGES","DevtoolsActions.PAUSE_RECORDING","DevtoolsActions.RESET","DevtoolsActions.COMMIT","DevtoolsActions.ROLLBACK","DevtoolsActions.TOGGLE_ACTION","DevtoolsActions.SET_ACTIONS_ACTIVE","actionIds","DevtoolsActions.JUMP_TO_STATE","DevtoolsActions.JUMP_TO_ACTION","DevtoolsActions.SWEEP","DevtoolsActions.PERFORM_ACTION","DevtoolsActions.IMPORT_STATE","StoreDevtools","reducers$","scannedActions","initialState","liftedInitialState","liftInitialState","liftReducer","liftReducerWith","liftedAction$","liftedReducer$","liftedStateSubject","liftedStateSubscription","reducedLiftedState","Actions.PERFORM_ACTION","extensionStartSubscription","refresh","liftedState$","state$","stateSubscription","performAction","Actions.Refresh","Actions.Reset","rollback","Actions.Rollback","commit","Actions.Commit","sweep","Actions.Sweep","toggleAction","Actions.ToggleAction","jumpToAction","Actions.JumpToAction","jumpToState","Actions.JumpToState","importState","Actions.ImportState","lockChanges","Actions.LockChanges","pauseRecording","Actions.PauseRecording","INITIAL_STATE","IS_EXTENSION_OR_MONITOR_PRESENT","createReduxDevtoolsExtension","extensionKey","createIsExtensionOrMonitorPresent","StateObservable","createStateObservable","ReducerManagerDispatcher","devtools","provideStoreDevtools","REGISTERED_ACTION_TYPES","defineType","_as","_p","creator","ACTIONS_SUBJECT_PROVIDERS","_ROOT_STORE_GUARD","_INITIAL_STATE","REDUCER_FACTORY","_REDUCER_FACTORY","INITIAL_REDUCERS","_INITIAL_REDUCERS","STORE_FEATURES","_STORE_REDUCERS","_FEATURE_REDUCERS","_FEATURE_CONFIGS","_STORE_FEATURES","_FEATURE_REDUCERS_TOKEN","FEATURE_REDUCERS","USER_PROVIDED_META_REDUCERS","META_REDUCERS","_RESOLVED_META_REDUCERS","USER_RUNTIME_CHECKS","_USER_RUNTIME_CHECKS","ACTIVE_RUNTIME_CHECKS","_ACTION_TYPE_UNIQUENESS_CHECK","combineReducers","reducers","reducerKeys","finalReducers","finalReducerKeys","hasChanged","previousStateForKey","nextStateForKey","composed","reducerFactory","metaReducers","ReducerObservable","ReducerManager","currentReducers","addFeature","addFeatures","reducerDict","createFeatureReducerFactory","createReducerFactory","addReducers","removeFeature","removeFeatures","removeReducers","addReducer","Vt","updateReducers","removeReducer","featureKey","featureKeys","keyToRemove","omit","REDUCER_MANAGER_PROVIDERS","SCANNED_ACTIONS_SUBJECT_PROVIDERS","reducer$","stateAndAction$","reduceState","stateActionPair","STATE_PROVIDERS","Store","actionsObserver","reducerManager","pathOrMapFn","STORE_PROVIDERS","propsOrPath","mapped$","pathSlices","pluck","currentProp","RUNTIME_CHECK_URL","isUndefined","isNull","isObjectLike","_ngrxMockEnvironment","defaultMemoize","projectionFn","isArgumentsEqual","isEqualCheck","isResultEqual","overrideResult","lastArguments","lastResult","memoized","isArgumentsChanged","newResult","setResult","clearResult","memoize","stateFn","defaultStateFn","tail","isSelectorsDictionary","extractArgsFromSelectorsDictionary","selectorsDictionary","resultKeys","selectorResults","Mi","projector","memoizedSelectors","release","memoizedProjector","memoizedState","createSelectorFactory","featureName","featureState","isNgrxMockEnvironment","_createStoreReducers","configs","featureStores","feat","conf","_createFeatureReducers","reducerCollection","_initialStateFactory","userProvidedMetaReducers","targetIsFunction","propValue","isFrozen","getUnserializable","isPlainObject","targetPrototype","throwIfUnserializable","unserializable","unserializablePath","createActiveRuntimeChecks","runtimeChecks","strictStateSerializability","strictActionSerializability","strictStateImmutability","strictActionImmutability","strictActionWithinNgZone","strictActionTypeUniqueness","createSerializationCheckMetaReducer","serializationCheckMetaReducer","ignoreNgrxAction","createImmutabilityCheckMetaReducer","act","immutabilityCheckMetaReducer","ngCore","inNgZoneAssertMetaReducer","provideRuntimeChecks","_runtimeChecksFactory","createInNgZoneCheckMetaReducer","checkForActionTypeUniqueness","_actionTypeUniquenessCheck","registrations","_provideStore","_concatMetaReducers","_provideState","featureNameOrSlice","_createFeatureStore","StoreRootModule","scannedActions$","actionCheck","StoreFeatureModule","featureReducers","feats","ons","existingReducer","TranslateFakeLoader","FakeMissingTranslationHandler","o1","o2","keySet","mergeDeep","ct","TranslateParser","TranslateDefaultParser","templateMatcher","interpolate","interpolateString","interpolateFunction","TranslateFakeCompiler","TranslateStore","currentLang","defaultLang","langs","onTranslationChange","onLangChange","onDefaultLangChange","USE_STORE","USE_DEFAULT_LANG","DEFAULT_LANGUAGE","USE_EXTEND","TranslateService","missingTranslationHandler","useDefaultLang","isolate","defaultLanguage","_onTranslationChange","_onLangChange","_onDefaultLangChange","_langs","_translations","_translationRequests","_defaultLang","_currentLang","retrieveTranslations","changeDefaultLang","getDefaultLang","changeLang","loadingTranslations","updateLangs","setTranslation","shouldMerge","getLangs","getParsedResult","getStreamOnTranslationChange","reloadLang","resetLang","getBrowserLang","browserLang","browserLanguage","getBrowserCultureLang","browserCultureLang","TranslatePipe","lastParams","updateValue","onTranslation","validArgs","isChildOfPicture","isImageElement","setImage","imagePath","useSrcset","srcset","setSources","setSourcesToDefault","setSourcesToLazy","setSourcesToError","setImageAndSources","setSourcesFn","setImageAndSourcesToDefault","setImageAndSourcesToLazy","setImageAndSourcesToError","Hooks","getNavigator","setPlatformId","onAttributeChange","newAttributes","removeCssClassName","cssClassName","addCssClassName","SharedHooks","defaultImagePath","hasCssClassName","skipLazyLoading","img","sizes","setErrorImage","errorImagePath","setLoadedImage","isBot","IntersectionObserverHooks","getObservable","isIntersecting","customObservable","scrollContainerKey","uniqKey","rootMargin","IntersectionObserver","entrys","loadingCallback","intersectionSubject","unobserve","LAZYLOAD_IMAGE_HOOKS","LazyLoadImageDirective","propertyChanges$","uid","debugSubscription","lazyImage","errorImage","scrollTarget","loadSubscription","lazyLoadImage","evntObservable","_angular_core__WEBPACK_IMPORTED_MODULE_10__","Rect","_window","inflate","inflateBy","intersectsWith","getIntersectionWith","resizeObservers","ResizeObserverBoxOptions","BORDER_BOX","CONTENT_BOX","DEVICE_PIXEL_CONTENT_BOX","ResizeObserverSize","inlineSize","blockSize","DOMRectReadOnly","toJSON","rectangle","isSVG","SVGElement","getBBox","scrollRegexp","verticalRegexp","IE","parseDimension","pixel","switchSizes","zeroBoxes","devicePixelContentBoxSize","borderBoxSize","contentBoxSize","contentRect","calculateBoxSizes","forceRecalculation","ownerSVGElement","boxSizing","writingMode","canScrollVertically","canScrollHorizontally","paddingTop","paddingLeft","borderTop","borderTopWidth","borderRight","borderRightWidth","borderBottom","borderBottomWidth","horizontalPadding","verticalPadding","horizontalBorderArea","borderLeftWidth","verticalBorderArea","horizontalScrollbarThickness","verticalScrollbarThickness","widthReduction","heightReduction","contentWidth","contentHeight","borderBoxWidth","borderBoxHeight","calculateBoxSize","observedBox","ResizeObserverEntry","calculateDepthForNode","broadcastActiveObservations","shallowestDepth","activeTargets","targetDepth","lastReportedSize","callbacks_1","gatherActiveObservationsAtDepth","skippedTargets","observationTargets","watching","observerConfig","until","toggle_1","el_1","queueMicroTask","queueResizeObserver","elementsHaveResized","ErrorEvent","deliverResizeLoopError","updateCount","ResizeObservation","isReplacedElement","skipNotifyOnElement","ResizeObserverDetail","resizeObserver","observerMap","getObservationIndex","ResizeObserverController","firstObservation","ResizeObserver","RESIZE_OBSERVER","NgResizeObserver","ResizeObserverService","chgRef","onResizeSubject","NgResizeObserverProvider","ngResizeObserverFactory","resizeObserverService","polyfillProvider","ponyFillFactory","Polyfill","ngResizeObserverProviders","DefaultPlyrDriver","PlyrComponent","plyrType","playerChange","createLazyEvent","reinitTriggers","plyrOptions","plyrPlaysInline","plyrCrossOrigin","initPlyr","updatePlyrSource","destroyPlayer","plyrDriver","ensureVideoElement","newPlayer","plyrTitle","plyrSources","plyrPoster","plyrTracks","newestOnTop","BasePortalHost","ToastRef","duplicatesCount","manualClose","_manualClose","manualClosed","timeoutReset","_resetTimeout","countDuplicate","_countDuplicate","_afterClosed","_activate","isInactive","afterActivate","onDuplicate","resetTimeout","ToastPackage","toastId","toastRef","_onAction","_onTap","triggerTap","tapToDismiss","onTap","triggerAction","onAction","TOAST_CONFIG","DomPortalHost","_hostDomElement","_portalHost","_createOverlayRef","getPaneElement","_paneElements","_createPortalHost","currentlyActive","toasts","toastrConfig","iconClasses","override","_preBuildNotification","applyConfig","warning","toast","_findToast","activeToast","maxOpened","findDuplicate","resetOnDuplicate","countDuplicates","includeTitleDuplicates","_buildNotification","toastComponent","duplicate","resetTimeoutOnDuplicate","preventDuplicates","previousToastMessage","keepInactive","autoDismiss","sanitizedMessage","toastPackage","toastInjector","ins","onShown","onHidden","Toast","displayStyle","toastClasses","easeTime","originalTimeout","activateToast","sub1","sub2","sub3","intervalId","disableTimeOut","outsideTimeout","hideTime","outsideInterval","progressAnimation","tapToast","stickAround","delayedHideToast","runInsideAngular","closeButton","titleClass","messageClass","provideToastr","DefaultGlobalConfig","timeoutID","_ref$noTrailing","noTrailing","noLeading","debounceMode","_ref$debounceMode","cancelled","lastExec","clearExistingTimeout","arguments_","_ref2$upcomingOnly","upcomingOnly","_ref$atBegin","atBegin","asyncGeneratorStep","adopt","verb","settle","resume"],"sourceRoot":"webpack:///","sources":["./projects/portal/src/app/components/footer/footer.component.html","./projects/portal/src/app/components/footer/footer.component.ts","./projects/portal/src/app/components/spinner/spinner.component.ts","./projects/portal/src/app/components/spinner/spinner.component.html","./projects/portal/src/app/constants/query-strings.const.ts","./projects/portal/src/app/enums/audio-player-type.enum.ts","./projects/portal/src/app/enums/content-type.enum.ts","./projects/portal/src/app/enums/facet-type.enum.ts","./projects/portal/src/app/enums/gtm-event.enum.ts","./projects/portal/src/app/enums/loading-keys.enum.ts","./projects/portal/src/app/enums/menu-type.enum.ts","./projects/portal/src/app/enums/page-type.enum.ts","./projects/portal/src/app/enums/period-selector.enum.ts","./projects/portal/src/app/enums/project-type.enum.ts","./projects/portal/src/app/enums/ps/ps-library-filter.enum.ts","./projects/portal/src/app/enums/section-type.enum.ts","./projects/portal/src/app/enums/umb-ui-settings.ts","./projects/portal/src/app/helpers/missing-translation.helper.ts","./projects/portal/src/app/mapper/activity/activity.mapper.ts","./projects/portal/src/app/mapper/book/book-collection.mapper.ts","./projects/portal/src/app/mapper/book/book-impression.mapper.ts","./projects/portal/src/app/mapper/book/book-library.mapper.ts","./projects/portal/src/app/enums/difficulty-type.enum.ts","./projects/portal/src/app/mapper/book/book-difficulties.mapper.ts","./projects/portal/src/app/mapper/book/book.mapper.ts","./projects/portal/src/app/mapper/course/course-favorite.mapper.ts","./projects/portal/src/app/mapper/course/course-library.mapper.ts","./projects/portal/src/app/mapper/course/course-tabs.mapper.ts","./projects/portal/src/app/mapper/course/course.mapper.ts","./projects/portal/src/app/mapper/ps/ps-article.mapper.ts","./projects/portal/src/app/mapper/ps/ps-assignment.mapper.ts","./projects/portal/src/app/mapper/shared/asset.mapper.ts","./projects/portal/src/app/modules/app/layout-audio/layout-audio.module.ts","./projects/portal/src/app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.actions.ts","./projects/portal/src/app/modules/routes/book-teacher-dashboard/dashboard-helper.service.ts","./projects/portal/src/app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.effects.ts","./projects/portal/src/app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.reducer.ts","./projects/portal/src/app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.selectors.ts","./projects/portal/src/app/modules/shared/audio-player/audio-player.module.ts","./projects/portal/src/app/modules/shared/audio-player/components/audio-selection-player/audio-selection-player.component.html","./projects/portal/src/app/modules/shared/audio-player/components/audio-selection-player/audio-selection-player.component.ts","./projects/portal/src/app/modules/shared/base/base.module.ts","./projects/portal/src/app/modules/shared/base/components/book-difficulties/book-difficulties.component.html","./projects/portal/src/app/modules/shared/base/components/book-difficulties/book-difficulties.component.ts","./projects/portal/src/app/modules/shared/base/components/select-impressions-modal/select-impressions-modal.component.html","./projects/portal/src/app/modules/shared/base/components/select-impressions-modal/select-impressions-modal.component.ts","./projects/portal/src/app/modules/shared/base/components/book-tile/book-tile.component.html","./projects/portal/src/app/modules/shared/base/components/book-tile/book-tile.component.ts","./projects/portal/src/app/modules/shared/base/components/checkbox/checkbox.component.ts","./projects/portal/src/app/modules/shared/base/components/checkbox/checkbox.component.html","./projects/portal/src/app/modules/shared/base/components/dropdown/dropdown.component.html","./projects/portal/src/app/modules/shared/base/components/dropdown/dropdown.component.ts","./projects/portal/src/app/services/ps/ps-favorite.service.ts","./projects/portal/src/app/modules/shared/base/components/favorite/favorite.component.html","./projects/portal/src/app/modules/shared/base/components/favorite/favorite.component.ts","./projects/portal/src/app/modules/shared/base/components/manage-book-collection/manage-book-collection.component.html","./projects/portal/src/app/modules/shared/base/components/manage-book-collection/manage-book-collection.component.ts","./projects/portal/src/app/modules/shared/library-search/components/book-card-preview/book-card-preview.component.html","./projects/portal/src/app/modules/shared/library-search/components/book-card-preview/book-card-preview.component.ts","./projects/portal/src/app/modules/shared/library-search/components/course-card-preview/course-card-preview.component.html","./projects/portal/src/app/modules/shared/library-search/components/course-card-preview/course-card-preview.component.ts","./projects/portal/src/app/modules/shared/library-search/components/library-search/library-search.component.html","./projects/portal/src/app/modules/shared/library-search/components/library-search/library-search.component.ts","./projects/portal/src/app/modules/shared/library-search/library-search.module.ts","./projects/portal/src/app/pipes/background-image.pipe.ts","./projects/portal/src/app/pipes/next-image.pipe.ts","./projects/portal/src/app/pipes/shared/shared-pipe.module.ts","./projects/portal/src/app/pipes/truncate.pipe.ts","./projects/portal/src/app/pipes/umbraco-image.pipe.ts","./projects/portal/src/app/services/activity/activity-favorite.service.ts","./projects/portal/src/app/services/book/book-collection-favorite.service.ts","./projects/portal/src/app/services/book/book-collection.service.ts","./projects/portal/src/app/services/book/book-continue.service.ts","./projects/portal/src/app/services/book/book-favorite.service.ts","./projects/portal/src/app/services/book/book-finished.service.ts","./projects/portal/src/app/services/book/book-impression.service.ts","./projects/portal/src/app/services/book/book-library.service.ts","./projects/portal/src/app/services/course/course-favorite-api.service.ts","./projects/portal/src/app/services/course/course-library.service.ts","./projects/portal/src/app/mapper/ps/ps-library.mapper.ts","./projects/portal/src/app/services/ps/ps-library.service.ts","./node_modules/current-device/es/index.js","./projects/portal/src/app/mapper/shared/site-configuration.mapper.ts","./projects/portal/src/app/services/shared/app-init.service.ts","./node_modules/rxjs/src/internal/operators/retry.ts","./projects/portal/src/app/services/shared/breadcrumbs.service.ts","./projects/portal/src/app/services/shared/breakpoints.service.ts","./projects/portal/src/app/services/shared/dropdown.service.ts","./projects/portal/src/app/services/shared/extended-dialog.service.ts","./projects/portal/src/app/services/shared/header.service.ts","./projects/portal/src/app/services/shared/helper.service.ts","./projects/portal/src/app/pipes/keep-html.pipe.ts","./projects/portal/src/app/services/shared/html.service.ts","./projects/portal/src/app/enums/text-to-speech-language.enum.ts","./projects/portal/src/app/services/shared/layout-audio.service.ts","./projects/portal/src/app/services/shared/level.service.ts","./projects/portal/src/app/services/shared/navbar.service.ts","./projects/portal/src/app/services/shared/page/page.service.ts","./projects/portal/src/app/services/shared/script.service.ts","./projects/portal/src/app/services/shared/selection.service.ts","./projects/portal/src/app/services/shared/seo.service.ts","./projects/portal/src/environments/environment.dev.ts","./projects/portal/src/app/enums/dimensions.enum.ts","../packages/animations/browser/src/error_helpers.ts","../packages/animations/browser/src/render/shared.ts","../packages/animations/browser/src/render/animation_driver.ts","../packages/animations/browser/src/util.ts","../packages/animations/browser/src/dsl/animation_transition_expr.ts","../packages/animations/browser/src/dsl/animation_ast_builder.ts","../packages/animations/browser/src/dsl/animation_timeline_instruction.ts","../packages/animations/browser/src/dsl/element_instruction_map.ts","../packages/animations/browser/src/dsl/animation_timeline_builder.ts","../packages/animations/browser/src/dsl/style_normalization/animation_style_normalizer.ts","../packages/animations/browser/src/dsl/style_normalization/web_animations_style_normalizer.ts","../packages/animations/browser/src/dsl/animation_transition_instruction.ts","../packages/animations/browser/src/dsl/animation_transition_factory.ts","../packages/animations/browser/src/dsl/animation_trigger.ts","../packages/animations/browser/src/render/timeline_animation_engine.ts","../packages/animations/browser/src/render/transition_animation_engine.ts","../packages/animations/browser/src/render/animation_engine_next.ts","../packages/animations/browser/src/render/special_cased_styles.ts","../packages/animations/browser/src/render/web_animations/web_animations_player.ts","../packages/animations/browser/src/render/web_animations/web_animations_driver.ts","../packages/platform-browser/animations/src/animation_builder.ts","../packages/platform-browser/animations/src/animation_renderer.ts","../packages/platform-browser/animations/src/providers.ts","../packages/platform-browser/animations/src/module.ts","./node_modules/@ngx-translate/http-loader/fesm2020/ngx-translate-http-loader.mjs","./projects/portal/src/app/guards/route-has-page.guard.ts","./projects/portal/src/app/guards/set-gtm-for-route.guard.ts","./projects/portal/src/app/guards/set-page-for-route.guard.ts","./projects/portal/src/app/app-routing.module.ts","./projects/portal/src/app/enums/header-type.enum.ts","./projects/portal/src/app/services/shared/mouse-and-keyboard.service.ts","./projects/portal/src/app/services/shared/window-scroll.service.ts","./projects/portal/src/app/enums/link-type.enum.ts","./projects/portal/src/app/mapper/shared/navbar.mapper.ts","./projects/portal/src/app/modules/app/header/components/navbar/navbar.component.html","./projects/portal/src/app/modules/app/header/components/navbar/navbar.component.ts","./projects/portal/src/app/services/shared/mega-menu.service.ts","./projects/portal/src/app/mapper/shared/mega-menu.mapper.ts","./projects/portal/src/app/modules/app/header/components/mega-menu/mega-menu.component.html","./projects/portal/src/app/modules/app/header/components/mega-menu/mega-menu.component.ts","./projects/portal/src/app/modules/app/header/components/user/user.component.ts","./projects/portal/src/app/modules/app/header/components/user/user.component.html","./projects/portal/src/app/modules/app/header/components/header-default/header-default.component.html","./projects/portal/src/app/modules/app/header/components/header-default/header-default.component.ts","./projects/portal/src/app/modules/shared/base/components/breadcrumbs/breadcrumbs.component.html","./projects/portal/src/app/modules/shared/base/components/breadcrumbs/breadcrumbs.component.ts","./node_modules/hls.js/dist/node_modules/url-toolkit/src/url-toolkit.js","./node_modules/hls.js/dist/src/polyfills/number.ts","./node_modules/hls.js/dist/src/events.ts","./node_modules/hls.js/dist/src/errors.ts","./node_modules/hls.js/dist/src/utils/logger.ts","./node_modules/hls.js/dist/src/utils/attr-list.ts","./node_modules/hls.js/dist/src/loader/date-range.ts","./node_modules/hls.js/dist/src/loader/load-stats.ts","./node_modules/hls.js/dist/src/loader/fragment.ts","./node_modules/hls.js/dist/src/loader/level-details.ts","./node_modules/hls.js/dist/src/utils/numeric-encoding-utils.ts","./node_modules/hls.js/dist/src/utils/keysystem-util.ts","./node_modules/hls.js/dist/src/utils/mediakeys-helper.ts","./node_modules/hls.js/dist/src/utils/typed-array.ts","./node_modules/hls.js/dist/src/demux/id3.ts","./node_modules/hls.js/dist/src/utils/hex.ts","./node_modules/hls.js/dist/src/utils/mp4-tools.ts","./node_modules/hls.js/dist/src/loader/level-key.ts","./node_modules/hls.js/dist/src/utils/variable-substitution.ts","./node_modules/hls.js/dist/src/utils/mediasource-helper.ts","./node_modules/hls.js/dist/src/utils/codecs.ts","./node_modules/hls.js/dist/src/loader/m3u8-parser.ts","./node_modules/hls.js/dist/src/types/loader.ts","./node_modules/hls.js/dist/src/loader/playlist-loader.ts","./node_modules/hls.js/dist/src/utils/texttrack-utils.ts","./node_modules/hls.js/dist/src/types/demuxer.ts","./node_modules/hls.js/dist/src/controller/id3-track-controller.ts","./node_modules/hls.js/dist/src/controller/latency-controller.ts","./node_modules/hls.js/dist/src/types/level.ts","./node_modules/hls.js/dist/src/controller/level-helper.ts","./node_modules/hls.js/dist/src/utils/error-helper.ts","./node_modules/hls.js/dist/src/utils/binary-search.ts","./node_modules/hls.js/dist/src/controller/fragment-finders.ts","./node_modules/hls.js/dist/src/controller/error-controller.ts","./node_modules/hls.js/dist/src/controller/base-playlist-controller.ts","./node_modules/hls.js/dist/src/controller/level-controller.ts","./node_modules/hls.js/dist/src/controller/fragment-tracker.ts","./node_modules/hls.js/dist/src/loader/fragment-loader.ts","./node_modules/hls.js/dist/src/loader/key-loader.ts","./node_modules/hls.js/dist/src/task-loop.ts","./node_modules/hls.js/dist/src/utils/buffer-helper.ts","./node_modules/hls.js/dist/src/types/transmuxer.ts","./node_modules/hls.js/dist/src/utils/discontinuities.ts","./node_modules/hls.js/dist/src/crypt/aes-crypto.ts","./node_modules/hls.js/dist/src/crypt/fast-aes-key.ts","./node_modules/hls.js/dist/src/crypt/aes-decryptor.ts","./node_modules/hls.js/dist/src/crypt/decrypter.ts","./node_modules/hls.js/dist/src/controller/base-stream-controller.ts","./node_modules/hls.js/dist/src/utils/time-ranges.ts","./node_modules/hls.js/dist/src/is-supported.ts","./node_modules/hls.js/dist/src/demux/dummy-demuxed-track.ts","./node_modules/hls.js/dist/src/demux/base-audio-demuxer.ts","./node_modules/hls.js/dist/src/demux/adts.ts","./node_modules/hls.js/dist/src/demux/mp4demuxer.ts","./node_modules/hls.js/dist/src/demux/mpegaudio.ts","./node_modules/hls.js/dist/src/demux/exp-golomb.ts","./node_modules/hls.js/dist/src/demux/sample-aes.ts","./node_modules/hls.js/dist/src/demux/tsdemuxer.ts","./node_modules/hls.js/dist/src/remux/aac-helper.ts","./node_modules/hls.js/dist/src/remux/mp4-generator.ts","./node_modules/hls.js/dist/src/utils/timescale-conversion.ts","./node_modules/hls.js/dist/src/remux/mp4-remuxer.ts","./node_modules/hls.js/dist/src/demux/transmuxer.ts","./node_modules/hls.js/dist/src/remux/passthrough-remuxer.ts","./node_modules/hls.js/dist/src/demux/aacdemuxer.ts","./node_modules/hls.js/dist/src/demux/mp3demuxer.ts","./node_modules/hls.js/dist/node_modules/eventemitter3/index.js","./node_modules/hls.js/dist/src/demux/transmuxer-interface.ts","./node_modules/hls.js/dist/src/demux/inject-worker.ts","./node_modules/hls.js/dist/src/controller/gap-controller.ts","./node_modules/hls.js/dist/src/controller/stream-controller.ts","./node_modules/hls.js/dist/src/utils/ewma.ts","./node_modules/hls.js/dist/src/utils/ewma-bandwidth-estimator.ts","./node_modules/hls.js/dist/src/demux/chunk-cache.ts","./node_modules/hls.js/dist/src/utils/media-option-attributes.ts","./node_modules/hls.js/dist/src/controller/subtitle-stream-controller.ts","./node_modules/hls.js/dist/src/controller/subtitle-track-controller.ts","./node_modules/hls.js/dist/src/controller/buffer-operation-queue.ts","./node_modules/hls.js/dist/src/controller/buffer-controller.ts","./node_modules/hls.js/dist/src/utils/cea-608-parser.ts","./node_modules/hls.js/dist/src/utils/output-filter.ts","./node_modules/hls.js/dist/src/utils/vttcue.ts","./node_modules/hls.js/dist/src/utils/vttparser.ts","./node_modules/hls.js/dist/src/utils/webvtt-parser.ts","./node_modules/hls.js/dist/src/utils/imsc1-ttml-parser.ts","./node_modules/hls.js/dist/src/controller/timeline-controller.ts","./node_modules/hls.js/dist/src/controller/cap-level-controller.ts","./node_modules/hls.js/dist/src/controller/eme-controller.ts","./node_modules/hls.js/dist/src/controller/cmcd-controller.ts","./node_modules/hls.js/dist/src/types/cmcd.ts","./node_modules/hls.js/dist/src/controller/content-steering-controller.ts","./node_modules/hls.js/dist/src/utils/xhr-loader.ts","./node_modules/hls.js/dist/src/utils/fetch-loader.ts","./node_modules/hls.js/dist/src/utils/cues.ts","./node_modules/hls.js/dist/src/config.ts","./node_modules/hls.js/dist/src/controller/abr-controller.ts","./node_modules/hls.js/dist/src/controller/fps-controller.ts","./node_modules/hls.js/dist/src/controller/audio-stream-controller.ts","./node_modules/hls.js/dist/src/controller/audio-track-controller.ts","./node_modules/hls.js/dist/src/hls.ts","./projects/portal/src/app/modules/shared/audio-player/components/audio-hls-player/hlsjs-plyr-driver.ts","./projects/portal/src/app/modules/shared/audio-player/components/audio-hls-player/audio-hls-player.component.html","./projects/portal/src/app/modules/shared/audio-player/components/audio-hls-player/audio-hls-player.component.ts","./projects/portal/src/app/modules/app/layout-audio/components/layout-audio-recorded/layout-audio-recorded.component.html","./projects/portal/src/app/modules/app/layout-audio/components/layout-audio-recorded/layout-audio-recorded.component.ts","./projects/portal/src/app/modules/app/layout-audio/components/layout-audio-partial/layout-audio-partial.component.html","./projects/portal/src/app/modules/app/layout-audio/components/layout-audio-partial/layout-audio-partial.component.ts","./projects/portal/src/app/modules/app/header/components/header-book/header-book.component.html","./projects/portal/src/app/modules/app/header/components/header-book/header-book.component.ts","./projects/portal/src/app/modules/app/header/components/header-course/header-course.component.ts","./projects/portal/src/app/modules/app/header/components/header-course/header-course.component.html","./projects/portal/src/app/modules/app/header/components/header/header.component.html","./projects/portal/src/app/modules/app/header/components/header/header.component.ts","./projects/portal/src/app/components/dropdown-overlay/dropdown-overlay.component.ts","./projects/portal/src/app/components/dropdown-overlay/dropdown-overlay.component.html","./projects/portal/src/app/components/loader/loader.component.html","./projects/portal/src/app/components/loader/loader.component.ts","./projects/portal/src/app/app.component.html","./projects/portal/src/app/app.component.ts","./projects/portal/src/app/modules/app/core/errors/global-error-handler.ts","./projects/portal/src/app/modules/app/header/header.module.ts","./node_modules/src/lib/message-format-config.ts","./node_modules/src/lib/translate-message-format-compiler.ts","./projects/portal/src/app/interceptors/refreshToken.interceptor.ts","./projects/portal/src/app/app.module.ts","./projects/portal/src/main.ts","./node_modules/@messageformat/core/messageformat.js","./node_modules/ng-inline-svg-2/lib_esmodule/inline-svg.config.js","./node_modules/ng-inline-svg-2/lib_esmodule/inline-svg.service.js","./node_modules/ng-inline-svg-2/lib_esmodule/inline-svg.component.js","./node_modules/ng-inline-svg-2/lib_esmodule/svg-cache.service.js","./node_modules/ng-inline-svg-2/lib_esmodule/svg-util.js","./node_modules/ng-inline-svg-2/lib_esmodule/inline-svg.directive.js","./node_modules/ng-inline-svg-2/lib_esmodule/inline-svg.module.js","./node_modules/plyr/dist/plyr.js","./node_modules/plyr/dist/node_modules/.pnpm/rangetouch@2.0.1/node_modules/rangetouch/dist/rangetouch.mjs","./node_modules/plyr/dist/src/js/utils/is.js","./node_modules/plyr/dist/src/js/utils/animation.js","./node_modules/plyr/dist/src/js/utils/browser.js","./node_modules/plyr/dist/src/js/utils/objects.js","./node_modules/plyr/dist/src/js/utils/elements.js","./node_modules/plyr/dist/src/js/support.js","./node_modules/plyr/dist/src/js/utils/events.js","./node_modules/plyr/dist/src/js/utils/promise.js","./node_modules/plyr/dist/src/js/utils/arrays.js","./node_modules/plyr/dist/src/js/utils/style.js","./node_modules/plyr/dist/src/js/html5.js","./node_modules/plyr/dist/src/js/utils/strings.js","./node_modules/plyr/dist/src/js/utils/i18n.js","./node_modules/plyr/dist/src/js/storage.js","./node_modules/plyr/dist/src/js/utils/fetch.js","./node_modules/plyr/dist/src/js/utils/load-sprite.js","./node_modules/plyr/dist/src/js/utils/time.js","./node_modules/plyr/dist/src/js/controls.js","./node_modules/plyr/dist/src/js/utils/urls.js","./node_modules/plyr/dist/src/js/captions.js","./node_modules/plyr/dist/src/js/config/defaults.js","./node_modules/plyr/dist/src/js/config/states.js","./node_modules/plyr/dist/src/js/config/types.js","./node_modules/plyr/dist/src/js/console.js","./node_modules/plyr/dist/src/js/fullscreen.js","./node_modules/plyr/dist/src/js/utils/load-image.js","./node_modules/plyr/dist/src/js/ui.js","./node_modules/plyr/dist/src/js/listeners.js","./node_modules/plyr/dist/node_modules/.pnpm/loadjs@4.2.0/node_modules/loadjs/dist/loadjs.umd.js","./node_modules/plyr/dist/src/js/utils/load-script.js","./node_modules/plyr/dist/src/js/plugins/vimeo.js","./node_modules/plyr/dist/src/js/plugins/youtube.js","./node_modules/plyr/dist/src/js/media.js","./node_modules/plyr/dist/src/js/plugins/ads.js","./node_modules/plyr/dist/src/js/utils/numbers.js","./node_modules/plyr/dist/src/js/plugins/preview-thumbnails.js","./node_modules/plyr/dist/src/js/source.js","./node_modules/plyr/dist/src/js/plyr.js","./node_modules/rxjs/src/internal/BehaviorSubject.ts","./node_modules/rxjs/src/internal/Observable.ts","./node_modules/rxjs/src/internal/ReplaySubject.ts","./node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts","./node_modules/rxjs/src/internal/Subject.ts","./node_modules/rxjs/src/internal/NotificationFactories.ts","./node_modules/rxjs/src/internal/Subscriber.ts","./node_modules/rxjs/src/internal/util/UnsubscriptionError.ts","./node_modules/rxjs/src/internal/Subscription.ts","./node_modules/rxjs/src/internal/config.ts","./node_modules/rxjs/src/internal/firstValueFrom.ts","./node_modules/rxjs/src/internal/observable/combineLatest.ts","./node_modules/rxjs/src/internal/observable/concat.ts","./node_modules/rxjs/src/internal/operators/concatAll.ts","./node_modules/rxjs/src/internal/observable/defer.ts","./node_modules/rxjs/src/internal/observable/empty.ts","./node_modules/rxjs/src/internal/observable/forkJoin.ts","./node_modules/rxjs/src/internal/operators/subscribeOn.ts","./node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts","./node_modules/rxjs/src/internal/observable/from.ts","./node_modules/rxjs/src/internal/scheduled/scheduled.ts","./node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts","./node_modules/rxjs/src/internal/scheduled/scheduleArray.ts","./node_modules/rxjs/src/internal/scheduled/schedulePromise.ts","./node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts","./node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts","./node_modules/rxjs/src/internal/observable/fromEvent.ts","./node_modules/rxjs/src/internal/observable/iif.ts","./node_modules/rxjs/src/internal/observable/innerFrom.ts","./node_modules/rxjs/src/internal/observable/merge.ts","./node_modules/rxjs/src/internal/observable/never.ts","./node_modules/rxjs/src/internal/observable/of.ts","./node_modules/rxjs/src/internal/observable/throwError.ts","./node_modules/rxjs/src/internal/observable/timer.ts","./node_modules/rxjs/src/internal/observable/zip.ts","./node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts","./node_modules/rxjs/src/internal/operators/catchError.ts","./node_modules/rxjs/src/internal/operators/concatMap.ts","./node_modules/rxjs/src/internal/operators/debounceTime.ts","./node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts","./node_modules/rxjs/src/internal/operators/delayWhen.ts","./node_modules/rxjs/src/internal/operators/delay.ts","./node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts","./node_modules/rxjs/src/internal/operators/exhaustMap.ts","./node_modules/rxjs/src/internal/operators/filter.ts","./node_modules/rxjs/src/internal/operators/finalize.ts","./node_modules/rxjs/src/internal/operators/first.ts","./node_modules/rxjs/src/internal/operators/ignoreElements.ts","./node_modules/rxjs/src/internal/operators/map.ts","./node_modules/rxjs/src/internal/operators/mapTo.ts","./node_modules/rxjs/src/internal/operators/mergeAll.ts","./node_modules/rxjs/src/internal/operators/mergeMap.ts","./node_modules/rxjs/src/internal/operators/mergeInternals.ts","./node_modules/rxjs/src/internal/operators/observeOn.ts","./node_modules/rxjs/src/internal/operators/scan.ts","./node_modules/rxjs/src/internal/operators/scanInternals.ts","./node_modules/rxjs/src/internal/operators/share.ts","./node_modules/rxjs/src/internal/operators/shareReplay.ts","./node_modules/rxjs/src/internal/operators/skip.ts","./node_modules/rxjs/src/internal/operators/startWith.ts","./node_modules/rxjs/src/internal/operators/switchMap.ts","./node_modules/rxjs/src/internal/operators/take.ts","./node_modules/rxjs/src/internal/operators/takeUntil.ts","./node_modules/rxjs/src/internal/operators/tap.ts","./node_modules/rxjs/src/internal/operators/throwIfEmpty.ts","./node_modules/rxjs/src/internal/operators/timeout.ts","./node_modules/rxjs/src/internal/operators/withLatestFrom.ts","./node_modules/rxjs/src/internal/scheduler/Action.ts","./node_modules/rxjs/src/internal/scheduler/intervalProvider.ts","./node_modules/rxjs/src/internal/scheduler/AsyncAction.ts","./node_modules/rxjs/src/internal/Scheduler.ts","./node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts","./node_modules/rxjs/src/internal/util/Immediate.ts","./node_modules/rxjs/src/internal/scheduler/immediateProvider.ts","./node_modules/rxjs/src/internal/scheduler/asap.ts","./node_modules/rxjs/src/internal/scheduler/AsapScheduler.ts","./node_modules/rxjs/src/internal/scheduler/AsapAction.ts","./node_modules/rxjs/src/internal/scheduler/async.ts","./node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts","./node_modules/rxjs/src/internal/scheduler/queue.ts","./node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts","./node_modules/rxjs/src/internal/scheduler/QueueAction.ts","./node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts","./node_modules/rxjs/src/internal/symbol/iterator.ts","./node_modules/rxjs/src/internal/symbol/observable.ts","./node_modules/rxjs/src/internal/util/EmptyError.ts","./node_modules/rxjs/src/internal/util/args.ts","./node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts","./node_modules/rxjs/src/internal/util/argsOrArgArray.ts","./node_modules/rxjs/src/internal/util/arrRemove.ts","./node_modules/rxjs/src/internal/util/createErrorClass.ts","./node_modules/rxjs/src/internal/util/createObject.ts","./node_modules/rxjs/src/internal/util/errorContext.ts","./node_modules/rxjs/src/internal/util/executeSchedule.ts","./node_modules/rxjs/src/internal/util/identity.ts","./node_modules/rxjs/src/internal/util/isArrayLike.ts","./node_modules/rxjs/src/internal/util/isAsyncIterable.ts","./node_modules/rxjs/src/internal/util/isDate.ts","./node_modules/rxjs/src/internal/util/isFunction.ts","./node_modules/rxjs/src/internal/util/isInteropObservable.ts","./node_modules/rxjs/src/internal/util/isIterable.ts","./node_modules/rxjs/src/internal/util/isPromise.ts","./node_modules/rxjs/src/internal/util/isReadableStreamLike.ts","./node_modules/rxjs/src/internal/util/isScheduler.ts","./node_modules/rxjs/src/internal/util/lift.ts","./node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts","./node_modules/rxjs/src/internal/util/noop.ts","./node_modules/rxjs/src/internal/util/pipe.ts","./node_modules/rxjs/src/internal/util/reportUnhandledError.ts","./node_modules/rxjs/src/internal/util/throwUnobservableError.ts","./node_modules/uuid/dist/esm-browser/native.js","./node_modules/uuid/dist/esm-browser/rng.js","./node_modules/uuid/dist/esm-browser/stringify.js","./node_modules/uuid/dist/esm-browser/v4.js","../packages/animations/src/animation_builder.ts","../packages/animations/src/animation_metadata.ts","../packages/animations/src/util.ts","../packages/animations/src/players/animation_player.ts","../packages/animations/src/players/animation_group_player.ts","../packages/animations/src/private_export.ts","../src/cdk/a11y/key-manager/list-key-manager.ts","../src/cdk/a11y/key-manager/focus-key-manager.ts","../src/cdk/a11y/interactivity-checker/interactivity-checker.ts","../src/cdk/a11y/aria-describer/aria-describer.ts","../src/cdk/a11y/focus-trap/focus-trap.ts","../src/cdk/a11y/fake-event-detection.ts","../src/cdk/a11y/input-modality/input-modality-detector.ts","../src/cdk/a11y/focus-monitor/focus-monitor.ts","../src/cdk/a11y/high-contrast-mode/high-contrast-mode-detector.ts","../src/cdk/a11y/a11y-module.ts","../src/cdk/bidi/dir-document-token.ts","../src/cdk/bidi/directionality.ts","../src/cdk/bidi/bidi-module.ts","../src/cdk/coercion/boolean-property.ts","../src/cdk/coercion/number-property.ts","../src/cdk/coercion/array.ts","../src/cdk/coercion/css-pixel-value.ts","../src/cdk/coercion/element.ts","../src/cdk/keycodes/keycodes.ts","../src/cdk/keycodes/modifiers.ts","../src/cdk/layout/media-matcher.ts","../src/cdk/layout/breakpoints-observer.ts","../src/cdk/observers/observe-content.ts","../src/cdk/overlay/scroll/block-scroll-strategy.ts","../src/cdk/overlay/scroll/close-scroll-strategy.ts","../src/cdk/overlay/scroll/noop-scroll-strategy.ts","../src/cdk/overlay/position/scroll-clip.ts","../src/cdk/overlay/scroll/reposition-scroll-strategy.ts","../src/cdk/overlay/scroll/scroll-strategy-options.ts","../src/cdk/overlay/overlay-config.ts","../src/cdk/overlay/position/connected-position.ts","../src/cdk/overlay/dispatchers/base-overlay-dispatcher.ts","../src/cdk/overlay/dispatchers/overlay-keyboard-dispatcher.ts","../src/cdk/overlay/dispatchers/overlay-outside-click-dispatcher.ts","../src/cdk/overlay/overlay-container.ts","../src/cdk/overlay/overlay-ref.ts","../src/cdk/overlay/position/flexible-connected-position-strategy.ts","../src/cdk/overlay/position/global-position-strategy.ts","../src/cdk/overlay/position/overlay-position-builder.ts","../src/cdk/overlay/overlay.ts","../src/cdk/overlay/overlay-directives.ts","../src/cdk/overlay/overlay-module.ts","../src/cdk/platform/platform.ts","../src/cdk/platform/features/passive-listeners.ts","../src/cdk/platform/features/scrolling.ts","../src/cdk/platform/features/shadow-dom.ts","../src/cdk/platform/features/test-environment.ts","../src/cdk/portal/portal.ts","../src/cdk/portal/dom-portal-outlet.ts","../src/cdk/portal/portal-directives.ts","./node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts","./node_modules/rxjs/src/internal/scheduler/animationFrame.ts","./node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts","./node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts","./node_modules/rxjs/src/internal/operators/auditTime.ts","./node_modules/rxjs/src/internal/operators/audit.ts","../src/cdk/scrolling/virtual-scroll-strategy.ts","../src/cdk/scrolling/scroll-dispatcher.ts","../src/cdk/scrolling/scrollable.ts","../src/cdk/scrolling/viewport-ruler.ts","../src/cdk/scrolling/virtual-scrollable.ts","../src/cdk/scrolling/virtual-scroll-viewport.ts","../src/cdk/scrolling/virtual-scroll-viewport.html","../src/cdk/scrolling/scrolling-module.ts","../packages/common/src/dom_adapter.ts","../packages/common/src/dom_tokens.ts","../packages/common/src/location/platform_location.ts","../packages/common/src/location/util.ts","../packages/common/src/location/location_strategy.ts","../packages/common/src/location/hash_location_strategy.ts","../packages/common/src/location/location.ts","../packages/common/src/i18n/locale_data_api.ts","../packages/common/src/i18n/format_date.ts","../packages/common/src/i18n/format_number.ts","../packages/common/src/cookie.ts","../packages/common/src/directives/ng_class.ts","../packages/common/src/directives/ng_for_of.ts","../packages/common/src/directives/ng_if.ts","../packages/common/src/directives/ng_plural.ts","../packages/common/src/directives/ng_style.ts","../packages/common/src/directives/ng_template_outlet.ts","../packages/common/src/pipes/invalid_pipe_argument_error.ts","../packages/common/src/pipes/async_pipe.ts","../packages/common/src/pipes/case_conversion_pipes.ts","../packages/common/src/pipes/date_pipe_config.ts","../packages/common/src/pipes/date_pipe.ts","../packages/common/src/pipes/json_pipe.ts","../packages/common/src/pipes/keyvalue_pipe.ts","../packages/common/src/pipes/number_pipe.ts","../packages/common/src/common_module.ts","../packages/common/src/platform_id.ts","../packages/common/src/viewport_scroller.ts","../packages/common/src/xhr.ts","../packages/common/http/src/backend.ts","../packages/common/http/src/headers.ts","../packages/common/http/src/params.ts","../packages/common/http/src/context.ts","../packages/common/http/src/request.ts","../packages/common/http/src/response.ts","../packages/common/http/src/client.ts","../packages/common/http/src/interceptor.ts","../packages/common/http/src/xhr.ts","../packages/common/http/src/xsrf.ts","../packages/common/http/src/provider.ts","../packages/common/http/src/module.ts","../packages/core/src/util/property.ts","../packages/core/src/util/stringify.ts","../packages/core/src/di/forward_ref.ts","../packages/core/src/di/interface/provider.ts","../packages/core/src/error_details_base_url.ts","../packages/core/src/errors.ts","../packages/core/src/render3/util/stringify_utils.ts","../packages/core/src/render3/errors_di.ts","../packages/core/src/util/assert.ts","../packages/core/src/di/interface/defs.ts","../packages/core/src/di/interface/injector.ts","../packages/core/src/di/inject_switch.ts","../packages/core/src/util/global.ts","../packages/core/src/di/injector_compatibility.ts","../packages/core/src/util/closure.ts","../packages/core/src/change_detection/constants.ts","../packages/core/src/metadata/view.ts","../packages/core/src/util/empty.ts","../packages/core/src/render3/fields.ts","../packages/core/src/render3/definition.ts","../packages/core/src/render3/interfaces/view.ts","../packages/core/src/render3/interfaces/container.ts","../packages/core/src/render3/interfaces/type_checks.ts","../packages/core/src/render3/definition_factory.ts","../packages/core/src/interface/simple_change.ts","../packages/core/src/render3/features/ng_onchanges_feature.ts","../packages/core/src/render3/profiler.ts","../packages/core/src/render3/namespaces.ts","../packages/core/src/render3/util/view_utils.ts","../packages/core/src/render3/state.ts","../packages/core/src/render3/hooks.ts","../packages/core/src/render3/interfaces/injector.ts","../packages/core/src/render3/util/attrs_utils.ts","../packages/core/src/render3/util/injector_utils.ts","../packages/core/src/render3/di.ts","../packages/core/src/render3/instructions/di_attr.ts","../packages/core/src/util/decorators.ts","../packages/core/src/di/injection_token.ts","../packages/core/src/util/array_utils.ts","../packages/core/src/di/metadata.ts","../packages/core/src/render/api_flags.ts","../packages/core/src/util/dom.ts","../packages/core/src/render3/interfaces/lview_tracking.ts","../packages/core/src/render3/interfaces/context.ts","../packages/core/src/render3/context_discovery.ts","../packages/core/src/render3/i18n/i18n_tree_shaking.ts","../packages/core/src/render3/util/view_traversal_utils.ts","../packages/core/src/render3/node_manipulation.ts","../packages/core/src/util/security/trusted_types.ts","../packages/core/src/render3/interfaces/document.ts","../packages/core/src/util/security/trusted_types_bypass.ts","../packages/core/src/sanitization/bypass.ts","../packages/core/src/sanitization/inert_body.ts","../packages/core/src/sanitization/url_sanitizer.ts","../packages/core/src/sanitization/html_sanitizer.ts","../packages/core/src/sanitization/security.ts","../packages/core/src/sanitization/sanitization.ts","../packages/core/src/di/initializer_token.ts","../packages/core/src/di/injector_token.ts","../packages/core/src/di/internal_tokens.ts","../packages/core/src/di/null_injector.ts","../packages/core/src/di/provider_collection.ts","../packages/core/src/di/scope.ts","../packages/core/src/di/r3_injector.ts","../packages/core/src/linker/component_factory.ts","../packages/core/src/linker/component_factory_resolver.ts","../packages/core/src/linker/element_ref.ts","../packages/core/src/render/api.ts","../packages/core/src/sanitization/sanitizer.ts","../packages/core/src/version.ts","../packages/core/src/view/provider_flags.ts","../packages/core/src/util/errors.ts","../packages/core/src/error_handler.ts","../packages/core/src/render3/util/misc_utils.ts","../packages/core/src/render3/styling/class_differ.ts","../packages/core/src/render3/node_selector_matcher.ts","../packages/core/src/render3/tokens.ts","../packages/core/src/render3/instructions/advance.ts","../packages/core/src/di/create_injector.ts","../packages/core/src/di/injector.ts","../packages/core/src/render3/instructions/di.ts","../packages/core/src/render3/instructions/shared.ts","../packages/core/src/render3/styling/static_styling.ts","../packages/core/src/render3/collect_native_nodes.ts","../packages/core/src/render3/view_ref.ts","../packages/core/src/render3/component_ref.ts","../packages/core/src/render3/features/inherit_definition_feature.ts","../packages/core/src/render3/features/host_directives_feature.ts","../packages/core/src/util/iterable.ts","../packages/core/src/render3/bindings.ts","../packages/core/src/render3/instructions/attribute.ts","../packages/core/src/render3/instructions/interpolation.ts","../packages/core/src/render3/instructions/template.ts","../packages/core/src/render3/instructions/storage.ts","../packages/core/src/render3/instructions/property.ts","../packages/core/src/render3/instructions/element.ts","../packages/core/src/render3/interfaces/node.ts","../packages/core/src/render3/instructions/element_container.ts","../packages/core/src/render3/instructions/get_current_view.ts","../packages/core/src/util/lang.ts","../packages/core/src/render3/instructions/listener.ts","../packages/core/src/render3/instructions/next_context.ts","../packages/core/src/render3/instructions/projection.ts","../packages/core/src/render3/instructions/property_interpolation.ts","../packages/core/src/render3/interfaces/styling.ts","../packages/core/src/render3/styling/style_binding_list.ts","../packages/core/src/render3/styling/styling_parser.ts","../packages/core/src/render3/instructions/styling.ts","../packages/core/src/render3/instructions/text.ts","../packages/core/src/render3/instructions/text_interpolation.ts","../packages/core/src/render3/instructions/class_map_interpolation.ts","../packages/core/src/render3/instructions/host_property.ts","../packages/core/src/i18n/locale_en.ts","../packages/core/src/i18n/locale_data_api.ts","../packages/core/src/i18n/localization.ts","../packages/core/src/render3/interfaces/i18n.ts","../packages/core/src/render3/i18n/i18n_locale_id.ts","../packages/core/src/render3/node_manipulation_i18n.ts","../packages/core/src/render3/i18n/i18n_insert_before_index.ts","../packages/core/src/render3/i18n/i18n_util.ts","../packages/core/src/render3/i18n/i18n_apply.ts","../packages/core/src/render3/instructions/i18n_icu_container_visitor.ts","../packages/core/src/render3/i18n/i18n_parse.ts","../packages/core/src/render3/instructions/i18n.ts","../packages/core/src/render3/di_setup.ts","../packages/core/src/render3/features/providers_feature.ts","../packages/core/src/linker/ng_module_factory.ts","../packages/core/src/render3/ng_module_ref.ts","../packages/core/src/render3/features/standalone_feature.ts","../packages/core/src/render3/pure_function.ts","../packages/core/src/render3/pipe.ts","../packages/core/src/event_emitter.ts","../packages/core/src/linker/query_list.ts","../packages/core/src/linker/template_ref.ts","../packages/core/src/linker/view_container_ref.ts","../packages/core/src/interface/type.ts","../packages/core/src/render3/query.ts","../packages/core/src/render3/view_engine_compatibility_prebound.ts","../packages/core/src/render3/jit/util.ts","../packages/core/src/util/noop.ts","../packages/core/src/r3_symbols.ts","../packages/core/src/application_init.ts","../packages/core/src/application_tokens.ts","../packages/core/src/console.ts","../packages/core/src/i18n/tokens.ts","../packages/core/src/linker/compiler.ts","../packages/core/src/util/microtask.ts","../packages/core/src/zone/ng_zone.ts","../packages/core/src/util/raf.ts","../packages/core/src/testability/testability.ts","../packages/core/src/application_ref.ts","../packages/core/src/util/is_dev_mode.ts","../packages/core/src/change_detection/change_detector_ref.ts","../packages/core/src/change_detection/differs/default_iterable_differ.ts","../packages/core/src/change_detection/differs/default_keyvalue_differ.ts","../packages/core/src/change_detection/differs/iterable_differs.ts","../packages/core/src/change_detection/differs/keyvalue_differs.ts","../packages/core/src/change_detection/change_detection.ts","../packages/core/src/platform_core_providers.ts","../packages/core/src/application_module.ts","../packages/core/src/util/coercion.ts","../packages/core/src/render3/component.ts","../packages/forms/src/directives/control_value_accessor.ts","../packages/forms/src/directives/checkbox_value_accessor.ts","../packages/forms/src/directives/default_value_accessor.ts","../packages/forms/src/validators.ts","../packages/forms/src/directives/abstract_control_directive.ts","../packages/forms/src/directives/control_container.ts","../packages/forms/src/directives/ng_control.ts","../packages/forms/src/directives/ng_control_status.ts","../packages/forms/src/directives/reactive_errors.ts","../packages/forms/src/model/abstract_model.ts","../packages/forms/src/model/form_group.ts","../packages/forms/src/directives/shared.ts","../packages/forms/src/directives/ng_form.ts","../packages/forms/src/util.ts","../packages/forms/src/model/form_control.ts","../packages/forms/src/directives/ng_model.ts","../packages/forms/src/directives/ng_no_validate_directive.ts","../packages/forms/src/directives/radio_control_value_accessor.ts","../packages/forms/src/directives/reactive_directives/form_control_directive.ts","../packages/forms/src/directives/reactive_directives/form_group_directive.ts","../packages/forms/src/directives/reactive_directives/form_control_name.ts","../packages/forms/src/directives/validators.ts","../packages/forms/src/directives.ts","../packages/forms/src/form_providers.ts","../src/material/core/common-behaviors/common-module.ts","../src/material/core/common-behaviors/disabled.ts","../src/material/core/common-behaviors/color.ts","../src/material/core/common-behaviors/disable-ripple.ts","../src/material/core/common-behaviors/tabindex.ts","../src/material/core/ripple/ripple-ref.ts","../src/material/core/ripple/ripple-event-manager.ts","../src/material/core/ripple/ripple-renderer.ts","../src/material/core/ripple/ripple.ts","../src/material/core/ripple/index.ts","../src/material/core/selection/pseudo-checkbox/pseudo-checkbox-module.ts","../src/cdk/dialog/dialog-config.ts","../src/cdk/dialog/dialog-container.ts","../src/cdk/dialog/dialog-container.html","../src/cdk/dialog/dialog-ref.ts","../src/cdk/dialog/dialog-injectors.ts","../src/cdk/dialog/dialog.ts","../src/cdk/dialog/dialog-module.ts","../src/material/dialog/dialog-config.ts","../src/material/dialog/dialog-container.ts","../src/material/dialog/dialog-ref.ts","../src/material/dialog/dialog.ts","../src/material/dialog/dialog-animations.ts","../src/material/legacy-dialog/dialog-animations.ts","../src/material/legacy-dialog/dialog-config.ts","../src/material/legacy-dialog/dialog-container.ts","../src/material/legacy-dialog/dialog-container.html","../src/material/legacy-dialog/dialog-ref.ts","../src/material/legacy-dialog/dialog.ts","../src/material/legacy-dialog/dialog-module.ts","../src/material/menu/menu-panel.ts","../src/material/menu/menu-item.html","../src/material/menu/menu-item.ts","../src/material/menu/menu-content.ts","../src/material/menu/menu-animations.ts","../src/material/menu/menu.ts","../src/material/menu/menu-trigger.ts","../src/material/legacy-menu/menu.ts","../src/material/legacy-menu/menu.html","../src/material/legacy-menu/menu-item.html","../src/material/legacy-menu/menu-trigger.ts","../src/material/legacy-menu/menu-content.ts","../src/material/legacy-menu/menu-module.ts","../packages/platform-browser/src/browser/generic_browser_adapter.ts","../packages/platform-browser/src/browser/browser_adapter.ts","../packages/platform-browser/src/browser/server-transition.ts","../packages/platform-browser/src/browser/xhr.ts","../packages/platform-browser/src/dom/events/event_manager.ts","../packages/platform-browser/src/dom/shared_styles_host.ts","../packages/platform-browser/src/dom/dom_renderer.ts","../packages/platform-browser/src/dom/events/dom_events.ts","../packages/platform-browser/src/dom/events/key_events.ts","../packages/platform-browser/src/browser.ts","../packages/platform-browser/src/browser/testability.ts","../packages/platform-browser/src/browser/meta.ts","../packages/platform-browser/src/browser/title.ts","../packages/platform-browser/src/browser/tools/browser.ts","../packages/platform-browser/src/dom/events/hammer_gestures.ts","../packages/platform-browser/src/security/dom_sanitization_service.ts","./node_modules/rxjs/src/internal/operators/refCount.ts","./node_modules/rxjs/src/internal/observable/ConnectableObservable.ts","./node_modules/rxjs/src/internal/operators/takeLast.ts","./node_modules/rxjs/src/internal/operators/last.ts","../packages/router/src/shared.ts","../packages/router/src/utils/collection.ts","../packages/router/src/url_tree.ts","../packages/router/src/create_url_tree.ts","../packages/router/src/events.ts","../packages/router/src/create_url_tree_strategy.ts","../packages/router/src/utils/tree.ts","../packages/router/src/router_state.ts","../packages/router/src/create_router_state.ts","../packages/router/src/navigation_canceling_error.ts","../packages/router/src/router_outlet_context.ts","../packages/router/src/directives/router_outlet.ts","../packages/router/src/components/empty_outlet.ts","../packages/router/src/utils/config.ts","../packages/router/src/operators/activate_routes.ts","../packages/router/src/utils/preactivation.ts","../packages/router/src/utils/type_guards.ts","../packages/router/src/operators/prioritized_guard_value.ts","../packages/router/src/operators/check_guards.ts","../packages/router/src/utils/config_matching.ts","../packages/router/src/apply_redirects.ts","../packages/router/src/recognize.ts","./node_modules/rxjs/src/internal/operators/takeWhile.ts","../packages/router/src/operators/resolve_data.ts","../packages/router/src/operators/switch_tap.ts","../packages/router/src/router_config_loader.ts","../packages/router/src/navigation_transition.ts","../packages/router/src/operators/apply_redirects.ts","../packages/router/src/operators/recognize.ts","../packages/router/src/page_title_strategy.ts","../packages/router/src/route_reuse_strategy.ts","../packages/router/src/router_config.ts","../packages/router/src/url_handling_strategy.ts","../packages/router/src/router.ts","../packages/router/src/directives/router_link.ts","../packages/router/src/router_preloader.ts","../packages/router/src/router_scroller.ts","../packages/router/src/utils/navigations.ts","../packages/router/src/provide_router.ts","../packages/router/src/router_module.ts","../src/cdk/collections/unique-selection-dispatcher.ts","../src/cdk/accordion/accordion.ts","../src/cdk/accordion/accordion-item.ts","../src/cdk/accordion/accordion-module.ts","../src/material/expansion/accordion-base.ts","../src/material/expansion/expansion-panel-header.html","../src/material/expansion/expansion-panel-content.ts","../src/material/expansion/expansion-animations.ts","../src/material/expansion/expansion-panel-base.ts","../src/material/expansion/expansion-panel.ts","../src/material/expansion/expansion-panel.html","../src/material/expansion/expansion-panel-header.ts","../src/material/expansion/accordion.ts","../src/material/expansion/expansion-module.ts","../src/material/icon/icon.ts","../src/material/icon/icon-module.ts","../src/material/icon/icon-registry.ts","../src/material/legacy-form-field/form-field.ts","../src/material/legacy-form-field/form-field-module.ts","../src/material/legacy-form-field/error.ts","../src/material/legacy-core/option/optgroup.ts","../src/material/legacy-core/option/index.ts","../src/material/select/select.ts","../src/material/legacy-select/select.ts","../src/material/legacy-select/select-module.ts","./projects/lru/felib/src/lib/animations/beziers.ts","./projects/lru/felib/src/lib/modules/checkbox/checkbox.component.html","./projects/lru/felib/src/lib/modules/dropdown/components/dropdown/dropdown.component.html","./projects/lru/felib/src/lib/modules/modal/components/modal/modal.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-picker/team-picker.component.html","./projects/lru/felib/src/lib/modules/lounge/components/__shared/team-header/team-header.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-assign-students/team-edit-assign-students.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-details-form/team-details-form.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-details/team-edit-details.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-picker-teacher/team-picker-teacher.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-assign-teachers/team-edit-assign-teachers.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-dropdown/team-edit-dropdown.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-box/team-box.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-creation.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-overview/team-overview.component.html","./projects/lru/felib/src/lib/modules/toast/components/toast-message/toast-message.component.html","./projects/lru/felib/src/lib/modules/toast/components/toast-message-list/toast-message-list.component.html","./projects/lru/felib/src/lib/components/loading-animation/enum/loading-animation-variant.enum.ts","./projects/lru/felib/src/lib/components/loading-animation/components/loading-animation.component.ts","./projects/lru/felib/src/lib/components/loading-animation/components/loading-animation.component.html","./projects/lru/felib/src/lib/components/loading-animation/loading-animation.module.ts","./projects/lru/felib/src/lib/modules/button/button.component.ts","./projects/lru/felib/src/lib/modules/button/button.component.html","./projects/lru/felib/src/lib/modules/button/button.module.ts","./projects/lru/felib/src/lib/modules/lounge/lounge-config.ts","./projects/lru/felib/src/lib/modules/icon/icon.component.ts","./projects/lru/felib/src/lib/modules/icon/icon.component.html","./projects/lru/felib/src/lib/modules/checkbox/checkbox.component.ts","./projects/lru/felib/src/lib/modules/icon/icon.module.ts","./projects/lru/felib/src/lib/modules/checkbox/checkbox.module.ts","./projects/lru/felib/src/lib/services/mouse-keyboard/mouse-keyboard.service.ts","./projects/lru/felib/src/lib/modules/dropdown/dropdown.service.ts","./projects/lru/felib/src/lib/modules/dropdown/components/dropdown-outlet/dropdown-outlet.component.ts","./projects/lru/felib/src/lib/utils/array.ts","./projects/lru/felib/src/lib/utils/query-selectors.ts","./projects/lru/felib/src/lib/modules/dropdown/dropdown-config.ts","./projects/lru/felib/src/lib/modules/z-index/store/z-index.actions.ts","./projects/lru/felib/src/lib/modules/z-index/store/z-index.reducers.ts","./projects/lru/felib/src/lib/modules/z-index/store/z-index.state.ts","./projects/lru/felib/src/lib/modules/z-index/store/z-index.selectors.ts","./projects/lru/felib/src/lib/modules/z-index/z-index-config.ts","./projects/lru/felib/src/lib/modules/z-index/services/z-index.service.ts","./projects/lru/felib/src/lib/modules/dropdown/components/dropdown/dropdown.component.ts","./projects/lru/felib/src/lib/modules/dropdown/dropdown.module.ts","./projects/lru/felib/src/lib/services/loading/shared-loading-keys.enums.ts","./projects/lru/felib/src/lib/services/gtm/gtm-events.const.ts","./projects/lru/felib/src/lib/modules/lounge/store/lounge.actions.ts","./projects/lru/felib/src/lib/utils/array.helper.ts","./projects/lru/felib/src/lib/modules/lounge/store/lounge.state.ts","./projects/lru/felib/src/lib/modules/lounge/store/lounge.reducers.ts","./projects/lru/felib/src/lib/modules/lounge/store/lounge.selectors.ts","./projects/lru/felib/src/lib/utils/observables.ts","./projects/lru/felib/src/lib/services/core/interfaces/backend-url-config.interface.ts","./projects/lru/felib/src/lib/services/core/api/config/api-service-config.ts","./projects/lru/felib/src/lib/services/core/enums/user-type.enum.ts","./projects/lru/felib/src/lib/services/core/user/user.service.ts","./projects/lru/felib/src/lib/services/gtm/google-tag-manager.service.ts","./projects/lru/felib/src/lib/modules/lounge/services/lounge.service.ts","./projects/lru/felib/src/lib/services/loading/store/loading.actions.ts","./projects/lru/felib/src/lib/services/loading/store/loading.reducers.ts","./projects/lru/felib/src/lib/services/loading/store/loading.state.ts","./projects/lru/felib/src/lib/services/loading/store/loading.selectors.ts","./projects/lru/felib/src/lib/services/loading/loading.service.ts","./projects/lru/felib/src/lib/modules/lounge/components/__shared/box/box.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/__shared/box/box.component.html","./projects/lru/felib/src/lib/modules/lounge/enums/lounge-modal-pages.enum.ts","./projects/lru/felib/src/lib/utils/uuid.ts","./projects/lru/felib/src/lib/modules/toast/store/toast.actions.ts","./projects/lru/felib/src/lib/modules/toast/store/toast.reducers.ts","./projects/lru/felib/src/lib/modules/toast/store/toast.state.ts","./projects/lru/felib/src/lib/modules/toast/store/toast.selectors.ts","./projects/lru/felib/src/lib/modules/toast/toast-config.ts","./projects/lru/felib/src/lib/modules/toast/services/toast.service.ts","./projects/lru/felib/src/lib/modules/lounge/services/lounge-modal.service.ts","./projects/lru/felib/src/lib/modules/modal/modal-config.ts","./projects/lru/felib/src/lib/modules/modal/modal.animations.ts","./projects/lru/felib/src/lib/modules/modal/modal.service.ts","./projects/lru/felib/src/lib/modules/z-index/z-index.module.ts","./projects/lru/felib/src/lib/modules/modal/components/modal/modal.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-picker/pipes/search-class-with-users.pipe.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-picker/team-picker.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/__shared/team-header/team-header.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-assign-students/team-edit-assign-students.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-delete/team-edit-delete.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-delete/team-edit-delete.component.html","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-details-form/team-details-form.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-details/team-edit-details.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-remove-teacher-self/team-edit-remove-teacher-self.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-remove-teacher-self/team-edit-remove-teacher-self.component.html","./projects/lru/felib/src/lib/utils/pipes/search-user-permission-with-selected-list.pipe.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-picker-teacher/team-picker-teacher.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-assign-teachers/team-edit-assign-teachers.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit-dropdown/team-edit-dropdown.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-edit/team-edit.component.ts","./projects/lru/felib/src/lib/modules/lounge/enums/sort-mode.enum.ts","./projects/lru/felib/src/lib/services/storage/storage.service.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-box/team-box.component.ts","./projects/lru/felib/src/lib/services/core/umbraco/umbraco.service.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/services/team-creation.service.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-creation/team-creation.component.ts","./projects/lru/felib/src/lib/modules/lounge/components/team-overview/team-overview.component.ts","./projects/lru/felib/src/lib/modules/modal/components/modal-outlet/modal-outlet.component.ts","./projects/lru/felib/src/lib/utils/scrollbar.ts","./projects/lru/felib/src/lib/modules/modal/modal.module.ts","./projects/lru/felib/src/lib/modules/toast/components/toast-message/toast-message.component.ts","./projects/lru/felib/src/lib/modules/toast/toast.animations.ts","./projects/lru/felib/src/lib/modules/toast/components/toast-message-list/toast-message-list.component.ts","./projects/lru/felib/src/lib/modules/toast/store/toast.effects.ts","./projects/lru/felib/src/lib/modules/toast/toast.module.ts","./projects/lru/felib/src/lib/services/core/api/api.service.ts","./projects/lru/felib/src/lib/modules/lounge/services/lounge-api.service.ts","./projects/lru/felib/src/lib/modules/lounge/store/lounge.effects.ts","./projects/lru/felib/src/lib/modules/lounge/lounge.module.ts","./projects/lru/felib/src/lib/services/core/api/interceptor/auth.interceptor.ts","./projects/lru/felib/src/lib/services/loading/store/loading.effects.ts","./projects/lru/felib/src/lib/services/core/core.module.ts","./projects/lru/felib/src/lib/services/core/local/local.service.ts","./projects/lru/felib/src/lib/services/core/init/init.service.ts","./projects/lru/felib/src/lib/services/css-color/css-color.service.ts","./node_modules/rxjs/src/internal/observable/race.ts","./node_modules/@popperjs/core/lib/utils/getOppositePlacement.js","./node_modules/@popperjs/core/lib/utils/getBasePlacement.js","./node_modules/@popperjs/core/lib/utils/getOppositeVariationPlacement.js","./node_modules/@popperjs/core/lib/enums.js","./node_modules/@popperjs/core/lib/dom-utils/getWindow.js","./node_modules/@popperjs/core/lib/dom-utils/instanceOf.js","./node_modules/@popperjs/core/lib/dom-utils/getDocumentElement.js","./node_modules/@popperjs/core/lib/utils/math.js","./node_modules/@popperjs/core/lib/utils/userAgent.js","./node_modules/@popperjs/core/lib/dom-utils/isLayoutViewport.js","./node_modules/@popperjs/core/lib/dom-utils/getBoundingClientRect.js","./node_modules/@popperjs/core/lib/dom-utils/getWindowScroll.js","./node_modules/@popperjs/core/lib/dom-utils/getWindowScrollBarX.js","./node_modules/@popperjs/core/lib/dom-utils/getComputedStyle.js","./node_modules/@popperjs/core/lib/dom-utils/getNodeName.js","./node_modules/@popperjs/core/lib/dom-utils/getParentNode.js","./node_modules/@popperjs/core/lib/dom-utils/isScrollParent.js","./node_modules/@popperjs/core/lib/dom-utils/getScrollParent.js","./node_modules/@popperjs/core/lib/dom-utils/listScrollParents.js","./node_modules/@popperjs/core/lib/dom-utils/isTableElement.js","./node_modules/@popperjs/core/lib/dom-utils/getOffsetParent.js","./node_modules/@popperjs/core/lib/dom-utils/contains.js","./node_modules/@popperjs/core/lib/utils/rectToClientRect.js","./node_modules/@popperjs/core/lib/dom-utils/getClippingRect.js","./node_modules/@popperjs/core/lib/dom-utils/getViewportRect.js","./node_modules/@popperjs/core/lib/dom-utils/getDocumentRect.js","./node_modules/@popperjs/core/lib/utils/getVariation.js","./node_modules/@popperjs/core/lib/utils/getMainAxisFromPlacement.js","./node_modules/@popperjs/core/lib/utils/computeOffsets.js","./node_modules/@popperjs/core/lib/utils/mergePaddingObject.js","./node_modules/@popperjs/core/lib/utils/getFreshSideObject.js","./node_modules/@popperjs/core/lib/utils/expandToHashMap.js","./node_modules/@popperjs/core/lib/utils/detectOverflow.js","./node_modules/@popperjs/core/lib/modifiers/flip.js","./node_modules/@popperjs/core/lib/utils/computeAutoPlacement.js","./node_modules/@popperjs/core/lib/utils/within.js","./node_modules/@popperjs/core/lib/dom-utils/getLayoutRect.js","./node_modules/@popperjs/core/lib/modifiers/preventOverflow.js","./node_modules/@popperjs/core/lib/utils/getAltAxis.js","./node_modules/@popperjs/core/lib/modifiers/arrow.js","./node_modules/@popperjs/core/lib/dom-utils/getCompositeRect.js","./node_modules/@popperjs/core/lib/dom-utils/getNodeScroll.js","./node_modules/@popperjs/core/lib/dom-utils/getHTMLElementScroll.js","./node_modules/@popperjs/core/lib/utils/orderModifiers.js","./node_modules/@popperjs/core/lib/utils/debounce.js","./node_modules/@popperjs/core/lib/createPopper.js","./node_modules/@popperjs/core/lib/utils/mergeByName.js","./node_modules/@popperjs/core/lib/modifiers/eventListeners.js","./node_modules/@popperjs/core/lib/modifiers/computeStyles.js","./node_modules/@popperjs/core/lib/popper-lite.js","./node_modules/@popperjs/core/lib/modifiers/popperOffsets.js","./node_modules/@popperjs/core/lib/modifiers/applyStyles.js","./node_modules/src/typeahead/highlight.ts","./node_modules/src/util/util.ts","./node_modules/src/environment.ts","./node_modules/src/util/transition/ngbTransition.ts","./node_modules/rxjs/src/internal/operators/endWith.ts","./node_modules/src/util/transition/util.ts","./node_modules/src/util/transition/ngbCollapseTransition.ts","./node_modules/src/ngb-config.ts","./node_modules/src/accordion/accordion-config.ts","./node_modules/src/accordion/accordion.ts","./node_modules/src/accordion/accordion.module.ts","./node_modules/src/alert/alert-transition.ts","./node_modules/src/alert/alert-config.ts","./node_modules/src/alert/alert.ts","./node_modules/src/alert/alert.module.ts","./node_modules/src/carousel/carousel-transition.ts","./node_modules/src/carousel/carousel-config.ts","./node_modules/src/carousel/carousel.ts","./node_modules/src/carousel/carousel.module.ts","./node_modules/src/collapse/collapse.module.ts","./node_modules/src/datepicker/ngb-date.ts","./node_modules/src/datepicker/datepicker-tools.ts","./node_modules/src/datepicker/ngb-calendar.ts","./node_modules/src/datepicker/datepicker-i18n.ts","./node_modules/src/datepicker/datepicker-service.ts","./node_modules/src/datepicker/datepicker-view-model.ts","./node_modules/src/datepicker/datepicker-day-view.ts","./node_modules/src/datepicker/datepicker-navigation-select.ts","./node_modules/src/datepicker/datepicker-navigation.ts","./node_modules/src/util/key.ts","./node_modules/src/datepicker/datepicker-keyboard-service.ts","./node_modules/src/datepicker/datepicker-config.ts","./node_modules/src/datepicker/adapters/ngb-date-adapter.ts","./node_modules/src/datepicker/datepicker.ts","./node_modules/src/util/autoclose.ts","./node_modules/src/util/focus-trap.ts","./node_modules/src/util/rtl.ts","./node_modules/src/util/positioning.ts","./node_modules/src/datepicker/hijri/ngb-calendar-islamic-umalqura.ts","./node_modules/src/datepicker/datepicker.module.ts","./node_modules/src/dropdown/dropdown.module.ts","./node_modules/src/util/popup.ts","./node_modules/src/modal/modal-backdrop.ts","./node_modules/src/modal/modal-ref.ts","./node_modules/src/modal/modal-dismiss-reasons.ts","./node_modules/src/modal/modal-window.ts","./node_modules/src/util/scrollbar.ts","./node_modules/src/modal/modal-stack.ts","./node_modules/src/modal/modal-config.ts","./node_modules/src/modal/modal.ts","./node_modules/src/modal/modal.module.ts","./node_modules/src/nav/nav-transition.ts","./node_modules/src/nav/nav-outlet.ts","./node_modules/src/nav/nav.module.ts","./node_modules/src/pagination/pagination-config.ts","./node_modules/src/pagination/pagination.ts","./node_modules/src/pagination/pagination.module.ts","./node_modules/src/util/triggers.ts","./node_modules/src/popover/popover-config.ts","./node_modules/src/popover/popover.module.ts","./node_modules/src/progressbar/progressbar-config.ts","./node_modules/src/progressbar/progressbar.ts","./node_modules/src/progressbar/progressbar.module.ts","./node_modules/src/rating/rating-config.ts","./node_modules/src/rating/rating.ts","./node_modules/src/rating/rating.module.ts","./node_modules/src/timepicker/ngb-time.ts","./node_modules/src/timepicker/timepicker-config.ts","./node_modules/src/timepicker/ngb-time-adapter.ts","./node_modules/src/timepicker/timepicker-i18n.ts","./node_modules/src/timepicker/timepicker.ts","./node_modules/src/timepicker/timepicker.module.ts","./node_modules/src/toast/toast-transition.ts","./node_modules/src/toast/toast-config.ts","./node_modules/src/toast/toast.ts","./node_modules/src/toast/toast.module.ts","./node_modules/src/tooltip/tooltip-config.ts","./node_modules/src/tooltip/tooltip.ts","./node_modules/src/tooltip/tooltip.module.ts","./node_modules/src/util/accessibility/live.ts","./node_modules/src/typeahead/typeahead.module.ts","./node_modules/src/offcanvas/offcanvas.module.ts","./node_modules/src/index.ts","./node_modules/rxjs/src/internal/Notification.ts","./node_modules/rxjs/src/internal/operators/groupBy.ts","./modules/effects/src/models.ts","./modules/effects/src/effect_creator.ts","./modules/effects/src/utils.ts","./modules/effects/src/effects_resolver.ts","./modules/effects/src/effects_metadata.ts","./node_modules/rxjs/src/internal/operators/materialize.ts","./modules/effects/src/effects_error_handler.ts","./modules/effects/src/actions.ts","./modules/effects/src/tokens.ts","./modules/effects/src/effects_actions.ts","./modules/effects/src/lifecycle_hooks.ts","./modules/effects/src/effect_sources.ts","./modules/effects/src/effect_notification.ts","./node_modules/rxjs/src/internal/operators/dematerialize.ts","./modules/effects/src/effects_runner.ts","./modules/effects/src/effects_root_module.ts","./modules/effects/src/effects_feature_module.ts","./modules/effects/src/effects_module.ts","./modules/effects/src/concat_latest_from.ts","./modules/store-devtools/src/actions.ts","./modules/store-devtools/src/config.ts","./modules/store-devtools/src/utils.ts","./modules/store-devtools/src/devtools-dispatcher.ts","./modules/store-devtools/src/extension.ts","./modules/store-devtools/src/reducer.ts","./modules/store-devtools/src/devtools.ts","./modules/store-devtools/src/provide-store-devtools.ts","./modules/store-devtools/src/instrument.ts","./modules/store/src/globals.ts","./modules/store/src/action_creator.ts","./modules/store/src/actions_subject.ts","./modules/store/src/tokens.ts","./modules/store/src/utils.ts","./modules/store/src/reducer_manager.ts","./modules/store/src/scanned_actions_subject.ts","./modules/store/src/state.ts","./modules/store/src/store.ts","./node_modules/rxjs/src/internal/operators/pluck.ts","./modules/store/src/meta-reducers/utils.ts","./modules/store/src/flags.ts","./modules/store/src/selector.ts","./modules/store/src/store_config.ts","./modules/store/src/meta-reducers/immutability_reducer.ts","./modules/store/src/meta-reducers/serialization_reducer.ts","./modules/store/src/runtime_checks.ts","./modules/store/src/meta-reducers/inNgZoneAssert_reducer.ts","./modules/store/src/provide_store.ts","./modules/store/src/store_module.ts","./modules/store/src/reducer_creator.ts","./node_modules/rxjs/src/internal/util/isObservable.ts","./node_modules/@ngx-translate/core/fesm2020/ngx-translate-core.mjs","./node_modules/src/types.ts","./node_modules/src/util/css.util.ts","./node_modules/src/shared-hooks/hooks.ts","./node_modules/src/intersection-observer-hooks/hooks.ts","./node_modules/src/token.ts","./node_modules/src/lazyload-image.directive.ts","./node_modules/src/lazyload-image.ts","./node_modules/src/lazyload-image.module.ts","./node_modules/src/scroll-hooks/rect.ts","./node_modules/@juggle/resize-observer/lib/utils/queueMicroTask.js","./node_modules/@juggle/resize-observer/lib/utils/resizeObservers.js","./node_modules/@juggle/resize-observer/lib/algorithms/deliverResizeLoopError.js","./node_modules/@juggle/resize-observer/lib/ResizeObserverBoxOptions.js","./node_modules/@juggle/resize-observer/lib/utils/freeze.js","./node_modules/@juggle/resize-observer/lib/ResizeObserverSize.js","./node_modules/@juggle/resize-observer/lib/DOMRectReadOnly.js","./node_modules/@juggle/resize-observer/lib/utils/element.js","./node_modules/@juggle/resize-observer/lib/utils/global.js","./node_modules/@juggle/resize-observer/lib/algorithms/calculateBoxSize.js","./node_modules/@juggle/resize-observer/lib/ResizeObserverEntry.js","./node_modules/@juggle/resize-observer/lib/algorithms/calculateDepthForNode.js","./node_modules/@juggle/resize-observer/lib/algorithms/broadcastActiveObservations.js","./node_modules/@juggle/resize-observer/lib/algorithms/gatherActiveObservationsAtDepth.js","./node_modules/@juggle/resize-observer/lib/utils/scheduler.js","./node_modules/@juggle/resize-observer/lib/utils/queueResizeObserver.js","./node_modules/@juggle/resize-observer/lib/utils/process.js","./node_modules/@juggle/resize-observer/lib/algorithms/hasActiveObservations.js","./node_modules/@juggle/resize-observer/lib/algorithms/hasSkippedObservations.js","./node_modules/@juggle/resize-observer/lib/ResizeObservation.js","./node_modules/@juggle/resize-observer/lib/ResizeObserverDetail.js","./node_modules/@juggle/resize-observer/lib/ResizeObserverController.js","./node_modules/@juggle/resize-observer/lib/ResizeObserver.js","./projects/ng-resize-observer/src/lib/resize-observer.ts","./projects/ng-resize-observer/src/lib/ng-resize-observer.service.ts","./projects/ng-resize-observer/src/lib/ponyfill.module.ts","./projects/ng-resize-observer/src/public-api.ts","./projects/ngx-plyr/src/lib/plyr-driver/default-plyr-driver.ts","./projects/ngx-plyr/src/lib/plyr/plyr.component.ts","./projects/ngx-plyr/src/lib/plyr.module.ts","./node_modules/src/lib/portal/portal.ts","./node_modules/src/lib/toastr/toast-ref.ts","./node_modules/src/lib/toastr/toastr-config.ts","./node_modules/src/lib/portal/dom-portal-host.ts","./node_modules/src/lib/overlay/overlay-container.ts","./node_modules/src/lib/overlay/overlay-ref.ts","./node_modules/src/lib/overlay/overlay.ts","./node_modules/src/lib/toastr/toastr.service.ts","./node_modules/src/lib/toastr/toast.component.ts","./node_modules/src/lib/toastr/toast.provider.ts","./node_modules/src/lib/toastr/toastr.module.ts","./node_modules/throttle-debounce/throttle.js","./node_modules/throttle-debounce/debounce.js","./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js","./node_modules/tslib/tslib.es6.mjs"],"sourcesContent":["\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { Router, RouterEvent, RoutesRecognized } from '@angular/router';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { environment } from '@portal-env/environment';\r\nimport { switchMap } from 'rxjs/operators';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\n\r\n@Component({\r\n selector: 'portal-footer',\r\n templateUrl: './footer.component.html',\r\n styleUrls: ['./footer.component.scss'],\r\n})\r\nexport class FooterComponent implements OnInit {\r\n enabled = false;\r\n loading = false;\r\n loaded = false;\r\n cssLoaded = false;\r\n data?: string;\r\n\r\n constructor(private appSiteService: AppInitService, private router: Router) {}\r\n\r\n ngOnInit() {\r\n this.router.events.pipe(switchMap((x) => this.handleLoadOrInjectFooter(x as RouterEvent))).subscribe();\r\n }\r\n\r\n async handleLoadOrInjectFooter(data: RouterEvent) {\r\n if (data instanceof RoutesRecognized) {\r\n const pageType = data.state.root.firstChild?.data.pageType as PageTypeEnum;\r\n if (pageType === PageTypeEnum.Book) {\r\n this.enabled = false;\r\n } else {\r\n this.enabled = true;\r\n if (this.loaded && !this.loading) {\r\n await this.injectFooter();\r\n } else if (!this.loaded && !this.loading) {\r\n this.loading = true;\r\n await this.loadFooter();\r\n }\r\n }\r\n }\r\n }\r\n\r\n private async loadFooter() {\r\n const portalId = this.appSiteService.siteConfiguration.PortalId;\r\n\r\n if (portalId !== undefined) {\r\n const url = `${environment.apIUmbBaseUrl}js/footer/?t=${portalId}`;\r\n await fetch(url)\r\n .then((response) => {\r\n return response.text();\r\n })\r\n .then(async (text) => {\r\n this.data = text.replace('{{id}}', portalId);\r\n await this.injectFooter();\r\n });\r\n }\r\n }\r\n\r\n private async injectFooter() {\r\n if (this.data !== undefined && !this.loaded) {\r\n (await eval(this.data)) as Promise;\r\n\r\n const footerHTMLCollection = document.getElementsByTagName('footer');\r\n if (footerHTMLCollection.length) {\r\n const interval = setInterval(() => {\r\n if (getComputedStyle(footerHTMLCollection[0], undefined).display === 'flex') {\r\n this.cssLoaded = true;\r\n this.loaded = true;\r\n this.loading = false;\r\n clearInterval(interval);\r\n }\r\n }, 50);\r\n }\r\n }\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'portal-spinner',\r\n templateUrl: './spinner.component.html',\r\n styleUrls: ['./spinner.component.scss'],\r\n standalone: true,\r\n imports: [CommonModule],\r\n})\r\nexport class SpinnerComponent {\r\n @Input() size?: number = 20;\r\n}\r\n","
\r\n","import { IQueryStrings } from '@portal-app/interfaces/project/query-strings.interface';\r\n\r\nexport const QueryStrings: IQueryStrings = {\r\n About: { da: 'om', en: 'about' },\r\n Activities: { da: 'aktiviteter', en: 'activities' },\r\n AnnualPlan: { da: 'aarsplan', en: 'annualplan' },\r\n AssignmentTypes: { da: 'opgavetyper', en: 'assignmenttypes' },\r\n Assignments: { da: 'opgaver-aktiviteter', en: 'assignments' },\r\n AssetTopics: { da: 'emner', en: 'assettopics' },\r\n Audios: { da: 'lyd', en: 'audios' },\r\n Categories: { da: 'emner', en: 'categories' },\r\n Class: { da: 'klasse', en: 'class' },\r\n Classes: { da: 'klasser', en: 'classes' },\r\n CommonGoals: { da: 'faelles-maal', en: 'commongoals' },\r\n CollaborationTypes: { da: 'samarbejdsformer', en: 'collaborationtypes' },\r\n Courses: { da: 'forloeb', en: 'courses' },\r\n DifficultyGroups: { da: 'laeseniveauer', en: 'difficultygroups' },\r\n Documents: { da: 'dokumenter', en: 'documents' },\r\n Downloads: { da: 'downloads', en: 'downloads' },\r\n Edit: { da: 'edit', en: 'edit' },\r\n Gallery: { da: 'galleri', en: 'gallery' },\r\n Genres: { da: 'genre', en: 'genres' },\r\n Geogebras: { da: 'geogebras', en: 'geogebras' },\r\n Grades: { da: 'klassetrin', en: 'grades' },\r\n HasAudioBook: { da: 'audio-bog', en: 'audiobook' },\r\n Illustrations: { da: 'illustrationer', en: 'illustrations' },\r\n Images: { da: 'billeder', en: 'images' },\r\n Languages: { da: 'sprog', en: 'languages' },\r\n Levels: { da: 'klassetrin', en: 'levels' },\r\n Link: { da: 'link', en: 'link' },\r\n List: { da: 'liste', en: 'list' },\r\n OnlyFavourite: { da: 'kun-favoritter', en: 'onlyfavorite' },\r\n OnlyLicense: { da: 'kun-licens', en: 'onlylicense' },\r\n Open: { da: 'aabne', en: 'open' },\r\n Page: { da: 'side', en: 'page' },\r\n Query: { da: 'soegning', en: 'query' },\r\n ReadingLevels: { da: 'laeseniveau', en: 'readinglevels' },\r\n SeriesTitle: { da: 'serier', en: 'series' },\r\n Student: { da: 'elev', en: 'student' },\r\n SubTab: { da: 'under-tab', en: 'subtab' },\r\n Subjects: { da: 'fag', en: 'subjects' },\r\n Tab: { da: 'tab', en: 'tab' },\r\n Texts: { da: 'tekster', en: 'texts' },\r\n Topics: { da: 'emner', en: 'topics' },\r\n Videos: { da: 'videoer', en: 'videos' },\r\n Writers: { da: 'forfattere', en: 'writers' },\r\n Year: { da: 'aar', en: 'year' },\r\n Periods: { da: 'periode', en: 'period' },\r\n};\r\n","export enum AudioPlayerTypeEnum {\r\n Full = 'full',\r\n PartialDesktop = 'partial-desktop',\r\n PartialTouch = 'partial-touch',\r\n Recorded = 'recorded',\r\n MP3 = 'mp3',\r\n}\r\n","export enum ContentTypeEnum {\r\n Courses = 'Courses',\r\n Texts = 'Pages',\r\n Assignments = 'Assignments',\r\n Activities = 'Activities',\r\n Books = 'Books',\r\n Collections = 'Collections',\r\n Gallery = 'Gallery',\r\n List = 'List',\r\n AnnualPlan = 'AnnualPlan',\r\n About = 'About',\r\n SharedGoals = 'SharedGoals',\r\n Downloads = 'Downloads',\r\n Images = 'Images',\r\n Videos = 'Videos',\r\n Audios = 'Audios',\r\n Documents = 'Documents',\r\n GeoGebras = 'GeoGebras',\r\n PsArticles = 'PsArticles',\r\n PsAssignments = 'PsAssignments',\r\n PSThemes = 'PsThemes',\r\n}\r\n","export enum FacetTypeEnum {\r\n AssignmentTypes = 'AssignmentTypesEnum',\r\n CollaborationTypes = 'CollaborationTypes',\r\n Genres = 'Genres',\r\n Levels = 'Levels',\r\n Topics = 'Topics',\r\n Writers = 'Writers',\r\n Grades = 'Grades',\r\n ReadingLevels = 'ReadingLevels',\r\n DifficultyGroups = 'DifficultyGroups',\r\n Categories = 'Categories',\r\n Languages = 'Languages',\r\n Illustrations = 'Illustrations',\r\n Classes = 'Classes',\r\n Subjects = 'Subjects',\r\n HasAudioBook = 'HasAudioBook',\r\n SeriesTitle = 'SeriesTitle',\r\n AssetTopics = 'AssetTopics',\r\n Periods = 'Periods',\r\n}\r\n","export enum GTMEvent {\r\n GTMJS = 'gtm.js',\r\n Page = 'page',\r\n\r\n // Toggle Component\r\n Toggle = 'Toggle',\r\n\r\n // Audio player\r\n Open_recorded = 'Open_recorded',\r\n Close_recorded = 'Closed_recorded',\r\n Play_recorded = 'Play_recorded',\r\n Pause_recorded = 'Pause_recorded',\r\n Ended_recorded = 'Ended_recorded',\r\n Seeked_recorded = 'Seeked_recorded',\r\n Forward_recorded = 'Forward_recorded',\r\n Backwards_recorded = 'Backwards_recorded',\r\n\r\n Play_selected = 'Play_selected',\r\n Pause_selected = 'Pause_selected',\r\n Ended_selected = 'Ended_selected',\r\n Forward_selected = 'Forward_selected',\r\n Backwards_selected = 'Backwards_selected',\r\n\r\n Play_full = 'Play_full',\r\n Pause_full = 'Pause_full',\r\n Ended_full = 'Ended_full',\r\n Forward_full = 'Forward_full',\r\n Backwards_full = 'Backwards_full',\r\n Audio_started = 'Audio_started',\r\n Audio_paused = 'Audio_paused',\r\n Audio_download = 'Audio_download',\r\n\r\n // Favourite\r\n Favourite_set = 'favourite-set',\r\n Favourite_remove = 'favourite-remove',\r\n\r\n // Images\r\n Image_fullscreen = 'image-fullscreen',\r\n\r\n // Course\r\n Course_more_info_open = 'course-moreinfo-open',\r\n Course_more_info_open_course = 'course-moreinfo-opencourse',\r\n\r\n // Library\r\n Media_accordion = 'media-accordion',\r\n Media_open = 'media-open',\r\n\r\n Library_filters_modal = 'library-filters-modal',\r\n Library_set_filter = 'library-set-filter',\r\n\r\n Library_search_autocomplete = 'library-search-autocomplete',\r\n\r\n // AnnualPlan\r\n Annual_plan_open_course = 'annualplan-open-course',\r\n Annual_plan_open_course_open = 'annualplan-open-course-open',\r\n Annual_plan_print = 'annualplan-print',\r\n\r\n // Student Answers\r\n Student_answers_choose_class = 'student-answers-choose-class',\r\n Student_answers_choose_student = 'student-answers-choose-student',\r\n Student_answers_print = 'student-answers-print',\r\n Student_answers_see_results = 'student-answers-see-results',\r\n Student_answers_choose_see_students = 'student-answers-choose-see-students',\r\n\r\n // Superbog\r\n\r\n // Læsekasse\r\n Collection_open = 'collection-open',\r\n Collection_change_cover = 'collection-change-cover',\r\n Collection_assign_class = 'collection-assign-class',\r\n Collection_unassign_class = 'collection-unassign-class',\r\n Collection_save = 'collection-save',\r\n Collection_create = 'collection-create',\r\n Collection_delete = 'collection-delete',\r\n Collection_show_institution = 'collection-show-institution',\r\n Collection_hide_institution = 'collection-hide-institution',\r\n\r\n // Filters\r\n Filter_add_tag = 'filter-add-tag',\r\n Filter_remove_all = 'filter-remove-all',\r\n Filter_remove_tag = 'filter-remove-tag',\r\n\r\n // Book\r\n Open_book = 'open-book',\r\n Remove_from_collection = 'remove-from-collection',\r\n Add_to_collection = 'add-to-collection',\r\n\r\n // Bog info\r\n Bookinfo_openbook = 'bookinfo-openbook',\r\n\r\n // Reader\r\n Reader_contenttable = 'reader-contenttable',\r\n Reader_progressbar = 'reader-progressbar',\r\n Reader_nextpage = 'reader-nextpage',\r\n Reader_previouspage = 'reader-previouspage',\r\n Reader_recommendation_tag = 'reader-recommendation-tag',\r\n Reader_recommendation_tag_remove = 'reader-recommendation-tag-remove',\r\n Reader_close_book = 'reader-close-book',\r\n Reader_changesize = 'reader-changesize',\r\n Reader_changefont = 'reader-changefont',\r\n Reader_linespace = 'reader-linespace',\r\n Reader_changecolor = 'reader-changecolor',\r\n Reader_changepagetype = 'reader-changepagetype',\r\n\r\n // Forside\r\n Overview_readbook_remove = 'overview-readbook-remove',\r\n Overview_continuebook_remove = 'overview-continuebook-remove',\r\n Overview_readbook_recommendation_tag = 'overview-readbook-recommendation-tag',\r\n Overview_readbook_recommendation_tag_remove = 'overview-readbook-recommendation-tag-remove',\r\n\r\n // Lærer dashboard\r\n Dashboard_class = 'dashboard-class',\r\n Dashboard_student = 'dashboard-student',\r\n Dashboard_date = 'dashboard-date',\r\n\r\n // PS Opgaver\r\n filter_accordion = 'filter-accordion',\r\n filter_subject = 'filter-subject',\r\n filter_topic = 'filter-topic',\r\n filter_class = 'filter-class',\r\n filter_remove_all = 'filter-remove-all',\r\n Assignment_accordion = 'assignment-accordion',\r\n Assignment_open = 'assignment-open',\r\n Assignment_close = 'assignment-close',\r\n Assignment_copylink = 'assignment-copylink',\r\n Assignment_download_all = 'assignment-downloadall',\r\n Assignment_download = 'assignment-download',\r\n Article_print = 'article-print',\r\n}\r\n","export enum LoadingKey {\r\n Page = 'page',\r\n}\r\n","export enum MenuTypeEnum {\r\n Primary = 'primary',\r\n Mega = 'mega',\r\n Level = 'level',\r\n Submenu = 'submenu',\r\n}\r\n","export enum PageTypeEnum {\r\n // umbraco related\r\n FrontPage = 'frontpage',\r\n ContentPage = 'contentpage',\r\n\r\n // course related\r\n CourseLibrary = 'course-library',\r\n CourseStudentAnswers = 'course-student-answers',\r\n CourseAnnualPlan = 'course-annual-plan',\r\n CourseFavorites = 'course-favorites',\r\n CourseFrontpage = 'course',\r\n\r\n // book related\r\n BookLibrary = 'book-library',\r\n BookFavorites = 'book-favorites',\r\n BookTeacherDashboard = 'book-teacher-dashboard',\r\n BookInfo = 'book-info',\r\n BookTag = 'book-tag',\r\n Book = 'book',\r\n BookCollection = 'book-collection',\r\n MyBookCollections = 'my-book-collections',\r\n BookCollectionAdd = 'book-collection-add',\r\n BookCollectionEdit = 'book-collection-edit',\r\n BookCollectionView = 'book-collection-view',\r\n\r\n // ps related\r\n PsArticle = 'ps-article',\r\n PsArticleLibrary = 'ps-article-library',\r\n PsAssignment = 'ps-assignment',\r\n PsAssignmentLibrary = 'ps-assignment-library',\r\n PsThemeLibrary = 'ps-theme-library',\r\n\r\n // printbar related\r\n PrintbarAssignmentLibrary = 'printbar-assignment-library',\r\n PrintbarAssignment = 'printbar-assignment',\r\n\r\n //lounge related\r\n LoungeTeamAdmin = 'lounge-team-admin',\r\n\r\n // internal\r\n Error = 'error',\r\n Error503 = 'error-503',\r\n}\r\n\r\nexport enum CoursePageTypeEnum {\r\n Course = 'Course',\r\n Page = 'Page',\r\n Assignment = 'Assignment',\r\n Question = 'Question',\r\n Chapter = 'Chapter',\r\n}\r\n","export enum PeriodSelectorEnum {\r\n now = 'Now',\r\n day = 'Day',\r\n week = 'Week',\r\n month = 'Month',\r\n schoolYear = 'SchoolYear',\r\n}\r\n","export enum ProjectTypeEnum {\r\n Superbog = 'Superbog',\r\n SuperReader = 'SuperReader',\r\n Fagportal = 'Fagportal',\r\n HDBHDW = 'HDBHDW',\r\n PS = 'PS',\r\n PrintBar = 'PrintBar',\r\n Other = 'Andet',\r\n}\r\n","export enum PsLibraryFilterEnum {\r\n Class = 'Class',\r\n Topic = 'Topic',\r\n Subject = 'Subject',\r\n Author = 'Author',\r\n Theme = 'Theme',\r\n Level = 'Level',\r\n}\r\n","export enum SectionTypeEnum {\r\n CourseContinue = 'course-continue-where-you-left',\r\n BookContinue = 'book-continue-where-you-left',\r\n\r\n BookMyFavorites = 'book-my-favourites',\r\n\r\n BookInform = 'book-inform',\r\n\r\n CourseList = 'course-list',\r\n ActivityList = 'activity-list',\r\n BookList = 'book-list',\r\n\r\n H1 = 'h1',\r\n H2 = 'h2',\r\n H3 = 'h3',\r\n H4 = 'h4',\r\n RichTextEditor = 'rte',\r\n PortalContentpagesList = 'portal-contentpages-list',\r\n Image = 'media-image',\r\n Quote = 'quote',\r\n Embed = 'embed',\r\n CallToAction = 'call-to-action',\r\n CallToActionFeaturedCourse = 'cta-featured-course',\r\n CallToActionFeaturedTheme = 'cta-featured-theme', // ps theme\r\n CallToActionStandard = 'cta-standard',\r\n DocumentCollection = 'media-document-collection',\r\n NotImplemented = 'not-implemented',\r\n DataMissing = \"api-data-missing (can't implement)\",\r\n ImageGallery = 'image-gallery',\r\n CallToActionButtons = 'cta-buttons',\r\n\r\n // fagportaler\r\n StudentAnswers = 'student-answers',\r\n StudentAnswersCourseResults = 'student-answers-course-results',\r\n\r\n //// FROM SUPERBOG PROJECT\r\n ClassReads = 'class-reads',\r\n MyBookCollections = 'my-reading-boxes',\r\n FinishedBooks = 'read-books',\r\n\r\n // PS\r\n PsAssignments = 'ps-assignment-list',\r\n PsArticles = 'ps-article-list',\r\n\r\n /** Not yet implemented */\r\n TagCloudList = 'tag-cloud-list',\r\n ThemeBasic = 'theme-basic',\r\n\r\n /** Deprecated */\r\n Headline = 'headline',\r\n}\r\n","export enum UmbSettingWidthEnum {\r\n fullWidth = 'full-width',\r\n large = 'large',\r\n medium = 'medium',\r\n small = 'small',\r\n}\r\n\r\nexport enum UmbSettingAlignEnum {\r\n Left = 'left',\r\n Right = 'right',\r\n Center = 'center',\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { MissingTranslationHandler, MissingTranslationHandlerParams } from '@ngx-translate/core';\r\n\r\n@Injectable()\r\nexport class MissingTranslationHelper implements MissingTranslationHandler {\r\n handle(params: MissingTranslationHandlerParams) {\r\n if (params.interpolateParams) {\r\n const key = 'default';\r\n const param = params.interpolateParams[key as keyof object];\r\n if (param === undefined) {\r\n return '';\r\n }\r\n return param || params.key;\r\n }\r\n return params.key;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport { INextActivitySearchResponse } from '@portal-app/interfaces/activity/activity-search-response.interface';\r\nimport { INextCourseSearchActivity } from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { IActivityList, ITabActivity } from '@portal-app/interfaces/course/project/course-tabs.interface';\r\nimport { HtmlService } from '@portal-app/services/shared/html.service';\r\nimport { environment } from '@portal-env/environment';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ActivityMapper {\r\n constructor(private htmlService: HtmlService) {}\r\n\r\n mapActivitiesToTab2(activities: ITabActivity[], hasFavorite?: boolean) {\r\n const item: IActivityList = {\r\n SliderSettings: {\r\n Type: SectionTypeEnum.ActivityList,\r\n MaxSlidesPerView: 5,\r\n },\r\n Items: activities,\r\n };\r\n\r\n return item;\r\n }\r\n\r\n mapActivitiesFromApi(activities: INextActivitySearchResponse[], hasFavorite?: boolean, trackingUrl?: string) {\r\n const result: ITabActivity[] = [];\r\n\r\n if (!activities) {\r\n // dont trust the api\r\n return result;\r\n }\r\n for (const item of activities) {\r\n result.push({\r\n Id: item.id,\r\n Asset: item.asset,\r\n Duration: item.duration,\r\n Description: this.htmlService.fixHtml(item.description),\r\n Title: item.title,\r\n Url: `${environment.activityUrl()}${item.url}${trackingUrl || ''}`,\r\n FavoriteLoaded: true,\r\n ObjectType: ContentTypeEnum.Activities,\r\n IsFavorite: hasFavorite ? true : false,\r\n Types: item.types,\r\n });\r\n }\r\n\r\n this.mapActivitiesToTab2(result, hasFavorite);\r\n\r\n return result;\r\n }\r\n\r\n mapActivitiesToTab(activities: INextCourseSearchActivity[], hasFavorite?: boolean, trackingUrl?: string) {\r\n const result: ITabActivity[] = [];\r\n activities.forEach((activityWrapper) => {\r\n const item: ITabActivity = {\r\n Id: activityWrapper.activity.id,\r\n Title: activityWrapper.activity.title,\r\n Url: `${environment.activityUrl()}${activityWrapper.activity.url}${trackingUrl || ''}`,\r\n Description: activityWrapper.activity.description,\r\n Label: activityWrapper.activity.label,\r\n Duration: activityWrapper.activity.duration,\r\n Asset: activityWrapper.activity.asset,\r\n Topics: activityWrapper.activity.topics,\r\n Types: activityWrapper.activity.types,\r\n Writers: activityWrapper.activity.writers,\r\n Levels: activityWrapper.activity.levels,\r\n IsLocked: activityWrapper.locked,\r\n IsFavorite: hasFavorite ? true : false,\r\n FavoriteLoaded: hasFavorite ? true : false,\r\n ObjectType: ContentTypeEnum.Activities,\r\n };\r\n\r\n result.push(item);\r\n });\r\n const item: IActivityList = {\r\n SliderSettings: {\r\n Type: SectionTypeEnum.ActivityList,\r\n MaxSlidesPerView: 5,\r\n },\r\n Items: result,\r\n };\r\n\r\n this.mapActivitiesToTab2(result, hasFavorite);\r\n\r\n return item;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { INextBookCollection } from '@portal-app/interfaces/book/next/next-book-collection.interface';\r\nimport { ICollectionTile } from '@portal-app/interfaces/project/section.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookCollectionMapper {\r\n mapBookCollectionFromApi(collections: INextBookCollection[]): ICollectionTile[] {\r\n const result: ICollectionTile[] = [];\r\n if (collections?.length) {\r\n for (const collection of collections) {\r\n result.push({\r\n Id: collection.Id,\r\n Author: {\r\n Id: collection.Creator.Id,\r\n Name: collection.Creator.Name,\r\n Type: collection.Type,\r\n },\r\n Image: {\r\n Id: collection.CoverImage.Id,\r\n Title: collection.CoverImage.Title,\r\n Description: collection.CoverImage.Description,\r\n Copyright: collection.CoverImage.Copyright,\r\n FileType: collection.CoverImage.FileType,\r\n Path: collection.CoverImage.Path,\r\n Type: collection.CoverImage.Type,\r\n Dimensions: collection.CoverImage.Dimensions,\r\n },\r\n Title: collection.Title,\r\n Icon: '',\r\n Owner: collection.Owner,\r\n Classes: undefined,\r\n IsFavorite: collection.IsFavorite,\r\n });\r\n }\r\n }\r\n return result;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { IBookSelectedImpression } from '@portal-app/interfaces/book/project/book-impression.interface';\r\nimport { INextImpressionTag, INextImpressionTag2 } from '@portal-app/interfaces/next/next-tag.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookImpressionMapper {\r\n mapSelectImpressionsFromApi(all: INextImpressionTag[], selected: INextImpressionTag[]): IBookSelectedImpression[] {\r\n const result: IBookSelectedImpression[] = [];\r\n for (const item of all) {\r\n result.push({\r\n Slug: item.Slug,\r\n Title: item.Title,\r\n Icon: item.Icon,\r\n Selected: selected?.some((element) => element.Slug === item.Slug) || false,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n mapList(impressions2?: INextImpressionTag2[]) {\r\n return impressions2?.map((x) => this.map(x));\r\n }\r\n\r\n map(impression2: INextImpressionTag2): INextImpressionTag {\r\n return {\r\n Id: impression2.id,\r\n Title: impression2.title,\r\n Slug: impression2.slug,\r\n Icon: impression2.icon,\r\n };\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { FacetTypeEnum } from '@portal-app/enums/facet-type.enum';\r\nimport {\r\n ILibraryFacet,\r\n ILibraryFacets,\r\n ISearchAutoComplete,\r\n} from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { INextBookSearchAutoCompleteResponse } from '../../interfaces/book/next/next-book-library.interface';\r\nimport { INextSearchResponseFacets } from '../../interfaces/next/next-library';\r\nimport { BookMapper } from './book.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookLibraryMapper {\r\n constructor(\r\n private helperService: HelperService,\r\n private bookMapper: BookMapper,\r\n private translationService: TranslateService\r\n ) {}\r\n\r\n mapFacetsFromApi(facets: INextSearchResponseFacets[]) {\r\n const result: ILibraryFacets[] = [];\r\n if (facets.length) {\r\n for (const facet of facets) {\r\n if (FacetTypeEnum[facet.type as keyof typeof FacetTypeEnum] && facet.items.length) {\r\n // 2021-11-30\r\n // for some reason it should not be possible to select books with no audio book\r\n // Oskars decision. Frederik and Olivia does not agree with this\r\n facet.items = facet.items.filter(\r\n (item) =>\r\n (facet.type === FacetTypeEnum.HasAudioBook && item.value.toLowerCase() === 'true') ||\r\n facet.type !== FacetTypeEnum.HasAudioBook\r\n );\r\n result.push({\r\n Title: `FacetType.${facet.type}`,\r\n UrlTitle: QueryStrings[facet.type as keyof typeof QueryStrings]?.en,\r\n Type: FacetTypeEnum[facet.type as keyof typeof FacetTypeEnum],\r\n Items: facet.items.map((item) => {\r\n let facetResult: ILibraryFacet;\r\n if (facet.type === FacetTypeEnum.Illustrations) {\r\n facetResult = {\r\n Title: this.translationService.instant(`IllustrationTag.${item.value}`),\r\n Value: item.key,\r\n Count: item.count,\r\n Selected: item.selected,\r\n };\r\n } else if (facet.type === FacetTypeEnum.HasAudioBook) {\r\n facetResult = {\r\n Title: this.translationService.instant('Label.HasAudioBook'),\r\n Value: item.key,\r\n Count: item.count,\r\n Selected: item.selected,\r\n };\r\n } else {\r\n facetResult = {\r\n Title: item.value,\r\n Value: item.key,\r\n Count: item.count,\r\n Selected: item.selected,\r\n };\r\n }\r\n return facetResult;\r\n }),\r\n Open: this.helperService.getParameterByQueryStringAndSuffix(\r\n QueryStrings[facet.type as keyof typeof QueryStrings],\r\n QueryStrings.Open\r\n )\r\n ? true\r\n : false,\r\n });\r\n }\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n mapAutoCompleteFromApi(query: string, autocomplete: INextBookSearchAutoCompleteResponse) {\r\n const result: ISearchAutoComplete = {\r\n Suggestions: [],\r\n Courses: [],\r\n Books: [],\r\n BookCollections: [],\r\n };\r\n if (autocomplete.autocompleteItems) {\r\n for (const item of autocomplete.autocompleteItems) {\r\n if (item.queryPlusText !== query) {\r\n result.Suggestions.push(item.queryPlusText);\r\n }\r\n }\r\n }\r\n if (autocomplete.suggestions) {\r\n for (const item of autocomplete.suggestions) {\r\n if (item.book) {\r\n const book = this.bookMapper.mapBookFromApi2(item.book);\r\n result.Books.push(book);\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n}\r\n","export enum DifficultyTypeEnum {\r\n LIX = 'LIX',\r\n LET = 'LET',\r\n LUS = 'LUS',\r\n LEVEL = 'LEVEL',\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { IBookTag } from '@portal-app/interfaces/book/project/book.interface';\r\nimport { INextTag, INextTag2 } from '@portal-app/interfaces/next/next-tag.interface';\r\nimport { DifficultyTypeEnum } from '../../enums/difficulty-type.enum';\r\nimport { AppInitService } from '../../services/shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookDifficultiesMapper {\r\n constructor(private appInitService: AppInitService, private translate: TranslateService) {}\r\n\r\n mapBookDifficultyFromApi(difficulties: INextTag[]): IBookTag[] {\r\n const result: IBookTag[] = [];\r\n let a: INextTag | undefined;\r\n if (this.appInitService.isSuperbog) {\r\n let b: INextTag | undefined;\r\n if (difficulties.length) {\r\n a = difficulties.find((item) => item.Type === DifficultyTypeEnum.LIX);\r\n b = difficulties.find((item) => item.Type === DifficultyTypeEnum.LET);\r\n }\r\n\r\n if (a) {\r\n result.push(this.getElement(a, DifficultyTypeEnum.LIX));\r\n }\r\n\r\n if (b) {\r\n result.push(this.getElement(b, DifficultyTypeEnum.LET));\r\n }\r\n } else if (this.appInitService.isSuperreader) {\r\n if (difficulties.length) {\r\n a = difficulties.find((item) => item.Type === DifficultyTypeEnum.LEVEL);\r\n }\r\n if (a) {\r\n result.push(this.getElement(a, DifficultyTypeEnum.LEVEL));\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n mapBookDifficultyFromApi2(difficulties: INextTag2[]): IBookTag[] {\r\n if (!difficulties || difficulties.length === 0) {\r\n return [];\r\n }\r\n\r\n const result: IBookTag[] = [];\r\n if (this.appInitService.isSuperbog) {\r\n const lixTag = difficulties.find((item) => item.type === DifficultyTypeEnum.LIX);\r\n const letTag = difficulties.find((item) => item.type === DifficultyTypeEnum.LET);\r\n\r\n if (lixTag) {\r\n result.push(this.getElement2(lixTag, DifficultyTypeEnum.LIX));\r\n }\r\n if (letTag) {\r\n result.push(this.getElement2(letTag, DifficultyTypeEnum.LET));\r\n }\r\n } else if (this.appInitService.isSuperreader) {\r\n const lvlTag = difficulties.find((item) => item.type === DifficultyTypeEnum.LEVEL);\r\n\r\n if (lvlTag) {\r\n result.push(this.getElement2(lvlTag, DifficultyTypeEnum.LEVEL));\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n getElement(element: INextTag, type: DifficultyTypeEnum): IBookTag {\r\n if (element) {\r\n const splitTitle = element.Title.split(' ');\r\n if (splitTitle.length) {\r\n const title = splitTitle[0];\r\n const value = splitTitle[1] || '-';\r\n return {\r\n Title: this.translate.instant(`DifficultyType.${title}`, {\r\n default: title,\r\n }),\r\n Value: value,\r\n Type: element.Type,\r\n };\r\n }\r\n }\r\n return {\r\n Title: type,\r\n Value: '-',\r\n Type: type,\r\n };\r\n }\r\n\r\n getElement2(element: INextTag2, type: DifficultyTypeEnum): IBookTag {\r\n if (element) {\r\n const splitTitle = element.title.split(' ');\r\n if (splitTitle.length) {\r\n const title = splitTitle[0];\r\n const value = splitTitle[1] || '-';\r\n return {\r\n Title: this.translate.instant(`DifficultyType.${title}`, {\r\n default: title,\r\n }),\r\n Value: value,\r\n Type: element.type,\r\n };\r\n }\r\n }\r\n return {\r\n Title: type,\r\n Value: '-',\r\n Type: type,\r\n };\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { INextBook, INextBook2 } from '@portal-app/interfaces/book/next/next-book';\r\nimport { IBookTile } from '@portal-app/interfaces/project/section.interface';\r\nimport { AssetMapper } from '../shared/asset.mapper';\r\nimport { BookDifficultiesMapper } from './book-difficulties.mapper';\r\nimport { BookImpressionMapper } from './book-impression.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookMapper {\r\n constructor(\r\n private bookDifficultiesMapper: BookDifficultiesMapper,\r\n private bookImpressionMapper: BookImpressionMapper,\r\n private assetMapper: AssetMapper\r\n ) {}\r\n\r\n mapBookFromApi(book: INextBook, isFinished?: boolean): IBookTile {\r\n return {\r\n Id: book.Id,\r\n Slug: book.Slug,\r\n HasAudio: book.HasAudioBook,\r\n Image: book.CoverImage,\r\n IsFavorite: book.IsFavorite,\r\n Title: book.Title,\r\n Friends: book.Users,\r\n Progress: isFinished ? 100 : book?.Progress,\r\n Difficulties: this.bookDifficultiesMapper.mapBookDifficultyFromApi(book.Difficulties),\r\n Impressions: book.Impressions ?? [],\r\n };\r\n }\r\n\r\n mapBookFromApi2(book: INextBook2, isFinished?: boolean): IBookTile {\r\n return {\r\n Id: book.id,\r\n Slug: book.slug,\r\n HasAudio: book.hasAudioBook,\r\n Image: this.assetMapper.map(book.coverImage),\r\n IsFavorite: book.isFavorite,\r\n Title: book.title,\r\n Friends: book.users,\r\n Progress: isFinished ? 100 : book?.progress,\r\n Difficulties: this.bookDifficultiesMapper.mapBookDifficultyFromApi2(book.difficulties),\r\n Impressions: this.bookImpressionMapper.mapList(book.impressions),\r\n };\r\n }\r\n\r\n mapBooksFromApi(books: INextBook[], isFinished?: boolean) {\r\n return books.map((x) => this.mapBookFromApi(x, isFinished));\r\n }\r\n\r\n mapBooksFromApi2(books: INextBook2[], isFinished?: boolean) {\r\n return books.map((x) => this.mapBookFromApi2(x, isFinished));\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\nimport { IItemBase } from '@portal-app/interfaces/course/project/course-tabs.interface';\r\nimport { CourseFavoriteApiService } from '@portal-app/services/course/course-favorite-api.service';\r\nimport { EMPTY, of } from 'rxjs';\r\nimport { catchError, map, tap } from 'rxjs/operators';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseFavoriteMapper {\r\n constructor(private courseFavoriteApiService: CourseFavoriteApiService, private userService: UserService) {}\r\n\r\n setTextsFavorite(items: IItemBase[]) {\r\n if (this.userService.isLoggedIn && items.length) {\r\n const ids = items.map((item) => item.Id);\r\n this.courseFavoriteApiService\r\n .getFavoriteTextsByIds(ids)\r\n .pipe(\r\n catchError(() => {\r\n items.map((item) => (item.FavoriteLoaded = true));\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n for (const item of items) {\r\n item.IsFavorite = data.find((elem) => elem.Id === item.Id)?.IsFavorite;\r\n item.FavoriteLoaded = true;\r\n }\r\n });\r\n }\r\n }\r\n\r\n setTasksFavorite(items: IItemBase[]) {\r\n if (this.userService.isLoggedIn && items.length) {\r\n const ids = items.map((item) => item.Id);\r\n this.courseFavoriteApiService\r\n .getFavoriteTasksByIds(ids)\r\n .pipe(\r\n catchError(() => {\r\n items.map((item) => (item.FavoriteLoaded = true));\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n for (const item of items) {\r\n item.IsFavorite = data.find((elem) => elem.Id === item.Id)?.IsFavorite;\r\n item.FavoriteLoaded = true;\r\n }\r\n });\r\n }\r\n }\r\n\r\n setCoursesFavorite(items: IItemBase[]) {\r\n return this.setFavorite(items, 'course');\r\n }\r\n\r\n setActivitiesFavorite(items: IItemBase[]) {\r\n return this.setFavorite(items, 'activity');\r\n }\r\n\r\n private setFavorite(items: IItemBase[], type: 'activity' | 'course') {\r\n if (this.userService.isLoggedIn && items.length) {\r\n const ids = items.map((item) => item.Id);\r\n\r\n const request =\r\n type === 'activity'\r\n ? this.courseFavoriteApiService.getFavoriteActivitiesByIds(ids)\r\n : this.courseFavoriteApiService.getFavoriteCourseByIds(ids);\r\n\r\n return request.pipe(\r\n tap((favorites) => {\r\n for (const item of items) {\r\n item.IsFavorite = favorites.find((elem) => elem.Id === item.Id)?.IsFavorite;\r\n item.FavoriteLoaded = true;\r\n }\r\n }),\r\n catchError(() => {\r\n items.forEach((item) => (item.FavoriteLoaded = true));\r\n return of(false);\r\n }),\r\n map(() => true)\r\n );\r\n }\r\n\r\n return of(false);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport { FacetTypeEnum } from '@portal-app/enums/facet-type.enum';\r\nimport { INextCourseSearchAutoCompleteResponse } from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { ILibraryFacets, ISearchAutoComplete } from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { CourseFavoriteApiService } from '@portal-app/services/course/course-favorite-api.service';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { LevelService } from '@portal-app/services/shared/level.service';\r\nimport { EMPTY } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { INextSearchResponseFacets } from '../../interfaces/next/next-library';\r\nimport { AssetMapper } from '../shared/asset.mapper';\r\nimport { CourseMapper } from './course.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseLibraryMapper {\r\n constructor(\r\n private helperService: HelperService,\r\n private appInitService: AppInitService,\r\n private courseMapper: CourseMapper,\r\n private courseFavoriteApiService: CourseFavoriteApiService,\r\n private userService: UserService,\r\n private levelService: LevelService,\r\n private translate: TranslateService,\r\n private assetMapper: AssetMapper\r\n ) {}\r\n\r\n getFacetItemTitle(title: string, type: string): string {\r\n if (type === FacetTypeEnum.CollaborationTypes) {\r\n return this.translate.instant(`CollaborationType.${title}`, {\r\n default: title,\r\n });\r\n } else if (type === FacetTypeEnum.Genres) {\r\n return this.translate.instant(`GenreType.${title}`, { default: title });\r\n } else {\r\n return title;\r\n }\r\n }\r\n\r\n mapFacetsFromApi(facets: INextSearchResponseFacets[]): ILibraryFacets[] {\r\n const result: ILibraryFacets[] = [];\r\n if (facets.length) {\r\n for (const facet of facets) {\r\n if (FacetTypeEnum[facet.type as keyof typeof FacetTypeEnum] && facet.items.length) {\r\n result.push({\r\n Title: this.translate.instant(`FacetType.${facet.type}`, {\r\n default: facet.type,\r\n }),\r\n UrlTitle: QueryStrings[facet.type as keyof typeof QueryStrings]?.en,\r\n Type: FacetTypeEnum[facet.type as keyof typeof FacetTypeEnum],\r\n Items: facet.items.map((item) => ({\r\n Title: this.getFacetItemTitle(item.value, facet.type),\r\n Value: item.key,\r\n Count: item.count,\r\n Selected: item.selected,\r\n })),\r\n Open: this.helperService.getParameterByQueryStringAndSuffix(\r\n QueryStrings[facet.type as keyof typeof QueryStrings],\r\n QueryStrings.Open\r\n )\r\n ? true\r\n : false,\r\n });\r\n }\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n mapAutoCompleteFromApi(query: string, autocomplete: INextCourseSearchAutoCompleteResponse): ISearchAutoComplete {\r\n const result: ISearchAutoComplete = {\r\n Suggestions: [],\r\n Courses: [],\r\n Books: [],\r\n BookCollections: [],\r\n };\r\n if (autocomplete.autocompleteItems) {\r\n for (const item of autocomplete.autocompleteItems) {\r\n if (item.queryPlusText !== query) {\r\n result.Suggestions.push(item.queryPlusText);\r\n }\r\n }\r\n }\r\n\r\n if (autocomplete.suggestions) {\r\n for (const item of autocomplete.suggestions) {\r\n if (item.course) {\r\n result.Courses.push({\r\n Asset: this.assetMapper.map(item.course.asset),\r\n Id: item.course.id,\r\n Levels: this.levelService.convertLevelsToString(item.course.levels),\r\n StatusLabel: item.course.statusLabel,\r\n Title: item.course.title,\r\n Url: `${this.appInitService.siteConfiguration.BasePath}${item.course.url}`,\r\n IsLocked: item.locked,\r\n FavoriteLoaded: false,\r\n ObjectType: ContentTypeEnum.Courses,\r\n IsActive: this.courseMapper.getCourseIsActive(item.course.status),\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (this.userService.isLoggedIn && result.Courses.length) {\r\n const ids = result.Courses.map((item) => item.Id);\r\n this.courseFavoriteApiService\r\n .getFavoriteCourseByIds(ids)\r\n .pipe(\r\n catchError((e) => {\r\n result.Courses.map((item) => (item.FavoriteLoaded = true));\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n if (data) {\r\n for (const item of result.Courses) {\r\n item.IsFavorite = data.find((elem) => elem.Id === item.Id)?.IsFavorite;\r\n item.FavoriteLoaded = true;\r\n }\r\n }\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport {\r\n INextCourseSearchActivity,\r\n INextCourseSearchAssignment,\r\n INextCourseSearchAssignment2,\r\n INextCourseSearchCourse,\r\n INextCourseSearchMedia,\r\n INextCourseSearchPage,\r\n INextCourseSearchPage2,\r\n INextCourseSearchResponse2,\r\n} from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { ILibraryTab, ILibraryTabGroup } from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { ITabMedia, ITabTask, ITabText } from '@portal-app/interfaces/course/project/course-tabs.interface';\r\nimport { INextFavoriteCourseTab } from '@portal-app/interfaces/course/project/interface.favorite-course';\r\nimport { INextAsset } from '@portal-app/interfaces/next/next-asset.interface';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { LevelService } from '@portal-app/services/shared/level.service';\r\nimport { environment } from '@portal-env/environment';\r\nimport { ContentTypeEnum } from '../../enums/content-type.enum';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { HelperService } from '../../services/shared/helper.service';\r\nimport { HtmlService } from '../../services/shared/html.service';\r\nimport { ActivityMapper } from '../activity/activity.mapper';\r\nimport { CourseMapper } from './course.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseTabsMapper {\r\n constructor(\r\n private appInitService: AppInitService,\r\n private courseMapper: CourseMapper,\r\n private activityMapper: ActivityMapper,\r\n private levelService: LevelService,\r\n private translate: TranslateService,\r\n private helperService: HelperService,\r\n private htmlService: HtmlService\r\n ) {}\r\n\r\n mapFavoriteTabsFromApi(\r\n courses: INextCourseSearchCourse[],\r\n texts: INextCourseSearchPage2[],\r\n tasks: INextCourseSearchAssignment2[],\r\n activities: INextCourseSearchActivity[]\r\n ): INextFavoriteCourseTab[] {\r\n const result: INextFavoriteCourseTab[] = [\r\n {\r\n UrlTitle: QueryStrings.Courses.en,\r\n TabsType: ContentTypeEnum.Courses,\r\n Length: courses.length,\r\n Courses: {\r\n SliderSettings: {\r\n Type: SectionTypeEnum.CourseList,\r\n MaxSlidesPerView: 5,\r\n },\r\n Items: this.courseMapper.mapCoursesFromApi(courses, true, '?portalclick=coursesfavorites'),\r\n },\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: courses.length,\r\n Index: 1,\r\n PageSize: 24,\r\n },\r\n IsAvailable: true,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Texts.en,\r\n TabsType: ContentTypeEnum.Texts,\r\n Texts: this.mapTextsFromApi2(texts, true, '?portalclick=pagesfavorites'),\r\n Length: texts.length,\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: texts.length,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: true,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Activities.en,\r\n TabsType: ContentTypeEnum.Activities,\r\n Activities: this.activityMapper.mapActivitiesToTab(activities, true, '?portalclick=assignmentsfavorites'),\r\n Length: activities.length,\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: activities.length,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: true,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Assignments.en,\r\n TabsType: ContentTypeEnum.Assignments,\r\n Tasks: this.mapTasksFromApi2(tasks, true, '?portalclick=assignmentsfavorites'),\r\n Length: tasks.length,\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: tasks.length,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: true,\r\n },\r\n ];\r\n\r\n return result;\r\n }\r\n\r\n mapLibraryTabsFromApi(azureSearch: INextCourseSearchResponse2): ILibraryTabGroup[] {\r\n const result: ILibraryTabGroup[] = [\r\n {\r\n Title: this.translate.instant('CourseTabs.Library'),\r\n Tabs: [\r\n {\r\n UrlTitle: QueryStrings.Texts.en,\r\n TabsType: ContentTypeEnum.Texts,\r\n Texts: this.mapTextsFromApi(azureSearch.library.pages, undefined, '?portalclick=pageslibrary'),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.pages.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.pages.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Images.en,\r\n TabsType: ContentTypeEnum.Images,\r\n Media: this.mapMediaFromApi(azureSearch.library.images, ContentTypeEnum.Images),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.images.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.images.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Videos.en,\r\n TabsType: ContentTypeEnum.Videos,\r\n Media: this.mapMediaFromApi(azureSearch.library.videos, ContentTypeEnum.Videos),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.videos.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.videos.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Audios.en,\r\n TabsType: ContentTypeEnum.Audios,\r\n Media: this.mapMediaFromApi(azureSearch.library.audios, ContentTypeEnum.Audios),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.audios.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.audios.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Documents.en,\r\n TabsType: ContentTypeEnum.Documents,\r\n Media: this.mapMediaFromApi(azureSearch.library.documents, ContentTypeEnum.Documents),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.documents.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.documents.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Geogebras.en,\r\n TabsType: ContentTypeEnum.GeoGebras,\r\n Media: this.mapMediaFromApi(azureSearch.library.geoGebras, ContentTypeEnum.GeoGebras),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.geoGebras.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.geoGebras.isAvailable,\r\n },\r\n ],\r\n },\r\n {\r\n Title: this.translate.instant('CourseTabs.Course'),\r\n Tabs: [\r\n {\r\n UrlTitle: QueryStrings.Courses.en,\r\n TabsType: ContentTypeEnum.Courses,\r\n Courses: {\r\n SliderSettings: {\r\n Type: SectionTypeEnum.CourseList,\r\n MaxSlidesPerView: 5,\r\n },\r\n Items: this.courseMapper.mapCoursesFromApi2(\r\n azureSearch.courses.courses,\r\n undefined,\r\n '?portalclick=courseslibrary'\r\n ),\r\n },\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.courses.count,\r\n Index: 1,\r\n PageSize: 24,\r\n },\r\n IsAvailable: azureSearch.searchCount.courses.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Activities.en,\r\n TabsType: ContentTypeEnum.Activities,\r\n Activities: this.activityMapper.mapActivitiesToTab(\r\n azureSearch.courses.activities,\r\n undefined,\r\n '?portalclick=activitieslibrary'\r\n ),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.activities.count,\r\n Index: 1,\r\n PageSize: 24,\r\n },\r\n IsAvailable: azureSearch.searchCount.activities.isAvailable,\r\n },\r\n {\r\n UrlTitle: QueryStrings.Assignments.en,\r\n TabsType: ContentTypeEnum.Assignments,\r\n Tasks: this.mapTasksFromApi(azureSearch.courses.assignments, undefined, '?portalclick=assignmentslibrary'),\r\n Pagination: {\r\n Type: PageTypeEnum.CourseLibrary,\r\n CollectionSize: azureSearch.searchCount.assignments.count,\r\n Index: 1,\r\n PageSize: 10,\r\n },\r\n IsAvailable: azureSearch.searchCount.assignments.isAvailable,\r\n },\r\n ],\r\n },\r\n ];\r\n return result;\r\n }\r\n\r\n mapTextsFromApi(texts: INextCourseSearchPage[], hasFavorite?: boolean, trackingUrl?: string): ITabText[] {\r\n const result: ITabText[] = [];\r\n for (const text of texts) {\r\n result.push({\r\n Id: text.page.id,\r\n Title: text.page.title,\r\n Genres: text.page.genres.length\r\n ? text.page.genres.map((item) =>\r\n this.translate.instant(`GenreType.${item}`, {\r\n default: item,\r\n })\r\n )\r\n : [],\r\n Levels: this.levelService.convertLevelsToString(text.page.levels),\r\n Authors: text.page.writers ? text.page.writers : [],\r\n CourseTitle: text.page.courseTitle,\r\n NormalPages: text.page.normalPageCount,\r\n ShowNormalPages: text.page.showNormalPages,\r\n Period: text.page.period === 'Ingen' ? undefined : text.page.period,\r\n Edition: text.page.edition,\r\n Url:\r\n text.page.pageType === 'ActivityPage'\r\n ? `${environment.activityUrl()}${text.page.url}${trackingUrl || ''}`\r\n : `${this.appInitService.siteConfiguration.BasePath}${text.page.url}${trackingUrl || ''}`,\r\n IsLocked: text.locked,\r\n FavoriteLoaded: hasFavorite ? true : false,\r\n ObjectType: ContentTypeEnum.Texts,\r\n IsFavorite: hasFavorite ? true : false,\r\n Highlights: text.page.highlights,\r\n Teaser: this.htmlService.fixHtml(text.page.descriptionPreview),\r\n });\r\n }\r\n return result;\r\n }\r\n mapTextsFromApi2(texts: INextCourseSearchPage2[], hasFavorite?: boolean, trackingUrl?: string): ITabText[] {\r\n const result: ITabText[] = [];\r\n for (const text of texts) {\r\n result.push({\r\n Id: text.Page.Id,\r\n Title: text.Page.Title,\r\n Genres: text.Page.Genres.length\r\n ? text.Page.Genres.map((item) =>\r\n this.translate.instant(`GenreType.${item}`, {\r\n default: item,\r\n })\r\n )\r\n : [],\r\n Levels: this.levelService.convertLevelsToString(text.Page.Levels),\r\n Authors: text.Page.Writers ? text.Page.Writers : [],\r\n CourseTitle: text.Page.CourseTitle,\r\n NormalPages: text.Page.NormalPageCount,\r\n ShowNormalPages: text.Page.ShowNormalPages,\r\n Period: text.Page.Period === 'Ingen' ? undefined : text.Page.Period,\r\n Edition: text.Page.Edition,\r\n Url:\r\n text.Page.PageType === 'ActivityPage'\r\n ? `${environment.activityUrl()}${text.Page.Url}${trackingUrl || ''}`\r\n : `${this.appInitService.siteConfiguration.BasePath}${text.Page.Url}${trackingUrl || ''}`,\r\n IsLocked: text.Locked,\r\n FavoriteLoaded: hasFavorite ? true : false,\r\n ObjectType: ContentTypeEnum.Texts,\r\n IsFavorite: hasFavorite ? true : false,\r\n Highlights: text.Page.Highlights,\r\n });\r\n }\r\n return result;\r\n }\r\n\r\n mapTasksFromApi(tasks: INextCourseSearchAssignment[], hasFavorite?: boolean, trackingUrl?: string): ITabTask[] {\r\n const result: ITabTask[] = [];\r\n for (const task of tasks) {\r\n const item: ITabTask = {\r\n Id: task.assignment.id,\r\n Title: task.assignment.title,\r\n CourseTitle: task.assignment.courseTitle,\r\n CollaborationTitle: this.translate.instant(`CollaborationType.${task.assignment.collaborationType}`, {\r\n default: task.assignment.collaborationType,\r\n }),\r\n Types: task.assignment.types,\r\n Url: `${this.appInitService.siteConfiguration.BasePath}${task.assignment.url}${trackingUrl || ''}`,\r\n IsLocked: task.locked,\r\n FavoriteLoaded: hasFavorite ? true : false,\r\n ObjectType: ContentTypeEnum.Assignments,\r\n IsFavorite: hasFavorite ? true : false,\r\n };\r\n if (item.CollaborationTitle !== 'Ingen samarbejdsform') {\r\n item.CollaborationIcon = `collaboration-${task.assignment.collaborationType.toLowerCase()}.svg`;\r\n }\r\n result.push(item);\r\n }\r\n return result;\r\n }\r\n mapTasksFromApi2(tasks: INextCourseSearchAssignment2[], hasFavorite?: boolean, trackingUrl?: string): ITabTask[] {\r\n const result: ITabTask[] = [];\r\n for (const task of tasks) {\r\n const item: ITabTask = {\r\n Id: task.Assignment.Id,\r\n Title: task.Assignment.Title,\r\n CourseTitle: task.Assignment.CourseTitle,\r\n CollaborationTitle: this.translate.instant(`CollaborationType.${task.Assignment.CollaborationType}`, {\r\n default: task.Assignment.CollaborationType,\r\n }),\r\n Types: task.Assignment.Types,\r\n Url: `${this.appInitService.siteConfiguration.BasePath}${task.Assignment.Url}${trackingUrl || ''}`,\r\n IsLocked: task.Locked,\r\n FavoriteLoaded: hasFavorite ? true : false,\r\n ObjectType: ContentTypeEnum.Assignments,\r\n IsFavorite: hasFavorite ? true : false,\r\n };\r\n if (item.CollaborationTitle !== 'Ingen samarbejdsform') {\r\n item.CollaborationIcon = `collaboration-${task.Assignment.CollaborationType.toLowerCase()}.svg`;\r\n }\r\n result.push(item);\r\n }\r\n return result;\r\n }\r\n\r\n mapMediaFromApi(medias: INextCourseSearchMedia[], type: ContentTypeEnum): ITabMedia[] {\r\n const result: ITabMedia[] = [];\r\n let aspectRatio16By9 = false;\r\n let expandable = false;\r\n if (type === ContentTypeEnum.Images) {\r\n aspectRatio16By9 = true;\r\n expandable = true;\r\n } else if (type === ContentTypeEnum.Videos) {\r\n aspectRatio16By9 = true;\r\n expandable = true;\r\n } else if (type === ContentTypeEnum.Audios) {\r\n aspectRatio16By9 = true;\r\n expandable = true;\r\n } else if (type === ContentTypeEnum.Documents) {\r\n aspectRatio16By9 = false;\r\n expandable = false;\r\n } else if (type === ContentTypeEnum.GeoGebras) {\r\n aspectRatio16By9 = true;\r\n expandable = true;\r\n }\r\n\r\n for (const media of medias) {\r\n let duration: string | undefined;\r\n if (media.durationInSeconds) {\r\n const strPadLeft = (durationString: number, pad: string, length: number) => {\r\n return (new Array(length + 1).join(pad) + durationString).slice(-length);\r\n };\r\n const minutes = Math.floor(media.durationInSeconds / 60);\r\n const seconds = media.durationInSeconds - minutes * 60;\r\n const final = strPadLeft(minutes, '0', 2) + ':' + strPadLeft(seconds, '0', 2);\r\n duration = this.translate.instant(`Label.LengthBlank`, {\r\n number: final,\r\n });\r\n }\r\n let svg: string | undefined;\r\n if (type === ContentTypeEnum.GeoGebras) {\r\n media.path = `https://www.geogebra.org/material/iframe/id/${media.geoGebraId}`;\r\n } else if (type === ContentTypeEnum.Images) {\r\n media.path = media.thumbnailPath; // this sucks balls\r\n } else if (type === ContentTypeEnum.Documents) {\r\n svg = this.helperService.getFileIconSvg(media.type);\r\n }\r\n const item: ITabMedia = {\r\n ThumbnailPath: media.thumbnailPath,\r\n FavoriteLoaded: true, // not enabled\r\n Genres: media.genres ? media.genres : [],\r\n Id: media.assetId, // used for favorites\r\n Keywords: media.keywords ? media.keywords : [],\r\n Levels: this.levelService.convertLevelsToString(media.levels),\r\n ObjectType: type, // used for favorites\r\n Path: media.path,\r\n Subjects: media.subjects ? media.subjects : [],\r\n Title: media.title,\r\n Copyright: media.copyright,\r\n Duration: duration,\r\n IsFavorite: false, // used for favorites\r\n IsLocked: media.locked,\r\n Open: false,\r\n AspectRatio16By9: aspectRatio16By9,\r\n Expandable: expandable,\r\n Image:\r\n type === ContentTypeEnum.Images && media.basePath\r\n ? ({\r\n BasePath: media.basePath,\r\n Dimensions: {\r\n Height: media.dimensions?.height,\r\n Width: media.dimensions?.width,\r\n },\r\n Path: undefined,\r\n Type: 'Image',\r\n } as INextAsset)\r\n : undefined,\r\n Svg: svg,\r\n };\r\n result.push(item);\r\n }\r\n return result;\r\n }\r\n\r\n replaceCoursesTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab, trackingUrl?: string) {\r\n if (tab?.Courses) {\r\n tab.Courses.Items = this.courseMapper.mapCoursesFromApi2(azureSearch.courses.courses, undefined, trackingUrl);\r\n }\r\n\r\n if (tab) {\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.courses.count;\r\n }\r\n }\r\n\r\n replaceActivitiesTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab, trackingUrl?: string) {\r\n if (tab) {\r\n tab.Activities = this.activityMapper.mapActivitiesToTab(azureSearch.courses.activities, undefined, trackingUrl);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.activities.count;\r\n }\r\n }\r\n\r\n replaceTextsTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab, trackingUrl?: string) {\r\n if (tab) {\r\n tab.Texts = this.mapTextsFromApi(azureSearch.library.pages, undefined, trackingUrl);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.pages.count;\r\n }\r\n }\r\n\r\n replaceTasksTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab, trackingUrl?: string) {\r\n if (tab) {\r\n tab.Tasks = this.mapTasksFromApi(azureSearch.courses.assignments, undefined, trackingUrl);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.assignments.count;\r\n }\r\n }\r\n\r\n replaceImagesTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab) {\r\n if (tab) {\r\n tab.Media = this.mapMediaFromApi(azureSearch.library.images, ContentTypeEnum.Images);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.images.count;\r\n }\r\n }\r\n\r\n replaceVideosTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab) {\r\n if (tab) {\r\n tab.Media = this.mapMediaFromApi(azureSearch.library.videos, ContentTypeEnum.Videos);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.videos.count;\r\n }\r\n }\r\n\r\n replaceAudiosTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab) {\r\n if (tab) {\r\n tab.Media = this.mapMediaFromApi(azureSearch.library.audios, ContentTypeEnum.Audios);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.audios.count;\r\n }\r\n }\r\n\r\n replaceDocumentsTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab) {\r\n if (tab) {\r\n tab.Media = this.mapMediaFromApi(azureSearch.library.documents, ContentTypeEnum.Documents);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.documents.count;\r\n }\r\n }\r\n\r\n replaceGeoGebrasTab(azureSearch: INextCourseSearchResponse2, tab?: ILibraryTab) {\r\n if (tab) {\r\n tab.Media = this.mapMediaFromApi(azureSearch.library.geoGebras, ContentTypeEnum.GeoGebras);\r\n tab.Pagination.CollectionSize = azureSearch.searchCount.geoGebras.count;\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport {\r\n INextCourseSearchCourse,\r\n INextCourseSearchCourse2,\r\n} from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { ICourseTile } from '@portal-app/interfaces/course/project/course.interface';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { HtmlService } from '@portal-app/services/shared/html.service';\r\nimport { LevelService } from '@portal-app/services/shared/level.service';\r\nimport { AssetMapper } from '../shared/asset.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseMapper {\r\n constructor(\r\n private appInitService: AppInitService,\r\n private helperService: HelperService,\r\n private levelService: LevelService,\r\n private htmlService: HtmlService,\r\n private translate: TranslateService,\r\n private assetMapper: AssetMapper\r\n ) {}\r\n\r\n mapCoursesFromApi(courses: INextCourseSearchCourse[], hasFavorite?: boolean, trackingUrl?: string): ICourseTile[] {\r\n const result: ICourseTile[] = [];\r\n if (!courses) {\r\n // dont trust the api\r\n return result;\r\n }\r\n for (const item of courses) {\r\n result.push({\r\n Id: item.Course.Id,\r\n Asset: item.Course.Asset,\r\n Description: this.htmlService.fixHtml(item.Course.Description),\r\n Levels: this.levelService.convertLevelsToString(item.Course.Levels),\r\n StatusLabel: item.Course.StatusLabel,\r\n Title: item.Course.Title,\r\n TitleMobile: this.helperService.truncateString(item.Course.Title, 45),\r\n Url: `${this.appInitService.siteConfiguration.BasePath}${item.Course.Url}${trackingUrl || ''}`,\r\n IsLocked: item.Locked,\r\n FavoriteLoaded: true,\r\n ObjectType: ContentTypeEnum.Courses,\r\n LessonOrDurationLabel: this.helperService.getLessonOrDurationLabel(item.Course.Duration),\r\n IsActive: this.getCourseIsActive(item.Course.Status),\r\n IsFavorite: hasFavorite,\r\n PromiseOfLearning: item.Course.PromiseOfLearning\r\n ? {\r\n Title: this.translate.instant('Label.WhenYouAreFinishedWithTheBlank', {\r\n name: this.translate.instant('ContentType.TheCourse').toLowerCase(),\r\n }),\r\n Description: this.htmlService.fixHtml(item.Course.PromiseOfLearning) ?? '',\r\n }\r\n : undefined,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n mapCoursesFromApi2(courses: INextCourseSearchCourse2[], hasFavorite?: boolean, trackingUrl?: string): ICourseTile[] {\r\n const result: ICourseTile[] = [];\r\n\r\n if (!courses) {\r\n // dont trust the api\r\n return result;\r\n }\r\n for (const item of courses) {\r\n result.push({\r\n Id: item.course.id,\r\n Asset: this.assetMapper.map(item.course.asset),\r\n Description: this.htmlService.fixHtml(item.course.description),\r\n Levels: this.levelService.convertLevelsToString(item.course.levels),\r\n StatusLabel: item.course.statusLabel,\r\n Title: item.course.title,\r\n TitleMobile: this.helperService.truncateString(item.course.title, 45),\r\n Url: `${this.appInitService.siteConfiguration.BasePath}${item.course.url}${trackingUrl || ''}`,\r\n IsLocked: item.locked,\r\n FavoriteLoaded: true,\r\n ObjectType: ContentTypeEnum.Courses,\r\n LessonOrDurationLabel: this.helperService.getLessonOrDurationLabel(item.course.duration),\r\n IsActive: this.getCourseIsActive(item.course.status),\r\n IsFavorite: hasFavorite,\r\n PromiseOfLearning: item.course.promiseOfLearning\r\n ? {\r\n Title: this.translate.instant('Label.WhenYouAreFinishedWithTheBlank', {\r\n name: this.translate.instant('ContentType.TheCourse').toLowerCase(),\r\n }),\r\n Description: this.htmlService.fixHtml(item.course.promiseOfLearning) ?? '',\r\n }\r\n : undefined,\r\n });\r\n }\r\n\r\n return result;\r\n }\r\n\r\n getCourseIsActive(status: string) {\r\n return !(status === 'Draft' || status === 'InActive');\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { IPsArticle } from '@portal-app/interfaces/ps/project/ps-article.interface';\r\nimport { HtmlService } from '@portal-app/services/shared/html.service';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { PsLibraryFilterEnum } from '../../enums/ps/ps-library-filter.enum';\r\nimport { SectionTypeEnum } from '../../enums/section-type.enum';\r\nimport { IUmbPsArticle } from '../../interfaces/ps/umbraco/umb-ps-article.interface';\r\nimport { HelperService } from '../../services/shared/helper.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PsArticleMapper {\r\n constructor(\r\n private htmlService: HtmlService,\r\n private helperService: HelperService,\r\n private translateService: TranslateService\r\n ) {}\r\n\r\n mapPsArticleFromApi(article: IUmbPsArticle): IPsArticle {\r\n return {\r\n Label: article.label,\r\n Authors: article.authors.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Author,\r\n })),\r\n Id: article.id.toString(),\r\n IsFavorite: article.isFavorite,\r\n Title: article.title,\r\n Topics: article.topics.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Topic,\r\n })),\r\n Teaser: this.htmlService.fixHtml(this.htmlService.truncateHTML(article.teaser, 150)),\r\n ContentGridHtml: this.htmlService.fixHtml(article.contentGridHtml),\r\n PublishDate: this.helperService.getLocalizedDate(new Date(article.publishDate)),\r\n Image: article.image,\r\n Related: article.relatedArticles?.length\r\n ? {\r\n Articles: this.mapPsArticlesFromApi(article.relatedArticles),\r\n SliderSettings: {\r\n Type: SectionTypeEnum.PsArticles,\r\n UseSlider: true,\r\n MaxSlidesPerView: 5,\r\n Title: this.translateService.instant('PsArticle.RelatedTitle'),\r\n },\r\n }\r\n : undefined,\r\n Url: article.customUrl\r\n ? this.helperService.getCustomUrl(article.customUrl)\r\n : `/${PageTypeEnum.PsArticle}/${article.id}`,\r\n };\r\n }\r\n\r\n mapPsArticlesFromApi(articles: IUmbPsArticle[]): IPsArticle[] {\r\n const result: IPsArticle[] = [];\r\n articles.forEach((article) => {\r\n result.push(this.mapPsArticleFromApi(article));\r\n });\r\n return result;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { PsLibraryFilterEnum } from '../../enums/ps/ps-library-filter.enum';\r\nimport { IPsAssignment } from '../../interfaces/ps/project/ps-assignment.interface';\r\nimport { IUmbPsAssignment } from '../../interfaces/ps/umbraco/umb-ps-assignment.interface';\r\nimport { HelperService } from '../../services/shared/helper.service';\r\nimport { HtmlService } from '../../services/shared/html.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PsAssignmentMapper {\r\n constructor(private htmlService: HtmlService, private helperService: HelperService) {}\r\n\r\n mapPsAssignmentFromApi(assignment: IUmbPsAssignment, truncate?: number): IPsAssignment {\r\n return {\r\n Id: assignment.id,\r\n Topics: assignment.topics?.length\r\n ? assignment.topics.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Topic,\r\n }))\r\n : [],\r\n Authors: assignment.authors?.length\r\n ? assignment.authors.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Author,\r\n }))\r\n : [],\r\n AudioFilesCount: assignment.audioFilesCount,\r\n AudioFiles: assignment.audioFiles?.length\r\n ? assignment.audioFiles.map((elem) => ({\r\n Svg: this.helperService.getFileIconSvg(elem.fileExtension),\r\n FileName: elem.fileName,\r\n Title: elem.title,\r\n Url: elem.url,\r\n Caption: elem.caption,\r\n CopyrightText: elem.copyrightText,\r\n }))\r\n : [],\r\n Documents: assignment.documents?.length\r\n ? assignment.documents.map((elem) => ({\r\n Svg: this.helperService.getFileIconSvg(elem.fileExtension),\r\n FileName: elem.fileName,\r\n Title: elem.title,\r\n Url: elem.url,\r\n Caption: elem.caption,\r\n CopyrightText: elem.copyrightText,\r\n }))\r\n : [],\r\n IsFavorite: assignment.isFavorite,\r\n Levels: assignment.levels?.length\r\n ? assignment.levels.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Level,\r\n }))\r\n : [],\r\n PublishDate: assignment.publishDate ? new Date(assignment.publishDate) : undefined,\r\n Subjects: assignment.subjects.length\r\n ? assignment.subjects.map((subject) => ({\r\n Id: subject.id,\r\n Title: subject.title,\r\n BackgroundColor: subject.backgroundColor,\r\n TextColor: subject.textColor,\r\n Type: PsLibraryFilterEnum.Subject,\r\n }))\r\n : [],\r\n TeacherDocuments: assignment.teacherDocuments?.length\r\n ? assignment.teacherDocuments.map((elem) => ({\r\n Svg: this.helperService.getFileIconSvg(elem.fileExtension),\r\n FileName: elem.fileName,\r\n Title: elem.title,\r\n Url: elem.url,\r\n Caption: elem.caption,\r\n CopyrightText: elem.copyrightText,\r\n }))\r\n : [],\r\n Teaser: this.htmlService.fixHtml(this.htmlService.truncateHTML(assignment.teaser, truncate)),\r\n Themes: assignment.themes?.length\r\n ? assignment.themes.map((elem) => ({\r\n Id: elem.id,\r\n Title: elem.title,\r\n Type: PsLibraryFilterEnum.Theme,\r\n }))\r\n : [],\r\n Title: assignment.title,\r\n Thumbnail: assignment.thumbnail,\r\n Url: assignment.customUrl\r\n ? `/${this.helperService.getCustomUrl(assignment.customUrl)!}`\r\n : `/${PageTypeEnum.PsAssignment}/${assignment.id}`,\r\n Open: false,\r\n DownloadUrl: assignment.downloadUrl,\r\n HasFiles:\r\n (assignment.audioFiles?.length || assignment.documents?.length || assignment.teacherDocuments?.length) > 0,\r\n };\r\n }\r\n\r\n mapPsAssignmentsFromApi(assignments?: IUmbPsAssignment[], truncate?: number): IPsAssignment[] {\r\n const result: IPsAssignment[] = [];\r\n assignments?.forEach((article) => {\r\n result.push(this.mapPsAssignmentFromApi(article, truncate));\r\n });\r\n return result;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { INextAsset, INextAsset2 } from '@portal-app/interfaces/next/next-asset.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class AssetMapper {\r\n map(asset2?: INextAsset2): INextAsset | undefined {\r\n if (!asset2) {\r\n return;\r\n }\r\n\r\n return {\r\n Id: asset2.id,\r\n Title: asset2.title,\r\n Description: asset2.description,\r\n Copyright: asset2.copyright,\r\n FileType: asset2.fileType,\r\n Path: asset2.path,\r\n Type: asset2.type,\r\n Dimensions: asset2.dimensions ? { Width: asset2.dimensions.width, Height: asset2.dimensions.height } : undefined,\r\n BasePath: asset2.basePath,\r\n ChangeFormat: asset2.changeFormat,\r\n Slug: asset2.slug,\r\n FileName: asset2.fileName,\r\n FileSize: asset2.fileSize,\r\n };\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { AudioPlayerModule } from '../../shared/audio-player/audio-player.module';\r\nimport { BaseModule } from '../../shared/base/base.module';\r\nimport { LayoutAudioFullComponent } from './components/layout-audio-full/layout-audio-full.component';\r\nimport { LayoutAudioPartialComponent } from './components/layout-audio-partial/layout-audio-partial.component';\r\nimport { LayoutAudioRecordedComponent } from './components/layout-audio-recorded/layout-audio-recorded.component';\r\n\r\n@NgModule({\r\n declarations: [LayoutAudioFullComponent, LayoutAudioRecordedComponent, LayoutAudioPartialComponent],\r\n imports: [CommonModule, BaseModule, AudioPlayerModule],\r\n exports: [LayoutAudioFullComponent, LayoutAudioRecordedComponent, LayoutAudioPartialComponent],\r\n})\r\nexport class LayoutAudioModule {}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { createAction, props } from '@ngrx/store';\r\nimport { PeriodSelectorEnum } from '@portal-app/enums/period-selector.enum';\r\nimport { IBookTile, ICollectionTile } from '@portal-app/interfaces/project/section.interface';\r\nimport { ISelectedClass, ITeacherClassStudentItem, ITeamsAndClasses } from './teacher-dashboard.reducer';\r\n\r\nconst modulePrefix = '[TeacherDashboard]';\r\n\r\nexport const GetTeamsAndClasses = createAction(`${modulePrefix} GetTeamsAndClasses`);\r\n\r\nexport const SelectTeacherClassIdAction = createAction(\r\n `${modulePrefix} SelectTeacherClassId`,\r\n props<{ selectedClass: ISelectedClass }>()\r\n);\r\n\r\nexport const SetSelectedStudent = createAction(\r\n `${modulePrefix} Set Selected Student`,\r\n props<{ student?: ITeacherClassStudentItem }>()\r\n);\r\n\r\nexport const SelectedBookTapNavigationAction = createAction(\r\n `${modulePrefix} SelectedBookTabNavigation`,\r\n props<{ bookTab: string }>()\r\n);\r\n\r\nexport const SelectBookPeriod = createAction(`${modulePrefix} change period book selection`, props<{ data: string }>());\r\n\r\nexport const SetBookPeriod = createAction(`${modulePrefix} only set the period`, props<{ data: PeriodSelectorEnum }>());\r\n\r\nexport const SetOnlyBookPeriodTime = createAction(\r\n `${modulePrefix} Only begin date for book period`,\r\n props<{ data: string }>()\r\n);\r\n\r\nexport const SetBookPeriodTime = createAction(`${modulePrefix} begin date for book period`, props<{ data: string }>());\r\n\r\nexport const GetTeamsAndClassesSuccess = createAction(\r\n `${modulePrefix} GetTeamsAndClassesSuccess`,\r\n props<{ data: ITeamsAndClasses }>()\r\n);\r\n\r\nexport const GetTeacherClassesFailureAction = createAction(\r\n `${modulePrefix} GetTeacherClassesFailure`,\r\n props<{ error: HttpErrorResponse }>()\r\n);\r\n\r\nexport const GetBookCollectionAction = createAction('[GetBookCollection] GetBookCollection');\r\n\r\nexport const GetBookCollectionSuccessAction = createAction(\r\n 'GetBookCollectionSuccessAction',\r\n props<{ bookCollectionData: ICollectionTile[] }>()\r\n);\r\nexport const GetBookCollectionFailureAction = createAction(\r\n '[GetBookCollectionFailureAction] GetBookCollectionFailureAction',\r\n props<{ error: HttpErrorResponse }>()\r\n);\r\nexport const GetStudentsInClassSuccessAction = createAction(\r\n 'GetStudentsInClassSuccessAction',\r\n props<{ studentsData: ITeacherClassStudentItem[] }>()\r\n);\r\n\r\nexport const GetStudentsInClassFailureAction = createAction(\r\n 'GetStudentsInClassFailureAction',\r\n props<{ error: HttpErrorResponse }>()\r\n);\r\n\r\nexport const ToggleBookCollectionFavouriteAction = createAction(\r\n '[TeacherDashboard] toggleBookCollectionFavourite',\r\n props<{ data: boolean; id: string }>()\r\n);\r\n\r\nexport const ToggleBookContinueFavouriteAction = createAction(\r\n '[TeacherDashboard] toggle favourite for books continue',\r\n props<{ data: boolean; id: string }>()\r\n);\r\n\r\nexport const ToggleBookFinishedFavouriteAction = createAction(\r\n '[TeacherDashboard] toggle favourite for finished books',\r\n props<{ data: boolean; id: string }>()\r\n);\r\n\r\nexport const GetStudentsInClassAction = createAction(\r\n 'GetStudentsInClassAction',\r\n props<{ selectedClass: ISelectedClass }>()\r\n);\r\n\r\nexport const GetBooksForUser = createAction('GetBooksForUser', props<{ userId: string }>());\r\n\r\nexport const GetBooksForUserSuccess = createAction(\r\n 'GetBooksForUserSuccess',\r\n props<{ booksInProgress: IBookTile[]; booksFinished: IBookTile[] }>()\r\n);\r\n","import { PeriodSelectorEnum } from '@portal-app/enums/period-selector.enum';\r\n\r\nexport function periodDateHelper(period: PeriodSelectorEnum): string {\r\n let newDateSec: number;\r\n let newDate: Date;\r\n const today = new Date().getTime();\r\n\r\n switch (period) {\r\n case PeriodSelectorEnum.now:\r\n newDateSec = today - 60 * 60 * 1000;\r\n newDate = new Date(newDateSec);\r\n break;\r\n case PeriodSelectorEnum.day:\r\n newDateSec = today - 60 * 60 * 1000 * 24;\r\n newDate = new Date(newDateSec);\r\n break;\r\n case PeriodSelectorEnum.month:\r\n newDateSec = today - 60 * 60 * 1000 * 24 * 30;\r\n newDate = new Date(newDateSec);\r\n break;\r\n case PeriodSelectorEnum.week:\r\n newDateSec = today - 60 * 60 * 1000 * 24 * 7;\r\n newDate = new Date(newDateSec);\r\n break;\r\n case PeriodSelectorEnum.schoolYear:\r\n newDateSec = today - 60 * 60 * 1000 * 24 * 365;\r\n newDate = new Date(newDateSec);\r\n break;\r\n default:\r\n // Return month as a default date\r\n newDateSec = today - 60 * 60 * 1000 * 24 * 30;\r\n newDate = new Date(newDateSec);\r\n }\r\n\r\n return `${newDate.getUTCFullYear().toString()}-${newDate.getUTCMonth() + 1}-${newDate.getUTCDate()}`;\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, LoadingService } from '@lru/felib';\r\nimport { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';\r\nimport { Store } from '@ngrx/store';\r\nimport { LoadingKey } from '@portal-app/enums/loading-keys.enum';\r\nimport { PeriodSelectorEnum } from '@portal-app/enums/period-selector.enum';\r\nimport { INextBookCollection } from '@portal-app/interfaces/book/next/next-book-collection.interface';\r\nimport { IBookTile } from '@portal-app/interfaces/project/section.interface';\r\nimport { BookCollectionMapper } from '@portal-app/mapper/book/book-collection.mapper';\r\nimport { BookMapper } from '@portal-app/mapper/book/book.mapper';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { of } from 'rxjs';\r\nimport { catchError, map, mergeMap, tap } from 'rxjs/operators';\r\nimport { periodDateHelper } from '../dashboard-helper.service';\r\nimport { BookTeacherDashboardStudentBooksResponse } from '../interfaces/book-teacher-dashboard.interface';\r\nimport * as TeacherDashboardStoreActions from './teacher-dashboard.actions';\r\nimport {\r\n ITeacherClassStudentItem,\r\n ITeacherDashboardState,\r\n ITeamsAndClassesResponse,\r\n} from './teacher-dashboard.reducer';\r\nimport { selectGetSelectedClass, selectorGetSelectedPeriodToDate } from './teacher-dashboard.selectors';\r\n\r\n@Injectable()\r\nexport class TeacherDashboardStoreEffects {\r\n constructor(\r\n private bookMapper: BookMapper,\r\n private actions$: Actions,\r\n private apiService: ApiService,\r\n private appInitService: AppInitService,\r\n private store: Store,\r\n private bookCollectionMapper: BookCollectionMapper,\r\n private loadingService: LoadingService\r\n ) {}\r\n\r\n /** Get classes for institution */\r\n GetTeacherClasses$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.GetTeamsAndClasses),\r\n tap(() => this.loadingService.start(LoadingKey.Page)),\r\n mergeMap(() =>\r\n this.apiService\r\n .getLounge(`v1/team/listwithclasses?productId=${this.productId()}`)\r\n .pipe(\r\n map((data: ITeamsAndClassesResponse) =>\r\n TeacherDashboardStoreActions.GetTeamsAndClassesSuccess({\r\n data: data.result,\r\n })\r\n ),\r\n tap(() => this.loadingService.stop(LoadingKey.Page))\r\n )\r\n ),\r\n catchError((error: HttpErrorResponse) => {\r\n this.loadingService.stop(LoadingKey.Page);\r\n return of(\r\n TeacherDashboardStoreActions.GetTeacherClassesFailureAction({\r\n error,\r\n })\r\n );\r\n })\r\n )\r\n );\r\n\r\n /**\r\n * Get students in a selected class.\r\n * Fetch student by class id & institutionId\r\n * @param data.id - class ID\r\n * @param data.institutionId - institutionId is based on the teacher login\r\n */\r\n GetStudentsInClass$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.GetStudentsInClassAction),\r\n concatLatestFrom(() => this.store.select(selectorGetSelectedPeriodToDate)),\r\n tap(() => this.loadingService.start(LoadingKey.Page)),\r\n mergeMap(([data, beginDate]) => {\r\n return this.apiService\r\n .postNext(`BookProgress/GetUsersBookInteractionState`, {\r\n TeamId: data.selectedClass.classId,\r\n ProjectGroupId: this.projectGroupId(),\r\n IsDlpClass: data.selectedClass.isDlpClass,\r\n LevelIds: data.selectedClass.levelIds,\r\n StartDate: beginDate,\r\n EndDate: '',\r\n })\r\n .pipe(\r\n map((studentsData) => {\r\n this.loadingService.stop(LoadingKey.Page);\r\n return TeacherDashboardStoreActions.GetStudentsInClassSuccessAction({\r\n studentsData,\r\n });\r\n }),\r\n catchError((error: HttpErrorResponse) => {\r\n this.loadingService.stop(LoadingKey.Page);\r\n return of(\r\n TeacherDashboardStoreActions.GetStudentsInClassFailureAction({\r\n error,\r\n })\r\n );\r\n })\r\n );\r\n })\r\n )\r\n );\r\n\r\n GetBookCollections$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.GetBookCollectionAction),\r\n concatLatestFrom(() => this.store.select(selectGetSelectedClass)),\r\n mergeMap(([data, _class]) =>\r\n this.apiService\r\n .postNext(`BookBox/GetBookBoxesByTeamId`, {\r\n TeamId: _class?.classId,\r\n ProjectGroupId: this.projectGroupId(),\r\n IsDlpClass: _class?.isDlpClass,\r\n })\r\n .pipe(\r\n map((_bookCollectionData) => {\r\n const bookCollectionData = this.bookCollectionMapper.mapBookCollectionFromApi(_bookCollectionData);\r\n return TeacherDashboardStoreActions.GetBookCollectionSuccessAction({ bookCollectionData });\r\n }),\r\n catchError((error: HttpErrorResponse) =>\r\n of(\r\n TeacherDashboardStoreActions.GetBookCollectionFailureAction({\r\n error,\r\n })\r\n )\r\n )\r\n )\r\n )\r\n )\r\n );\r\n\r\n GetBooksForUser$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.GetBooksForUser),\r\n concatLatestFrom(() => this.store.select(selectorGetSelectedPeriodToDate)),\r\n mergeMap(([data, period]) =>\r\n this.apiService\r\n .getNext(\r\n `Book/GetBooksCompletedAndInProgressByStudentId/${\r\n data.userId\r\n }?projectGroupId=${this.projectGroupId()}&startDate=${period}`\r\n )\r\n .pipe(\r\n map((studentBooks) => {\r\n const booksInProgress = this.bookMapper.mapBooksFromApi(studentBooks.BooksInProgress);\r\n\r\n let booksFinished: IBookTile[] = [];\r\n\r\n if (studentBooks.BooksCompleted && studentBooks.BooksCompleted.length) {\r\n booksFinished = this.bookMapper.mapBooksFromApi(studentBooks.BooksCompleted);\r\n }\r\n\r\n return TeacherDashboardStoreActions.GetBooksForUserSuccess({\r\n booksInProgress,\r\n booksFinished,\r\n });\r\n }),\r\n catchError((error: HttpErrorResponse) =>\r\n of(\r\n TeacherDashboardStoreActions.GetStudentsInClassFailureAction({\r\n error,\r\n })\r\n )\r\n )\r\n )\r\n )\r\n )\r\n );\r\n\r\n SetBookPeriodTime$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.SetBookPeriodTime),\r\n concatLatestFrom(() => [this.store.select(selectGetSelectedClass)]),\r\n mergeMap(([data, _class]) => [\r\n TeacherDashboardStoreActions.GetStudentsInClassAction({\r\n selectedClass: {\r\n classId: _class?.classId || '',\r\n isDlpClass: _class?.isDlpClass || false,\r\n levelIds: _class?.levelIds || [],\r\n },\r\n }),\r\n ])\r\n )\r\n );\r\n\r\n SetBookPeriod$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.SetBookPeriod),\r\n map((data) => {\r\n return TeacherDashboardStoreActions.SetOnlyBookPeriodTime({\r\n data: periodDateHelper(data.data),\r\n });\r\n })\r\n )\r\n );\r\n\r\n SelectBookPeriod$ = createEffect(() =>\r\n this.actions$.pipe(\r\n ofType(TeacherDashboardStoreActions.SelectBookPeriod),\r\n map((data) => {\r\n return TeacherDashboardStoreActions.SetBookPeriodTime({\r\n data: periodDateHelper(data.data as PeriodSelectorEnum),\r\n });\r\n })\r\n )\r\n );\r\n\r\n private projectGroupId() {\r\n return this.appInitService.siteConfiguration.ProjectGroup;\r\n }\r\n\r\n private productId() {\r\n return this.appInitService.siteConfiguration.Id;\r\n }\r\n}\r\n","import { ClassDto } from '@lru/felib/lib/modules/lounge/interfaces/endpoint/dtos/dto-class.interface';\r\nimport { Action, createReducer, on } from '@ngrx/store';\r\nimport { IBookTile, ICollectionTile } from '@portal-app/interfaces/project/section.interface';\r\nimport * as TeacherDashboardStoreActions from './teacher-dashboard.actions';\r\n// import { act } from \"@ngrx/effects\";\r\n\r\nexport const teacherDashboardFeatureKey = 'BookTeacherDashboard';\r\n\r\nexport interface ITeamsAndClassesResponse {\r\n result: ITeamsAndClasses;\r\n error?: LoungeError;\r\n}\r\n\r\nexport interface LoungeError {\r\n errorCode: string;\r\n parameters: object;\r\n}\r\n\r\nexport interface ITeamsAndClasses {\r\n classes: ClassDto[];\r\n teamsWithTeachers: ITeacherClassesItem[];\r\n}\r\n\r\nexport interface ITeacherClassesItem {\r\n id: string;\r\n title: string;\r\n isDlpClass: boolean;\r\n levelIds: string[];\r\n}\r\n\r\nexport interface ITeacherClassStudentItem {\r\n DisplayName: string;\r\n FirstName: string;\r\n Initials: string;\r\n IsActive: boolean;\r\n LastName: string;\r\n UserId: string;\r\n}\r\n\r\nexport interface ISelectedClass {\r\n classId: string;\r\n isDlpClass: boolean;\r\n levelIds: string[];\r\n}\r\n\r\n// Overall state - extend as nessary\r\nexport interface ITeacherDashboardState {\r\n selectedClass?: ISelectedClass;\r\n selectedStudent?: ITeacherClassStudentItem;\r\n selectedBookTab: string;\r\n selectedPeriod: string;\r\n selectedPeriodToDate: string;\r\n teamsAndClasses?: ITeamsAndClasses;\r\n students: ITeacherClassStudentItem[];\r\n bookCollection: ICollectionTile[];\r\n booksInProgress: IBookTile[];\r\n booksFinished: IBookTile[];\r\n}\r\n\r\nexport const initialTeacherDashboardState: ITeacherDashboardState = {\r\n selectedClass: undefined,\r\n selectedStudent: undefined,\r\n selectedBookTab: '',\r\n selectedPeriod: '',\r\n selectedPeriodToDate: '',\r\n teamsAndClasses: undefined,\r\n students: [],\r\n bookCollection: [],\r\n booksInProgress: [],\r\n booksFinished: [],\r\n};\r\n\r\nexport const getTeacherClassesSuccessReducer = createReducer(\r\n initialTeacherDashboardState,\r\n on(TeacherDashboardStoreActions.ToggleBookCollectionFavouriteAction, (state, action) => {\r\n return {\r\n ...state,\r\n bookCollection: state.bookCollection\r\n .map((item) => ({ ...item }))\r\n .map((item) => {\r\n if (item.Id === action.id) {\r\n return {\r\n ...item,\r\n IsFavorite: action.data,\r\n };\r\n } else {\r\n return item;\r\n }\r\n }),\r\n };\r\n }),\r\n on(TeacherDashboardStoreActions.ToggleBookContinueFavouriteAction, (state, action) => {\r\n return {\r\n ...state,\r\n booksInProgress: state.booksInProgress\r\n .map((item) => ({ ...item }))\r\n .map((item) => {\r\n if (item.Id === action.id) {\r\n return {\r\n ...item,\r\n IsFavorite: action.data,\r\n };\r\n } else {\r\n return item;\r\n }\r\n }),\r\n };\r\n }),\r\n on(TeacherDashboardStoreActions.ToggleBookFinishedFavouriteAction, (state, action) => {\r\n return {\r\n ...state,\r\n booksFinished: state.booksFinished\r\n .map((item) => ({ ...item }))\r\n .map((item) => {\r\n if (item.Id === action.id) {\r\n return {\r\n ...item,\r\n IsFavorite: action.data,\r\n };\r\n } else {\r\n return item;\r\n }\r\n }),\r\n };\r\n }),\r\n on(TeacherDashboardStoreActions.GetBookCollectionSuccessAction, (state, action) => ({\r\n ...state,\r\n bookCollection: action.bookCollectionData,\r\n })),\r\n on(TeacherDashboardStoreActions.SelectBookPeriod, (state, action) => ({\r\n ...state,\r\n selectedPeriod: action.data,\r\n })),\r\n on(TeacherDashboardStoreActions.SetBookPeriodTime, (state, action) => ({\r\n ...state,\r\n selectedPeriodToDate: action.data,\r\n })),\r\n on(TeacherDashboardStoreActions.SetBookPeriod, (state, action) => ({\r\n ...state,\r\n selectedPeriod: action.data,\r\n })),\r\n on(TeacherDashboardStoreActions.SetOnlyBookPeriodTime, (state, action) => ({\r\n ...state,\r\n selectedPeriodToDate: action.data,\r\n })),\r\n on(TeacherDashboardStoreActions.GetTeamsAndClassesSuccess, (state, action) => ({\r\n ...state,\r\n teamsAndClasses: action.data,\r\n })),\r\n on(TeacherDashboardStoreActions.GetStudentsInClassSuccessAction, (state, action) => {\r\n const newSortedData = [...action.studentsData];\r\n newSortedData.sort(sortByDisplayName);\r\n return {\r\n ...state,\r\n students: newSortedData,\r\n };\r\n }),\r\n on(TeacherDashboardStoreActions.SelectTeacherClassIdAction, (state, action) => ({\r\n ...state,\r\n selectedClass: action.selectedClass,\r\n })),\r\n on(TeacherDashboardStoreActions.SelectedBookTapNavigationAction, (state, action) => ({\r\n ...state,\r\n selectedBookTab: action.bookTab,\r\n })),\r\n on(TeacherDashboardStoreActions.SetSelectedStudent, (state, action) => ({\r\n ...state,\r\n selectedStudent: action.student,\r\n })),\r\n on(TeacherDashboardStoreActions.GetBooksForUserSuccess, (state, action) => ({\r\n ...state,\r\n booksInProgress: action.booksInProgress,\r\n booksFinished: action.booksFinished,\r\n }))\r\n);\r\n\r\nexport function reducer(state: ITeacherDashboardState | undefined, action: Action) {\r\n return getTeacherClassesSuccessReducer(state, action);\r\n}\r\n\r\nfunction sortByDisplayName(a: ITeacherClassStudentItem, b: ITeacherClassStudentItem): number {\r\n const compare = a.DisplayName.localeCompare(b.DisplayName, 'da-DK', {\r\n sensitivity: 'base',\r\n });\r\n if (compare > 0) {\r\n return 1;\r\n }\r\n if (compare < 0) {\r\n return -1;\r\n }\r\n return compare;\r\n}\r\n","import { createFeatureSelector, createSelector } from '@ngrx/store';\r\nimport { ITeacherDashboardState, teacherDashboardFeatureKey } from './teacher-dashboard.reducer';\r\n\r\nconst selectTeacherClassState = createFeatureSelector(teacherDashboardFeatureKey);\r\n\r\nexport const selectTeamsAndClasses = createSelector(selectTeacherClassState, (state) => state.teamsAndClasses);\r\n\r\nexport const selectGetSelectedClass = createSelector(selectTeacherClassState, (state) => state.selectedClass);\r\n\r\nexport const selectGetSelectedStudent = createSelector(selectTeacherClassState, (state) => state.selectedStudent);\r\nexport const selectGetSelectedStudentId = createSelector(selectGetSelectedStudent, (state) => state?.UserId);\r\nexport const selectGetSelectedStudentName = createSelector(selectGetSelectedStudent, (state) => state?.DisplayName);\r\n\r\nexport const selectorGetSelectedPeriod = createSelector(selectTeacherClassState, (state) => state.selectedPeriod);\r\nexport const selectorGetSelectedPeriodToDate = createSelector(\r\n selectTeacherClassState,\r\n (state) => state.selectedPeriodToDate\r\n);\r\n\r\nexport const selectStudentsByClass = createSelector(selectTeacherClassState, (state) => state.students);\r\nexport const selectorGetSelectedBookTab = createSelector(selectTeacherClassState, (state) => state.selectedBookTab);\r\n\r\nexport const selectGetBookCollection = createSelector(selectTeacherClassState, (state) => state.bookCollection);\r\nexport const selectBooksInProgress = createSelector(selectTeacherClassState, (state) => state.booksInProgress);\r\nexport const selectBooksFinished = createSelector(selectTeacherClassState, (state) => state.booksFinished);\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { PlyrModule } from 'ngx-plyr3';\r\nimport { BaseModule } from '../base/base.module';\r\nimport { AudioHlsPlayerComponent } from './components/audio-hls-player/audio-hls-player.component';\r\nimport { AudioMp3PlayerComponent } from './components/audio-mp3-player/audio-mp3-player.component';\r\nimport { AudioSelectionPlayerComponent } from './components/audio-selection-player/audio-selection-player.component';\r\n\r\n@NgModule({\r\n declarations: [AudioHlsPlayerComponent, AudioMp3PlayerComponent, AudioSelectionPlayerComponent],\r\n imports: [CommonModule, BaseModule, PlyrModule],\r\n exports: [AudioHlsPlayerComponent, AudioMp3PlayerComponent, AudioSelectionPlayerComponent],\r\n})\r\nexport class AudioPlayerModule {}\r\n","
\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n\r\n","import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';\r\nimport { GoogleTagManagerService } from '@lru/felib';\r\nimport { AudioPlayerTypeEnum } from '@portal-app/enums/audio-player-type.enum';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport {\r\n IAudioPlayerMark,\r\n IAudioSelectionPlayer,\r\n IAudioSentenceButtons,\r\n ISelection,\r\n} from '@portal-app/interfaces/project/layout-audio.interface';\r\n\r\nimport { LayoutAudioService } from '@portal-app/services/shared/layout-audio.service';\r\nimport { SelectionService } from '@portal-app/services/shared/selection.service';\r\nimport { PlyrEvent } from 'plyr';\r\n\r\n@Component({\r\n selector: 'portal-audio-selection-player[src][type][marks][selections][sentenceButtons]',\r\n templateUrl: './audio-selection-player.component.html',\r\n styleUrls: ['./audio-selection-player.component.scss'],\r\n})\r\nexport class AudioSelectionPlayerComponent implements OnInit, OnChanges, OnDestroy {\r\n @Input() src!: string;\r\n @Input() type!: AudioPlayerTypeEnum;\r\n @Input() marks!: IAudioPlayerMark[];\r\n @Input() selections!: ISelection[];\r\n @Input() sentenceButtons!: IAudioSentenceButtons;\r\n @Input() autoPlay = false;\r\n @Input() highlight = false;\r\n @Input() autofocus = false;\r\n\r\n player?: Plyr;\r\n source?: Plyr.Source;\r\n loadedInterval?: NodeJS.Timeout;\r\n playingInterval?: NodeJS.Timeout;\r\n item?: IAudioSelectionPlayer;\r\n loaded = false;\r\n\r\n options: Plyr.Options = {\r\n autoplay: false,\r\n invertTime: false,\r\n disableContextMenu: true,\r\n settings: ['quality', 'speed', 'loop'],\r\n controls: ['play'],\r\n };\r\n\r\n constructor(\r\n public layoutAudioService: LayoutAudioService,\r\n private selectionService: SelectionService,\r\n private gtmService: GoogleTagManagerService,\r\n private elementRef: ElementRef\r\n ) {}\r\n\r\n ngOnInit() {\r\n if (this.src) {\r\n this.source = {\r\n src: this.src,\r\n type: 'audio/mp3',\r\n };\r\n } else {\r\n this.source = undefined;\r\n }\r\n this.item = {\r\n Type: this.type,\r\n Marks: this.marks ? this.marks : [],\r\n Selections: this.selections,\r\n AutoPlay: this.autoPlay,\r\n Highlight: this.highlight,\r\n SentenceButtons: this.sentenceButtons,\r\n };\r\n }\r\n\r\n ngOnChanges() {\r\n if (this.item) {\r\n this.item = {\r\n Type: this.type,\r\n Marks: this.marks ?? [],\r\n Selections: this.selections,\r\n AutoPlay: this.autoPlay,\r\n Highlight: this.highlight,\r\n SentenceButtons: this.sentenceButtons,\r\n };\r\n }\r\n if (this.item) {\r\n if (this.item.Type === AudioPlayerTypeEnum.Full || this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.item.Selections?.forEach((selection) => {\r\n if (this.item) {\r\n this.selectionService.resetSelection(selection.Target, this.item.Type);\r\n }\r\n });\r\n }\r\n if (this.item.Highlight || this.item.AutoPlay) {\r\n this.prepare();\r\n }\r\n }\r\n }\r\n\r\n async ngOnDestroy() {\r\n this.clearIntervals();\r\n if (this.item) {\r\n if (this.item.Type === AudioPlayerTypeEnum.Full || this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.item.Selections?.forEach((selection) => {\r\n if (this.item) {\r\n this.selectionService.resetSelection(selection.Target, this.item.Type);\r\n }\r\n });\r\n }\r\n if (this.player) {\r\n await this.layoutAudioService.removePlayer(this.player, this.src);\r\n }\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.layoutAudioService.resetFull();\r\n }\r\n if (\r\n this.item.Type === AudioPlayerTypeEnum.PartialDesktop ||\r\n this.item.Type === AudioPlayerTypeEnum.PartialTouch\r\n ) {\r\n await this.layoutAudioService.togglePartialDestroyed(true);\r\n }\r\n }\r\n }\r\n\r\n clearIntervals() {\r\n if (this.playingInterval) {\r\n clearInterval(this.playingInterval);\r\n }\r\n if (this.loadedInterval) {\r\n clearInterval(this.loadedInterval);\r\n }\r\n }\r\n\r\n plyrInit(event: Plyr) {\r\n this.loadedInterval = setInterval(async () => {\r\n if (event.duration) {\r\n if (this.loadedInterval) {\r\n clearInterval(this.loadedInterval);\r\n }\r\n this.loaded = true;\r\n this.player = event;\r\n\r\n await this.layoutAudioService.addPlayer(this.player, this.src);\r\n if (this.item) {\r\n if (this.item.Highlight || this.item.AutoPlay) {\r\n this.prepare();\r\n } else if (this.item.Marks) {\r\n this.setSentenceButtonsEnabled(this.item.Marks, this.player.currentTime);\r\n }\r\n\r\n if (this.autofocus) {\r\n const element = this.elementRef.nativeElement.firstChild as HTMLElement | undefined;\r\n if (element) {\r\n element.focus();\r\n }\r\n }\r\n }\r\n }\r\n }, 100);\r\n }\r\n\r\n async plyrPlay(event: PlyrEvent) {\r\n await this.layoutAudioService.pauseOtherPlayers(this.src);\r\n\r\n if (this.item) {\r\n this.playingInterval = setInterval(() => {\r\n this.prepare();\r\n }, 100);\r\n\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Play_full);\r\n } else if (this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Play_selected);\r\n }\r\n }\r\n\r\n this.layoutAudioService.handlePlyrEvents(event);\r\n }\r\n\r\n setSentenceButtonsEnabled(marks: IAudioPlayerMark[], currentTime: number) {\r\n if (this.item) {\r\n const previous = marks\r\n .map((item) => {\r\n return parseInt(item.Sentence.time, 10) / 1000;\r\n })\r\n .filter((item) => item < currentTime);\r\n const next = marks\r\n .map((item) => {\r\n return parseInt(item.Sentence.time, 10) / 1000;\r\n })\r\n .find((item) => item > currentTime);\r\n\r\n this.item.SentenceButtons = {\r\n PreviousEnabled: previous.length ? true : false,\r\n NextEnabled: next ? true : false,\r\n };\r\n }\r\n }\r\n\r\n prepare() {\r\n if (this.item && this.player) {\r\n const currentTime = Math.round((this.player?.currentTime || 0) * 1000);\r\n if (\r\n this.item.AutoPlay &&\r\n !this.player.playing &&\r\n (this.item.Type === AudioPlayerTypeEnum.Full || this.item.Type === AudioPlayerTypeEnum.PartialDesktop)\r\n ) {\r\n this.item.AutoPlay = false;\r\n this.player.play();\r\n }\r\n if (this.item.Marks) {\r\n this.setSentenceButtonsEnabled(this.item.Marks, this.player.currentTime);\r\n if (this.item.Type === AudioPlayerTypeEnum.Full || this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.selectionService.highlightWord(\r\n this.item.Marks,\r\n currentTime,\r\n this.player.playing,\r\n this.item.Type,\r\n this.item.Selections\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n plyrPause(event: PlyrEvent) {\r\n this.clearIntervals();\r\n if (this.item && (this.item.Highlight || this.item.AutoPlay)) {\r\n this.prepare();\r\n\r\n if (event.detail.plyr.duration !== 0 && event.detail.plyr.duration !== event.detail.plyr.currentTime) {\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Pause_full);\r\n } else if (this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Pause_selected);\r\n }\r\n } else {\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Ended_full);\r\n } else if (this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Ended_selected);\r\n }\r\n }\r\n }\r\n\r\n this.layoutAudioService.handlePlyrEvents(event);\r\n }\r\n\r\n plyrEnded(event: PlyrEvent) {\r\n this.clearIntervals();\r\n if (this.item && this.player) {\r\n this.player.currentTime = 0;\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.item.Selections?.forEach((selection) => {\r\n if (this.item) {\r\n this.selectionService.resetSelection(selection.Target, this.item.Type);\r\n }\r\n });\r\n if (this.item.Marks) {\r\n this.setSentenceButtonsEnabled(this.item.Marks, this.player.currentTime);\r\n }\r\n } else {\r\n this.prepare();\r\n }\r\n }\r\n }\r\n\r\n onClickPreviousMark() {\r\n if (this.item && this.player && this.item?.Marks) {\r\n const found = this.item.Marks.map((item) => {\r\n return parseInt(item.Sentence.time, 10) / 1000;\r\n }).filter((item) => item < (this.player?.currentTime || 0));\r\n if (found.length) {\r\n this.player.currentTime = found[found.length - 1];\r\n if (this.player.playing && found.length > 1) {\r\n // this ensures that it jumps to previous sentence instead of just restarting the same sentence every time \"previous\" button is pressed while playing.\r\n this.player.currentTime = found[found.length - 2];\r\n } else {\r\n this.player.currentTime = found[found.length - 1];\r\n }\r\n const currentTime = Math.round(this.player.currentTime * 1000);\r\n this.selectionService.highlightWord(\r\n this.item.Marks,\r\n currentTime,\r\n this.player.playing,\r\n this.item.Type,\r\n this.item.Selections\r\n );\r\n }\r\n this.setSentenceButtonsEnabled(this.item.Marks, this.player.currentTime);\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Backwards_full);\r\n } else if (this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Backwards_selected);\r\n }\r\n }\r\n }\r\n\r\n onClickNextMark() {\r\n if (this.item && this.player && this.item?.Marks) {\r\n const found = this.item.Marks.map((item) => {\r\n return parseInt(item.Sentence.time, 10) / 1000;\r\n }).find((item) => item > (this.player?.currentTime || 0));\r\n if (found !== undefined) {\r\n this.player.currentTime = found;\r\n let increase = 0;\r\n while (this.player.currentTime < found) {\r\n increase += 0.0001;\r\n this.player.currentTime = this.player.currentTime + increase;\r\n }\r\n const currentTime = Math.round(this.player.currentTime * 1000);\r\n this.selectionService.highlightWord(\r\n this.item.Marks,\r\n currentTime,\r\n this.player.playing,\r\n this.item.Type,\r\n this.item.Selections\r\n );\r\n }\r\n this.setSentenceButtonsEnabled(this.item.Marks, this.player.currentTime);\r\n if (this.item.Type === AudioPlayerTypeEnum.Full) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Forward_full);\r\n } else if (this.item.Type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Forward_selected);\r\n }\r\n }\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu';\r\nimport { RouterModule } from '@angular/router';\r\nimport { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';\r\nimport { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core';\r\nimport { MissingTranslationHelper } from '@portal-app/helpers/missing-translation.helper';\r\nimport { SharedPipeModule } from '@portal-app/pipes/shared/shared-pipe.module';\r\nimport { InlineSVGModule } from 'ng-inline-svg-2';\r\nimport { LazyLoadImageModule } from 'ng-lazyload-image';\r\nimport { BookDifficultiesComponent } from './components/book-difficulties/book-difficulties.component';\r\nimport { BookTileComponent } from './components/book-tile/book-tile.component';\r\nimport { BreadcrumbsComponent } from './components/breadcrumbs/breadcrumbs.component';\r\nimport { CheckboxComponent } from './components/checkbox/checkbox.component';\r\nimport { DropdownComponent } from './components/dropdown/dropdown.component';\r\nimport { FavoriteComponent } from './components/favorite/favorite.component';\r\nimport { LibraryActiveFiltersComponent } from './components/library-active-filters/library-active-filters.component';\r\nimport { ManageBookCollectionComponent } from './components/manage-book-collection/manage-book-collection.component';\r\nimport { SelectImpressionsModalComponent } from './components/select-impressions-modal/select-impressions-modal.component';\r\nimport { ToggleComponent } from './components/toggle/toggle.component';\r\n\r\n@NgModule({\r\n declarations: [\r\n FavoriteComponent,\r\n BreadcrumbsComponent,\r\n LibraryActiveFiltersComponent,\r\n BookTileComponent,\r\n SelectImpressionsModalComponent,\r\n CheckboxComponent,\r\n ToggleComponent,\r\n BookDifficultiesComponent,\r\n ManageBookCollectionComponent,\r\n DropdownComponent,\r\n ],\r\n imports: [\r\n CommonModule,\r\n RouterModule,\r\n SharedPipeModule,\r\n LazyLoadImageModule,\r\n InlineSVGModule.forRoot({ baseUrl: '/assets/svg/' }),\r\n FormsModule,\r\n ReactiveFormsModule,\r\n MatMenuModule,\r\n TranslateModule.forChild(),\r\n ],\r\n exports: [\r\n SharedPipeModule,\r\n RouterModule,\r\n LazyLoadImageModule,\r\n InlineSVGModule,\r\n FavoriteComponent,\r\n NgbPaginationModule,\r\n BreadcrumbsComponent,\r\n MatMenuModule,\r\n LibraryActiveFiltersComponent,\r\n BookTileComponent,\r\n CheckboxComponent,\r\n ToggleComponent,\r\n BookDifficultiesComponent,\r\n ManageBookCollectionComponent,\r\n DropdownComponent,\r\n TranslateModule,\r\n ],\r\n providers: [\r\n { provide: Window, useValue: window },\r\n {\r\n provide: MissingTranslationHandler,\r\n useClass: MissingTranslationHelper,\r\n },\r\n ],\r\n})\r\nexport class BaseModule {}\r\n","
\r\n \r\n
\r\n \r\n {{ item.Value }}\r\n
\r\n
·
\r\n
\r\n
\r\n","import { Component, Input } from '@angular/core';\r\nimport { IBookTag } from '@portal-app/interfaces/book/project/book.interface';\r\n\r\n@Component({\r\n selector: 'portal-book-difficulties[items]',\r\n templateUrl: './book-difficulties.component.html',\r\n styleUrls: ['./book-difficulties.component.scss'],\r\n})\r\nexport class BookDifficultiesComponent {\r\n @Input() items!: IBookTag[];\r\n}\r\n","\r\n

{{ 'SelectImpressionsModal.WhatDoYouThink' | translate }}

\r\n
\r\n

{{ 'SelectImpressionsModal.ChooseMax' | translate }} {{ total }}

\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n","import { Component, Inject, OnInit } from '@angular/core';\r\nimport {\r\n MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,\r\n MatLegacyDialogRef as MatDialogRef,\r\n} from '@angular/material/legacy-dialog';\r\nimport { Router } from '@angular/router';\r\nimport { GoogleTagManagerService } from '@lru/felib';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { IBookSelectedImpression } from '@portal-app/interfaces/book/project/book-impression.interface';\r\nimport { INextImpressionTag } from '@portal-app/interfaces/next/next-tag.interface';\r\nimport { IBookTile_template } from '@portal-app/interfaces/project/section.interface';\r\nimport { BookImpressionMapper } from '@portal-app/mapper/book/book-impression.mapper';\r\nimport { BookImpressionService } from '@portal-app/services/book/book-impression.service';\r\n\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { take } from 'rxjs/operators';\r\n\r\n@Component({\r\n templateUrl: './select-impressions-modal.component.html',\r\n styleUrls: ['./select-impressions-modal.component.scss'],\r\n})\r\nexport class SelectImpressionsModalComponent implements OnInit {\r\n item: IBookTile_template;\r\n impressions?: IBookSelectedImpression[];\r\n total = 3;\r\n remaining?: number;\r\n\r\n constructor(\r\n @Inject(MAT_DIALOG_DATA) public data: IBookTile_template,\r\n private dialogRef: MatDialogRef,\r\n private router: Router,\r\n private bookImpressionService: BookImpressionService,\r\n private bookImpressionMapper: BookImpressionMapper,\r\n private gtmService: GoogleTagManagerService\r\n ) {\r\n this.item = this.data;\r\n }\r\n\r\n async ngOnInit() {\r\n this.router.events.pipe(take(1)).subscribe(() => {\r\n this.dialogRef.close();\r\n });\r\n\r\n const impressions = await firstValueFrom(this.bookImpressionService.getImpressions());\r\n\r\n if (this.item.Id) {\r\n const observable = this.bookImpressionService.fetchAndUpdate(this.item.Id);\r\n let selected: INextImpressionTag[] | undefined;\r\n\r\n if (observable) {\r\n selected = await firstValueFrom(observable);\r\n this.impressions = this.bookImpressionMapper.mapSelectImpressionsFromApi(impressions, selected);\r\n }\r\n }\r\n\r\n this.setRemaining();\r\n }\r\n\r\n setRemaining() {\r\n if (this.impressions?.length) {\r\n this.remaining = this.total - this.impressions.filter((element) => element.Selected).length;\r\n }\r\n }\r\n\r\n async checkImpression(event: Event, impression: IBookSelectedImpression) {\r\n const target = event.target as HTMLInputElement;\r\n\r\n if (target.checked === true) {\r\n if (this.remaining && this.item.Id) {\r\n impression.Selected = true;\r\n await firstValueFrom(this.bookImpressionService.addSelectedImpressions(this.item.Id, impression.Slug || ''));\r\n\r\n this.gtmService.pushTagWithUserType(GTMEvent.Overview_readbook_recommendation_tag, {\r\n book: this.item.Title,\r\n tag: impression.Title,\r\n });\r\n } else {\r\n target.checked = false;\r\n impression.Selected = false;\r\n }\r\n } else if (this.item.Id) {\r\n impression.Selected = false;\r\n await firstValueFrom(this.bookImpressionService.removeSelectedImpressions(this.item.Id, impression.Slug || ''));\r\n this.gtmService.pushTagWithUserType(GTMEvent.Overview_readbook_recommendation_tag_remove, {\r\n book: this.item.Title,\r\n tag: impression.Title,\r\n });\r\n }\r\n this.setRemaining();\r\n }\r\n\r\n closeModal() {\r\n this.dialogRef.close();\r\n }\r\n}\r\n","\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n
\r\n
\r\n\r\n\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n \r\n
\r\n
{{ item.Title }}
\r\n
\r\n
\r\n \r\n \r\n
\r\n \r\n
{{ item.Title }}
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n {{ friend }}\r\n
\r\n
\r\n
\r\n
{{ 'BookTile.IThink' | translate }}
\r\n
\r\n {{ impression.Icon }}\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n\r\n
\r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n
    \r\n
  • \r\n {{ 'BookTile.WhatDoYouThink' | translate }}\r\n
  • \r\n
  • \r\n {{ 'BookTile.Remove' | translate }}\r\n
  • \r\n
\r\n
\r\n
\r\n
\r\n
\r\n","import { Component, Input, OnInit } from '@angular/core';\r\nimport { MatLegacyDialogConfig as MatDialogConfig } from '@angular/material/legacy-dialog';\r\nimport { GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport { IBookTile_template } from '@portal-app/interfaces/project/section.interface';\r\nimport { BookContinueService } from '@portal-app/services/book/book-continue.service';\r\nimport { BookFinishedService } from '@portal-app/services/book/book-finished.service';\r\nimport { ExtendedDialogService } from '@portal-app/services/shared/extended-dialog.service';\r\n\r\nimport { ISliderSettings } from '@portal-app/modules/shared/slider/interfaces/slider-settings.interface';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { PageTypeEnum } from '../../../../../enums/page-type.enum';\r\nimport { SelectImpressionsModalComponent } from '../select-impressions-modal/select-impressions-modal.component';\r\n\r\n@Component({\r\n selector: 'portal-book-tile[item][settings][type]',\r\n templateUrl: './book-tile.component.html',\r\n styleUrls: ['./book-tile.component.scss'],\r\n})\r\nexport class BookTileComponent implements OnInit {\r\n @Input() item?: IBookTile_template;\r\n @Input() showProgressbar = false;\r\n @Input() settings?: ISliderSettings;\r\n @Input() type?: SectionTypeEnum;\r\n user = this.userService.isLoggedIn;\r\n isBookFinished = false;\r\n\r\n constructor(\r\n private bookFinishedService: BookFinishedService,\r\n private dialog: ExtendedDialogService,\r\n private bookContinueService: BookContinueService,\r\n private userService: UserService,\r\n private gtmService: GoogleTagManagerService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.isBookFinished = this.item?.Progress === 100;\r\n }\r\n\r\n /**\r\n * Remove a book from either the continue list or the finish book list\r\n */\r\n async removeFromList() {\r\n if (this.item?.Id) {\r\n if (this.settings?.Type === SectionTypeEnum.BookContinue) {\r\n await firstValueFrom(this.bookContinueService.setBookContinue(this.item.Id, '', 0));\r\n this.gtmService.pushTagWithUserType(GTMEvent.Overview_continuebook_remove, { book: this.item.Title });\r\n } else {\r\n await firstValueFrom(this.bookFinishedService.setBookFinished(this.item.Id, false));\r\n }\r\n\r\n if (this.settings?.Type === SectionTypeEnum.FinishedBooks) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Overview_readbook_remove, {\r\n book: this.item.Title,\r\n });\r\n }\r\n }\r\n }\r\n\r\n onImpressionsClick() {\r\n const dialogConfig = new MatDialogConfig();\r\n dialogConfig.disableClose = false;\r\n dialogConfig.autoFocus = true;\r\n dialogConfig.restoreFocus = true;\r\n dialogConfig.data = this.item;\r\n this.dialog.open(SelectImpressionsModalComponent, dialogConfig);\r\n }\r\n\r\n get SectionTypeEnum() {\r\n return SectionTypeEnum;\r\n }\r\n\r\n get ContentTypeEnum() {\r\n return ContentTypeEnum;\r\n }\r\n\r\n menuOpened() {\r\n document.documentElement.classList.add('cdk-dropdown');\r\n }\r\n\r\n menuClosed() {\r\n document.documentElement.classList.remove('cdk-dropdown');\r\n }\r\n\r\n onTileClick() {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Open_book, {\r\n book: this.item?.Title,\r\n type: this.type,\r\n });\r\n }\r\n\r\n get PageTypeEnum() {\r\n return PageTypeEnum;\r\n }\r\n}\r\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'portal-checkbox[checked]',\r\n templateUrl: './checkbox.component.html',\r\n styleUrls: ['./checkbox.component.scss'],\r\n})\r\nexport class CheckboxComponent {\r\n @Input() checked!: boolean;\r\n @Output() changed = new EventEmitter();\r\n\r\n onChange(value: boolean) {\r\n this.changed.emit(value);\r\n }\r\n}\r\n","\r\n","\r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n\r\n","import { Component, Input, OnInit } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { take } from 'rxjs/operators';\r\nimport { PageTypeEnum } from '../../../../../enums/page-type.enum';\r\nimport { IDropdown } from '../../../../../interfaces/project/dropdown.interface';\r\nimport { BookLibraryService } from '../../../../../services/book/book-library.service';\r\nimport { CourseLibraryService } from '../../../../../services/course/course-library.service';\r\nimport { AppInitService } from '../../../../../services/shared/app-init.service';\r\nimport { BreakpointsService } from '../../../../../services/shared/breakpoints.service';\r\nimport { DropdownService } from '../../../../../services/shared/dropdown.service';\r\n\r\n@Component({\r\n selector: 'portal-dropdown[ariaLabel]',\r\n templateUrl: './dropdown.component.html',\r\n styleUrls: ['./dropdown.component.scss'],\r\n})\r\nexport class DropdownComponent implements OnInit {\r\n @Input() id: string = this.generateUUID();\r\n @Input() darkOverlay = false;\r\n @Input() zIndex!: number;\r\n @Input() buttonClasses!: string;\r\n @Input() contentClasses!: string;\r\n @Input() pageType!: string;\r\n @Input() libraryUrl!: string;\r\n @Input() useArrow = false;\r\n @Input() iconSize = 10;\r\n @Input() ariaLabel!: string;\r\n @Input() useCustomAriaLabel = false;\r\n dropdownOpen?: IDropdown;\r\n large = false;\r\n\r\n constructor(\r\n private dropdownService: DropdownService,\r\n private breakpointsService: BreakpointsService,\r\n private router: Router,\r\n private appInitService: AppInitService,\r\n private courseLibraryService: CourseLibraryService,\r\n private bookLibraryService: BookLibraryService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.dropdownService.open$.subscribe((value) => {\r\n this.dropdownOpen = value;\r\n });\r\n\r\n this.breakpointsService.large$.subscribe((data) => {\r\n if (data && this.dropdownOpen?.Id === 'search') {\r\n this.dropdownService.closeDropdown();\r\n }\r\n this.large = data;\r\n });\r\n }\r\n\r\n onToggleDropdown() {\r\n if (this.id === 'search') {\r\n this.breakpointsService.large$.pipe(take(1)).subscribe((data) => {\r\n if (data) {\r\n if (this.pageType !== PageTypeEnum.CourseLibrary && this.pageType !== PageTypeEnum.BookLibrary) {\r\n this.router.navigate([this.libraryUrl]);\r\n } else {\r\n // set focus on searchInput\r\n }\r\n }\r\n });\r\n this.breakpointsService.underLarge$.pipe(take(1)).subscribe((data) => {\r\n if (data) {\r\n if (this.pageType !== PageTypeEnum.CourseLibrary && this.appInitService.isFagportal) {\r\n this.displaySearchOnFagportal();\r\n } else if (\r\n (this.appInitService.isSuperbog || this.appInitService.isSuperreader) &&\r\n this.pageType !== PageTypeEnum.BookLibrary\r\n ) {\r\n this.displaySearchOnBoodAndReader();\r\n }\r\n }\r\n });\r\n } else {\r\n // Remove search field modal\r\n this.dropdownService.toggleDropdown(this.id, this.darkOverlay);\r\n }\r\n }\r\n\r\n /**\r\n * On Superbog and Superreader we display the search input field as an modal, unless the user is on the library page\r\n */\r\n private displaySearchOnBoodAndReader() {\r\n if (!this.bookLibraryService.filters.FiltersLoaded) {\r\n this.bookLibraryService.initializeFilters();\r\n }\r\n\r\n if (this.libraryUrl !== window.location.pathname) {\r\n this.displaySearchField();\r\n }\r\n }\r\n\r\n /**\r\n * On Fagportal we don't have the search input field on the library page on small devices.\r\n * We display the search input field as an modal when ever the search icon in the header is clicked.\r\n */\r\n private displaySearchOnFagportal() {\r\n if (!this.courseLibraryService.filters.FiltersLoaded) {\r\n this.courseLibraryService.initializeFilters();\r\n }\r\n this.displaySearchField();\r\n }\r\n\r\n /**\r\n * Displaying the search input field after the loader is finish\r\n */\r\n private displaySearchField() {\r\n this.dropdownService.toggleDropdown(this.id, this.darkOverlay, this.zIndex);\r\n }\r\n\r\n generateUUID() {\r\n let d = new Date().getTime(); // Timestamp\r\n let d2 = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0; // Time in microseconds since page-load or 0 if unsupported\r\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\r\n let r = Math.random() * 16; // random number between 0 and 16\r\n if (d > 0) {\r\n // Use timestamp until depleted\r\n r = (d + r) % 16 | 0;\r\n d = Math.floor(d / 16);\r\n } else {\r\n // Use microseconds since page-load if supported\r\n r = (d2 + r) % 16 | 0;\r\n d2 = Math.floor(d2 / 16);\r\n }\r\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\r\n });\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService } from '@lru/felib';\r\nimport { IUmbFavoritePayload, IUmbFavoriteResponse } from '@portal-app/interfaces/umbraco/umb-favorite.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PsFavoriteService {\r\n constructor(private apiService: ApiService) {}\r\n\r\n addFavorite(id: string) {\r\n const body: IUmbFavoritePayload = {\r\n contentId: id,\r\n isFavorite: true,\r\n };\r\n return this.apiService.postUmbraco('psportal/content/favourite/save', body);\r\n }\r\n\r\n deleteFavorite(contentId: string) {\r\n return this.apiService.deleteUmbraco('psportal/content/favourite/remove/' + contentId);\r\n }\r\n}\r\n","\r\n \r\n \r\n \r\n\r\n","import { Component, Inject, Injector, Input } from '@angular/core';\r\nimport { GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { Store } from '@ngrx/store';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport {\r\n ToggleBookCollectionFavouriteAction,\r\n ToggleBookContinueFavouriteAction,\r\n ToggleBookFinishedFavouriteAction,\r\n} from '@portal-app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.actions';\r\nimport { ITeacherDashboardState } from '@portal-app/modules/routes/book-teacher-dashboard/store/teacher-dashboard.reducer';\r\nimport { ActivityFavoriteService } from '@portal-app/services/activity/activity-favorite.service';\r\nimport { BookFavoriteService } from '@portal-app/services/book/book-favorite.service';\r\nimport { CourseFavoriteApiService } from '@portal-app/services/course/course-favorite-api.service';\r\nimport { PsFavoriteService } from '@portal-app/services/ps/ps-favorite.service';\r\n\r\nimport { IndividualConfig, ToastrService } from 'ngx-toastr';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { BookCollectionFavoriteService } from '../../../../../services/book/book-collection-favorite.service';\r\nimport { PSLibraryService } from '../../../../../services/ps/ps-library.service';\r\n\r\n@Component({\r\n selector: 'portal-favorite[isFavorite][type][id]',\r\n templateUrl: './favorite.component.html',\r\n styleUrls: ['./favorite.component.scss'],\r\n})\r\nexport class FavoriteComponent {\r\n @Input() isFavorite?: boolean;\r\n @Input() type?: string;\r\n @Input() id?: string;\r\n @Input() fill = false;\r\n @Input() title?: string;\r\n @Input() subType?: SectionTypeEnum;\r\n @Input() className?: string;\r\n\r\n private apiLocked = false;\r\n private toastrOptions: Partial = {\r\n toastClass: 'ngx-toastr favorite',\r\n };\r\n\r\n constructor(\r\n public userService: UserService,\r\n private courseFavoriteApiService: CourseFavoriteApiService,\r\n @Inject(Injector) private readonly injector: Injector,\r\n private bookFavoriteService: BookFavoriteService,\r\n private bookCollectionFavoriteService: BookCollectionFavoriteService,\r\n private psFavoriteService: PsFavoriteService,\r\n private store: Store,\r\n private translate: TranslateService,\r\n private psLibraryService: PSLibraryService,\r\n private activityFavoriteService: ActivityFavoriteService,\r\n private gtmService: GoogleTagManagerService\r\n ) {}\r\n\r\n private get toastr() {\r\n return this.injector.get(ToastrService);\r\n }\r\n\r\n async onFavoriteClick() {\r\n if (this.userService.isLoggedIn && !this.apiLocked) {\r\n this.apiLocked = true;\r\n\r\n this.gtmService.pushTagWithUserType(this.isFavorite ? GTMEvent.Favourite_remove : GTMEvent.Favourite_set, {\r\n id: this.id,\r\n title: this.title,\r\n type: this.type,\r\n subType: this.subType,\r\n favorite: !this.isFavorite,\r\n });\r\n\r\n switch (this.type) {\r\n case ContentTypeEnum.Texts:\r\n this.isFavorite ? await this.removeTextFavourite() : await this.addTextFavourite();\r\n break;\r\n case ContentTypeEnum.Assignments:\r\n this.isFavorite ? await this.removeTaskFavourite() : await this.addTaskFavourite();\r\n break;\r\n case ContentTypeEnum.Courses:\r\n this.isFavorite ? await this.removeCourseFavourite() : await this.addCourseFavourite();\r\n break;\r\n case ContentTypeEnum.Books:\r\n this.isFavorite ? await this.unmarkBookAsFavourite() : await this.markBookAsFavourite();\r\n break;\r\n case ContentTypeEnum.Collections:\r\n this.isFavorite ? await this.unmarkCollectionAsFavourite() : await this.markCollectionAsFavourite();\r\n break;\r\n\r\n case ContentTypeEnum.Activities:\r\n this.isFavorite ? await this.unmarkActivityAsFavourite() : await this.markActivityAsFavourite();\r\n break;\r\n\r\n case ContentTypeEnum.PsArticles:\r\n case ContentTypeEnum.PsAssignments:\r\n this.isFavorite ? await this.psDeleteFavourite() : await this.psAddFavourite();\r\n }\r\n }\r\n }\r\n\r\n private async markActivityAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.activityFavoriteService.markFavorite(this.id));\r\n\r\n this.setFavoriteAndUnlockApi();\r\n this.toastAdd('ContentType.TheActivity');\r\n }\r\n\r\n private async unmarkActivityAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.activityFavoriteService.removeFavorite(this.id));\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private async addTextFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.addTextFavorite(this.id));\r\n\r\n this.setFavoriteAndUnlockApi();\r\n this.toastAdd('ContentType.TheText');\r\n }\r\n\r\n private async removeTextFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.removeTextFavorite(this.id));\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private async removeTaskFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.removeTaskFavorite(this.id));\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private async addTaskFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.addTaskFavorite(this.id));\r\n\r\n this.setFavoriteAndUnlockApi();\r\n this.toastAdd('ContentType.TheTask');\r\n }\r\n\r\n private async removeCourseFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.removeCourseFavorite(this.id));\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private async addCourseFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.courseFavoriteApiService.addCourseFavorite(this.id));\r\n\r\n this.setFavoriteAndUnlockApi();\r\n this.toastAdd('ContentType.TheCourse');\r\n }\r\n\r\n private async psAddFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.psFavoriteService.addFavorite(this.id));\r\n this.isFavorite = !this.isFavorite;\r\n await this.psLibraryService.setTotalFavoritesCount(this.id);\r\n\r\n this.apiLocked = false;\r\n let name: string;\r\n if (this.type === ContentTypeEnum.PsArticles) {\r\n name = this.translate.instant('ContentType.TheArticle');\r\n } else {\r\n name = this.translate.instant('ContentType.TheAssignment');\r\n }\r\n\r\n this.toastAdd(name);\r\n }\r\n\r\n private async psDeleteFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.psFavoriteService.deleteFavorite(this.id));\r\n this.isFavorite = !this.isFavorite;\r\n await this.psLibraryService.setTotalFavoritesCount(this.id);\r\n this.apiLocked = false;\r\n }\r\n\r\n private async markBookAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.bookFavoriteService.addBookToFavorites(this.id));\r\n if (this.subType && this.subType === SectionTypeEnum.FinishedBooks) {\r\n this.store.dispatch(\r\n ToggleBookFinishedFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n } else if (this.subType && this.subType === SectionTypeEnum.BookContinue) {\r\n this.store.dispatch(\r\n ToggleBookContinueFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n }\r\n\r\n this.setFavoriteAndUnlockApi();\r\n\r\n this.toastAdd('ContentType.TheBook');\r\n }\r\n\r\n private async unmarkBookAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.bookFavoriteService.deleteBookFromFavorites(this.id));\r\n\r\n if (this.subType && this.subType === SectionTypeEnum.FinishedBooks) {\r\n this.store.dispatch(\r\n ToggleBookFinishedFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n } else if (this.subType && this.subType === SectionTypeEnum.BookContinue) {\r\n this.store.dispatch(\r\n ToggleBookContinueFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n }\r\n\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private async markCollectionAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.bookCollectionFavoriteService.addCollectionToFavorites(this.id));\r\n this.store.dispatch(\r\n ToggleBookCollectionFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n\r\n this.setFavoriteAndUnlockApi();\r\n\r\n this.toastAdd('ContentType.TheBookCollection');\r\n }\r\n\r\n private async unmarkCollectionAsFavourite() {\r\n if (!this.id) {\r\n return;\r\n }\r\n\r\n await firstValueFrom(this.bookCollectionFavoriteService.deleteCollectionFromFavorites(this.id));\r\n this.store.dispatch(\r\n ToggleBookCollectionFavouriteAction({\r\n data: !this.isFavorite,\r\n id: this.id,\r\n })\r\n );\r\n\r\n this.setFavoriteAndUnlockApi();\r\n }\r\n\r\n private setFavoriteAndUnlockApi() {\r\n this.isFavorite = !this.isFavorite;\r\n this.apiLocked = false;\r\n }\r\n\r\n private toastAdd(translationKey: string) {\r\n this.toastr.info(\r\n this.translate.instant('Label.BlankAddedToFavorites', {\r\n name: this.translate.instant(translationKey),\r\n }),\r\n '',\r\n this.toastrOptions\r\n );\r\n }\r\n}\r\n","
\r\n \r\n \r\n \r\n \r\n
    \r\n
  • \r\n

    {{ headerText }}

    \r\n
  • \r\n \r\n \r\n {{ 'ManageBookCollection.CreateNewBookbox' | translate }}\r\n \r\n \r\n \r\n {{ collection.Title }}\r\n \r\n \r\n
\r\n
\r\n
\r\n","import { Component, Input } from '@angular/core';\r\nimport { GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\n\r\nimport { ToastrService } from 'ngx-toastr';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { PageTypeEnum } from '../../../../../enums/page-type.enum';\r\nimport { ISelectable } from '../../../../../interfaces/project/section.interface';\r\nimport { BookCollectionService } from '../../../../../services/book/book-collection.service';\r\n\r\n@Component({\r\n selector: 'portal-manage-book-collection[id][title]',\r\n templateUrl: './manage-book-collection.component.html',\r\n styleUrls: ['./manage-book-collection.component.scss'],\r\n})\r\nexport class ManageBookCollectionComponent {\r\n @Input() id!: string;\r\n @Input() title!: string;\r\n @Input() headerText?: string;\r\n\r\n isTeacher: boolean = this.userService.isTeacher;\r\n collections?: ISelectable[];\r\n\r\n constructor(\r\n private userService: UserService,\r\n private bookCollectionService: BookCollectionService,\r\n private toastrService: ToastrService,\r\n private gtmService: GoogleTagManagerService,\r\n private translateService: TranslateService\r\n ) {}\r\n\r\n menuOpened() {\r\n document.documentElement.classList.add('cdk-dropdown');\r\n }\r\n\r\n menuClosed() {\r\n document.documentElement.classList.remove('cdk-dropdown');\r\n }\r\n\r\n /**\r\n * Gets data for all collections and their books and sets up a map of which collections contain the current book.\r\n */\r\n initializeBookCollections() {\r\n if (this.collections?.length) {\r\n return;\r\n }\r\n this.bookCollectionService.getBookTileAvailableCollections().subscribe((collections) => {\r\n this.collections = collections.map((item) => {\r\n return {\r\n Slug: item.Id,\r\n Title: item.Title,\r\n Selected: false,\r\n };\r\n });\r\n this.collections.forEach((collection) => {\r\n this.fetchCollectionStatus(collection);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Fetches data for the given collection, optionally clearing the cache and fetching new data from the server.\r\n * When a collection is fetched, the local variable determining wether the book is present in the collection is updated.\r\n */\r\n fetchCollectionStatus(item: ISelectable) {\r\n this.bookCollectionService.getBooksInCollection(item.Slug).subscribe((books) => {\r\n if (books.find((elem) => elem.Id === this.id)) {\r\n item.Selected = true;\r\n }\r\n });\r\n }\r\n\r\n async onAddToCollectionClick(collection: ISelectable) {\r\n await firstValueFrom(this.bookCollectionService.addBookToCollection(collection.Slug, this.id));\r\n collection.Selected = true;\r\n this.toastrService.success(\r\n this.translateService.instant('ManageBookCollection.AddedToCollection', {\r\n bookTitle: this.title,\r\n collectionTitle: collection.Title,\r\n })\r\n );\r\n this.fetchCollectionStatus(collection);\r\n\r\n this.gtmService.pushTagWithUserType(GTMEvent.Add_to_collection, {\r\n book: this.title,\r\n });\r\n }\r\n\r\n async onRemoveFromCollectionClick(collection: ISelectable) {\r\n await firstValueFrom(this.bookCollectionService.removeBookFromCollection(collection.Slug, this.id));\r\n collection.Selected = false;\r\n this.toastrService.success(\r\n this.translateService.instant('ManageBookCollection.RemoveFromCollection', {\r\n bookTitle: this.title,\r\n collectionTitle: collection.Title,\r\n })\r\n );\r\n\r\n this.fetchCollectionStatus(collection);\r\n\r\n this.gtmService.pushTagWithUserType(GTMEvent.Remove_from_collection, {\r\n book: this.title,\r\n });\r\n }\r\n\r\n onClickCreateCollection() {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Collection_create, {\r\n book: this.title,\r\n });\r\n }\r\n\r\n get PageTypeEnum() {\r\n return PageTypeEnum;\r\n }\r\n}\r\n","
\r\n \r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n","import { Component, Input } from '@angular/core';\r\nimport { IBookTile } from '@portal-app/interfaces/project/section.interface';\r\nimport { ISliderSettings } from '@portal-app/modules/shared/slider/interfaces/slider-settings.interface';\r\n\r\n@Component({\r\n selector: 'portal-book-card-preview[item][settings]',\r\n templateUrl: './book-card-preview.component.html',\r\n styleUrls: ['./book-card-preview.component.scss'],\r\n})\r\nexport class BookCardPreviewComponent {\r\n @Input() item!: IBookTile;\r\n @Input() settings!: ISliderSettings;\r\n}\r\n","
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n {{ 'ContentType.Subject' | translate }}\r\n
\r\n
\r\n {{ subject }}\r\n
\r\n
\r\n
\r\n\r\n","import { Component, Input } from '@angular/core';\r\nimport { ICourseTile } from '@portal-app/interfaces/course/project/course.interface';\r\n\r\n@Component({\r\n selector: 'portal-course-card-preview[item]',\r\n templateUrl: './course-card-preview.component.html',\r\n styleUrls: ['./course-card-preview.component.scss'],\r\n})\r\nexport class CourseCardPreviewComponent {\r\n @Input() item!: ICourseTile;\r\n}\r\n","
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
    \r\n
  • \r\n {{ item }}\r\n
  • \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
    \r\n
  • \r\n \r\n \r\n \r\n
  • \r\n
\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
    \r\n
  • \r\n \r\n \r\n \r\n
  • \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Component, HostListener, Input, OnDestroy, OnInit } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { PageTypeEnum } from '@portal-app/enums/page-type.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport { IBookLibraryFilters } from '@portal-app/interfaces/book/project/book-library.interface';\r\nimport {\r\n ICourseLibraryFilters,\r\n ISearchAutoComplete,\r\n} from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { ICourseTile } from '@portal-app/interfaces/course/project/course.interface';\r\nimport { IPsLibraryFilters } from '@portal-app/interfaces/ps/project/ps-library.interface';\r\nimport { BookLibraryMapper } from '@portal-app/mapper/book/book-library.mapper';\r\nimport { CourseLibraryMapper } from '@portal-app/mapper/course/course-library.mapper';\r\nimport { BookLibraryService } from '@portal-app/services/book/book-library.service';\r\nimport { CourseLibraryService } from '@portal-app/services/course/course-library.service';\r\nimport { PSLibraryService } from '@portal-app/services/ps/ps-library.service';\r\n\r\nimport { GoogleTagManagerService } from '@lru/felib';\r\nimport { ISliderSettings } from '@portal-app/modules/shared/slider/interfaces/slider-settings.interface';\r\nimport { EMPTY, Subject, Subscription } from 'rxjs';\r\nimport { catchError, debounceTime } from 'rxjs/operators';\r\nimport { ProjectTypeEnum } from '../../../../../enums/project-type.enum';\r\nimport { AppInitService } from '../../../../../services/shared/app-init.service';\r\nimport { DropdownService } from '../../../../../services/shared/dropdown.service';\r\n\r\n@Component({\r\n selector: 'portal-library-search[type]',\r\n templateUrl: './library-search.component.html',\r\n styleUrls: ['./library-search.component.scss'],\r\n})\r\nexport class LibrarySearchComponent implements OnInit, OnDestroy {\r\n @Input() type!: string;\r\n @Input() libraryUrl?: string;\r\n\r\n focus = false;\r\n enterActivated = false;\r\n filters?: ICourseLibraryFilters | IBookLibraryFilters | IPsLibraryFilters;\r\n filterTextChanged = new Subject();\r\n autocomplete?: ISearchAutoComplete;\r\n activeQuery = '';\r\n currentQuery = '';\r\n bookSliderSettings: ISliderSettings = {\r\n Type: SectionTypeEnum.BookList,\r\n PreviewTile: true,\r\n MaxSlidesPerView: 5,\r\n };\r\n autoCompleteSubscription?: Subscription;\r\n filtersSubscription?: Subscription;\r\n theme = this.appInitService.isPs ? 'dark' : 'light';\r\n projectType = this.appInitService.siteConfiguration.ProjectType;\r\n\r\n constructor(\r\n private courseLibraryService: CourseLibraryService,\r\n private bookLibraryService: BookLibraryService,\r\n private psLibraryService: PSLibraryService,\r\n private courseLibraryMapper: CourseLibraryMapper,\r\n private bookLibraryMapper: BookLibraryMapper,\r\n private router: Router,\r\n private dropdownService: DropdownService,\r\n private appInitService: AppInitService,\r\n private gtmService: GoogleTagManagerService\r\n ) {}\r\n\r\n ngOnDestroy() {\r\n this.filtersSubscription?.unsubscribe();\r\n this.autoCompleteSubscription?.unsubscribe();\r\n }\r\n\r\n ngOnInit() {\r\n switch (this.type) {\r\n case PageTypeEnum.BookLibrary: {\r\n this.filtersSubscription = this.bookLibraryService.data$.subscribe((data) => {\r\n this.filters = data;\r\n this.currentQuery = this.filters.Query;\r\n });\r\n break;\r\n }\r\n case PageTypeEnum.CourseLibrary: {\r\n this.filtersSubscription = this.courseLibraryService.data$.subscribe((data) => {\r\n this.filters = data;\r\n this.currentQuery = this.filters.Query;\r\n });\r\n break;\r\n }\r\n case PageTypeEnum.PsAssignmentLibrary:\r\n case PageTypeEnum.PrintbarAssignmentLibrary: {\r\n this.filtersSubscription = this.psLibraryService.data$.subscribe((data) => {\r\n this.filters = data;\r\n this.currentQuery = this.filters.Query;\r\n });\r\n break;\r\n }\r\n }\r\n\r\n this.filterTextChanged.pipe(debounceTime(500)).subscribe((filterQuery) => {\r\n if (this.enterActivated) {\r\n this.enterActivated = false;\r\n this.autocomplete = undefined;\r\n return;\r\n }\r\n if (filterQuery && filterQuery.length >= 2) {\r\n if (this.autoCompleteSubscription) {\r\n this.autoCompleteSubscription.unsubscribe();\r\n }\r\n if (this.type === PageTypeEnum.BookLibrary) {\r\n this.autoCompleteSubscription = this.bookLibraryService.postAzureAutoComplete(filterQuery).subscribe(\r\n (autocomplete) => {\r\n this.autocomplete = this.bookLibraryMapper.mapAutoCompleteFromApi(filterQuery, autocomplete);\r\n if (this.enterActivated) {\r\n this.enterActivated = false;\r\n this.autocomplete = undefined;\r\n return;\r\n }\r\n if (\r\n this.autocomplete.Suggestions.length ||\r\n this.autocomplete.Courses.length ||\r\n this.autocomplete.Books.length ||\r\n this.autocomplete.BookCollections.length\r\n ) {\r\n this.focus = true;\r\n } else {\r\n this.focus = false;\r\n }\r\n this.enterActivated = false;\r\n },\r\n (error: HttpErrorResponse) => {\r\n // hide suggestions\r\n this.autocomplete = undefined;\r\n this.focus = false;\r\n this.enterActivated = false;\r\n }\r\n );\r\n } else if (this.type === PageTypeEnum.CourseLibrary) {\r\n this.autoCompleteSubscription = this.courseLibraryService\r\n .postAzureAutoComplete(filterQuery)\r\n .pipe(\r\n catchError(() => {\r\n // hide suggestions\r\n this.autocomplete = undefined;\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((autocomplete) => {\r\n this.autocomplete = this.courseLibraryMapper.mapAutoCompleteFromApi(filterQuery, autocomplete);\r\n if (this.enterActivated) {\r\n this.enterActivated = false;\r\n this.autocomplete = undefined;\r\n return;\r\n }\r\n if (\r\n this.autocomplete.Suggestions.length ||\r\n this.autocomplete.Courses.length ||\r\n this.autocomplete.Books.length ||\r\n this.autocomplete.BookCollections.length\r\n ) {\r\n this.focus = true;\r\n } else {\r\n this.focus = false;\r\n }\r\n });\r\n }\r\n } else {\r\n // hide suggestions\r\n this.autocomplete = undefined;\r\n }\r\n });\r\n }\r\n\r\n async onKeyup(query: string, event: KeyboardEvent) {\r\n let trimmedQuery = query.trim();\r\n if (event.keyCode === 13) {\r\n this.focus = false;\r\n this.enterActivated = true;\r\n if (this.filters) {\r\n this.filters.Query = trimmedQuery;\r\n }\r\n await this.query();\r\n } else if (this.activeQuery !== trimmedQuery) {\r\n this.activeQuery = trimmedQuery;\r\n this.filterTextChanged.next(this.activeQuery);\r\n }\r\n }\r\n\r\n onFocus() {\r\n if (\r\n this.autocomplete?.Suggestions.length ||\r\n this.autocomplete?.Courses.length ||\r\n this.autocomplete?.Books.length ||\r\n this.autocomplete?.BookCollections.length\r\n ) {\r\n this.focus = true;\r\n }\r\n }\r\n\r\n onClickAutoComplete(item: ICourseTile) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Library_search_autocomplete, { title: item.Title });\r\n }\r\n\r\n clearQuery() {\r\n this.currentQuery = '';\r\n this.activeQuery = '';\r\n if (this.type === PageTypeEnum.BookLibrary) {\r\n this.bookLibraryService.clearQuery();\r\n } else if (this.type === PageTypeEnum.CourseLibrary) {\r\n this.courseLibraryService.clearQuery();\r\n }\r\n this.autocomplete = undefined;\r\n }\r\n\r\n async changeQuery(query: string) {\r\n this.currentQuery = query;\r\n await this.query();\r\n }\r\n\r\n async query() {\r\n if (this.filters) {\r\n this.filters.Query = this.currentQuery;\r\n\r\n if (this.libraryUrl === window.location.pathname || !this.libraryUrl) {\r\n this.focus = false;\r\n if (this.type === PageTypeEnum.BookLibrary) {\r\n this.bookLibraryService.query();\r\n } else if (this.type === PageTypeEnum.CourseLibrary) {\r\n this.courseLibraryService.query();\r\n } else if (\r\n this.type === PageTypeEnum.PsArticleLibrary ||\r\n this.type === PageTypeEnum.PsAssignmentLibrary ||\r\n this.type === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n await this.psLibraryService.search(this.filters.Query);\r\n }\r\n } else {\r\n this.dropdownService.closeDropdown();\r\n\r\n await this.router.navigate([this.libraryUrl]);\r\n\r\n this.focus = false;\r\n if (this.type === PageTypeEnum.BookLibrary) {\r\n this.bookLibraryService.query();\r\n } else if (this.type === PageTypeEnum.CourseLibrary) {\r\n this.courseLibraryService.query();\r\n } else if (\r\n this.filters &&\r\n (this.type === PageTypeEnum.PsArticleLibrary || this.type === PageTypeEnum.PsAssignmentLibrary)\r\n ) {\r\n await this.psLibraryService.search(this.filters.Query);\r\n }\r\n }\r\n }\r\n }\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n documentClick(target: HTMLElement) {\r\n if (!target.closest('portal-library-search')) {\r\n this.focus = false;\r\n }\r\n }\r\n @HostListener('document:keyup', ['$event'])\r\n handleKeyup(e: KeyboardEvent) {\r\n const target = e.target as HTMLElement;\r\n if (e.which === 9 && !target.closest('portal-library-search')) {\r\n this.focus = false;\r\n }\r\n }\r\n\r\n get PageTypeEnum() {\r\n return PageTypeEnum;\r\n }\r\n\r\n get ProjectTypeEnum(): typeof ProjectTypeEnum {\r\n return ProjectTypeEnum;\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { BaseModule } from '../base/base.module';\r\nimport { BookCardPreviewComponent } from './components/book-card-preview/book-card-preview.component';\r\nimport { CourseCardPreviewComponent } from './components/course-card-preview/course-card-preview.component';\r\nimport { LibrarySearchComponent } from './components/library-search/library-search.component';\r\n\r\n@NgModule({\r\n declarations: [LibrarySearchComponent, BookCardPreviewComponent, CourseCardPreviewComponent],\r\n imports: [CommonModule, BaseModule, FormsModule],\r\n exports: [LibrarySearchComponent, BookCardPreviewComponent, CourseCardPreviewComponent],\r\n})\r\nexport class LibrarySearchModule {}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'backgroundImage',\r\n})\r\nexport class BackgroundImagePipe implements PipeTransform {\r\n transform(value?: string) {\r\n if (value) {\r\n value = 'url(' + value + ')';\r\n }\r\n return value ?? '';\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { INextAsset } from '@portal-app/interfaces/next/next-asset.interface';\r\nimport { IDimensionElement, IDimensionRatio } from '@portal-app/interfaces/project/dimension.interface';\r\nimport { environment } from '@portal-env/environment';\r\n\r\n@Pipe({\r\n name: 'nextImage',\r\n})\r\nexport class NextImagePipe implements PipeTransform {\r\n transform(asset?: INextAsset, width?: number, height?: number, mode?: string, fileType?: string) {\r\n if (!asset || asset.Type !== 'Image') {\r\n return '';\r\n }\r\n let assetDimensionsWidth;\r\n let assetDimensionsHeight;\r\n const getPercentageChange = (oldNumber: number, newNumber: number) => {\r\n const decreaseValue = oldNumber - newNumber;\r\n return 1 - decreaseValue / oldNumber;\r\n };\r\n\r\n if (asset.Dimensions) {\r\n if (!width && height) {\r\n const difference = getPercentageChange(asset.Dimensions.Height, height);\r\n assetDimensionsWidth = asset.Dimensions.Width * difference;\r\n }\r\n if (width && !height) {\r\n const difference = getPercentageChange(asset.Dimensions.Width, width);\r\n assetDimensionsHeight = asset.Dimensions.Height * difference;\r\n }\r\n if (!width && !height) {\r\n assetDimensionsWidth = asset.Dimensions.Width;\r\n assetDimensionsHeight = asset.Dimensions.Height;\r\n }\r\n }\r\n\r\n const useMode = mode ? (mode === 'max' ? 'max' : 'crop') : 'max';\r\n const useWidth = width ? width : assetDimensionsWidth;\r\n const useHeight = height ? height : assetDimensionsHeight;\r\n if (!useWidth || !useHeight) {\r\n return '';\r\n }\r\n const currentRatio = useHeight / useWidth;\r\n const closestRatio = environment.dimensions.reduce((a: IDimensionRatio, b: IDimensionRatio) => {\r\n return Math.abs(b.Ratio - currentRatio) < Math.abs(a.Ratio - currentRatio) ? b : a;\r\n });\r\n const availableDimensions = environment.dimensions.find((e) => e.Ratio === closestRatio.Ratio)?.Dimensions;\r\n if (!availableDimensions) {\r\n return '';\r\n }\r\n const closestDimensions = availableDimensions.reduce((a: IDimensionElement, b: IDimensionElement) => {\r\n const part1 = Math.abs(b.Width - useWidth);\r\n const part2 = Math.abs(a.Width - useWidth);\r\n const result = part1 < part2 && b.Width >= useWidth ? b : a;\r\n return result;\r\n });\r\n\r\n const path = asset.BasePath\r\n ? asset.BasePath\r\n : !asset.Path?.includes('http') && asset.Path\r\n ? environment.assetBasePath + asset.Path\r\n : asset.Path;\r\n\r\n fileType = (asset.FileType ? asset.FileType : 'jpg').toLowerCase();\r\n\r\n return `${path!}/${useMode}/${closestDimensions.Width}x${closestDimensions.Height}.${fileType}`;\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { AssociatedAppPipe } from '@portal-app/pipes/associated-app.pipe';\r\nimport { BackgroundImagePipe } from '@portal-app/pipes/background-image.pipe';\r\nimport { NextImagePipe } from '@portal-app/pipes/next-image.pipe';\r\nimport { TruncatePipe } from '@portal-app/pipes/truncate.pipe';\r\nimport { UmbracoImageLowResolutionPipe } from '@portal-app/pipes/umbraco-image-low-resolution.pipe';\r\nimport { UmbracoImagePipe } from '@portal-app/pipes/umbraco-image.pipe';\r\nimport { DurationPipe } from '../duration.pipe';\r\nimport { LevelPipe } from '../level.pipe';\r\nimport { NextImage2Pipe } from '../next-image-2.pipe';\r\nimport { SafePipe } from '../safe.pipe';\r\nimport { UmbracoAlignPipe } from '../umbraco-align.pipe';\r\nimport { UmbracoWidthPipe } from '../umbraco-width.pipe';\r\n\r\n@NgModule({\r\n declarations: [\r\n TruncatePipe,\r\n UmbracoImagePipe,\r\n UmbracoWidthPipe,\r\n UmbracoAlignPipe,\r\n BackgroundImagePipe,\r\n NextImagePipe,\r\n NextImage2Pipe,\r\n DurationPipe,\r\n LevelPipe,\r\n UmbracoImageLowResolutionPipe,\r\n AssociatedAppPipe,\r\n SafePipe,\r\n ],\r\n exports: [\r\n TruncatePipe,\r\n NextImagePipe,\r\n NextImage2Pipe,\r\n DurationPipe,\r\n LevelPipe,\r\n UmbracoImagePipe,\r\n UmbracoWidthPipe,\r\n UmbracoAlignPipe,\r\n UmbracoImageLowResolutionPipe,\r\n BackgroundImagePipe,\r\n AssociatedAppPipe,\r\n SafePipe,\r\n ],\r\n})\r\nexport class SharedPipeModule {}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'truncate',\r\n})\r\nexport class TruncatePipe implements PipeTransform {\r\n transform(value: string, limit = 25, ellipsis = '...') {\r\n const cleanText = this.strip(value);\r\n // split on characters\r\n return cleanText.length > limit ? cleanText.substring(0, limit) + ellipsis : cleanText;\r\n // split on words\r\n // return cleanText.split(' ').length > limit ? cleanText.split(' ').splice(0, limit).join(' ') + ellipsis : cleanText;\r\n }\r\n\r\n strip(html: string): string {\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n return doc.body.textContent || '';\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\n\r\n@Pipe({\r\n name: 'umbracoImage',\r\n})\r\nexport class UmbracoImagePipe implements PipeTransform {\r\n transform(\r\n value?: string,\r\n width?: number,\r\n height?: number,\r\n mode?: string,\r\n backgroundColor?: string,\r\n quality?: number\r\n ) {\r\n const imgQuality = quality || 80;\r\n\r\n if (value) {\r\n const tempParameters = [];\r\n let parameters = '';\r\n\r\n if (window.useWebP) {\r\n tempParameters.push('format=webp');\r\n }\r\n if (backgroundColor) {\r\n tempParameters.push('bgcolor=' + backgroundColor);\r\n }\r\n tempParameters.push(`quality=${imgQuality}`);\r\n if (width) {\r\n tempParameters.push(`width=${width}`);\r\n }\r\n if (height) {\r\n tempParameters.push(`height=${height}`);\r\n }\r\n if (mode === 'crop') {\r\n tempParameters.push('mode=' + mode);\r\n }\r\n if (tempParameters.length) {\r\n parameters = '?' + tempParameters.join('&');\r\n }\r\n value = value + parameters;\r\n }\r\n return value ?? '';\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService } from '@lru/felib';\r\nimport {\r\n INextCourseSearchActivity,\r\n INextCourseSearchActivityObject2,\r\n} from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { map } from 'rxjs';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ActivityFavoriteService {\r\n constructor(private api: ApiService, private initService: AppInitService) {}\r\n\r\n private contentType = 'Activity';\r\n\r\n getFavoriteActivitiesByProjectGroupId() {\r\n // // this api call was supposed to be generic but its not. its only for activities\r\n return this.api\r\n .getNext(\r\n `Favorite/GetFavoriteContent?id=${this.initService.siteConfiguration.ProjectGroup}`\r\n )\r\n .pipe(map((activities) => this.mapGetFavoriteContentResponse(activities)));\r\n }\r\n\r\n markFavorite(id: string) {\r\n return this.api.postNext(`Favorite/AddContentToFavorites?id=${id}&contentType=${this.contentType}`);\r\n }\r\n\r\n removeFavorite(id: string) {\r\n return this.api.deleteNext(`Favorite/DeleteContentFromFavorites?id=${id}&contentType=${this.contentType}`);\r\n }\r\n\r\n private mapGetFavoriteContentResponse(activities?: INextCourseSearchActivityObject2[]) {\r\n if (!activities) {\r\n return;\r\n }\r\n\r\n const list: INextCourseSearchActivity[] = [];\r\n activities.forEach((activity) => {\r\n list.push({\r\n activity: {\r\n id: activity.Id,\r\n duration: { hours: activity.Duration.Hours, minutes: activity.Duration.Minutes },\r\n label: activity.Label,\r\n levels: activity.Levels,\r\n title: activity.Title,\r\n topics: activity.Topics,\r\n types: activity.Types,\r\n url: activity.Url,\r\n asset: activity.Asset\r\n ? {\r\n path: activity.Asset.Path,\r\n type: activity.Asset.Type,\r\n basePath: activity.Asset.BasePath,\r\n changeFormat: activity.Asset.ChangeFormat,\r\n copyright: activity.Asset.Copyright,\r\n description: activity.Asset.Description,\r\n dimensions: activity.Asset.Dimensions\r\n ? { width: activity.Asset.Dimensions.Width, height: activity.Asset.Dimensions.Height }\r\n : undefined,\r\n fileName: activity.Asset.FileName,\r\n fileSize: activity.Asset.FileSize,\r\n fileType: activity.Asset.FileType,\r\n id: activity.Asset.Id,\r\n slug: activity.Asset.Slug,\r\n title: activity.Asset.Title,\r\n }\r\n : undefined,\r\n writers: activity.Writers,\r\n description: activity.Description,\r\n },\r\n hasLicense: false,\r\n isShowcase: false,\r\n });\r\n });\r\n\r\n return list;\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { EMPTY, ReplaySubject } from 'rxjs';\r\nimport { catchError, map } from 'rxjs/operators';\r\nimport { INextBookCollection } from '../../interfaces/book/next/next-book-collection.interface';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookCollectionFavoriteService {\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(private api: ApiService, private userService: UserService, private appInitService: AppInitService) {}\r\n\r\n private loaded = false;\r\n initialize() {\r\n const subject = new ReplaySubject(1);\r\n if (!this.loaded) {\r\n this.fetchAndUpdate()\r\n .pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n subject.next(false);\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n if (data) {\r\n subject.next(true);\r\n this.loaded = true;\r\n } else {\r\n subject.next(false);\r\n }\r\n });\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n fetchAndUpdate() {\r\n const subject = new ReplaySubject(1);\r\n if (\r\n this.userService.isLoggedIn &&\r\n this.userService.isTeacher &&\r\n (this.appInitService.isSuperbog || this.appInitService.isSuperreader)\r\n ) {\r\n this.api\r\n .getNext(\r\n `BookBox/GetFavoriteBookBoxes?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`\r\n )\r\n .pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n subject.next(false);\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n subject.next(true);\r\n this.data.next(data || []);\r\n });\r\n } else {\r\n this.data.next([]);\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n addCollectionToFavorites(id: string) {\r\n return this.api.postNext(`BookBoxFavorite/AddBookBoxToFavorites/${id}`).pipe(\r\n map((result: string) => {\r\n this.fetchAndUpdate();\r\n return result;\r\n })\r\n );\r\n }\r\n\r\n deleteCollectionFromFavorites(id: string) {\r\n return this.api.deleteNext(`BookBoxFavorite/DeleteBookBoxFromFavorites/${id}`).pipe(\r\n map((result: string) => {\r\n this.fetchAndUpdate();\r\n return result;\r\n })\r\n );\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { INextBook } from '@portal-app/interfaces/book/next/next-book';\r\nimport {\r\n INextBookCollection,\r\n INextBookCollectionAdd,\r\n INextBookCollectionEdit,\r\n} from '@portal-app/interfaces/book/next/next-book-collection.interface';\r\nimport { ICheckbox } from '@portal-app/interfaces/project/input.interface';\r\nimport { IBookTileInform, ICollectionTileEmpty } from '@portal-app/interfaces/project/section.interface';\r\nimport { BookCollectionMapper } from '@portal-app/mapper/book/book-collection.mapper';\r\nimport { BookMapper } from '@portal-app/mapper/book/book.mapper';\r\nimport { map } from 'rxjs/operators';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookCollectionService {\r\n constructor(\r\n private api: ApiService,\r\n private bookMapper: BookMapper,\r\n private bookCollectionMapper: BookCollectionMapper,\r\n private userService: UserService,\r\n private appInitService: AppInitService\r\n ) {}\r\n\r\n get(id: string) {\r\n return this.api.getNext(`BookBox/GetBookBox/${id}`);\r\n }\r\n\r\n create(body: INextBookCollectionAdd) {\r\n return this.api.postNext('BookBox/CreateBookBox', body);\r\n }\r\n\r\n edit(body: INextBookCollectionEdit) {\r\n return this.api.putNext('BookBox/UpdateBookBox', body);\r\n }\r\n\r\n delete(id: string) {\r\n return this.api.deleteNext(`BookBox/DeleteBookBox/${id}`);\r\n }\r\n\r\n changePublic(id: string) {\r\n return this.api.patchNext(`BookBox/ChangeBookBoxState/${id}`);\r\n }\r\n\r\n /**\r\n * Gets the users book collections.\r\n * The output is cached for subsequent requests.\r\n */\r\n getMyBookCollections() {\r\n let url: string;\r\n if (this.userService.isTeacher) {\r\n url = `BookBox/GetAllBookBoxesAvailable?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`;\r\n } else if (this.userService.isStudent) {\r\n url = `BookBox/GetBookBoxesSharedWithMyTeams?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`;\r\n } else {\r\n url = `BookBox/GetBookBoxes?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`;\r\n }\r\n return this.api\r\n .getNext(url)\r\n .pipe(map((collections) => this.bookCollectionMapper.mapBookCollectionFromApi(collections)));\r\n }\r\n\r\n /**\r\n * Gets the books in the given collection.\r\n * The output is cached for subsequent requests.\r\n */\r\n getBooksInCollection(id: string) {\r\n return this.api\r\n .getNext(`Book/GetBooksByBookBoxId/${id}`)\r\n .pipe(map((books) => this.bookMapper.mapBooksFromApi(books)));\r\n }\r\n\r\n addBookToCollection(collectionId: string, bookId: string) {\r\n return this.api.postNext('BookBox/AddBookToBookBox', {\r\n BookBoxId: collectionId,\r\n BookId: bookId,\r\n });\r\n }\r\n\r\n removeBookFromCollection(collectionId: string, bookId: string) {\r\n return this.api.deleteNext('BookBox/RemoveBookFromBookBox', {\r\n BookBoxId: collectionId,\r\n BookId: bookId,\r\n });\r\n }\r\n\r\n getTeamsAvailable(collectionId: string) {\r\n return this.api.getNext(\r\n `BookBox/CheckBookboxSharedWithTeams/${collectionId}?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}&productId=${this.appInitService.siteConfiguration.Id}`\r\n );\r\n }\r\n\r\n addTeamToCollection(collectionId: string, teamId: string) {\r\n return this.api.postNext('BookBox/AddBookBoxToTeam', {\r\n BookBoxId: collectionId,\r\n TeamId: teamId,\r\n });\r\n }\r\n\r\n removeTeamFromCollection(collectionId: string, teamId: string) {\r\n return this.api.deleteNext('BookBox/RemoveBookBoxFromTeam', {\r\n BookBoxId: collectionId,\r\n TeamId: teamId,\r\n });\r\n }\r\n\r\n getBookById(id: string) {\r\n return this.api.getNext(`Book/GetBookOverviewById/${id}`);\r\n }\r\n\r\n getSingleInfoTile(tile: IBookTileInform) {\r\n const data: IBookTileInform[] = [\r\n {\r\n IsEmpty: true,\r\n IsInform: true,\r\n ...tile,\r\n },\r\n ];\r\n return data;\r\n }\r\n\r\n getEmptyBookCollectionList(amount: number, loading?: boolean) {\r\n const data: ICollectionTileEmpty[] = [];\r\n\r\n for (let index = 0; index < amount; index++) {\r\n data.push({ IsEmpty: true, Loading: loading ?? false });\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * @param status (is BookBoxStatus on the endpoint)\r\n *\r\n * it's required on the endpoint and is default set to 0 (0,1,2 => All, Public, Private)\r\n * */\r\n getBookTileAvailableCollections(status: number = 0) {\r\n return this.api\r\n .getNext(\r\n `BookBox/GetMyBookBoxes?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}&status=${status}`\r\n )\r\n .pipe(map((collections) => this.bookCollectionMapper.mapBookCollectionFromApi(collections)));\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { IBookLocationSave } from '@portal-app/interfaces/book/project/book-location.interface';\r\nimport { ReplaySubject } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\nimport { INextBook } from '../../interfaces/book/next/next-book';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookContinueService {\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(\r\n private apiService: ApiService,\r\n private userService: UserService,\r\n private appInitService: AppInitService\r\n ) {}\r\n\r\n private loaded = false;\r\n initialize() {\r\n const subject = new ReplaySubject(1);\r\n if (!this.loaded) {\r\n this.fetchAndUpdate().subscribe(\r\n (data) => {\r\n if (data) {\r\n subject.next(true);\r\n this.loaded = true;\r\n } else {\r\n subject.next(false);\r\n }\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n fetchAndUpdate() {\r\n const subject = new ReplaySubject(1);\r\n if (this.userService.isLoggedIn && (this.appInitService.isSuperbog || this.appInitService.isSuperreader)) {\r\n this.apiService\r\n .getNext(\r\n `Book/GetBooksInProgress?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`\r\n )\r\n .subscribe(\r\n (data) => {\r\n this.data.next(data || []);\r\n subject.next(true);\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(false);\r\n }\r\n return subject;\r\n }\r\n\r\n setBookContinue(bookId: string, progress: string, percentage: number) {\r\n const body: IBookLocationSave = {\r\n BookId: bookId,\r\n Progress: progress,\r\n Percentage: percentage,\r\n };\r\n return this.apiService.postNext(`BookProgress/SaveProgress`, body).pipe(\r\n map((result: string) => {\r\n this.fetchAndUpdate();\r\n return result;\r\n })\r\n );\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { INextBook } from '@portal-app/interfaces/book/next/next-book';\r\nimport { ReplaySubject } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookFavoriteService {\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(private api: ApiService, private userService: UserService, private appInitService: AppInitService) {}\r\n\r\n private loaded = false;\r\n\r\n initialize() {\r\n const subject = new ReplaySubject(1);\r\n if (!this.loaded) {\r\n this.fetchAndUpdate().subscribe(\r\n (data) => {\r\n if (data) {\r\n subject.next(true);\r\n this.loaded = true;\r\n } else {\r\n subject.next(false);\r\n }\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n fetchAndUpdate() {\r\n const subject = new ReplaySubject(1);\r\n if (this.userService.isLoggedIn && (this.appInitService.isSuperbog || this.appInitService.isSuperreader)) {\r\n this.api\r\n .getNext(\r\n `Book/GetFavoriteBooks?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`\r\n )\r\n .subscribe(\r\n (data) => {\r\n subject.next(true);\r\n this.data.next(data || []);\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n addBookToFavorites(id: string) {\r\n return this.api.postNext(`BookFavorite/AddBookToFavorites/${id}`).pipe(\r\n map((result: string) => {\r\n this.fetchAndUpdate();\r\n return result;\r\n })\r\n );\r\n }\r\n\r\n deleteBookFromFavorites(id: string) {\r\n return this.api.deleteNext(`BookFavorite/DeleteBookFromFavorites/${id}`).pipe(\r\n map((result: string) => {\r\n this.fetchAndUpdate();\r\n return result;\r\n })\r\n );\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { ReplaySubject, of } from 'rxjs';\r\nimport { tap } from 'rxjs/operators';\r\nimport { INextBook } from '../../interfaces/book/next/next-book';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookFinishedService {\r\n private data = new ReplaySubject(1);\r\n private loaded = false;\r\n\r\n data$ = this.data.asObservable();\r\n\r\n getBookFinished(id: string) {\r\n return of(false);\r\n }\r\n\r\n constructor(\r\n private apiService: ApiService,\r\n private userService: UserService,\r\n private appInitService: AppInitService\r\n ) {}\r\n\r\n initialize() {\r\n const subject = new ReplaySubject(1);\r\n if (!this.loaded) {\r\n this.fetchAndUpdate().subscribe(\r\n (data) => {\r\n if (data) {\r\n subject.next(true);\r\n this.loaded = true;\r\n } else {\r\n subject.next(false);\r\n }\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n fetchAndUpdate() {\r\n const subject = new ReplaySubject(1);\r\n if (this.userService.isLoggedIn && (this.appInitService.isSuperbog || this.appInitService.isSuperreader)) {\r\n this.apiService\r\n .getNext(\r\n `Book/GetFinishedBooks?projectGroupId=${this.appInitService.siteConfiguration.ProjectGroup}`\r\n )\r\n .subscribe(\r\n (data) => {\r\n this.data.next(data || []);\r\n subject.next(true);\r\n },\r\n (error: HttpErrorResponse) => {\r\n subject.next(false);\r\n }\r\n );\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n setBookFinished(id: string, state: boolean) {\r\n return this.apiService\r\n .postNext(`BookProgress/FinishBook/${id}?finished=${state}`)\r\n .pipe(tap(() => this.fetchAndUpdate()));\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService } from '@lru/felib';\r\nimport {\r\n IBookImpressionPercentages,\r\n IBookImpressions,\r\n} from '@portal-app/interfaces/book/project/book-impression.interface';\r\nimport { INextImpressionTag } from '@portal-app/interfaces/next/next-tag.interface';\r\nimport { Subject } from 'rxjs';\r\nimport { map, tap, withLatestFrom } from 'rxjs/operators';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookImpressionService {\r\n private data = new Subject();\r\n data$ = this.data.asObservable();\r\n\r\n constructor(private apiService: ApiService) {}\r\n\r\n fetchAndUpdate(bookId: string) {\r\n return this.apiService.getNext(`${this.getSelectedImpressionsUrl}${bookId}`).pipe(\r\n tap((data) => {\r\n this.data.next(\r\n {\r\n Id: bookId,\r\n Impressions: data,\r\n } || undefined\r\n );\r\n })\r\n );\r\n }\r\n\r\n getImpressions() {\r\n return this.apiService.getNext(this.getImpressionsUrl);\r\n }\r\n\r\n addSelectedImpressions(bookId: string, impressionId?: string) {\r\n const body = {\r\n BookId: bookId,\r\n Slug: impressionId,\r\n };\r\n\r\n return this.apiService.postNext(this.addSelectedImpressionsUrl, body).pipe(\r\n withLatestFrom(this.fetchAndUpdate(bookId)),\r\n tap(([_, impressionTags]) => this.data.next({ Id: bookId, Impressions: impressionTags })),\r\n map(([result, _]) => result)\r\n );\r\n }\r\n\r\n removeSelectedImpressions(bookId: string, impressionId?: string) {\r\n const body = {\r\n BookId: bookId,\r\n Slug: impressionId,\r\n };\r\n return this.apiService.deleteNext(this.removeSelectedImpressionsUrl, body).pipe(\r\n withLatestFrom(this.fetchAndUpdate(bookId)),\r\n tap(([_, impressionTags]) => this.data.next({ Id: bookId, Impressions: impressionTags })),\r\n map(([result, _]) => result)\r\n );\r\n }\r\n\r\n getImpressionPercentages(bookId: string) {\r\n return this.apiService.getNext(`${this.getImpressionPercentagesUrl}${bookId}`);\r\n }\r\n\r\n get getImpressionsUrl() {\r\n return 'BookImpression/GetImpressionTypes';\r\n }\r\n\r\n get getSelectedImpressionsUrl() {\r\n return 'BookImpression/GetUsersImpressionById/';\r\n }\r\n\r\n get addSelectedImpressionsUrl() {\r\n return 'BookImpression/SaveImpression';\r\n }\r\n\r\n get removeSelectedImpressionsUrl() {\r\n return 'BookImpression/DeleteImpression';\r\n }\r\n\r\n get getImpressionPercentagesUrl() {\r\n return 'BookImpression/GetImpressionsById/';\r\n }\r\n}\r\n","import { Location, PlatformLocation } from '@angular/common';\r\nimport { HttpErrorResponse, HttpParams } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { FacetTypeEnum } from '@portal-app/enums/facet-type.enum';\r\n\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { PageTypeEnum } from '@portal-app/enums/page-type.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport { ILibraryFacet, ILibraryFacets } from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { DropdownService } from '@portal-app/services/shared/dropdown.service';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { EMPTY, ReplaySubject } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport {\r\n INextBookSearchAutoCompleteResponse,\r\n INextBookSearchResponse,\r\n} from '../../interfaces/book/next/next-book-library.interface';\r\nimport { IBookLibraryFilters } from '../../interfaces/book/project/book-library.interface';\r\nimport { INextSearchSuggestions } from '../../interfaces/next/next-library';\r\nimport { BookLibraryMapper } from '../../mapper/book/book-library.mapper';\r\nimport { BookMapper } from '../../mapper/book/book.mapper';\r\nimport { PageService } from '../shared/page/page.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BookLibraryService {\r\n filters: IBookLibraryFilters;\r\n\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(\r\n private helperService: HelperService,\r\n private appInitService: AppInitService,\r\n private dropdownService: DropdownService,\r\n private readonly location: Location,\r\n private api: ApiService,\r\n private userService: UserService,\r\n private bookLibraryMapper: BookLibraryMapper,\r\n private bookMapper: BookMapper,\r\n private platformLocation: PlatformLocation,\r\n private pageService: PageService,\r\n private translate: TranslateService\r\n ) {\r\n this.filters = {\r\n FiltersLoaded: false,\r\n SearchLoaded: false,\r\n LoggedIn: this.userService.isLoggedIn,\r\n Loading: false,\r\n Query: '',\r\n SearchBody: {\r\n ProjectGroupId: this.appInitService.siteConfiguration.ProjectGroup || '',\r\n Top: 20,\r\n Skip: 0,\r\n Query: '',\r\n FacetCount: 500,\r\n Categories: [],\r\n DifficultyGroups: [],\r\n Grades: [],\r\n ReadingLevels: [],\r\n Languages: [],\r\n Illustrations: [],\r\n HasAudioBook: [],\r\n SeriesTitles: [],\r\n },\r\n Facets: undefined,\r\n Books: undefined,\r\n Collections: undefined,\r\n };\r\n this.platformLocation.onPopState(() => {\r\n if (this.filters) {\r\n this.filters.FiltersLoaded = false;\r\n this.filters.SearchLoaded = false;\r\n }\r\n });\r\n }\r\n\r\n initializeFilters() {\r\n const urlQuery = this.helperService.getQueryParam(QueryStrings.Query) || '';\r\n\r\n this.filters.Query = urlQuery;\r\n this.filters.SearchBody.Query = urlQuery ? urlQuery : '*';\r\n\r\n this.filters.SearchBody.Skip = 0;\r\n this.filters.SearchBody.Categories = this.helperService.getQuerystringFacetList(QueryStrings.Categories);\r\n this.filters.SearchBody.DifficultyGroups = this.helperService.getQuerystringFacetList(\r\n QueryStrings.DifficultyGroups\r\n );\r\n this.filters.SearchBody.ReadingLevels = this.helperService.getQuerystringFacetList(QueryStrings.ReadingLevels);\r\n this.filters.SearchBody.Grades = this.helperService.getQuerystringFacetList(QueryStrings.Grades);\r\n this.filters.SearchBody.Languages = this.helperService.getQuerystringFacetList(QueryStrings.Languages);\r\n this.filters.SearchBody.Illustrations = this.helperService.getQuerystringFacetList(QueryStrings.Illustrations);\r\n this.filters.SearchBody.HasAudioBook = this.helperService.getQuerystringFacetListAsBooleans(\r\n QueryStrings.HasAudioBook\r\n );\r\n this.filters.SearchBody.SeriesTitles = this.helperService.getQuerystringFacetList(QueryStrings.SeriesTitle);\r\n\r\n this.filters.FiltersLoaded = true;\r\n this.data.next(this.filters);\r\n }\r\n\r\n initializeSearch() {\r\n this.postAzureSearch()\r\n .pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n this.pageService.showError(window.location.pathname, error.status);\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => {\r\n this.filters.Books = {\r\n SliderSettings: {\r\n MaxSlidesPerView: 5,\r\n Type: SectionTypeEnum.BookList,\r\n UseSlider: false,\r\n Title: this.translate.instant('BookList.Title'),\r\n Total: data.count,\r\n },\r\n Items: data.results ? this.bookMapper.mapBooksFromApi2(data.results) : [],\r\n Pagination: {\r\n Type: PageTypeEnum.BookLibrary,\r\n CollectionSize: data.count,\r\n Index: 1,\r\n PageSize: this.filters.SearchBody.Top,\r\n },\r\n };\r\n this.filters.Facets = this.bookLibraryMapper.mapFacetsFromApi(data.facets);\r\n this.filters.SearchLoaded = true;\r\n this.data.next(this.filters);\r\n });\r\n }\r\n\r\n postAzureSearch() {\r\n return this.api.postNextSearch('SearchBooksAsync', this.filters.SearchBody);\r\n }\r\n\r\n postAzureAutoComplete(query: string) {\r\n const body: INextSearchSuggestions = {\r\n Fuzzy: true,\r\n ProjectGroupId: this.appInitService.siteConfiguration.ProjectGroup || '',\r\n Query: query,\r\n Top: 3,\r\n };\r\n\r\n return this.api.postNextSearch('BookSearchSuggestionsAsync', body);\r\n }\r\n\r\n setQueryString(replaceState?: boolean) {\r\n let params = new HttpParams();\r\n\r\n params = this.setQueryStringFacets(params);\r\n\r\n params = this.setQueryStringSearchBody(params);\r\n\r\n if (replaceState) {\r\n this.location.replaceState(window.location.pathname, params.toString());\r\n } else {\r\n this.location.go(window.location.pathname, params.toString());\r\n }\r\n }\r\n\r\n private setQueryStringSearchBody(params: HttpParams) {\r\n if (this.filters.SearchBody.Query !== '*' && this.filters.SearchBody.Query) {\r\n params = params.append(QueryStrings.Query.en, this.filters.SearchBody.Query);\r\n }\r\n\r\n if (this.filters.SearchBody.ReadingLevels.length) {\r\n params = params.append(\r\n QueryStrings.ReadingLevels.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.ReadingLevels)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.Categories.length) {\r\n params = params.append(\r\n QueryStrings.Categories.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Categories)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.DifficultyGroups.length) {\r\n params = params.append(\r\n QueryStrings.DifficultyGroups.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.DifficultyGroups)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.Grades.length) {\r\n params = params.append(\r\n QueryStrings.Grades.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Grades)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.Languages.length) {\r\n params = params.append(\r\n QueryStrings.Languages.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Languages)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.Illustrations.length) {\r\n params = params.append(\r\n QueryStrings.Illustrations.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Illustrations)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.HasAudioBook.length) {\r\n params = params.append(QueryStrings.HasAudioBook.en, this.filters.SearchBody.HasAudioBook.join(','));\r\n }\r\n\r\n if (this.filters.SearchBody.SeriesTitles.length) {\r\n params = params.append(\r\n QueryStrings.SeriesTitle.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.SeriesTitles)\r\n );\r\n }\r\n\r\n return params;\r\n }\r\n\r\n private setQueryStringFacets(params: HttpParams) {\r\n if (this.filters.Facets) {\r\n for (const facet of this.filters.Facets) {\r\n if (facet.Open) {\r\n params = params.append(facet.UrlTitle + QueryStrings.Open.en, 'true');\r\n }\r\n }\r\n }\r\n return params;\r\n }\r\n\r\n query() {\r\n this.filters.SearchBody.Query = this.filters.Query ? this.filters.Query : '*';\r\n this.search();\r\n }\r\n\r\n clearQuery() {\r\n this.filters.Query = '';\r\n this.query();\r\n }\r\n\r\n search(closeDropdown?: boolean) {\r\n if (closeDropdown) {\r\n this.dropdownService.closeDropdown();\r\n }\r\n this.filters.Loading = true;\r\n this.setQueryString();\r\n this.postAzureSearch()\r\n .pipe(\r\n catchError(() => {\r\n this.filters.Loading = false;\r\n return EMPTY;\r\n })\r\n )\r\n .subscribe((data) => this.handleBookSearchResponse(data));\r\n }\r\n\r\n private handleBookSearchResponse(data: INextBookSearchResponse) {\r\n if (this.filters.Books) {\r\n this.filters.Books.Items = data.results ? this.bookMapper.mapBooksFromApi2(data.results) : [];\r\n if (this.filters.Books.Pagination) {\r\n this.filters.Books.Pagination.CollectionSize = data.count;\r\n }\r\n this.filters.Books.SliderSettings.Total = data.count;\r\n }\r\n this.filters.Facets = this.bookLibraryMapper.mapFacetsFromApi(data.facets);\r\n this.filters.Loading = false;\r\n this.data.next(this.filters);\r\n }\r\n\r\n changeFacet(facet: ILibraryFacets) {\r\n switch (facet.Type) {\r\n case FacetTypeEnum.Categories:\r\n this.filters.SearchBody.Categories = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.DifficultyGroups:\r\n this.filters.SearchBody.DifficultyGroups = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.Grades:\r\n this.filters.SearchBody.Grades = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.Languages:\r\n this.filters.SearchBody.Languages = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.Illustrations:\r\n this.filters.SearchBody.Illustrations = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.SeriesTitle:\r\n this.filters.SearchBody.SeriesTitles = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.ReadingLevels:\r\n this.filters.SearchBody.ReadingLevels = this.mapFacet(facet.Items);\r\n break;\r\n case FacetTypeEnum.HasAudioBook:\r\n this.filters.SearchBody.HasAudioBook = facet.Items.filter((item) => item.Selected === true).map(\r\n (item) => item.Value.toLowerCase() === 'true'\r\n );\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n private mapFacet(facets: ILibraryFacet[]) {\r\n return facets.filter((facet) => facet.Selected === true).map((facet) => facet.Value);\r\n }\r\n\r\n toggleFacetOpen(facet: ILibraryFacets) {\r\n this.filters?.Facets?.map((elem) => {\r\n if (elem.Title === facet.Title) {\r\n elem.Open = !facet.Open;\r\n } else {\r\n elem.Open = false;\r\n }\r\n });\r\n this.setQueryString();\r\n }\r\n\r\n reset() {\r\n this.filters.Query = '';\r\n this.filters.SearchBody.Query = '*';\r\n\r\n if (this.filters.Facets) {\r\n for (const facet of this.filters.Facets) {\r\n facet.Open = false;\r\n for (const item of facet.Items) {\r\n item.Selected = false;\r\n }\r\n }\r\n }\r\n\r\n this.filters.SearchBody.Skip = 0;\r\n\r\n this.filters.SearchBody.Categories = [];\r\n this.filters.SearchBody.DifficultyGroups = [];\r\n this.filters.SearchBody.Grades = [];\r\n this.filters.SearchBody.Languages = [];\r\n this.filters.SearchBody.Illustrations = [];\r\n this.filters.SearchBody.HasAudioBook = [];\r\n this.filters.SearchBody.SeriesTitles = [];\r\n this.filters.SearchBody.ReadingLevels = [];\r\n\r\n this.search();\r\n }\r\n\r\n setFacets(facets?: ILibraryFacets[]) {\r\n this.filters.Facets = facets;\r\n facets?.forEach((facet) => {\r\n this.changeFacet(facet);\r\n });\r\n this.data.next(this.filters);\r\n }\r\n\r\n changePage(pageIndex: number) {\r\n if (this.filters?.Books?.Pagination) {\r\n this.filters.Books.Pagination.Index = pageIndex;\r\n }\r\n this.filters.SearchBody.Skip = (pageIndex - 1) * this.filters.SearchBody.Top;\r\n window.scroll(0, 0);\r\n this.search();\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService } from '@lru/felib';\r\nimport {\r\n INextCourseSearchAssignment2,\r\n INextCourseSearchCourse,\r\n INextCourseSearchPage2,\r\n} from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport { INextFavorite } from '@portal-app/interfaces/next/next-favorite.interface';\r\nimport { AppInitService } from '../shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseFavoriteApiService {\r\n constructor(private apiService: ApiService, private appInitService: AppInitService) {}\r\n\r\n getFavoriteActivitiesByIds(ids: (string | undefined)[]) {\r\n return this.apiService.postNext('Favorite/CheckIfContentsIsFavorite', ids);\r\n }\r\n\r\n getFavoriteCourseByIds(ids: (string | undefined)[]) {\r\n return this.apiService.postNext('Favorite/AreCourseAliasesFavorites', ids);\r\n }\r\n\r\n getFavoriteTextsByIds(ids: (string | undefined)[]) {\r\n return this.apiService.postNext('Favorite/AreChapterPagesFavorites', ids);\r\n }\r\n\r\n getFavoriteTasksByIds(ids: (string | undefined)[]) {\r\n return this.apiService.postNext('Favorite/AreAssignmentsFavorites', ids);\r\n }\r\n\r\n getFavoriteCoursesByProjectGroupId() {\r\n return this.apiService.getNext(\r\n `Favorite/GetFavoriteCourses/${this.appInitService.siteConfiguration.ProjectGroup}`\r\n );\r\n }\r\n\r\n getFavoriteTextsByProjectGroupId() {\r\n return this.apiService.getNext(\r\n `Favorite/GetFavoriteChapterPages/${this.appInitService.siteConfiguration.ProjectGroup}`\r\n );\r\n }\r\n\r\n getFavoriteTasksByIdsByProjectGroupId() {\r\n return this.apiService.getNext(\r\n `Favorite/GetFavoriteAssignments/${this.appInitService.siteConfiguration.ProjectGroup}`\r\n );\r\n }\r\n\r\n addCourseFavorite(id: string) {\r\n return this.apiService.postNext(`Favorite/AddCourseToFavorites/${id}`);\r\n }\r\n\r\n addTextFavorite(id: string) {\r\n return this.apiService.postNext(`Favorite/AddChapterPageToFavorites/${id}`);\r\n }\r\n\r\n addTaskFavorite(id: string) {\r\n return this.apiService.postNext(`Favorite/AddAssignmentToFavorites/${id}`);\r\n }\r\n\r\n removeCourseFavorite(id: string) {\r\n return this.apiService.deleteNext(`Favorite/DeleteCourseFromFavorites/${id}`);\r\n }\r\n\r\n removeTextFavorite(id: string) {\r\n return this.apiService.deleteNext(`Favorite/DeleteChapterPageFromFavorites/${id}`);\r\n }\r\n\r\n removeTaskFavorite(id: string) {\r\n return this.apiService.deleteNext(`Favorite/DeleteAssignmentFromFavorites/${id}`);\r\n }\r\n}\r\n","import { Location, PlatformLocation } from '@angular/common';\r\nimport { HttpErrorResponse, HttpParams } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { FacetTypeEnum } from '@portal-app/enums/facet-type.enum';\r\nimport {\r\n INextCourseSearchAutoCompleteResponse,\r\n INextCourseSearchResponse2,\r\n} from '@portal-app/interfaces/course/next/next-course-library.interface';\r\nimport {\r\n ICourseLibraryFilters,\r\n ILibraryFacets,\r\n ILibraryTab,\r\n} from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { CourseFavoriteMapper } from '@portal-app/mapper/course/course-favorite.mapper';\r\nimport { CourseLibraryMapper } from '@portal-app/mapper/course/course-library.mapper';\r\nimport { CourseTabsMapper } from '@portal-app/mapper/course/course-tabs.mapper';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { DropdownService } from '@portal-app/services/shared/dropdown.service';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { HtmlService } from '@portal-app/services/shared/html.service';\r\nimport { EMPTY, ReplaySubject, firstValueFrom } from 'rxjs';\r\nimport { catchError, switchMap, tap } from 'rxjs/operators';\r\nimport { ContentTypeEnum } from '../../enums/content-type.enum';\r\nimport { INextSearchSuggestions } from '../../interfaces/next/next-library';\r\nimport { PageService } from '../shared/page/page.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class CourseLibraryService {\r\n filters: ICourseLibraryFilters;\r\n\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(\r\n private courseFavoriteMapper: CourseFavoriteMapper,\r\n private courseTabsMapper: CourseTabsMapper,\r\n private helperService: HelperService,\r\n private appInitService: AppInitService,\r\n private dropdownService: DropdownService,\r\n private courseLibraryMapper: CourseLibraryMapper,\r\n private readonly location: Location,\r\n private api: ApiService,\r\n private userService: UserService,\r\n private htmlService: HtmlService,\r\n private platformLocation: PlatformLocation,\r\n private translateService: TranslateService,\r\n private pageService: PageService\r\n ) {\r\n const tab = this.helperService.getQueryParam(QueryStrings.Tab);\r\n this.filters = {\r\n FiltersLoaded: false,\r\n SearchLoaded: false,\r\n LoggedIn: this.userService.isLoggedIn,\r\n MinShown: 3,\r\n MinToCollapse: 6,\r\n Loading: false,\r\n Query: '',\r\n SearchBody: {\r\n ProjectGroupId: this.appInitService.siteConfiguration.ProjectGroup || '',\r\n SearchIn:\r\n QueryStrings.Courses.en === tab || QueryStrings.Courses.da === tab\r\n ? ContentTypeEnum.Courses\r\n : ContentTypeEnum.Texts,\r\n Top: 10,\r\n Skip: 0,\r\n Query: '*',\r\n OnlyLicense: false,\r\n AssignmentTypes: [],\r\n CollaborationTypes: [],\r\n Genres: [],\r\n Levels: [],\r\n Topics: [],\r\n Writers: [],\r\n Subjects: [],\r\n FacetCount: 500,\r\n },\r\n TabGroups: [],\r\n Facets: undefined,\r\n SearchCount: undefined,\r\n CurrentTab: undefined,\r\n OnlyLicense: {\r\n Title:\r\n this.htmlService.fixHtml(\r\n this.userService.isLoggedIn\r\n ? this.translateService.instant('CourseLibrary.Filters.OnlyLicenseLoggedIn')\r\n : this.translateService.instant('CourseLibrary.Filters.OnlyLicenseLoggedOut')\r\n ) || '',\r\n Checked: false,\r\n },\r\n };\r\n this.filters.SearchBody.Top = this.getPageSize();\r\n this.platformLocation.onPopState(() => {\r\n if (this.filters) {\r\n this.filters.FiltersLoaded = false;\r\n this.filters.SearchLoaded = false;\r\n }\r\n });\r\n }\r\n\r\n initializeFilters() {\r\n const onlyLicenseParam = this.helperService.getQueryParam(QueryStrings.OnlyLicense);\r\n\r\n const urlQuery = this.helperService.getQueryParam(QueryStrings.Query) || '*';\r\n this.filters.Query = urlQuery !== '*' ? urlQuery : '';\r\n this.filters.SearchBody.Query = urlQuery;\r\n if (this.appInitService.siteConfiguration.onlyLicenseToggle) {\r\n this.filters.SearchBody.OnlyLicense = onlyLicenseParam ? onlyLicenseParam !== 'false' : this.filters.LoggedIn;\r\n this.filters.OnlyLicense.Checked = this.filters.SearchBody.OnlyLicense;\r\n }\r\n const tab = this.helperService.getQueryParam(QueryStrings.Tab);\r\n\r\n if (tab) {\r\n this.filters.SearchBody.SearchIn =\r\n this.helperService.getKeyName(QueryStrings, tab) !== 'Texts'\r\n ? this.helperService.getKeyName(QueryStrings, tab) || ContentTypeEnum.Texts\r\n : ContentTypeEnum.Texts;\r\n } else {\r\n this.filters.SearchBody.SearchIn = ContentTypeEnum.Texts;\r\n }\r\n this.filters.SearchBody.Top = this.getPageSize();\r\n\r\n const urlPage = this.helperService.getQueryParam(QueryStrings.Page);\r\n this.filters.SearchBody.Skip = urlPage\r\n ? (this.helperService.tryParseInt(urlPage, 0) - 1) * this.filters.SearchBody.Top\r\n : 0;\r\n this.filters.SearchBody.AssignmentTypes = this.helperService.getQuerystringFacetList(QueryStrings.AssignmentTypes);\r\n this.filters.SearchBody.CollaborationTypes = this.helperService.getQuerystringFacetList(\r\n QueryStrings.CollaborationTypes\r\n );\r\n this.filters.SearchBody.Genres = this.helperService.getQuerystringFacetList(QueryStrings.Genres);\r\n this.filters.SearchBody.Levels = this.helperService.getQuerystringFacetList(QueryStrings.Levels);\r\n this.filters.SearchBody.Topics = this.helperService.getQuerystringFacetList(QueryStrings.Topics);\r\n this.filters.SearchBody.Writers = this.helperService.getQuerystringFacetList(QueryStrings.Writers);\r\n this.filters.SearchBody.Subjects = this.helperService.getQuerystringFacetList(QueryStrings.Subjects);\r\n\r\n this.filters.FiltersLoaded = true;\r\n this.data.next(this.filters);\r\n }\r\n\r\n initializeSearch() {\r\n this.postAzureSearch()\r\n .pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n this.pageService.showError(window.location.pathname, error.status);\r\n\r\n return EMPTY;\r\n }),\r\n tap((data) => {\r\n this.filters.TabGroups = this.courseTabsMapper.mapLibraryTabsFromApi(data);\r\n this.filters.Facets = this.courseLibraryMapper.mapFacetsFromApi(data.facets);\r\n this.filters.SearchCount = data.searchCount;\r\n this.filters.CurrentTab = this.setCurrentTab();\r\n\r\n if (this.filters.CurrentTab) {\r\n this.filters.CurrentTab.Pagination.Index = this.filters.SearchBody.Skip / this.filters.SearchBody.Top + 1;\r\n }\r\n }),\r\n switchMap(() => this.setFavorites())\r\n )\r\n .subscribe(() => {\r\n this.filters.SearchLoaded = true;\r\n this.data.next(this.filters);\r\n });\r\n }\r\n\r\n private setCurrentTab() {\r\n let CurrentTab: ILibraryTab | undefined = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Texts)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Texts);\r\n\r\n if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Assignments) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Assignments)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Assignments);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Courses) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Courses)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Courses);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Activities) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Activities)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Activities);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Images) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Images)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Images);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Videos) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Videos)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Videos);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Audios) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Audios)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Audios);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Documents) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Documents)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Documents);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.GeoGebras) {\r\n CurrentTab = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.GeoGebras)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.GeoGebras);\r\n }\r\n return CurrentTab;\r\n }\r\n\r\n postAzureSearch() {\r\n return this.api.postNextSearch('SearchPortalAsync', this.filters.SearchBody);\r\n }\r\n\r\n postAzureAutoComplete(query: string) {\r\n const body: INextSearchSuggestions = {\r\n Fuzzy: true,\r\n ProjectGroupId: this.appInitService.siteConfiguration.ProjectGroup || '',\r\n Query: query,\r\n Top: 3,\r\n };\r\n\r\n return this.api.postNextSearch('PortalSearchSuggestionsAsync', body);\r\n }\r\n\r\n setQueryString(replaceState?: boolean) {\r\n let params = new HttpParams();\r\n\r\n if (this.filters.SearchBody.SearchIn !== ContentTypeEnum.Texts && this.filters.CurrentTab) {\r\n params = params.append(QueryStrings.Tab.en, this.filters.CurrentTab.UrlTitle);\r\n }\r\n\r\n if (\r\n (this.filters.LoggedIn && !this.filters.SearchBody.OnlyLicense) ||\r\n (!this.filters.LoggedIn && this.filters.SearchBody.OnlyLicense)\r\n ) {\r\n params = params.append(QueryStrings.OnlyLicense.en, false);\r\n }\r\n\r\n if (this.filters.SearchBody.Query !== '*' && this.filters.SearchBody.Query) {\r\n params = params.append(QueryStrings.Query.en, this.filters.SearchBody.Query);\r\n }\r\n if (this.filters.Facets) {\r\n for (const facet of this.filters.Facets) {\r\n if (facet.Open) {\r\n params = params.append(facet.UrlTitle + QueryStrings.Open.en, 'true');\r\n }\r\n }\r\n }\r\n\r\n if (this.filters.SearchBody.AssignmentTypes?.length) {\r\n params = params.append(\r\n QueryStrings.AssignmentTypes.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.AssignmentTypes)\r\n );\r\n }\r\n if (this.filters.SearchBody.CollaborationTypes?.length) {\r\n params = params.append(\r\n QueryStrings.CollaborationTypes.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.CollaborationTypes)\r\n );\r\n }\r\n if (this.filters.SearchBody.Genres?.length) {\r\n params = params.append(\r\n QueryStrings.Genres.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Genres)\r\n );\r\n }\r\n if (this.filters.SearchBody.Levels?.length) {\r\n params = params.append(\r\n QueryStrings.Levels.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Levels)\r\n );\r\n }\r\n if (this.filters.SearchBody.Topics?.length) {\r\n params = params.append(\r\n QueryStrings.Topics.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Topics)\r\n );\r\n }\r\n if (this.filters.SearchBody.Writers?.length) {\r\n params = params.append(\r\n QueryStrings.Writers.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Writers)\r\n );\r\n }\r\n if (this.filters.SearchBody.Subjects?.length) {\r\n params = params.append(\r\n QueryStrings.Subjects.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Subjects)\r\n );\r\n }\r\n if (this.filters.SearchBody.Periods?.length) {\r\n params = params.append(\r\n QueryStrings.Periods.en,\r\n this.helperService.encodeStringArray(this.filters.SearchBody.Periods)\r\n );\r\n }\r\n\r\n if (this.filters.SearchBody.Skip) {\r\n params = params.append(\r\n QueryStrings.Page.en,\r\n (this.filters.SearchBody.Skip / this.filters.SearchBody.Top + 1).toString()\r\n );\r\n }\r\n\r\n if (replaceState) {\r\n this.location.replaceState(window.location.pathname, params.toString());\r\n } else {\r\n this.location.go(window.location.pathname, params.toString());\r\n }\r\n }\r\n\r\n changePage(pageIndex: number) {\r\n if (this.filters.CurrentTab) {\r\n this.filters.CurrentTab.Pagination.Index = pageIndex;\r\n this.filters.SearchBody.Skip = (pageIndex - 1) * this.filters.SearchBody.Top;\r\n this.filters.SearchBody.SearchIn = this.filters.CurrentTab.TabsType;\r\n this.filters.SearchBody.Top = this.getPageSize();\r\n window.scroll(0, 0);\r\n this.search();\r\n }\r\n }\r\n\r\n changeTab(tab: ILibraryTab) {\r\n this.filters.CurrentTab = tab;\r\n this.filters.SearchBody.SearchIn = tab.TabsType;\r\n this.filters.SearchBody.Top = this.getPageSize();\r\n this.filters.SearchBody.Skip = (tab.Pagination.Index - 1) * this.filters.SearchBody.Top;\r\n this.search();\r\n }\r\n\r\n onlyLicenseChange(checked: boolean) {\r\n this.filters.OnlyLicense.Checked = checked;\r\n this.filters.SearchBody.OnlyLicense = checked;\r\n this.clearPageIndex();\r\n this.search();\r\n }\r\n\r\n async setFavorites() {\r\n const courses = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Courses)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Courses)?.Courses;\r\n const texts = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Texts)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Texts)?.Texts;\r\n\r\n const tasks = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Assignments)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Assignments)?.Tasks;\r\n\r\n const activities = this.filters.TabGroups.find((x) =>\r\n x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Activities)\r\n )?.Tabs.find((x) => x.TabsType === ContentTypeEnum.Activities)?.Activities;\r\n\r\n if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Activities && activities?.Items.length) {\r\n await firstValueFrom(this.courseFavoriteMapper.setActivitiesFavorite(activities.Items));\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Assignments && tasks?.length) {\r\n this.courseFavoriteMapper.setTasksFavorite(tasks);\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Courses && courses?.Items.length) {\r\n await firstValueFrom(this.courseFavoriteMapper.setCoursesFavorite(courses.Items));\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Images) {\r\n // debugger;\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Videos) {\r\n // debugger;\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Audios) {\r\n // debugger;\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.Documents) {\r\n // debugger;\r\n } else if (this.filters.SearchBody.SearchIn === ContentTypeEnum.GeoGebras) {\r\n // debugger;\r\n } else if (texts) {\r\n this.courseFavoriteMapper.setTextsFavorite(texts);\r\n }\r\n }\r\n\r\n query() {\r\n this.clearPageIndex();\r\n this.filters.SearchBody.Query = this.filters.Query === '' ? '*' : this.filters.Query;\r\n this.search();\r\n }\r\n\r\n clearQuery() {\r\n this.filters.Query = '';\r\n this.query();\r\n }\r\n\r\n search() {\r\n this.dropdownService.closeDropdown();\r\n this.filters.Loading = true;\r\n this.setQueryString();\r\n\r\n this.postAzureSearch()\r\n .pipe(\r\n catchError(() => {\r\n this.filters.Loading = false;\r\n return EMPTY;\r\n }),\r\n tap((data) => {\r\n this.replaceTabs(data);\r\n this.filters.Facets = this.courseLibraryMapper.mapFacetsFromApi(data.facets);\r\n this.filters.SearchCount = data.searchCount;\r\n }),\r\n switchMap(() => this.setFavorites())\r\n )\r\n .subscribe(() => {\r\n this.filters.Loading = false;\r\n this.data.next(this.filters);\r\n });\r\n }\r\n\r\n private replaceTabs(data: INextCourseSearchResponse2) {\r\n this.courseTabsMapper.replaceCoursesTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Courses))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Courses\r\n ),\r\n '?portalclick=courseslibrary'\r\n );\r\n this.courseTabsMapper.replaceTasksTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Assignments))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Assignments\r\n ),\r\n '?portalclick=assignmentslibrary'\r\n );\r\n this.courseTabsMapper.replaceActivitiesTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Activities))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Activities\r\n ),\r\n '?portalclick=activitieslibrary'\r\n );\r\n this.courseTabsMapper.replaceTextsTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Texts))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Texts\r\n ),\r\n '?portalclick=pageslibrary'\r\n );\r\n\r\n this.courseTabsMapper.replaceImagesTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Images))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Images\r\n )\r\n );\r\n this.courseTabsMapper.replaceVideosTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Videos))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Videos\r\n )\r\n );\r\n this.courseTabsMapper.replaceAudiosTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Audios))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Audios\r\n )\r\n );\r\n this.courseTabsMapper.replaceDocumentsTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.Documents))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.Documents\r\n )\r\n );\r\n this.courseTabsMapper.replaceGeoGebrasTab(\r\n data,\r\n this.filters.TabGroups.find((x) => x.Tabs.find((d) => d.TabsType === ContentTypeEnum.GeoGebras))?.Tabs.find(\r\n (x) => x.TabsType === ContentTypeEnum.GeoGebras\r\n )\r\n );\r\n }\r\n\r\n changeFacet(facet: ILibraryFacets) {\r\n if (facet.Type === FacetTypeEnum.AssignmentTypes) {\r\n this.filters.SearchBody.AssignmentTypes = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.CollaborationTypes) {\r\n this.filters.SearchBody.CollaborationTypes = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Genres) {\r\n this.filters.SearchBody.Genres = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Levels) {\r\n this.filters.SearchBody.Levels = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Topics) {\r\n this.filters.SearchBody.Topics = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Writers) {\r\n this.filters.SearchBody.Writers = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Subjects) {\r\n this.filters.SearchBody.Subjects = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n } else if (facet.Type === FacetTypeEnum.Periods) {\r\n this.filters.SearchBody.Periods = facet.Items.filter((item) => item.Selected === true).map((item) => {\r\n return item.Value;\r\n });\r\n }\r\n this.clearPageIndex();\r\n this.search();\r\n }\r\n\r\n toggleFacetOpen(facet: ILibraryFacets) {\r\n facet.Open = !facet.Open;\r\n this.setQueryString();\r\n }\r\n\r\n clearPageIndex() {\r\n for (const group of this.filters.TabGroups) {\r\n for (const tab of group.Tabs) {\r\n tab.Pagination.Index = 1;\r\n }\r\n }\r\n if (this.filters.CurrentTab) {\r\n this.filters.CurrentTab.Pagination.Index = 1;\r\n }\r\n this.filters.SearchBody.Skip = 0;\r\n }\r\n\r\n reset() {\r\n this.filters.Query = '';\r\n this.filters.SearchBody.Query = '*';\r\n this.resetFacets();\r\n this.search();\r\n }\r\n\r\n resetFacets() {\r\n if (this.filters.Facets) {\r\n for (const facet of this.filters.Facets) {\r\n facet.Open = false;\r\n for (const item of facet.Items) {\r\n item.Selected = false;\r\n }\r\n }\r\n }\r\n\r\n this.clearPageIndex();\r\n this.filters.SearchBody.Skip = 0;\r\n this.filters.SearchBody.AssignmentTypes = [];\r\n this.filters.SearchBody.CollaborationTypes = [];\r\n this.filters.SearchBody.Genres = [];\r\n this.filters.SearchBody.Levels = [];\r\n this.filters.SearchBody.Topics = [];\r\n this.filters.SearchBody.Writers = [];\r\n this.filters.SearchBody.Subjects = [];\r\n }\r\n\r\n getPageSize() {\r\n if (\r\n this.filters.SearchBody.SearchIn === ContentTypeEnum.Courses ||\r\n this.filters.SearchBody.SearchIn === ContentTypeEnum.Activities\r\n ) {\r\n return 24;\r\n } else {\r\n return 10;\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { PsLibraryFilterEnum } from '../../enums/ps/ps-library-filter.enum';\r\nimport { IPsLibrary } from '../../interfaces/ps/project/ps-library.interface';\r\nimport { IUmbPsLibrary } from '../../interfaces/ps/umbraco/umb-ps-library.interface';\r\nimport { PsArticleMapper } from './ps-article.mapper';\r\nimport { PsAssignmentMapper } from './ps-assignment.mapper';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PsLibraryMapper {\r\n constructor(private psAssignmentMapper: PsAssignmentMapper, private psArticleMapper: PsArticleMapper) {}\r\n\r\n mapLibraryFromApi(data: IUmbPsLibrary): IPsLibrary {\r\n return {\r\n Classes: data.classTags?.length\r\n ? data.classTags.map((item) => ({\r\n Id: item.id,\r\n Title: item.title,\r\n Selected: item.selected,\r\n Type: PsLibraryFilterEnum.Class,\r\n Count: item.itemsCount,\r\n }))\r\n : [],\r\n Subjects: data.subjectTags?.length\r\n ? data.subjectTags.map((item) => ({\r\n Id: item.id,\r\n Title: item.title,\r\n Selected: item.selected,\r\n BackgroundColor: item.backgroundColor,\r\n TextColor: item.textColor,\r\n Type: PsLibraryFilterEnum.Subject,\r\n Count: item.itemsCount,\r\n }))\r\n : [],\r\n Topics: data.topicTags?.length\r\n ? data.topicTags.map((item) => ({\r\n Id: item.id,\r\n Title: item.title,\r\n Selected: item.selected,\r\n Type: PsLibraryFilterEnum.Topic,\r\n Count: item.itemsCount,\r\n }))\r\n : [],\r\n Assignments: data.assignments?.length\r\n ? this.psAssignmentMapper.mapPsAssignmentsFromApi(data.assignments, 250)\r\n : [],\r\n Articles: data.articles?.length ? this.psArticleMapper.mapPsArticlesFromApi(data.articles) : [],\r\n Pagination: {\r\n CollectionSize: data.pagination.collectionSize,\r\n Index: data.pagination.pageIndex,\r\n PageSize: data.pagination.pageSize,\r\n Type: PageTypeEnum.PsArticleLibrary,\r\n },\r\n };\r\n }\r\n}\r\n","import { Location, PlatformLocation } from '@angular/common';\r\nimport { HttpErrorResponse, HttpParams } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { ApiService, GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { ContentTypeEnum } from '@portal-app/enums/content-type.enum';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { EMPTY, ReplaySubject, catchError, firstValueFrom, tap } from 'rxjs';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { PsLibraryFilterEnum } from '../../enums/ps/ps-library-filter.enum';\r\nimport { ILibraryTag } from '../../interfaces/course/project/course-library.interface';\r\nimport { IPsAssignment } from '../../interfaces/ps/project/ps-assignment.interface';\r\nimport { IPsLibraryFilters } from '../../interfaces/ps/project/ps-library.interface';\r\nimport { IUmbPsLibrary } from '../../interfaces/ps/umbraco/umb-ps-library.interface';\r\nimport { PsLibraryMapper } from '../../mapper/ps/ps-library.mapper';\r\nimport { AppInitService } from '../shared/app-init.service';\r\nimport { NavbarService } from '../shared/navbar.service';\r\nimport { PageService } from '../shared/page/page.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PSLibraryService {\r\n filters?: IPsLibraryFilters;\r\n\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n constructor(\r\n private helperService: HelperService,\r\n private platformLocation: PlatformLocation,\r\n private readonly location: Location,\r\n private psLibraryMapper: PsLibraryMapper,\r\n private apiService: ApiService,\r\n private pageService: PageService,\r\n private translate: TranslateService,\r\n private userService: UserService,\r\n private router: Router,\r\n private navbarService: NavbarService,\r\n private gtmService: GoogleTagManagerService,\r\n private appInitService: AppInitService\r\n ) {\r\n this.platformLocation.onPopState(() => {\r\n this.setFiltersToUnloaded();\r\n });\r\n }\r\n\r\n setFiltersToUnloaded() {\r\n if (this.filters) {\r\n this.filters.Loaded = false;\r\n }\r\n }\r\n\r\n private initializeFilters(pageType: PageTypeEnum, id?: number) {\r\n let title: string | undefined;\r\n let contentType: string | undefined;\r\n if (pageType === PageTypeEnum.PsArticleLibrary) {\r\n title = this.translate.instant('ContentType.Articles');\r\n contentType = ContentTypeEnum.PsArticles;\r\n } else if (pageType === PageTypeEnum.PsAssignmentLibrary || pageType === PageTypeEnum.PrintbarAssignmentLibrary) {\r\n title = this.translate.instant('ContentType.Assignments');\r\n contentType = ContentTypeEnum.PsAssignments;\r\n } else if (pageType === PageTypeEnum.PsThemeLibrary) {\r\n contentType = ContentTypeEnum.PSThemes;\r\n }\r\n if (contentType) {\r\n this.filters = {\r\n PageType: pageType,\r\n ContentType: contentType,\r\n Title: title,\r\n Loaded: false,\r\n Loading: false,\r\n SearchBody: {\r\n Id: id,\r\n PageIndex: 1,\r\n SearchText: '',\r\n SelectedTopics: [],\r\n SelectedClasses: [],\r\n SelectedSubjects: [],\r\n OnlyFavorite: undefined,\r\n },\r\n Query: '',\r\n ShowSearch:\r\n pageType === PageTypeEnum.PsAssignmentLibrary || pageType === PageTypeEnum.PrintbarAssignmentLibrary,\r\n ShowSubjectsInHeader:\r\n pageType === PageTypeEnum.PsAssignmentLibrary || pageType === PageTypeEnum.PrintbarAssignmentLibrary,\r\n AssignmentsOpen: [],\r\n OnlyFavorite: {\r\n Checked: false,\r\n Title: this.translate.instant('PsLibrary.FilterOnlyFavoriteTitle'),\r\n },\r\n };\r\n this.data.next(this.filters);\r\n }\r\n }\r\n\r\n async initialize(pageType: PageTypeEnum, id?: number) {\r\n this.initializeFilters(pageType, id);\r\n if (this.filters) {\r\n if (pageType === PageTypeEnum.PsAssignmentLibrary || pageType === PageTypeEnum.PrintbarAssignmentLibrary) {\r\n const assignmentsOpen = this.helperService.getQuerystringFacetList(QueryStrings.Open);\r\n\r\n if (assignmentsOpen.length) {\r\n this.filters.AssignmentsOpen = assignmentsOpen.map((item) => parseInt(item, 0));\r\n }\r\n }\r\n\r\n const urlQuery: string = this.helperService.getQueryParam(QueryStrings.Query) || '*';\r\n this.filters.Query = urlQuery !== '*' ? urlQuery : '';\r\n this.filters.SearchBody.SearchText = urlQuery;\r\n\r\n this.filters.SearchBody.OnlyFavorite = this.userService.isLoggedIn\r\n ? this.helperService.getQueryParam(QueryStrings.OnlyFavourite) === 'true'\r\n : false;\r\n this.filters.OnlyFavorite.Checked = this.filters.SearchBody.OnlyFavorite;\r\n\r\n const page = this.helperService.getQueryParam(QueryStrings.Page);\r\n if (page) {\r\n this.filters.SearchBody.PageIndex = this.helperService.tryParseInt(page, 1);\r\n }\r\n\r\n this.filters.SearchBody.SelectedTopics = this.helperService\r\n .getQuerystringFacetList(QueryStrings.Topics)\r\n .map((item) => parseInt(item, 0));\r\n this.filters.SearchBody.SelectedClasses = this.helperService\r\n .getQuerystringFacetList(QueryStrings.Classes)\r\n .map((item) => parseInt(item, 0));\r\n this.filters.SearchBody.SelectedSubjects = this.helperService\r\n .getQuerystringFacetList(QueryStrings.Subjects)\r\n .map((item) => parseInt(item, 0));\r\n\r\n await this.search();\r\n }\r\n return;\r\n }\r\n\r\n async clearQuery() {\r\n if (this.filters) {\r\n this.filters.Query = '';\r\n await this.search();\r\n }\r\n }\r\n\r\n async search(query?: string) {\r\n if (this.filters) {\r\n this.filters.SearchBody.SearchText = query ? query : this.filters.Query;\r\n const post = this.postSearch();\r\n if (post) {\r\n await firstValueFrom(\r\n post.pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n this.pageService.showError(window.location.pathname, error.status);\r\n return EMPTY;\r\n }),\r\n tap((data) => {\r\n if (this.filters) {\r\n if (this.filters.PageType === PageTypeEnum.PsThemeLibrary) {\r\n this.filters.Title = data.psTheme?.title;\r\n }\r\n this.filters.Data = this.psLibraryMapper.mapLibraryFromApi(data);\r\n if (\r\n this.filters.PageType === PageTypeEnum.PsAssignmentLibrary ||\r\n this.filters.PageType === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n this.filters.AssignmentsOpen.forEach((id) => {\r\n const assignment = this.filters?.Data?.Assignments.find((item) => item.Id === id);\r\n if (assignment) {\r\n assignment.Open = true;\r\n }\r\n });\r\n }\r\n const subject = this.filters.Data.Subjects.find((item) => item.Selected === true);\r\n this.filters.SelectedSubjectBackgroundColor = subject?.BackgroundColor;\r\n this.filters.SelectedSubjectTextColor = subject?.TextColor;\r\n this.setQueryString(true);\r\n this.filters.Loaded = true;\r\n this.data.next(this.filters);\r\n }\r\n })\r\n )\r\n );\r\n }\r\n }\r\n }\r\n\r\n async resetFilters() {\r\n if (this.filters) {\r\n this.filters.SearchBody.SelectedTopics = [];\r\n this.filters.SearchBody.SelectedClasses = [];\r\n this.filters.SearchBody.SelectedSubjects = [];\r\n await this.search();\r\n }\r\n }\r\n\r\n postSearch() {\r\n if (this.filters) {\r\n const body = {\r\n id: this.filters.SearchBody.Id,\r\n pageIndex: this.filters.SearchBody.PageIndex,\r\n selectedTopics: this.filters.SearchBody.SelectedTopics,\r\n selectedSubjects: this.filters.SearchBody.SelectedSubjects,\r\n selectedClasses: this.filters.SearchBody.SelectedClasses,\r\n searchText: this.filters.SearchBody.SearchText,\r\n onlyFavorite: this.filters.SearchBody.OnlyFavorite,\r\n useFallbackSubject: this.appInitService.siteConfiguration.ProjectType === 'PS',\r\n };\r\n if (\r\n this.filters.PageType === PageTypeEnum.PsAssignmentLibrary ||\r\n this.filters.PageType === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n return this.apiService.postUmbraco(\r\n `alineaportal/psassignment/search/${this.appInitService.siteConfiguration.Id}`,\r\n body\r\n );\r\n } else if (this.filters.PageType === PageTypeEnum.PsArticleLibrary) {\r\n return this.apiService.postUmbraco(\r\n `alineaportal/psarticle/search/${this.appInitService.siteConfiguration.Id}`,\r\n body\r\n );\r\n } else if (this.filters.PageType === PageTypeEnum.PsThemeLibrary) {\r\n return this.apiService.postUmbraco(`alineaportal/pstheme/page/fetch/`, body);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n setQueryString(replaceState?: boolean) {\r\n if (this.filters) {\r\n const link = this.helperService.getQueryParam(QueryStrings.Link);\r\n if (!link) {\r\n let params = new HttpParams();\r\n\r\n if (this.filters.SearchBody.SearchText !== '*' && this.filters.SearchBody.SearchText !== '') {\r\n params = params.append(QueryStrings.Query.en, this.filters.SearchBody.SearchText);\r\n }\r\n\r\n if (this.userService.isLoggedIn && this.filters.SearchBody.OnlyFavorite) {\r\n params = params.append(QueryStrings.OnlyFavourite.en, this.filters.SearchBody.OnlyFavorite.toString());\r\n }\r\n\r\n if (this.filters.SearchBody.SelectedTopics.length) {\r\n params = params.append(QueryStrings.Topics.en, this.filters.SearchBody.SelectedTopics.join(','));\r\n }\r\n\r\n if (this.filters.SearchBody.SelectedClasses.length) {\r\n params = params.append(QueryStrings.Classes.en, this.filters.SearchBody.SelectedClasses.join(','));\r\n }\r\n\r\n if (this.filters.SearchBody.SelectedSubjects.length) {\r\n params = params.append(QueryStrings.Subjects.en, this.filters.SearchBody.SelectedSubjects.join(','));\r\n }\r\n\r\n if (this.filters.SearchBody.PageIndex > 1) {\r\n params = params.append(QueryStrings.Page.en, this.filters.SearchBody.PageIndex.toString());\r\n }\r\n\r\n const assignmentsOpen = this.filters.Data?.Assignments.filter((item) => item.Open === true).map((item) => {\r\n return item.Id;\r\n });\r\n if (assignmentsOpen?.length) {\r\n params = params.append(QueryStrings.Open.en, assignmentsOpen.toString());\r\n }\r\n\r\n if (replaceState) {\r\n this.location.replaceState(window.location.pathname, params.toString());\r\n } else {\r\n this.location.go(window.location.pathname, params.toString());\r\n }\r\n } else {\r\n const params = new URLSearchParams(window.location.search);\r\n params.delete(QueryStrings.Link.en);\r\n this.location.replaceState(window.location.pathname, params.toString());\r\n }\r\n }\r\n }\r\n\r\n toggleFiltersOpen() {\r\n if (this.filters) {\r\n this.filters.FiltersOpen = !this.filters.FiltersOpen;\r\n this.gtmService.pushTagWithUserType(GTMEvent.filter_accordion, {\r\n setting: this.filters.FiltersOpen,\r\n });\r\n }\r\n }\r\n\r\n async toggleSubjectFilter(filter: ILibraryTag) {\r\n if (this.filters?.Data) {\r\n if (\r\n this.filters.PageType === PageTypeEnum.PsAssignmentLibrary ||\r\n this.filters.PageType === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n this.filters.SearchBody.SelectedClasses = [];\r\n this.filters.SearchBody.SelectedTopics = [];\r\n }\r\n this.filters.Data.Subjects = this.filters.Data.Subjects.map((item) => {\r\n if (item.Id === filter.Id) {\r\n item.Selected = !item.Selected;\r\n } else {\r\n item.Selected = item.Id === filter.Id;\r\n }\r\n return item;\r\n });\r\n const elem = this.filters.Data.Subjects.find((item) => item.Id === filter.Id);\r\n if (elem) {\r\n if (elem.Selected) {\r\n this.filters.SearchBody.SelectedSubjects = [elem.Id];\r\n this.filters.SelectedSubjectBackgroundColor = elem.BackgroundColor;\r\n this.filters.SelectedSubjectTextColor = elem.TextColor;\r\n } else {\r\n this.filters.SearchBody.SelectedSubjects = [];\r\n this.filters.SelectedSubjectBackgroundColor = undefined;\r\n this.filters.SelectedSubjectTextColor = undefined;\r\n }\r\n this.filters.SearchBody.PageIndex = 1;\r\n await this.search();\r\n this.setQueryString();\r\n }\r\n }\r\n }\r\n\r\n async toggleFilter(filter: ILibraryTag) {\r\n if (this.filters) {\r\n let elem: ILibraryTag | undefined;\r\n if (filter.Type === PsLibraryFilterEnum.Topic) {\r\n elem = this.filters.Data?.Topics.find((item) => item.Id === filter.Id);\r\n } else if (filter.Type === PsLibraryFilterEnum.Class) {\r\n elem = this.filters.Data?.Classes.find((item) => item.Id === filter.Id);\r\n } else if (filter.Type === PsLibraryFilterEnum.Subject) {\r\n elem = this.filters.Data?.Subjects.find((item) => item.Id === filter.Id);\r\n }\r\n if (elem) {\r\n elem.Selected = !elem.Selected;\r\n if (elem.Selected) {\r\n if (filter.Type === PsLibraryFilterEnum.Topic) {\r\n this.filters.SearchBody.SelectedTopics.push(elem.Id);\r\n } else if (filter.Type === PsLibraryFilterEnum.Class) {\r\n this.filters.SearchBody.SelectedClasses.push(elem.Id);\r\n } else if (filter.Type === PsLibraryFilterEnum.Subject) {\r\n this.filters.SearchBody.SelectedSubjects.push(elem.Id);\r\n }\r\n } else {\r\n if (filter.Type === PsLibraryFilterEnum.Topic) {\r\n this.filters.SearchBody.SelectedTopics = this.filters.SearchBody.SelectedTopics.filter(\r\n (item) => item !== elem?.Id\r\n );\r\n } else if (filter.Type === PsLibraryFilterEnum.Class) {\r\n this.filters.SearchBody.SelectedClasses = this.filters.SearchBody.SelectedClasses.filter(\r\n (item) => item !== elem?.Id\r\n );\r\n } else if (filter.Type === PsLibraryFilterEnum.Subject) {\r\n this.filters.SearchBody.SelectedSubjects = this.filters.SearchBody.SelectedSubjects.filter(\r\n (item) => item !== elem?.Id\r\n );\r\n }\r\n }\r\n this.filters.SearchBody.PageIndex = 1;\r\n await this.search();\r\n this.setQueryString();\r\n }\r\n }\r\n }\r\n\r\n setAssignmentOpen(assignment: IPsAssignment) {\r\n if (this.filters) {\r\n if (assignment.Open) {\r\n this.filters.AssignmentsOpen.push(assignment.Id);\r\n } else {\r\n this.filters.AssignmentsOpen = this.filters.AssignmentsOpen.filter((item) => item !== assignment.Id);\r\n }\r\n this.setQueryString();\r\n }\r\n }\r\n\r\n async changePage(pageIndex: number) {\r\n if (this.filters?.Data) {\r\n this.filters.Data.Pagination.Index = pageIndex;\r\n this.filters.SearchBody.PageIndex = pageIndex;\r\n window.scroll(0, 0);\r\n await this.search();\r\n }\r\n }\r\n\r\n async onlyFavoriteChange(checked: boolean) {\r\n if (this.filters) {\r\n this.filters.SearchBody.OnlyFavorite = checked;\r\n await this.search();\r\n }\r\n }\r\n\r\n async setTotalFavoritesCount(id: string) {\r\n if (this.filters) {\r\n const found =\r\n this.filters.Data?.Articles.find((item) => item.Id.toString() === id) ||\r\n this.filters.Data?.Assignments.find((item) => item.Id.toString() === id);\r\n\r\n if (found) {\r\n found.IsFavorite = !found.IsFavorite;\r\n }\r\n\r\n if (\r\n !this.filters.Data?.Articles.find((item) => item.IsFavorite) &&\r\n !this.filters.Data?.Assignments.find((item) => item.IsFavorite)\r\n ) {\r\n this.filters.OnlyFavorite.Checked = false;\r\n this.filters.SearchBody.OnlyFavorite = false;\r\n await this.search();\r\n }\r\n }\r\n }\r\n\r\n async assignmentTagClick(tag: ILibraryTag) {\r\n const url = await firstValueFrom(this.navbarService.psAssignmentLibraryUrl$);\r\n let params = new HttpParams();\r\n\r\n if (tag.Type === PsLibraryFilterEnum.Level) {\r\n params = params.append(QueryStrings.Classes.en, tag.Id);\r\n } else if (tag.Type === PsLibraryFilterEnum.Topic) {\r\n params = params.append(QueryStrings.Topics.en, tag.Id);\r\n }\r\n\r\n params = params.append(QueryStrings.Link.en, true);\r\n\r\n await this.router.navigateByUrl(`${url}?${params.toString()}`, {\r\n skipLocationChange: false,\r\n });\r\n }\r\n\r\n async articleTagClick(tag: ILibraryTag) {\r\n const url = await firstValueFrom(this.navbarService.psArticleLibraryUrl$);\r\n\r\n let params = new HttpParams();\r\n\r\n if (tag.Type === PsLibraryFilterEnum.Topic) {\r\n params = params.append(QueryStrings.Topics.en, tag.Id);\r\n }\r\n params = params.append(QueryStrings.Link.en, true);\r\n\r\n await this.router.navigateByUrl(`${url}?${params.toString()}`, {\r\n skipLocationChange: false,\r\n });\r\n }\r\n}\r\n","var _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n// Save the previous value of the device variable.\nvar previousDevice = window.device;\n\nvar device = {};\n\nvar changeOrientationList = [];\n\n// Add device as a global object.\nwindow.device = device;\n\n// The element.\nvar documentElement = window.document.documentElement;\n\n// The client user agent string.\n// Lowercase, so we can use the more efficient indexOf(), instead of Regex\nvar userAgent = window.navigator.userAgent.toLowerCase();\n\n// Detectable television devices.\nvar television = ['googletv', 'viera', 'smarttv', 'internet.tv', 'netcast', 'nettv', 'appletv', 'boxee', 'kylo', 'roku', 'dlnadoc', 'pov_tv', 'hbbtv', 'ce-html'];\n\n// Main functions\n// --------------\n\ndevice.macos = function () {\n return find('mac');\n};\n\ndevice.ios = function () {\n return device.iphone() || device.ipod() || device.ipad();\n};\n\ndevice.iphone = function () {\n return !device.windows() && find('iphone');\n};\n\ndevice.ipod = function () {\n return find('ipod');\n};\n\ndevice.ipad = function () {\n var iPadOS13Up = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;\n return find('ipad') || iPadOS13Up;\n};\n\ndevice.android = function () {\n return !device.windows() && find('android');\n};\n\ndevice.androidPhone = function () {\n return device.android() && find('mobile');\n};\n\ndevice.androidTablet = function () {\n return device.android() && !find('mobile');\n};\n\ndevice.blackberry = function () {\n return find('blackberry') || find('bb10');\n};\n\ndevice.blackberryPhone = function () {\n return device.blackberry() && !find('tablet');\n};\n\ndevice.blackberryTablet = function () {\n return device.blackberry() && find('tablet');\n};\n\ndevice.windows = function () {\n return find('windows');\n};\n\ndevice.windowsPhone = function () {\n return device.windows() && find('phone');\n};\n\ndevice.windowsTablet = function () {\n return device.windows() && find('touch') && !device.windowsPhone();\n};\n\ndevice.fxos = function () {\n return (find('(mobile') || find('(tablet')) && find(' rv:');\n};\n\ndevice.fxosPhone = function () {\n return device.fxos() && find('mobile');\n};\n\ndevice.fxosTablet = function () {\n return device.fxos() && find('tablet');\n};\n\ndevice.meego = function () {\n return find('meego');\n};\n\ndevice.cordova = function () {\n return window.cordova && location.protocol === 'file:';\n};\n\ndevice.nodeWebkit = function () {\n return _typeof(window.process) === 'object';\n};\n\ndevice.mobile = function () {\n return device.androidPhone() || device.iphone() || device.ipod() || device.windowsPhone() || device.blackberryPhone() || device.fxosPhone() || device.meego();\n};\n\ndevice.tablet = function () {\n return device.ipad() || device.androidTablet() || device.blackberryTablet() || device.windowsTablet() || device.fxosTablet();\n};\n\ndevice.desktop = function () {\n return !device.tablet() && !device.mobile();\n};\n\ndevice.television = function () {\n var i = 0;\n while (i < television.length) {\n if (find(television[i])) {\n return true;\n }\n i++;\n }\n return false;\n};\n\ndevice.portrait = function () {\n if (screen.orientation && Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {\n return includes(screen.orientation.type, 'portrait');\n }\n if (device.ios() && Object.prototype.hasOwnProperty.call(window, 'orientation')) {\n return Math.abs(window.orientation) !== 90;\n }\n return window.innerHeight / window.innerWidth > 1;\n};\n\ndevice.landscape = function () {\n if (screen.orientation && Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {\n return includes(screen.orientation.type, 'landscape');\n }\n if (device.ios() && Object.prototype.hasOwnProperty.call(window, 'orientation')) {\n return Math.abs(window.orientation) === 90;\n }\n return window.innerHeight / window.innerWidth < 1;\n};\n\n// Public Utility Functions\n// ------------------------\n\n// Run device.js in noConflict mode,\n// returning the device variable to its previous owner.\ndevice.noConflict = function () {\n window.device = previousDevice;\n return this;\n};\n\n// Private Utility Functions\n// -------------------------\n\n// Check if element exists\nfunction includes(haystack, needle) {\n return haystack.indexOf(needle) !== -1;\n}\n\n// Simple UA string search\nfunction find(needle) {\n return includes(userAgent, needle);\n}\n\n// Check if documentElement already has a given class.\nfunction hasClass(className) {\n return documentElement.className.match(new RegExp(className, 'i'));\n}\n\n// Add one or more CSS classes to the element.\nfunction addClass(className) {\n var currentClassNames = null;\n if (!hasClass(className)) {\n currentClassNames = documentElement.className.replace(/^\\s+|\\s+$/g, '');\n documentElement.className = currentClassNames + ' ' + className;\n }\n}\n\n// Remove single CSS class from the element.\nfunction removeClass(className) {\n if (hasClass(className)) {\n documentElement.className = documentElement.className.replace(' ' + className, '');\n }\n}\n\n// HTML Element Handling\n// ---------------------\n\n// Insert the appropriate CSS class based on the _user_agent.\n\nif (device.ios()) {\n if (device.ipad()) {\n addClass('ios ipad tablet');\n } else if (device.iphone()) {\n addClass('ios iphone mobile');\n } else if (device.ipod()) {\n addClass('ios ipod mobile');\n }\n} else if (device.macos()) {\n addClass('macos desktop');\n} else if (device.android()) {\n if (device.androidTablet()) {\n addClass('android tablet');\n } else {\n addClass('android mobile');\n }\n} else if (device.blackberry()) {\n if (device.blackberryTablet()) {\n addClass('blackberry tablet');\n } else {\n addClass('blackberry mobile');\n }\n} else if (device.windows()) {\n if (device.windowsTablet()) {\n addClass('windows tablet');\n } else if (device.windowsPhone()) {\n addClass('windows mobile');\n } else {\n addClass('windows desktop');\n }\n} else if (device.fxos()) {\n if (device.fxosTablet()) {\n addClass('fxos tablet');\n } else {\n addClass('fxos mobile');\n }\n} else if (device.meego()) {\n addClass('meego mobile');\n} else if (device.nodeWebkit()) {\n addClass('node-webkit');\n} else if (device.television()) {\n addClass('television');\n} else if (device.desktop()) {\n addClass('desktop');\n}\n\nif (device.cordova()) {\n addClass('cordova');\n}\n\n// Orientation Handling\n// --------------------\n\n// Handle device orientation changes.\nfunction handleOrientation() {\n if (device.landscape()) {\n removeClass('portrait');\n addClass('landscape');\n walkOnChangeOrientationList('landscape');\n } else {\n removeClass('landscape');\n addClass('portrait');\n walkOnChangeOrientationList('portrait');\n }\n setOrientationCache();\n}\n\nfunction walkOnChangeOrientationList(newOrientation) {\n for (var index = 0; index < changeOrientationList.length; index++) {\n changeOrientationList[index](newOrientation);\n }\n}\n\ndevice.onChangeOrientation = function (cb) {\n if (typeof cb == 'function') {\n changeOrientationList.push(cb);\n }\n};\n\n// Detect whether device supports orientationchange event,\n// otherwise fall back to the resize event.\nvar orientationEvent = 'resize';\nif (Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {\n orientationEvent = 'orientationchange';\n}\n\n// Listen for changes in orientation.\nif (window.addEventListener) {\n window.addEventListener(orientationEvent, handleOrientation, false);\n} else if (window.attachEvent) {\n window.attachEvent(orientationEvent, handleOrientation);\n} else {\n window[orientationEvent] = handleOrientation;\n}\n\nhandleOrientation();\n\n// Public functions to get the current value of type, os, or orientation\n// ---------------------------------------------------------------------\n\nfunction findMatch(arr) {\n for (var i = 0; i < arr.length; i++) {\n if (device[arr[i]]()) {\n return arr[i];\n }\n }\n return 'unknown';\n}\n\ndevice.type = findMatch(['mobile', 'tablet', 'desktop']);\ndevice.os = findMatch(['ios', 'iphone', 'ipad', 'ipod', 'android', 'blackberry', 'macos', 'windows', 'fxos', 'meego', 'television']);\n\nfunction setOrientationCache() {\n device.orientation = findMatch(['portrait', 'landscape']);\n}\n\nsetOrientationCache();\n\nexport default device;","import { Injectable } from '@angular/core';\r\nimport { MenuTypeEnum } from '@portal-app/enums/menu-type.enum';\r\nimport {\r\n ILibraryCategory,\r\n ILibraryCategoryTag,\r\n ISiteConfiguration,\r\n ISiteHeaderColors,\r\n} from '@portal-app/interfaces/project/site-configuration.interface';\r\nimport {\r\n IUmbSiteConfiguration,\r\n IUmbSiteConfigurationSettings,\r\n IUmbSiteConfigurationSettingsFilterTag,\r\n} from '@portal-app/interfaces/umbraco/umb-site-configuration.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SiteConfigurationMapper {\r\n mapSiteConfigurationFromApi(siteConfiguration: IUmbSiteConfiguration): ISiteConfiguration {\r\n const result: ISiteConfiguration = {\r\n Id: siteConfiguration.id.toString(),\r\n BasePath: '',\r\n ISBNs: siteConfiguration.isbns || [],\r\n ProjectType: siteConfiguration.category,\r\n ProjectGroup: siteConfiguration.portalProducts[0].externalId,\r\n NavbarId: siteConfiguration.menus.find((x) => x.type === MenuTypeEnum.Primary && x.isActive === true)?.id,\r\n MegaMenuId: siteConfiguration.menus.find((x) => x.type === MenuTypeEnum.Mega && x.isActive === true)?.id,\r\n Title: siteConfiguration.name,\r\n PrimaryColor: siteConfiguration.primaryColor || '#ff0000',\r\n PrimaryTextColor: siteConfiguration.primaryTextColor || '#ffffff',\r\n SecondaryColor: siteConfiguration.secondaryColor || '#00ff00',\r\n SecondaryTextColor: siteConfiguration.secondaryTextColor || '#ffffff',\r\n SiteBackgroundColor: siteConfiguration.siteBackgroundColor || '#ffffff',\r\n SiteLinkColor: siteConfiguration.siteLinkColor || '#000000',\r\n SiteTextColor: siteConfiguration.siteTextColor || '#1b1b1b',\r\n PortalId: siteConfiguration.portalId,\r\n HeaderColors: this.getPortalHeaderColors(siteConfiguration),\r\n ErrorPages: siteConfiguration.errorpages.map((item) => {\r\n return {\r\n Id: item.id,\r\n StatusCode: item.statusCode.toString(),\r\n };\r\n }),\r\n GoogleVerificationId: siteConfiguration.googleSiteVerificationCode,\r\n GoogleTagManagerId: siteConfiguration.googleGTM,\r\n FrontpageId: siteConfiguration.frontpage ? siteConfiguration.frontpage.id : undefined,\r\n LibraryCategories: this.mapLibraryCategories(siteConfiguration.portalSettings),\r\n logo:\r\n siteConfiguration.logoImageUrl || siteConfiguration.mobileLogoImageUrl\r\n ? {\r\n mobile: siteConfiguration.mobileLogoImageUrl ?? undefined,\r\n default: siteConfiguration.logoImageUrl ?? undefined,\r\n }\r\n : undefined,\r\n language: siteConfiguration.languageIsoCode,\r\n onlyLicenseToggle: siteConfiguration.onlyLicenseToggle,\r\n };\r\n // result.ISBNs.push(\"9788723907998\"); //superreader\r\n // result.ISBNs.push(\"9788723526908\"); //dansk\r\n // result.ISBNs.push(\"fagportalstartsider\"); //fagportalstartsider\r\n return result;\r\n }\r\n\r\n mapLibraryCategories(settings: IUmbSiteConfigurationSettings): ILibraryCategory[] | undefined {\r\n if (!settings) {\r\n return;\r\n }\r\n const result: ILibraryCategory[] = [];\r\n for (const item of settings?.filtering?.filters) {\r\n const category: ILibraryCategory = {\r\n Text1: item.text1,\r\n Text2: item.text2,\r\n IconUrl: item.iconUrl,\r\n Emoji: item.emoji,\r\n BackgroundColorHex: item.backgroundColorHex,\r\n BookSubject: item.bookSubject ? this.mapLibraryCategoryTag(item.bookSubject) : undefined,\r\n BookTopic: item.bookTopic ? this.mapLibraryCategoryTag(item.bookTopic) : undefined,\r\n PortalLevels: item.portalLevels\r\n ? item.portalLevels.map((elem) => {\r\n return this.mapLibraryCategoryTag(elem);\r\n })\r\n : [],\r\n };\r\n result.push(category);\r\n }\r\n return result;\r\n }\r\n\r\n mapLibraryCategoryTag(item: IUmbSiteConfigurationSettingsFilterTag): ILibraryCategoryTag {\r\n const result: ILibraryCategoryTag = {\r\n Id: item.externalId,\r\n Title: item.title,\r\n };\r\n return result;\r\n }\r\n\r\n getPortalHeaderColors(siteConfiguration: IUmbSiteConfiguration): ISiteHeaderColors {\r\n const result: ISiteHeaderColors = {\r\n PrimaryBackgroundColor: '',\r\n PrimaryTextColor: '',\r\n SecondaryBackgroundColor: '',\r\n SecondaryTextColor: '',\r\n };\r\n\r\n if (siteConfiguration.headerPrimaryBackgroundColor) {\r\n result.PrimaryBackgroundColor = siteConfiguration.headerPrimaryBackgroundColor;\r\n } else {\r\n result.PrimaryBackgroundColor = siteConfiguration.primaryColor;\r\n }\r\n\r\n if (siteConfiguration.headerPrimaryTextColor) {\r\n result.PrimaryTextColor = siteConfiguration.headerPrimaryTextColor;\r\n } else {\r\n result.PrimaryTextColor = '#ffffff';\r\n }\r\n if (siteConfiguration.headerSecondaryBackgroundColor) {\r\n result.SecondaryBackgroundColor = siteConfiguration.headerSecondaryBackgroundColor;\r\n } else {\r\n if (siteConfiguration.headerPrimaryBackgroundColor) {\r\n result.SecondaryBackgroundColor = siteConfiguration.headerPrimaryBackgroundColor;\r\n } else {\r\n result.SecondaryBackgroundColor = siteConfiguration.primaryColor;\r\n }\r\n }\r\n\r\n if (siteConfiguration.headerSecondaryTextColor) {\r\n result.SecondaryTextColor = siteConfiguration.headerSecondaryTextColor;\r\n } else {\r\n if (siteConfiguration.headerPrimaryTextColor) {\r\n result.SecondaryTextColor = siteConfiguration.headerPrimaryTextColor;\r\n } else {\r\n result.SecondaryTextColor = '#ffffff';\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n}\r\n","import { DOCUMENT } from '@angular/common';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Inject, Injectable, Injector } from '@angular/core';\r\nimport { ApiService, CssColorService, GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { IIsbn } from '@lru/felib/lib/services/core/user/interfaces/isbn.interface';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { ProjectTypeEnum } from '@portal-app/enums/project-type.enum';\r\nimport { ISiteConfiguration } from '@portal-app/interfaces/project/site-configuration.interface';\r\nimport { UmbLanguageType } from '@portal-app/interfaces/umbraco/umb-language.type';\r\nimport { IUmbSiteConfiguration } from '@portal-app/interfaces/umbraco/umb-site-configuration.interface';\r\nimport { SiteConfigurationMapper } from '@portal-app/mapper/shared/site-configuration.mapper';\r\nimport { environment } from '@portal-env/environment';\r\nimport device from 'current-device';\r\nimport { firstValueFrom, iif, of } from 'rxjs';\r\nimport { map, retry, switchMap, tap } from 'rxjs/operators';\r\nimport { HelperService } from './helper.service';\r\nimport { SeoService } from './seo.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class AppInitService {\r\n siteConfiguration = this.setDefaultSiteConfiguration();\r\n\r\n constructor(\r\n private translateService: TranslateService,\r\n private apiService: ApiService,\r\n private siteConfigurationMapper: SiteConfigurationMapper,\r\n private userService: UserService,\r\n private httpClient: HttpClient,\r\n private helperService: HelperService,\r\n private googleTagManagerService: GoogleTagManagerService,\r\n private cssColorService: CssColorService,\r\n private injector: Injector,\r\n @Inject(DOCUMENT) private document: Document\r\n ) {}\r\n\r\n public setDefaultSiteConfiguration(): ISiteConfiguration {\r\n return {\r\n ISBNs: [],\r\n PrimaryColor: '#ff0000',\r\n PrimaryTextColor: '#ffffff',\r\n SecondaryColor: '#00ff00',\r\n SecondaryTextColor: '#ffffff',\r\n SiteBackgroundColor: '#ffffff',\r\n SiteLinkColor: '#000000',\r\n SiteTextColor: '#1b1b1b',\r\n ErrorPages: [],\r\n language: 'da',\r\n onlyLicenseToggle: true,\r\n };\r\n }\r\n\r\n async Init() {\r\n window.bk = window.bk || new Date().getTime();\r\n window.useWebP = this.canUseWebP();\r\n window.scrollLocked = false;\r\n window.scrollbarWidth = this.getScrollbarWidth();\r\n window.error = window.error;\r\n window.device = device;\r\n\r\n localStorage.removeItem('lastUpdated');\r\n await this.startup();\r\n }\r\n\r\n setLang(lang: UmbLanguageType, projectType?: ProjectTypeEnum) {\r\n /** Sets the lang attribute of the html tag in the root index.html */\r\n this.document.documentElement.setAttribute('lang', lang);\r\n\r\n const languagesToAdd = [`base/${lang}`];\r\n let useLang$ = this.translateService.use(`base/${lang}`);\r\n\r\n switch (projectType) {\r\n case ProjectTypeEnum.SuperReader:\r\n case ProjectTypeEnum.Superbog:\r\n languagesToAdd.push(`superreader/${lang}`);\r\n useLang$ = this.translateService.use(`superreader/${lang}`);\r\n break;\r\n case ProjectTypeEnum.PrintBar:\r\n languagesToAdd.push(`printbar/${lang}`);\r\n useLang$ = this.translateService.use(`printbar/${lang}`);\r\n break;\r\n }\r\n\r\n this.translateService.addLangs(languagesToAdd);\r\n this.translateService.setDefaultLang(`base/${lang}`);\r\n\r\n return useLang$;\r\n }\r\n\r\n private async startup() {\r\n return firstValueFrom(\r\n this.apiService\r\n .getUmbraco(`alineaportal/getportal/${this.hostName}/${this.userService.userType}`)\r\n .pipe(\r\n tap((config) => (this.siteConfiguration = this.siteConfigurationMapper.mapSiteConfigurationFromApi(config))),\r\n map((config) => this.siteConfigurationMapper.mapSiteConfigurationFromApi(config)),\r\n tap(() => {\r\n if (this.siteConfiguration.ProjectType && this.siteConfiguration.Title) {\r\n this.updateSiteManifest(this.siteConfiguration.ProjectType, this.siteConfiguration.Title);\r\n\r\n if (this.siteConfiguration.ProjectType) {\r\n this.setStylesheet(this.siteConfiguration.ProjectType);\r\n }\r\n\r\n if (this.siteConfiguration.ProjectType) {\r\n this.setTheme(this.siteConfiguration.ProjectType);\r\n }\r\n\r\n this.addGoogleTagManager();\r\n\r\n /** Using injector to not run into circular dependency - SeoService requires AppInitService */\r\n const seoService = this.injector.get(SeoService);\r\n seoService.setGoogleVerificationId(this.siteConfiguration.GoogleVerificationId);\r\n }\r\n }),\r\n switchMap(() =>\r\n this.setLang(\r\n this.siteConfiguration.language ?? environment.fallbackLanguage,\r\n this.siteConfiguration.ProjectType\r\n )\r\n ),\r\n switchMap(() => iif(() => !!this.siteConfiguration.ProjectGroup, this.gethHostUrl(), of(undefined))),\r\n retry(2),\r\n tap((basePath) => {\r\n if (this.siteConfiguration && basePath) {\r\n this.siteConfiguration.BasePath = basePath;\r\n }\r\n if (window.error?.Message) {\r\n throw window.error;\r\n }\r\n })\r\n )\r\n );\r\n }\r\n\r\n private gethHostUrl() {\r\n return this.apiService.getNext(`projectgroup/gethosturl/${this.siteConfiguration.ProjectGroup}`);\r\n }\r\n\r\n private addGoogleTagManager() {\r\n if (this.shouldUseTagManager && this.siteConfiguration?.GoogleTagManagerId) {\r\n this.googleTagManagerService.setId(this.siteConfiguration.GoogleTagManagerId);\r\n this.googleTagManagerService.addToDOM();\r\n }\r\n }\r\n\r\n /**\r\n * This will update the manifest.json\r\n * @param projectType - project category name (see ProjectTypeEnum)\r\n * @param name - project name\r\n */\r\n private async updateSiteManifest(projectType: ProjectTypeEnum, name: string) {\r\n const manifestName = this.isFagportal === true ? projectType + ' - ' + name : projectType;\r\n\r\n await firstValueFrom(\r\n this.httpClient.post(environment.internalBackendUrl() + 'Home/UpdateSiteManifest', {\r\n withCredentials: true,\r\n productName: manifestName,\r\n })\r\n );\r\n }\r\n\r\n private setTheme(projectType: ProjectTypeEnum) {\r\n if (projectType === ProjectTypeEnum.PS) {\r\n document.documentElement.classList.add('theme-dark');\r\n } else {\r\n document.documentElement.classList.add('theme-light');\r\n }\r\n }\r\n\r\n public setStylesheet(projectType: ProjectTypeEnum) {\r\n const head = document.head;\r\n const link = document.createElement('link');\r\n\r\n link.type = 'text/css';\r\n link.rel = 'stylesheet';\r\n\r\n // This is to include local style sheet for the specified project type\r\n let href = '';\r\n switch (projectType) {\r\n case ProjectTypeEnum.Fagportal:\r\n href = 'fag';\r\n break;\r\n case ProjectTypeEnum.SuperReader:\r\n case ProjectTypeEnum.Superbog:\r\n href = 'sup';\r\n this.cssColorService.setCssColors({\r\n prefix: 'felib',\r\n items: [\r\n {\r\n name: 'primary-teacher',\r\n hex100: this.siteConfiguration.PrimaryColor,\r\n add100Suffix: true,\r\n variants: [80, 50, 20, 10],\r\n },\r\n {\r\n name: 'primary-student',\r\n hex100: this.siteConfiguration.PrimaryColor,\r\n add100Suffix: true,\r\n variants: [80, 50, 20, 10],\r\n },\r\n {\r\n name: 'success',\r\n hex100: '#6dddb2',\r\n },\r\n {\r\n name: 'error',\r\n hex100: '#e8505c',\r\n },\r\n {\r\n name: 'grey',\r\n hex100: '#071839',\r\n add100Suffix: true,\r\n variants: [90, 80, 70, 60, 50, 40, 30, 20, 10],\r\n },\r\n ],\r\n });\r\n break;\r\n case ProjectTypeEnum.PS:\r\n href = 'ps';\r\n break;\r\n case ProjectTypeEnum.PrintBar:\r\n href = 'printbar';\r\n break;\r\n default:\r\n href = 'fag';\r\n }\r\n\r\n link.href = `${this.helperService.isLocalhost() ? '' : '/bundles'}/${href}.min.css?bk=${window.bk}`;\r\n\r\n head.appendChild(link);\r\n\r\n if (this.siteConfiguration) {\r\n const siteBackgroundColor = this.helperService.hexToRgb(this.siteConfiguration.SiteBackgroundColor);\r\n const siteTextColor = this.helperService.hexToRgb(this.siteConfiguration.SiteTextColor);\r\n const siteLinkColor = this.helperService.hexToRgb(this.siteConfiguration.SiteLinkColor);\r\n const primaryColor = this.helperService.hexToRgb(this.siteConfiguration.PrimaryColor);\r\n const primaryTextColor = this.helperService.hexToRgb(this.siteConfiguration.PrimaryTextColor);\r\n const secondaryColor = this.helperService.hexToRgb(this.siteConfiguration.SecondaryColor);\r\n const secondaryTextColor = this.helperService.hexToRgb(this.siteConfiguration.SecondaryTextColor);\r\n\r\n if (siteBackgroundColor) {\r\n document.documentElement.style.setProperty('--color-background', siteBackgroundColor);\r\n }\r\n if (siteTextColor) {\r\n document.documentElement.style.setProperty('--color-text', siteTextColor);\r\n }\r\n if (siteLinkColor) {\r\n document.documentElement.style.setProperty('--color-link', siteLinkColor);\r\n }\r\n if (primaryColor) {\r\n document.documentElement.style.setProperty('--color-primary-background', primaryColor);\r\n }\r\n if (primaryTextColor) {\r\n document.documentElement.style.setProperty('--color-primary-text', primaryTextColor);\r\n }\r\n if (secondaryColor) {\r\n document.documentElement.style.setProperty('--color-secondary-background', secondaryColor);\r\n }\r\n if (secondaryTextColor) {\r\n document.documentElement.style.setProperty('--color-secondary-text', secondaryTextColor);\r\n }\r\n }\r\n }\r\n\r\n private get hostName() {\r\n return this.helperService.isLocalhost() ? environment.localHostName : window.location.hostname;\r\n }\r\n\r\n getErrorPage(statusCode: string): number | undefined {\r\n return this.siteConfiguration.ErrorPages.find((item) => item.StatusCode === statusCode)?.Id;\r\n }\r\n\r\n private getScrollbarWidth() {\r\n // Creating invisible container\r\n const outer = document.createElement('div');\r\n outer.style.visibility = 'hidden';\r\n outer.style.overflow = 'scroll'; // forcing scrollbar to appear\r\n document.body.appendChild(outer);\r\n\r\n // Creating inner element and placing it in the container\r\n const inner = document.createElement('div');\r\n outer.appendChild(inner);\r\n\r\n // Calculating difference between container's full width and the child width\r\n const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\r\n\r\n // Removing temporary elements from the DOM\r\n outer.parentNode?.removeChild(outer);\r\n return scrollbarWidth;\r\n }\r\n\r\n private canUseWebP() {\r\n const elem = document.createElement('canvas');\r\n\r\n if (!!(elem.getContext && elem.getContext('2d'))) {\r\n // was able or not to get WebP representation\r\n return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;\r\n }\r\n\r\n // very old browser like IE 8, canvas not supported\r\n return false;\r\n }\r\n\r\n public setISBNs(isbns: string[]) {\r\n const body = {\r\n ISBNs: isbns,\r\n };\r\n\r\n this.apiService.postInternalBackend('ISBN/Check/', body).subscribe((isbns: IIsbn[]) => {\r\n if (isbns?.length) {\r\n this.userService.setISBNs(isbns);\r\n }\r\n });\r\n }\r\n\r\n get isPs() {\r\n return this.siteConfiguration.ProjectType === ProjectTypeEnum.PS;\r\n }\r\n get isSuperbog() {\r\n return this.siteConfiguration.ProjectType === ProjectTypeEnum.Superbog;\r\n }\r\n get isSuperreader() {\r\n return this.siteConfiguration.ProjectType === ProjectTypeEnum.SuperReader;\r\n }\r\n get isFagportal() {\r\n return this.siteConfiguration.ProjectType === ProjectTypeEnum.Fagportal;\r\n }\r\n\r\n get shouldUseTagManager() {\r\n if (location.hostname !== 'localhost' && this.siteConfiguration.GoogleTagManagerId) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n setHeaderHeight(height: number) {\r\n this.siteConfiguration.HeaderHeight = height;\r\n }\r\n}\r\n","import { MonoTypeOperatorFunction, ObservableInput } from '../types';\nimport { operate } from '../util/lift';\nimport { Subscription } from '../Subscription';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { identity } from '../util/identity';\nimport { timer } from '../observable/timer';\nimport { innerFrom } from '../observable/innerFrom';\n\n/**\n * The {@link retry} operator configuration object. `retry` either accepts a `number`\n * or an object described by this interface.\n */\nexport interface RetryConfig {\n /**\n * The maximum number of times to retry. If `count` is omitted, `retry` will try to\n * resubscribe on errors infinite number of times.\n */\n count?: number;\n /**\n * The number of milliseconds to delay before retrying, OR a function to\n * return a notifier for delaying. If a function is given, that function should\n * return a notifier that, when it emits will retry the source. If the notifier\n * completes _without_ emitting, the resulting observable will complete without error,\n * if the notifier errors, the error will be pushed to the result.\n */\n delay?: number | ((error: any, retryCount: number) => ObservableInput);\n /**\n * Whether or not to reset the retry counter when the retried subscription\n * emits its first value.\n */\n resetOnSuccess?: boolean;\n}\n\nexport function retry(count?: number): MonoTypeOperatorFunction;\nexport function retry(config: RetryConfig): MonoTypeOperatorFunction;\n\n/**\n * Returns an Observable that mirrors the source Observable with the exception of an `error`.\n *\n * If the source Observable calls `error`, this method will resubscribe to the source Observable for a maximum of\n * `count` resubscriptions rather than propagating the `error` call.\n *\n * ![](retry.png)\n *\n * The number of retries is determined by the `count` parameter. It can be set either by passing a number to\n * `retry` function or by setting `count` property when `retry` is configured using {@link RetryConfig}. If\n * `count` is omitted, `retry` will try to resubscribe on errors infinite number of times.\n *\n * Any and all items emitted by the source Observable will be emitted by the resulting Observable, even those\n * emitted during failed subscriptions. For example, if an Observable fails at first but emits `[1, 2]` then\n * succeeds the second time and emits: `[1, 2, 3, 4, 5, complete]` then the complete stream of emissions and\n * notifications would be: `[1, 2, 1, 2, 3, 4, 5, complete]`.\n *\n * ## Example\n *\n * ```ts\n * import { interval, mergeMap, throwError, of, retry } from 'rxjs';\n *\n * const source = interval(1000);\n * const result = source.pipe(\n * mergeMap(val => val > 5 ? throwError(() => 'Error!') : of(val)),\n * retry(2) // retry 2 times on error\n * );\n *\n * result.subscribe({\n * next: value => console.log(value),\n * error: err => console.log(`${ err }: Retried 2 times then quit!`)\n * });\n *\n * // Output:\n * // 0..1..2..3..4..5..\n * // 0..1..2..3..4..5..\n * // 0..1..2..3..4..5..\n * // 'Error!: Retried 2 times then quit!'\n * ```\n *\n * @see {@link retryWhen}\n *\n * @param configOrCount - Either number of retry attempts before failing or a {@link RetryConfig} object.\n * @return A function that returns an Observable that will resubscribe to the\n * source stream when the source stream errors, at most `count` times.\n */\nexport function retry(configOrCount: number | RetryConfig = Infinity): MonoTypeOperatorFunction {\n let config: RetryConfig;\n if (configOrCount && typeof configOrCount === 'object') {\n config = configOrCount;\n } else {\n config = {\n count: configOrCount as number,\n };\n }\n const { count = Infinity, delay, resetOnSuccess: resetOnSuccess = false } = config;\n\n return count <= 0\n ? identity\n : operate((source, subscriber) => {\n let soFar = 0;\n let innerSub: Subscription | null;\n const subscribeForRetry = () => {\n let syncUnsub = false;\n innerSub = source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n // If we're resetting on success\n if (resetOnSuccess) {\n soFar = 0;\n }\n subscriber.next(value);\n },\n // Completions are passed through to consumer.\n undefined,\n (err) => {\n if (soFar++ < count) {\n // We are still under our retry count\n const resub = () => {\n if (innerSub) {\n innerSub.unsubscribe();\n innerSub = null;\n subscribeForRetry();\n } else {\n syncUnsub = true;\n }\n };\n\n if (delay != null) {\n // The user specified a retry delay.\n // They gave us a number, use a timer, otherwise, it's a function,\n // and we're going to call it to get a notifier.\n const notifier = typeof delay === 'number' ? timer(delay) : innerFrom(delay(err, soFar));\n const notifierSubscriber = createOperatorSubscriber(\n subscriber,\n () => {\n // After we get the first notification, we\n // unsubscribe from the notifier, because we don't want anymore\n // and we resubscribe to the source.\n notifierSubscriber.unsubscribe();\n resub();\n },\n () => {\n // The notifier completed without emitting.\n // The author is telling us they want to complete.\n subscriber.complete();\n }\n );\n notifier.subscribe(notifierSubscriber);\n } else {\n // There was no notifier given. Just resub immediately.\n resub();\n }\n } else {\n // We're past our maximum number of retries.\n // Just send along the error.\n subscriber.error(err);\n }\n }\n )\n );\n if (syncUnsub) {\n innerSub.unsubscribe();\n innerSub = null;\n subscribeForRetry();\n }\n };\n subscribeForRetry();\n });\n}\n","import { Injectable } from '@angular/core';\r\nimport { ReplaySubject } from 'rxjs';\r\nimport { ILink } from '../../interfaces/project/link.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BreadcrumbsService {\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n setBreadcrumbs(items?: ILink[]) {\r\n if (items) {\r\n this.data.next(items);\r\n }\r\n }\r\n}\r\n","import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';\r\nimport { Injectable } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class BreakpointsService {\r\n private small = new BehaviorSubject(false);\r\n small$ = this.small.asObservable();\r\n\r\n private medium = new BehaviorSubject(false);\r\n medium$ = this.medium.asObservable();\r\n\r\n private large = new BehaviorSubject(false);\r\n large$ = this.large.asObservable();\r\n\r\n private xlarge = new BehaviorSubject(false);\r\n xlarge$ = this.xlarge.asObservable();\r\n\r\n private underLarge = new BehaviorSubject(false);\r\n underLarge$ = this.underLarge.asObservable();\r\n\r\n constructor(private breakpointObserver: BreakpointObserver, private mediaMatcher: MediaMatcher) {\r\n const breakpoints: string[] = ['(min-width: 0)', '(min-width: 768px)', '(min-width: 992px)', '(min-width: 1200px)'];\r\n\r\n if (this.mediaMatcher.matchMedia(breakpoints[3]).matches) {\r\n this.xlarge.next(true);\r\n this.large.next(true);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n } else if (this.mediaMatcher.matchMedia(breakpoints[2]).matches) {\r\n this.xlarge.next(false);\r\n this.large.next(true);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(false);\r\n } else if (this.mediaMatcher.matchMedia(breakpoints[1]).matches) {\r\n this.xlarge.next(false);\r\n this.large.next(false);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(true);\r\n } else if (this.mediaMatcher.matchMedia(breakpoints[0]).matches) {\r\n this.xlarge.next(false);\r\n this.large.next(false);\r\n this.medium.next(false);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(true);\r\n }\r\n\r\n this.breakpointObserver.observe(breakpoints).subscribe((result) => {\r\n if (result.matches) {\r\n if (result.breakpoints[breakpoints[3]]) {\r\n this.xlarge.next(true);\r\n this.large.next(true);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n } else if (result.breakpoints[breakpoints[2]]) {\r\n this.xlarge.next(false);\r\n this.large.next(true);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(false);\r\n } else if (result.breakpoints[breakpoints[1]]) {\r\n this.xlarge.next(false);\r\n this.large.next(false);\r\n this.medium.next(true);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(true);\r\n } else if (result.breakpoints[breakpoints[0]]) {\r\n this.xlarge.next(false);\r\n this.large.next(false);\r\n this.medium.next(false);\r\n this.small.next(true);\r\n\r\n this.underLarge.next(true);\r\n }\r\n }\r\n });\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { IDropdown } from '@portal-app/interfaces/project/dropdown.interface';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { take } from 'rxjs/operators';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class DropdownService {\r\n private open = new BehaviorSubject(undefined);\r\n open$ = this.open.asObservable();\r\n\r\n dropdowns: string[] = [];\r\n\r\n openDropdown(id: string, darkOverlay?: boolean) {\r\n const dropdown: IDropdown = {\r\n Id: id,\r\n DarkOverlay: darkOverlay,\r\n };\r\n this.open.next(dropdown);\r\n }\r\n\r\n closeDropdown() {\r\n this.open.next(undefined);\r\n }\r\n\r\n toggleDropdown(id: string, darkOverlay?: boolean, zIndex?: number) {\r\n this.open.pipe(take(1)).subscribe((open: IDropdown | undefined) => {\r\n if (id === open?.Id && id !== '') {\r\n this.open.next(undefined);\r\n } else {\r\n const dropdown: IDropdown = {\r\n Id: id,\r\n DarkOverlay: darkOverlay,\r\n ZIndex: zIndex,\r\n };\r\n this.open.next(dropdown);\r\n }\r\n });\r\n }\r\n}\r\n","import { ComponentType } from '@angular/cdk/overlay';\r\nimport { Injectable, TemplateRef } from '@angular/core';\r\nimport {\r\n MatLegacyDialog as MatDialog,\r\n MatLegacyDialogConfig as MatDialogConfig,\r\n MatLegacyDialogRef as MatDialogRef,\r\n} from '@angular/material/legacy-dialog';\r\nimport { take } from 'rxjs/operators';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ExtendedDialogService extends MatDialog {\r\n public open(componentOrTemplateRef: ComponentType | TemplateRef, config?: MatDialogConfig): MatDialogRef {\r\n window.scrollLocked = true;\r\n\r\n const dialogRef = super.open(componentOrTemplateRef, config);\r\n\r\n dialogRef\r\n .afterOpened()\r\n .pipe(take(1))\r\n .subscribe(() => {\r\n document.documentElement.classList.add('cdk-global-scrollblock');\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .pipe(take(1))\r\n .subscribe(() => {\r\n document.documentElement.classList.remove('cdk-global-scrollblock');\r\n window.scrollLocked = false;\r\n });\r\n\r\n return dialogRef;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { PageTypeEnum } from '@portal-app/enums/page-type.enum';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { ProjectTypeEnum } from '../../enums/project-type.enum';\r\nimport { IHeader } from '../../interfaces/project/header.interface';\r\nimport { AppInitService } from './app-init.service';\r\nimport { HelperService } from './helper.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class HeaderService {\r\n constructor(private appInitService: AppInitService, private helperService: HelperService) {}\r\n\r\n private behind = new BehaviorSubject(undefined);\r\n behind$ = this.behind.asObservable();\r\n\r\n /** Set header css colors based on multiple factors */\r\n setHeader(header: IHeader, projectType?: ProjectTypeEnum) {\r\n this.behind.subscribe((behind) => {\r\n document.documentElement.style.setProperty('--header-background-initial', header.InitialBackgroundColor || null);\r\n document.documentElement.style.setProperty('--header-text-initial', header.InitialTextColor || null);\r\n\r\n if (behind) {\r\n if (projectType === ProjectTypeEnum.PS) {\r\n document.documentElement.style.setProperty('--header-background-scrolled', '0,0,0');\r\n document.documentElement.style.setProperty('--header-text-scrolled', '255,255,255');\r\n } else {\r\n document.documentElement.style.setProperty('--header-background-scrolled', '255,255,255');\r\n document.documentElement.style.setProperty('--header-text-scrolled', '0,0,0');\r\n }\r\n } else {\r\n document.documentElement.style.setProperty(\r\n '--header-background-scrolled',\r\n header.ScrolledBackgroundColor || null\r\n );\r\n document.documentElement.style.setProperty('--header-text-scrolled', header.ScrolledTextColor || null);\r\n }\r\n });\r\n }\r\n\r\n /** Sets whether or not the header should be on top of content like the hero element or be above it.\r\n * @example If behind is set to true then the header would be transparant so you can see what it is on top of like the hero\r\n * */\r\n setBehind(pageType: PageTypeEnum, hasHero?: boolean) {\r\n if (\r\n pageType === PageTypeEnum.BookInfo ||\r\n pageType === PageTypeEnum.BookCollection ||\r\n pageType === PageTypeEnum.PsArticleLibrary ||\r\n pageType === PageTypeEnum.PsAssignmentLibrary ||\r\n pageType === PageTypeEnum.PsThemeLibrary ||\r\n pageType === PageTypeEnum.PsArticle ||\r\n pageType === PageTypeEnum.PsAssignment ||\r\n (this.appInitService.isPs && hasHero)\r\n ) {\r\n this.behind.next(true);\r\n } else {\r\n this.behind.next(false);\r\n }\r\n }\r\n\r\n resetHeader() {\r\n const projectType = this.appInitService.siteConfiguration.ProjectType;\r\n const header: IHeader = {\r\n InitialBackgroundColor: this.helperService.hexToRgb(\r\n this.appInitService.siteConfiguration.HeaderColors?.PrimaryBackgroundColor\r\n ),\r\n InitialTextColor: this.helperService.hexToRgb(\r\n this.appInitService.siteConfiguration.HeaderColors?.PrimaryTextColor\r\n ),\r\n ScrolledBackgroundColor: this.helperService.hexToRgb(\r\n this.appInitService.siteConfiguration.HeaderColors?.SecondaryBackgroundColor\r\n ),\r\n ScrolledTextColor: this.helperService.hexToRgb(\r\n this.appInitService.siteConfiguration.HeaderColors?.SecondaryTextColor\r\n ),\r\n };\r\n\r\n this.setHeader(header, projectType);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { QueryStrings } from '@portal-app/constants/query-strings.const';\r\nimport { UmbSettingAlignEnum, UmbSettingWidthEnum } from '@portal-app/enums/umb-ui-settings';\r\nimport { IBookLibraryFilters } from '@portal-app/interfaces/book/project/book-library.interface';\r\nimport { ICourseLibraryFilters } from '@portal-app/interfaces/course/project/course-library.interface';\r\nimport { IQueryString } from '@portal-app/interfaces/project/query-strings.interface';\r\nimport { TruncatePipe } from '@portal-app/pipes/truncate.pipe';\r\n\r\n/**\r\n * This service is available as an injectable class and consists of minor helper methods\r\n * to be shared across the application.\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class HelperService {\r\n constructor(private translate: TranslateService) {}\r\n\r\n hexToRgb(hex?: string) {\r\n if (!hex) {\r\n return;\r\n }\r\n\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n return result ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : undefined;\r\n }\r\n\r\n lightenDarkenColor(color: string, percent: number) {\r\n const num = parseInt(color.replace('#', ''), 16);\r\n const amt = Math.round(2.55 * percent);\r\n\r\n /* eslint-disable no-bitwise */\r\n const r = (num >> 16) + amt;\r\n const b = ((num >> 8) & 0x00ff) + amt;\r\n const g = (num & 0x0000ff) + amt;\r\n /* eslint-enable no-bitwise */\r\n\r\n return (\r\n '#' +\r\n (\r\n 0x1000000 +\r\n (r < 255 ? (r < 1 ? 0 : r) : 255) * 0x10000 +\r\n (b < 255 ? (b < 1 ? 0 : b) : 255) * 0x100 +\r\n (g < 255 ? (g < 1 ? 0 : g) : 255)\r\n )\r\n .toString(16)\r\n .slice(1)\r\n );\r\n }\r\n\r\n hexToRGB(hex?: string, alpha?: number) {\r\n if (!hex) {\r\n return;\r\n }\r\n\r\n const r = parseInt(hex.slice(1, 3), 16).toString();\r\n const g = parseInt(hex.slice(3, 5), 16).toString();\r\n const b = parseInt(hex.slice(5, 7), 16).toString();\r\n\r\n if (alpha) {\r\n return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha.toString() + ')';\r\n } else {\r\n return 'rgb(' + r + ', ' + g + ', ' + b + ')';\r\n }\r\n }\r\n\r\n /** @param type Supply name of querystring. Function will return first found querystring in the list */\r\n getQuerystringFacetList(type: IQueryString) {\r\n let items = this.getQueryParam(type);\r\n\r\n return items\r\n ? items.split(',').map((item) => {\r\n return decodeURIComponent(decodeURIComponent(item));\r\n })\r\n : [];\r\n }\r\n\r\n encodeStringArray(array: string[]) {\r\n return array.map((item) => encodeURIComponent(item)).join(',');\r\n }\r\n\r\n getQuerystringFacetListAsBooleans(type: IQueryString) {\r\n const items = this.getQueryParam(type);\r\n return items ? items.split(',').map((item) => item.toLowerCase() === 'true') : [];\r\n }\r\n\r\n getCookie(name: string) {\r\n const match = new RegExp('(^| )' + name + '=([^;]+)').exec(document.cookie);\r\n if (match) {\r\n return match[2];\r\n } else {\r\n return undefined;\r\n }\r\n }\r\n\r\n getCustomUrl(url?: string) {\r\n return url ? `/${url.replace('/', '')}` : url;\r\n }\r\n\r\n getFileIconSvg(extension: string) {\r\n switch (extension.toLowerCase()) {\r\n case 'xlsx':\r\n case 'xlsm':\r\n case 'xlsb':\r\n case 'xltx':\r\n return 'document-excel.svg';\r\n case 'mp3':\r\n return 'document-mp3.svg';\r\n case 'pdf':\r\n return 'document-pdf.svg';\r\n case 'doc':\r\n case 'docx':\r\n return 'document-word.svg';\r\n case 'pptx':\r\n case 'pptm':\r\n case 'ppt':\r\n return 'document-powerpoint.svg';\r\n default:\r\n return 'download.svg';\r\n }\r\n }\r\n\r\n getLocalizedDate(date: Date) {\r\n return date.toLocaleDateString(\r\n this.translate.instant('Label.LanguageCode', {\r\n default: 'da-DK',\r\n }),\r\n {\r\n year: 'numeric',\r\n month: 'long',\r\n day: 'numeric',\r\n }\r\n );\r\n }\r\n\r\n getKeyName(list: typeof QueryStrings, value: string = '') {\r\n if (!list) {\r\n return;\r\n }\r\n\r\n return Object.entries(list).find(([, val]) => val.da === value || val.en === value)?.[0];\r\n }\r\n\r\n anyFiltersActive(filters: IBookLibraryFilters | ICourseLibraryFilters) {\r\n let show = false;\r\n if (filters.Query) {\r\n show = true;\r\n return show;\r\n }\r\n if (filters.Facets) {\r\n for (const facet of filters.Facets) {\r\n show = facet.Items.filter((item) => item.Selected === true).length ? true : false;\r\n if (show) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return show;\r\n }\r\n\r\n getUmbracoAlign(align?: string, fallback?: UmbSettingAlignEnum) {\r\n const keys = Object.keys(UmbSettingAlignEnum);\r\n const values = Object.values(UmbSettingAlignEnum);\r\n const found = keys.findIndex((e) => e === align);\r\n if (found !== -1) {\r\n return values[found];\r\n } else if (fallback) {\r\n return fallback;\r\n } else {\r\n return UmbSettingAlignEnum.Left;\r\n }\r\n }\r\n\r\n getUmbracoWidth(width?: string) {\r\n const keys = Object.keys(UmbSettingWidthEnum);\r\n const values = Object.values(UmbSettingWidthEnum);\r\n const found = keys.findIndex((e) => e === width);\r\n if (found !== -1) {\r\n return values[found];\r\n } else {\r\n return UmbSettingWidthEnum.large;\r\n }\r\n }\r\n\r\n getUmbracoPercentageWidth(width?: number): string {\r\n if (width) {\r\n return `${width}%`;\r\n } else {\r\n return '100%';\r\n }\r\n }\r\n\r\n isLocalhost() {\r\n return window.location.hostname === 'localhost';\r\n }\r\n\r\n getHttpsUrl(url?: string) {\r\n if (!url) {\r\n return;\r\n }\r\n if (url.startsWith('www.') || !new RegExp('^(http|https)://', 'i').test(url)) {\r\n url = 'https://' + url;\r\n }\r\n return url;\r\n }\r\n\r\n isSafari() {\r\n return /^((?!chrome|android).)*safari/i.test(navigator.userAgent.toLowerCase());\r\n }\r\n\r\n tryParseInt(str: string, defaultValue: number) {\r\n let retValue = defaultValue;\r\n if (str !== null) {\r\n if (str.length > 0) {\r\n retValue = parseInt(str, 10);\r\n }\r\n }\r\n return retValue;\r\n }\r\n\r\n truncateString(text: string, length: number) {\r\n if (!text) {\r\n return;\r\n }\r\n return new TruncatePipe().transform(text, length);\r\n }\r\n\r\n getLessonOrDurationLabel(duration?: number, isLessons?: boolean) {\r\n let result: string | undefined;\r\n if (duration) {\r\n if (!isLessons) {\r\n duration = parseFloat(((duration / 45) * 2).toFixed(0)) / 2;\r\n }\r\n\r\n const durationTransformed = duration.toString().replace('.', ',');\r\n\r\n result =\r\n duration > 1\r\n ? this.translate.instant('Label.LessonOrDurationPlural', { duration: durationTransformed })\r\n : this.translate.instant('Label.LessonOrDuration', { duration: durationTransformed });\r\n }\r\n return result;\r\n }\r\n\r\n /** @param types Supply names of query params. Function will return first found parameter in the list */\r\n getQueryParam(queryString: IQueryString) {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n let result: string | undefined;\r\n\r\n Object.entries(queryString).every(([key, value]) => {\r\n const paramString = urlParams.get(value);\r\n if (paramString) {\r\n result = paramString;\r\n return false;\r\n }\r\n // We return true to keep iterating.\r\n return true;\r\n });\r\n\r\n return result;\r\n }\r\n\r\n getParameterByName(name: string, url = window.location.href) {\r\n name = name.replace(/[\\[\\]]/g, '\\\\$&');\r\n\r\n const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');\r\n const results = regex.exec(url);\r\n\r\n if (!results) return null;\r\n if (!results[2]) return '';\r\n return decodeURIComponent(results[2].replace(/\\+/g, ' '));\r\n }\r\n\r\n private getParameterByNameWithSuffix(facet: string, suffix: string) {\r\n return this.getParameterByName(`${facet}${suffix}`);\r\n }\r\n\r\n getParameterByQueryStringAndSuffix(queryString: IQueryString, suffix: IQueryString) {\r\n return (\r\n this.getParameterByNameWithSuffix(queryString.en, suffix.en) ??\r\n this.getParameterByNameWithSuffix(queryString.da, suffix.da)\r\n );\r\n }\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\r\n\r\n@Pipe({\r\n name: 'keepHtml',\r\n})\r\nexport class EscapeHtmlPipe implements PipeTransform {\r\n constructor(private sanitizer: DomSanitizer) {}\r\n\r\n transform(content: string): SafeHtml {\r\n return this.sanitizer.bypassSecurityTrustHtml(content);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\r\nimport { EscapeHtmlPipe } from '@portal-app/pipes/keep-html.pipe';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class HtmlService {\r\n constructor(private domSanitizer: DomSanitizer) {}\r\n\r\n fixHtml(text: string | undefined): SafeHtml | undefined {\r\n if (!text) {\r\n return;\r\n }\r\n return new EscapeHtmlPipe(this.domSanitizer).transform(text.replace(new RegExp('\\n', 'g'), '
'));\r\n }\r\n\r\n truncate(text: string, length?: number) {\r\n if (length && text.length > length) {\r\n return text.slice(0, length) + '...';\r\n } else {\r\n return text;\r\n }\r\n }\r\n\r\n truncateHTML(text: string, length?: number): string | undefined {\r\n if (!text) {\r\n return;\r\n }\r\n if (!length) {\r\n return text;\r\n }\r\n let truncated = text.substring(0, length);\r\n // Remove line breaks and surrounding whitespace\r\n truncated = truncated.replace(/(\\r\\n|\\n|\\r)/gm, '').trim();\r\n // If the text ends with an incomplete start tag, trim it off\r\n truncated = truncated.replace(/<(\\w*)(?:(?:\\s\\w+(?:={0,1}([\"']{0,1})\\w*\\2{0,1})))*$/g, '');\r\n // If the text ends with a truncated end tag, fix it.\r\n const truncatedEndTagExpr = /<\\/((?:\\w*))$/g;\r\n const truncatedEndTagMatch = truncatedEndTagExpr.exec(truncated);\r\n if (truncatedEndTagMatch != null) {\r\n const truncatedEndTag = truncatedEndTagMatch[1];\r\n // Check to see if there's an identifiable tag in the end tag\r\n if (truncatedEndTag.length > 0) {\r\n // If so, find the start tag, and close it\r\n const startTagExpr = new RegExp('<(' + truncatedEndTag + '\\\\w?)(?:(?:\\\\s\\\\w+(?:=([\"\\'])\\\\w*\\\\2)))*>');\r\n let testString = truncated;\r\n let startTagMatch = startTagExpr.exec(testString);\r\n\r\n let startTag = null;\r\n while (startTagMatch !== null) {\r\n startTag = startTagMatch[1];\r\n testString = testString.replace(startTagExpr, '');\r\n startTagMatch = startTagExpr.exec(testString);\r\n }\r\n if (startTag !== null) {\r\n truncated = truncated.replace(truncatedEndTagExpr, '');\r\n }\r\n } else {\r\n // Otherwise, cull off the broken end tag\r\n truncated = truncated.replace(truncatedEndTagExpr, '');\r\n }\r\n }\r\n // Now the tricky part. Reverse the text, and look for opening tags. For each opening tag,\r\n // check to see that he closing tag before it is for that tag. If not, append a closing tag.\r\n let testString = this.reverseHtml(truncated);\r\n const reverseTagOpenExpr = /<(?:([\"'])\\w*\\1=\\w+ )*(\\w*)>/;\r\n let tagMatch = reverseTagOpenExpr.exec(testString);\r\n if (tagMatch) {\r\n while (tagMatch !== null) {\r\n const tag = tagMatch[0],\r\n tagName = tagMatch[2],\r\n startPos = tagMatch.index,\r\n endPos = startPos + tag.length,\r\n fragment = testString.substring(0, endPos);\r\n // Test to see if an end tag is found in the fragment. If not, append one to the end\r\n // of the truncated HTML, thus closing the last unclosed tag\r\n if (!new RegExp('<' + tagName + '/>').test(fragment)) {\r\n truncated += '...';\r\n break;\r\n }\r\n // Get rid of the already tested fragment\r\n testString = testString.replace(fragment, '');\r\n // Get another tag to test\r\n tagMatch = reverseTagOpenExpr.exec(testString);\r\n }\r\n } else {\r\n return this.truncate(text, length);\r\n }\r\n\r\n return truncated;\r\n }\r\n\r\n private reverseHtml(str: string): string {\r\n const ph = String.fromCharCode(206);\r\n let result = str.split('').reverse().join('');\r\n while (result.indexOf('<') > -1) {\r\n result = result.replace('<', ph);\r\n }\r\n while (result.indexOf('>') > -1) {\r\n result = result.replace('>', '<');\r\n }\r\n while (result.indexOf(ph) > -1) {\r\n result = result.replace(ph, '>');\r\n }\r\n return result;\r\n }\r\n}\r\n","export enum TextToSpeechLanguageEnum {\r\n da = 'da',\r\n en = 'en',\r\n de = 'de',\r\n fr = 'fr',\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService, GoogleTagManagerService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { AudioPlayerTypeEnum } from '@portal-app/enums/audio-player-type.enum';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { TextToSpeechLanguageEnum } from '@portal-app/enums/text-to-speech-language.enum';\r\nimport { ILanguage } from '@portal-app/interfaces/project/input.interface';\r\nimport {\r\n IAudioHlsPlayer,\r\n IAudioPlayerMark,\r\n IAudioSelectionPlayer,\r\n ILayoutAudio,\r\n IPlayer,\r\n IPollyObject,\r\n ISelection,\r\n} from '@portal-app/interfaces/project/layout-audio.interface';\r\nimport Plyr, { PlyrEvent } from 'plyr';\r\nimport { BehaviorSubject, firstValueFrom } from 'rxjs';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { SelectionService } from './selection.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class LayoutAudioService {\r\n private data = new BehaviorSubject({\r\n Players: [],\r\n Languages: [\r\n {\r\n Id: TextToSpeechLanguageEnum.da,\r\n Title: this.translateService.instant('LayoutAudio.Languages.Da'),\r\n Checked: true,\r\n },\r\n {\r\n Id: TextToSpeechLanguageEnum.en,\r\n Title: this.translateService.instant('LayoutAudio.Languages.En'),\r\n Checked: false,\r\n },\r\n {\r\n Id: TextToSpeechLanguageEnum.de,\r\n Title: this.translateService.instant('LayoutAudio.Languages.De'),\r\n Checked: false,\r\n },\r\n {\r\n Id: TextToSpeechLanguageEnum.fr,\r\n Title: this.translateService.instant('LayoutAudio.Languages.Fr'),\r\n Checked: false,\r\n },\r\n ],\r\n PartialDestroyed: true,\r\n });\r\n data$ = this.data.asObservable();\r\n\r\n constructor(\r\n private apiService: ApiService,\r\n private selectionService: SelectionService,\r\n private gtmService: GoogleTagManagerService,\r\n private translateService: TranslateService\r\n ) {}\r\n\r\n async addPlayer(instance: Plyr, src: string) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.Players.push({\r\n Instance: instance,\r\n Src: src,\r\n });\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async removePlayer(instance: Plyr, src: string) {\r\n instance.stop();\r\n\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.Players = layoutAudio.Players.filter((i) => i.Src !== src);\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async togglePartialDestroyed(destroyed: boolean) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.PartialDestroyed = destroyed;\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async setActiveLanguage(id: string) {\r\n if (Object.values(TextToSpeechLanguageEnum).includes(id as TextToSpeechLanguageEnum)) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.Languages = layoutAudio.Languages.map((item) => {\r\n return { Id: item.Id, Title: item.Title, Checked: item.Id === id };\r\n });\r\n this.data.next(layoutAudio);\r\n }\r\n }\r\n\r\n async pauseOtherPlayers(src: string) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n const players = layoutAudio.Players.filter((item) => item.Src !== src);\r\n players.forEach((player) => player.Instance.pause());\r\n }\r\n\r\n async removeAll() {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.Full = undefined;\r\n layoutAudio.Recorded = undefined;\r\n layoutAudio.Partial = undefined;\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async initializeFull(selections: ISelection[]) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n const item: IAudioSelectionPlayer = {\r\n Type: AudioPlayerTypeEnum.Full,\r\n Enabled: true,\r\n Selections: selections,\r\n };\r\n layoutAudio.Full = item;\r\n layoutAudio.FullExpanded = false;\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async getFull() {\r\n let layoutAudio = await firstValueFrom(this.data$);\r\n this.data$\r\n .pipe(\r\n filter((item) => {\r\n return item.PartialDestroyed === true;\r\n }),\r\n take(1)\r\n )\r\n .subscribe((data) => {\r\n layoutAudio = data;\r\n if (layoutAudio.Full?.Src && !layoutAudio.FullExpanded) {\r\n layoutAudio.FullExpanded = true;\r\n layoutAudio.Full.AutoPlay = true;\r\n layoutAudio.RecordedExpanded = false;\r\n this.data.next(layoutAudio);\r\n return;\r\n }\r\n if (layoutAudio.Full?.Selections?.length) {\r\n const text: string[] = [];\r\n layoutAudio.Full.Selections.forEach((selection) => {\r\n text.push(selection.CoordinatesAndText.Text + '!');\r\n });\r\n const result = text.join(' ');\r\n const body = {\r\n Language: layoutAudio.Languages.find((item) => item.Checked === true)?.Id,\r\n InputText: result,\r\n };\r\n\r\n this.apiService.postNext('polly/TTS', body).subscribe({\r\n next: (polly: IPollyObject) => {\r\n const item = this.mapPollyToPlayer(\r\n polly,\r\n layoutAudio.Full?.Selections || [],\r\n AudioPlayerTypeEnum.Full,\r\n layoutAudio.Languages,\r\n true\r\n );\r\n layoutAudio.Full = item;\r\n layoutAudio.Full.AutoPlay = true;\r\n layoutAudio.FullExpanded = true;\r\n layoutAudio.RecordedExpanded = false;\r\n this.data.next(layoutAudio);\r\n },\r\n error: (polly: IPollyObject) => {\r\n layoutAudio.Full = undefined;\r\n this.data.next(layoutAudio);\r\n },\r\n });\r\n }\r\n });\r\n }\r\n\r\n async toggleFullExpanded(expanded: boolean, autoPlay: boolean) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.FullExpanded = expanded;\r\n layoutAudio.RecordedExpanded = false;\r\n if (layoutAudio.Full) {\r\n layoutAudio.Full.AutoPlay = autoPlay;\r\n }\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n findPlayer(src: string, players: IPlayer[]) {\r\n return players.find((item) => item.Src === src);\r\n }\r\n\r\n async resetFull() {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n if (layoutAudio.Full?.Selections && layoutAudio.Full?.Src) {\r\n layoutAudio.Full.Highlight = false;\r\n layoutAudio.Full.AutoPlay = false;\r\n\r\n const player = this.findPlayer(layoutAudio.Full.Src, layoutAudio.Players);\r\n if (player) {\r\n layoutAudio.Full.SentenceButtons = {\r\n PreviousEnabled: false,\r\n NextEnabled: true,\r\n };\r\n player.Instance.pause();\r\n player.Instance.currentTime = 0;\r\n layoutAudio.Full.Selections.forEach((selection) => {\r\n if (layoutAudio.Full) {\r\n this.selectionService.resetSelection(selection.Target, layoutAudio.Full.Type);\r\n }\r\n });\r\n }\r\n this.data.next(layoutAudio);\r\n }\r\n }\r\n\r\n async removeFull() {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n layoutAudio.Full = undefined;\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async getPartial(selection?: ISelection) {\r\n if (!selection?.CoordinatesAndText.Text) {\r\n return;\r\n }\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n const body = {\r\n Language: layoutAudio.Languages.find((item) => item.Checked === true)?.Id,\r\n InputText: selection.CoordinatesAndText.Text.replace('/', '.'), // polly takes \"/\" as a space so \"A/S\" becomes two words ... fixed by replacing it with \".\" just for polly.\r\n };\r\n this.apiService.postNext('polly/TTS', body).subscribe((polly: IPollyObject) => {\r\n if (layoutAudio.Full) {\r\n layoutAudio.Full.Enabled = false;\r\n layoutAudio.FullExpanded = false;\r\n }\r\n if (layoutAudio.Recorded) {\r\n if (layoutAudio.Recorded.Src) {\r\n const player = this.findPlayer(layoutAudio.Recorded.Src, layoutAudio.Players);\r\n if (player) {\r\n player.Instance.pause();\r\n }\r\n }\r\n layoutAudio.RecordedExpanded = false;\r\n }\r\n layoutAudio.Partial = this.mapPollyToPlayer(polly, [selection], selection.Type, layoutAudio.Languages, true);\r\n layoutAudio.PartialDestroyed = false;\r\n this.data.next(layoutAudio);\r\n });\r\n }\r\n\r\n async removePartial() {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n if (layoutAudio.Partial) {\r\n if (layoutAudio.Full) {\r\n layoutAudio.Full.Enabled = true;\r\n layoutAudio.Full.AutoPlay = false;\r\n layoutAudio.Full.Highlight = false;\r\n }\r\n layoutAudio.Partial = undefined;\r\n this.data.next(layoutAudio);\r\n }\r\n }\r\n\r\n async setRecorded(src: string) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n const item: IAudioHlsPlayer = {\r\n Src: src,\r\n ShowSecondsControls: true,\r\n };\r\n layoutAudio.Recorded = item;\r\n this.data.next(layoutAudio);\r\n }\r\n\r\n async toggleRecordedExpanded(expanded: boolean, autoPlay: boolean) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n await this.handleRecordedExpanded(layoutAudio, expanded, autoPlay);\r\n\r\n if (expanded) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Open_recorded);\r\n } else {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Close_recorded);\r\n }\r\n }\r\n\r\n async toggleFullEnabled(enabled: boolean) {\r\n const layoutAudio = await firstValueFrom(this.data$);\r\n\r\n if (layoutAudio.Full) {\r\n layoutAudio.Full.Enabled = enabled;\r\n this.data.next(layoutAudio);\r\n }\r\n }\r\n\r\n async handlePlyrEvents(event: PlyrEvent) {\r\n let gtmEvent;\r\n switch (event.type) {\r\n case 'pause':\r\n gtmEvent = GTMEvent.Audio_paused;\r\n break;\r\n case 'play':\r\n gtmEvent = GTMEvent.Audio_started;\r\n break;\r\n }\r\n\r\n if (gtmEvent) {\r\n this.gtmService.pushTagWithUserType(gtmEvent, {\r\n file: event.detail.plyr.source,\r\n });\r\n }\r\n }\r\n\r\n private mapPollyToPlayer(\r\n polly: IPollyObject,\r\n selections: ISelection[],\r\n type: AudioPlayerTypeEnum,\r\n languages: ILanguage[],\r\n highlight: boolean\r\n ): IAudioSelectionPlayer {\r\n const src = polly.Audio[0];\r\n const marks: IAudioPlayerMark[] = [];\r\n polly.Marks.forEach((mark) => {\r\n if (mark.type === 'sentence') {\r\n marks.push({\r\n Sentence: mark,\r\n Words: [],\r\n });\r\n } else if (mark.type === 'word') {\r\n marks[marks.length - 1].Words.push(mark);\r\n }\r\n });\r\n\r\n const item: IAudioSelectionPlayer = {\r\n Enabled: true,\r\n Src: src,\r\n Type: type,\r\n Marks: marks,\r\n Selections: selections,\r\n Highlight: highlight,\r\n SentenceButtons: {\r\n NextEnabled: marks.length ? true : false,\r\n PreviousEnabled: false,\r\n },\r\n };\r\n return item;\r\n }\r\n\r\n private async handleRecordedExpanded(data: ILayoutAudio, expanded: boolean, autoPlay: boolean) {\r\n if (data.Full) {\r\n data.Full.Enabled = !expanded;\r\n data.FullExpanded = false;\r\n data.Full.AutoPlay = true;\r\n }\r\n if (data.Recorded) {\r\n data.RecordedExpanded = expanded;\r\n if (data.Recorded.Src) {\r\n const player = this.findPlayer(data.Recorded.Src, data.Players);\r\n if (player) {\r\n if (autoPlay) {\r\n await player.Instance.play();\r\n } else {\r\n player.Instance.pause();\r\n }\r\n }\r\n }\r\n } else {\r\n data.RecordedExpanded = false;\r\n }\r\n this.data.next(data);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ILevel } from '@portal-app/interfaces/project/level.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class LevelService {\r\n /**\r\n * used to sort and combine levels to a pretty string\r\n */\r\n convertLevelsToString(levels: string[] | undefined): string | undefined {\r\n // below is for testing\r\n\r\n // levels = ['0 kl.', '1 kl.', '2 kl.', '4 specialklasse', '4 kl.', '5 kl.', 'fritid', '6 kl.', '9 kl.'];\r\n // levels = ['12 kl.', '1 kl.', '4 kl.', '6 specialklasse', '2 kl.'];\r\n // levels = ['12 kl.', '1 kl.', '4 kl.', 'specialklasse', '2 kl.'];\r\n\r\n if (!levels || !levels?.length) {\r\n return;\r\n }\r\n const data: ILevel[] = [];\r\n for (const level of levels) {\r\n const levelNumber = level.match(/\\d/g);\r\n if (levelNumber && level.indexOf(' kl.') > -1) {\r\n data.push({ Number: parseInt(levelNumber.join(''), 10) });\r\n } else {\r\n data.push({ String: level });\r\n }\r\n }\r\n\r\n data.sort((a, b) => {\r\n const x = a.Number ? a.Number : a.String ? parseInt(a.String, 10) : 0;\r\n const y = b.Number ? b.Number : b.String ? parseInt(b.String, 10) : 0;\r\n if (x < y) {\r\n return -1;\r\n } else if (x > y) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n const complete: string[] = [];\r\n let current: number[] = [];\r\n\r\n const finishCurrent = () => {\r\n if (current.length) {\r\n const part1 = current[0];\r\n const part2 = current[current.length - 1];\r\n if (part1 === part2) {\r\n complete.push(`${part1}. klasse`);\r\n } else {\r\n complete.push(`${part1}.-${part2}. klasse`);\r\n }\r\n current = [];\r\n }\r\n };\r\n\r\n data.forEach((item, index) => {\r\n if (item.Number !== undefined) {\r\n if (current.length) {\r\n const arrayValue = current[current.length - 1];\r\n if (item.Number - 1 === arrayValue) {\r\n current.push(item.Number);\r\n } else {\r\n finishCurrent();\r\n current.push(item.Number);\r\n }\r\n } else {\r\n current.push(item.Number);\r\n }\r\n } else {\r\n finishCurrent();\r\n if (item.String) {\r\n complete.push(item.String);\r\n }\r\n }\r\n });\r\n finishCurrent();\r\n return complete.join(' | ');\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { IUmbNavbar } from '@portal-app/interfaces/umbraco/umb-navbar.interface';\r\nimport { ReplaySubject } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class NavbarService {\r\n private data = new ReplaySubject(1);\r\n data$ = this.data.asObservable();\r\n\r\n private libraryUrl = new ReplaySubject(1);\r\n libraryUrl$ = this.libraryUrl.asObservable();\r\n\r\n private favoritesUrl = new ReplaySubject(1);\r\n favoritesUrl$ = this.favoritesUrl.asObservable();\r\n\r\n private courseStudentAnswersUrl = new ReplaySubject(1);\r\n courseStudentAnswersUrl$ = this.courseStudentAnswersUrl.asObservable();\r\n\r\n private courseAnnualPlanUrl = new ReplaySubject(1);\r\n courseAnnualPlanUrl$ = this.courseAnnualPlanUrl.asObservable();\r\n\r\n private psArticleLibraryUrl = new ReplaySubject(1);\r\n psArticleLibraryUrl$ = this.psArticleLibraryUrl.asObservable();\r\n\r\n private psAssignmentLibraryUrl = new ReplaySubject(1);\r\n psAssignmentLibraryUrl$ = this.psAssignmentLibraryUrl.asObservable();\r\n\r\n constructor(private api: ApiService, private userService: UserService) {}\r\n\r\n getNavbar(menuId: number) {\r\n this.api\r\n .getUmbraco(`alineaportal/menu/fetch/${menuId}/${this.userService.userType}`)\r\n .subscribe((data) => {\r\n this.data.next(data);\r\n });\r\n return this.data;\r\n }\r\n\r\n setLibrary(url?: string) {\r\n if (url) {\r\n this.libraryUrl.next(url);\r\n }\r\n }\r\n\r\n setCourseStudentAnswers(url?: string) {\r\n if (url) {\r\n this.courseStudentAnswersUrl.next(url);\r\n }\r\n }\r\n\r\n setFavorites(url?: string) {\r\n if (url) {\r\n this.favoritesUrl.next(url);\r\n }\r\n }\r\n\r\n setCourseAnnualPlan(url?: string) {\r\n if (url) {\r\n this.courseAnnualPlanUrl.next(url);\r\n }\r\n }\r\n\r\n setPsArticleLibrary(url?: string) {\r\n if (url) {\r\n this.psArticleLibraryUrl.next(url);\r\n }\r\n }\r\n\r\n setPsAssignmentLibrary(url?: string) {\r\n if (url) {\r\n this.psAssignmentLibraryUrl.next(url);\r\n }\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Injectable, OnDestroy } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { ApiService, UserService } from '@lru/felib';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { PageTypeEnum } from '@portal-app/enums/page-type.enum';\r\nimport { ProjectTypeEnum } from '@portal-app/enums/project-type.enum';\r\nimport { SectionTypeEnum } from '@portal-app/enums/section-type.enum';\r\nimport { INextAsset } from '@portal-app/interfaces/next/next-asset.interface';\r\nimport { NextImagePipe } from '@portal-app/pipes/next-image.pipe';\r\nimport { ReplaySubject, firstValueFrom, switchMap } from 'rxjs';\r\nimport { AppInitService } from '../app-init.service';\r\nimport { HtmlService } from '../html.service';\r\nimport { NavbarService } from '../navbar.service';\r\nimport { PageSettings } from './interfaces/page-settings.interface';\r\nimport { ContentPage } from './interfaces/umbraco-page.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class PageService implements OnDestroy {\r\n private page = new ReplaySubject(1);\r\n contentPage$ = this.page.asObservable();\r\n\r\n private pageSettings = new ReplaySubject(1);\r\n pageSettings$ = this.pageSettings.asObservable();\r\n\r\n private pageLoadSubscription = this.pageSettings$.pipe(switchMap((x) => this.loadPage(x))).subscribe();\r\n\r\n constructor(\r\n private apiService: ApiService,\r\n private userService: UserService,\r\n private appInitService: AppInitService,\r\n private router: Router,\r\n private nextImagePipe: NextImagePipe,\r\n private htmlService: HtmlService,\r\n private navbarService: NavbarService,\r\n private translateService: TranslateService\r\n ) {}\r\n\r\n setPageSettings(pageSettings: PageSettings) {\r\n this.pageSettings.next(pageSettings);\r\n }\r\n\r\n async loadPage(pageSettings: PageSettings) {\r\n await firstValueFrom(\r\n this.apiService.getUmbraco(\r\n `v3/alineaportal/contentpage/fetch/${this.userService.userType}/${pageSettings.pageId}/${\r\n this.appInitService.siteConfiguration.PortalId ?? ''\r\n }`\r\n )\r\n )\r\n .then((page: ContentPage) => {\r\n if (this.appInitService.siteConfiguration.ProjectType === 'PrintBar') {\r\n if (page.pageType === PageTypeEnum.PsAssignmentLibrary) {\r\n page.pageType = PageTypeEnum.PrintbarAssignmentLibrary;\r\n }\r\n if (page.pageType === PageTypeEnum.PsAssignment) {\r\n page.pageType = PageTypeEnum.PrintbarAssignment;\r\n }\r\n }\r\n\r\n this.page.next(page);\r\n\r\n if (\r\n page.pageType === PageTypeEnum.ContentPage ||\r\n page.pageType === PageTypeEnum.FrontPage ||\r\n page.pageType === PageTypeEnum.Error ||\r\n !page.pageType\r\n ) {\r\n this.router.navigate([PageTypeEnum.ContentPage], {\r\n skipLocationChange: true,\r\n });\r\n } else {\r\n this.router.navigate([page.pageType], {\r\n skipLocationChange: true,\r\n });\r\n }\r\n })\r\n .catch((e: HttpErrorResponse) => {\r\n if (pageSettings.fromError) {\r\n this.showError(pageSettings.pageUrl, 503);\r\n return;\r\n }\r\n const annualPlanUrl = 'annual-plan';\r\n const studentAnswersUrl = 'student-answers';\r\n const favoritesUrl = 'favorites';\r\n const libraryUrl = 'library';\r\n const courseLibraryUrl = 'course-library';\r\n const bookLibraryUrl = 'book-library';\r\n\r\n if (\r\n pageSettings.pageId === annualPlanUrl ||\r\n pageSettings.pageId === studentAnswersUrl ||\r\n pageSettings.pageId === favoritesUrl ||\r\n pageSettings.pageId === libraryUrl ||\r\n pageSettings.pageId === courseLibraryUrl ||\r\n pageSettings.pageId === bookLibraryUrl\r\n ) {\r\n const timeout = setTimeout(() => {\r\n this.showError(pageSettings.pageUrl, 404);\r\n }, 2000);\r\n\r\n if (pageSettings.pageId === annualPlanUrl) {\r\n this.navbarService.courseAnnualPlanUrl$.subscribe((url) => {\r\n clearTimeout(timeout);\r\n this.router.navigate([url]);\r\n });\r\n } else if (pageSettings.pageId === studentAnswersUrl) {\r\n this.navbarService.courseStudentAnswersUrl$.subscribe((url) => {\r\n clearTimeout(timeout);\r\n this.router.navigate([url]);\r\n });\r\n } else if (pageSettings.pageId === favoritesUrl) {\r\n this.navbarService.favoritesUrl$.subscribe((url) => {\r\n clearTimeout(timeout);\r\n this.router.navigate([url]);\r\n });\r\n } else if (\r\n pageSettings.pageId === libraryUrl ||\r\n pageSettings.pageId === courseLibraryUrl ||\r\n pageSettings.pageId === bookLibraryUrl\r\n ) {\r\n this.navbarService.libraryUrl$.subscribe((url) => {\r\n clearTimeout(timeout);\r\n this.router.navigate([url]);\r\n });\r\n }\r\n } else {\r\n this.showError(pageSettings.pageUrl, e.status);\r\n }\r\n });\r\n }\r\n\r\n async showError(pageUrl: string, statusCode: number) {\r\n let tempStatusCode = statusCode.toString();\r\n\r\n if (!tempStatusCode) {\r\n tempStatusCode = '500';\r\n }\r\n\r\n if (tempStatusCode === '503') {\r\n this.appInitService.setDefaultSiteConfiguration();\r\n // what project styling should be used if it doesnt know what project type it is?\r\n this.appInitService.setStylesheet(ProjectTypeEnum.Fagportal);\r\n\r\n const coverImage: INextAsset = {\r\n Dimensions: { Width: 1440, Height: 550 },\r\n FileType: 'png',\r\n Id: 'XengyaELEeuUsygYeGSXWg',\r\n Path: '2021-04/sxj1MjTsS57x/Cover-3',\r\n Title: 'BookBox Cover 3',\r\n Type: 'Image',\r\n };\r\n\r\n const htmlGridEditor: any = {\r\n type: SectionTypeEnum.RichTextEditor,\r\n html: this.htmlService.fixHtml(`

${this.translateService.instant('Page.503.SectionText')}

`),\r\n };\r\n\r\n this.page.next({\r\n hero: {\r\n textAlign: 'center',\r\n sectionAlign: 'center',\r\n headline: 'Der skete desværre en fejl :(',\r\n // description: 'Sitet kunne ikke loades',\r\n width: 'medium',\r\n backgroundImageUrl: this.nextImagePipe.transform(coverImage, 1920),\r\n // IsNextCoverImage: true,\r\n },\r\n sectionsV2: [\r\n {\r\n columns: [\r\n {\r\n gridEditors: [htmlGridEditor],\r\n width: 100, //'fullWidth', TODO\r\n },\r\n ],\r\n alignment: 'center',\r\n width: 'small',\r\n },\r\n ],\r\n });\r\n await this.router.navigate([PageTypeEnum.Error503], {\r\n skipLocationChange: true,\r\n });\r\n return;\r\n }\r\n if (tempStatusCode === '400') {\r\n // Thomas Olsen wants to handle 400 as 404\r\n tempStatusCode = '404';\r\n }\r\n\r\n let errorPageId = this.appInitService.getErrorPage(tempStatusCode);\r\n if (!errorPageId) {\r\n errorPageId = this.appInitService.getErrorPage('404');\r\n }\r\n if (tempStatusCode && errorPageId) {\r\n this.setPageSettings({\r\n pageId: errorPageId.toString(),\r\n pageUrl: pageUrl,\r\n fromError: true,\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.pageLoadSubscription?.unsubscribe();\r\n }\r\n}\r\n","import { DOCUMENT } from '@angular/common';\r\nimport { Inject, Injectable } from '@angular/core';\r\nimport { IScript } from '../../interfaces/project/script.interface';\r\n\r\n@Injectable()\r\nexport class ScriptService {\r\n private scripts: string[] = [];\r\n constructor(@Inject(DOCUMENT) private $document: Document) {}\r\n\r\n load(scripts: string[]) {\r\n const promises: Promise[] = [];\r\n\r\n scripts.forEach((script) => {\r\n const found = this.scripts.find((item) => item === script);\r\n if (found) {\r\n const promise = new Promise((resolve, reject) => {\r\n resolve({ Src: script, Loaded: true });\r\n });\r\n promises.push(promise);\r\n } else {\r\n this.scripts.push(script);\r\n const promise = this.loadScript(script);\r\n promises.push(promise);\r\n }\r\n });\r\n return Promise.all(promises);\r\n }\r\n\r\n private loadScript(script: string) {\r\n return new Promise((resolve, reject) => {\r\n const elem = this.$document.createElement('script');\r\n elem.type = 'text/javascript';\r\n elem.src = script;\r\n elem.onload = () => {\r\n resolve({ Src: script, Loaded: true });\r\n };\r\n elem.onerror = () => {\r\n elem.remove();\r\n this.scripts = this.scripts.filter((item) => item !== script);\r\n return reject({ Src: script, Loaded: false });\r\n };\r\n this.$document.getElementsByTagName('head')[0].appendChild(elem);\r\n });\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { AudioPlayerTypeEnum } from '@portal-app/enums/audio-player-type.enum';\r\nimport {\r\n IAudioPlayerMark,\r\n ICoordinates,\r\n ICoordinatesAndText,\r\n ISelection,\r\n} from '@portal-app/interfaces/project/layout-audio.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SelectionService {\r\n clearSelection(w?: Window) {\r\n const selection = w?.getSelection();\r\n if (selection) {\r\n if (selection?.empty) {\r\n // Chrome\r\n selection.empty();\r\n } else if (selection?.removeAllRanges) {\r\n // Firefox\r\n selection.removeAllRanges();\r\n }\r\n }\r\n }\r\n\r\n getSelection(\r\n type: AudioPlayerTypeEnum,\r\n w: Window,\r\n selection?: Selection,\r\n target?: HTMLBodyElement\r\n ): ISelection | undefined {\r\n if (\r\n target &&\r\n selection &&\r\n selection?.anchorNode !== null &&\r\n selection?.type !== 'None' &&\r\n selection?.toString() !== ''\r\n ) {\r\n try {\r\n if (type === AudioPlayerTypeEnum.PartialDesktop) {\r\n this.expandToWord(selection);\r\n }\r\n const result: ISelection = {\r\n Type: type,\r\n Target: target,\r\n Selection: selection,\r\n CoordinatesAndText: this.getCoordinatesAndText(\r\n selection.getRangeAt(0).commonAncestorContainer,\r\n selection,\r\n target,\r\n type\r\n ),\r\n Window: w,\r\n };\r\n return result;\r\n } catch (e) {\r\n console.warn(e);\r\n return;\r\n }\r\n } else {\r\n return;\r\n }\r\n }\r\n\r\n private expandToWord(selection: Selection): Selection {\r\n const rng2: Range = selection.getRangeAt(0);\r\n let startOffset = 0;\r\n if (rng2.startContainer.nodeValue !== null) {\r\n for (let i = rng2.startOffset; i >= 0; i--) {\r\n if (/\\S/.exec(rng2.startContainer.nodeValue[i])) {\r\n startOffset++;\r\n } else {\r\n break;\r\n }\r\n }\r\n }\r\n let endOffset = 0;\r\n if (rng2.endContainer.nodeValue !== null) {\r\n for (let i = rng2.endOffset; i < rng2.endContainer.nodeValue.length; i++) {\r\n if (/\\S/.exec(rng2.endContainer.nodeValue[i])) {\r\n endOffset++;\r\n } else {\r\n break;\r\n }\r\n }\r\n }\r\n startOffset = rng2.startOffset - startOffset;\r\n startOffset = startOffset < 0 ? 0 : rng2.startContainer.nodeValue === ' ' ? 1 : startOffset;\r\n endOffset = rng2.endOffset + endOffset;\r\n if (rng2.endContainer.nodeValue?.length) {\r\n endOffset =\r\n endOffset >= rng2.endContainer.nodeValue.length\r\n ? rng2.endContainer.nodeValue === ' '\r\n ? 0\r\n : rng2.endContainer.nodeValue.length\r\n : endOffset;\r\n }\r\n rng2.setStart(rng2.startContainer, startOffset);\r\n rng2.setEnd(rng2.endContainer, endOffset);\r\n selection.removeAllRanges();\r\n selection.addRange(rng2);\r\n return selection;\r\n }\r\n\r\n currentFrameAbsolutePosition(w: Window): ICoordinates {\r\n let currentWindow = w;\r\n let currentParentWindow: Window;\r\n const positions: ICoordinates[] = [];\r\n let rect;\r\n\r\n while (currentWindow !== w.top) {\r\n currentParentWindow = currentWindow.parent;\r\n for (const frame of Array.from(currentParentWindow.frames))\r\n if (frame === currentWindow) {\r\n for (const frameElement of Array.from(currentParentWindow.document.getElementsByTagName('iframe'))) {\r\n // TODO: be sure to test this\r\n if (frameElement.contentWindow === currentWindow) {\r\n rect = frameElement.getBoundingClientRect();\r\n positions.push({ X: rect.x, Y: rect.y });\r\n }\r\n }\r\n currentWindow = currentParentWindow;\r\n break;\r\n }\r\n }\r\n return positions.reduce(\r\n (accumulator, currentValue): ICoordinates => {\r\n return {\r\n X: accumulator.X + currentValue.X,\r\n Y: accumulator.Y + currentValue.Y,\r\n };\r\n },\r\n { X: 0, Y: 0 }\r\n );\r\n }\r\n\r\n private getCoordinatesAndText(\r\n node: Node,\r\n selection: Selection,\r\n target: HTMLElement,\r\n type: AudioPlayerTypeEnum\r\n ): ICoordinatesAndText {\r\n let text: string[] = [];\r\n const nodes: Node[] = [];\r\n const nonWhitespaceMatcher = /\\S/;\r\n const backwards = this.isSelectionBackwards(selection);\r\n const words: HTMLElement[] = [];\r\n let x = 0;\r\n let y = 0;\r\n function getTextNodes(nodeInput: Node) {\r\n const parent: HTMLElement | null = nodeInput.parentElement;\r\n if (parent) {\r\n let special = false;\r\n if (\r\n nodeInput.nodeValue !== null &&\r\n selection.containsNode(nodeInput, true) &&\r\n (nodeInput.nodeName.toLowerCase() === 'input' || nodeInput.nodeName.toLowerCase() === 'textarea') &&\r\n nonWhitespaceMatcher.test(nodeInput.nodeValue)\r\n ) {\r\n special = true;\r\n }\r\n if (\r\n nodeInput.nodeValue !== null &&\r\n !special &&\r\n selection.containsNode(nodeInput, true) &&\r\n nodeInput.nodeType === 3 &&\r\n !parent.classList.contains('no-select') &&\r\n !parent.closest('.no-select') &&\r\n parent.tagName !== 'SCRIPT'\r\n ) {\r\n if (!nonWhitespaceMatcher.test(nodeInput.nodeValue) && parent.classList.contains('space')) {\r\n if (type === AudioPlayerTypeEnum.PartialDesktop) {\r\n parent.classList.add('partial');\r\n }\r\n } else {\r\n text.push(nodeInput.nodeValue);\r\n if (parent.classList.contains('word')) {\r\n if (type === AudioPlayerTypeEnum.PartialDesktop) {\r\n parent.classList.add('partial');\r\n }\r\n words.push(parent);\r\n }\r\n nodes.push(nodeInput);\r\n if (text.length === 1) {\r\n if (type !== AudioPlayerTypeEnum.Full) {\r\n if (selection.anchorNode === selection.focusNode) {\r\n if (backwards) {\r\n text[0] = text[0].substring(0, selection.anchorOffset).substring(selection.focusOffset);\r\n } else {\r\n text[0] = text[0].substring(0, selection.focusOffset).substring(selection.anchorOffset);\r\n }\r\n } else {\r\n if (backwards) {\r\n text[0] = text[0].substring(selection.focusOffset);\r\n } else {\r\n text[0] = text[0].substring(selection.anchorOffset);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n for (let i = 0, len = nodeInput.childNodes.length; i < len; ++i) {\r\n getTextNodes(nodeInput.childNodes[i]);\r\n }\r\n }\r\n }\r\n }\r\n getTextNodes(node);\r\n if (text.length > 0 && text.length !== 1) {\r\n let sel = selection.toString();\r\n let foc: string;\r\n sel = sel.substring(sel.lastIndexOf(' ') + 1, sel.length);\r\n if (selection.focusNode) {\r\n if (selection.focusNode.nodeType === 3) {\r\n foc = selection.focusNode.toString();\r\n } else {\r\n foc = selection.focusNode.nodeValue !== null ? selection.focusNode.nodeValue : '';\r\n }\r\n foc = foc.substring(0, foc.indexOf(' ') + 1);\r\n }\r\n\r\n if (backwards) {\r\n text[text.length - 1] = text[text.length - 1].substring(0, selection.anchorOffset);\r\n }\r\n }\r\n if (target.classList.contains('no-select') && !backwards) {\r\n text = text.slice(0, -1);\r\n }\r\n\r\n if (words.length) {\r\n const selectedWord = words[0];\r\n if (selectedWord.ownerDocument.defaultView) {\r\n const coordinates = this.currentFrameAbsolutePosition(selectedWord.ownerDocument.defaultView);\r\n y = coordinates.Y + selectedWord.getBoundingClientRect().top;\r\n x = coordinates.X + selectedWord.getBoundingClientRect().left + selectedWord.getBoundingClientRect().width / 2;\r\n }\r\n }\r\n\r\n let textResult = text\r\n .join(' ')\r\n .replace(/(?:\\r\\n|\\r|\\n)/g, ' ')\r\n .replace(/ +\\./g, '. ')\r\n .replace(/\\s\\s+/g, ' ')\r\n .replace(/ !/g, '!')\r\n .replace(',.', '.')\r\n .trim();\r\n\r\n return {\r\n X: x,\r\n Y: y,\r\n Text: textResult,\r\n };\r\n }\r\n\r\n private isSelectionBackwards(selection: Selection) {\r\n let backwards = false;\r\n if (selection && selection.anchorNode && selection.focusNode) {\r\n if (!selection.isCollapsed) {\r\n const range = document.createRange();\r\n range.setStart(selection.anchorNode, selection.anchorOffset);\r\n range.setEnd(selection.focusNode, selection.focusOffset);\r\n backwards = range.collapsed;\r\n range.detach();\r\n }\r\n }\r\n return backwards;\r\n }\r\n\r\n private getDomWords(selection: ISelection, type: AudioPlayerTypeEnum) {\r\n return selection.Target.getElementsByClassName(\r\n type === AudioPlayerTypeEnum.PartialDesktop ? 'word partial' : 'word full'\r\n );\r\n }\r\n\r\n highlightWord(\r\n marks: IAudioPlayerMark[],\r\n currentTime: number,\r\n playing: boolean,\r\n type: AudioPlayerTypeEnum,\r\n selections?: ISelection[]\r\n ) {\r\n selections?.forEach((selection, index) => {\r\n if (!marks.length) {\r\n return;\r\n }\r\n const sentences = marks.filter((i) => Number(i.Sentence.time) <= currentTime);\r\n const selectedMark = sentences.length ? sentences[sentences.length - 1] : marks[0];\r\n if (!selectedMark.Words.length) {\r\n return;\r\n }\r\n const words = selectedMark.Words.filter((i) => Number(i.time) <= currentTime);\r\n const selectedWord = words.length ? words[words.length - 1] : selectedMark.Words[0];\r\n if (!selectedWord) {\r\n return;\r\n }\r\n let domWords = this.getDomWords(selection, type);\r\n if (!domWords.length) {\r\n if (\r\n (selection.Target.classList.contains('word') || selection.Target.classList.contains('partial')) &&\r\n selection.Target.parentElement\r\n ) {\r\n domWords = selection.Target.parentElement.getElementsByClassName('word partial');\r\n } else {\r\n return;\r\n }\r\n }\r\n for (const element of Array.from(domWords)) {\r\n element.classList.remove('full-highlight', 'full-paused', 'partial-highlight', 'partial-paused');\r\n }\r\n const markIndex = marks.findIndex((i) => i === selectedMark);\r\n if (markIndex === -1) {\r\n return;\r\n }\r\n let wordIndex = 0;\r\n if (markIndex > 0) {\r\n for (let i = 0; i < markIndex; i++) {\r\n const mark = marks[i];\r\n wordIndex = wordIndex + mark.Words.length;\r\n }\r\n }\r\n const selectedWordIndex = selectedMark.Words.findIndex((i) => i === selectedWord);\r\n wordIndex = wordIndex + selectedWordIndex;\r\n\r\n if (index) {\r\n for (let i = 0; i < index; i++) {\r\n const otherSelection = selections[i];\r\n const otherDomWords = this.getDomWords(otherSelection, type);\r\n wordIndex = wordIndex - otherDomWords.length;\r\n }\r\n }\r\n\r\n const domWord = domWords[wordIndex];\r\n if (!domWord) {\r\n return;\r\n }\r\n if (type === AudioPlayerTypeEnum.Full) {\r\n domWords[wordIndex].classList.add(playing ? 'full-highlight' : 'full-paused');\r\n } else if (type === AudioPlayerTypeEnum.PartialDesktop) {\r\n domWords[wordIndex].classList.add(playing ? 'partial-highlight' : 'partial-paused');\r\n }\r\n });\r\n }\r\n\r\n resetSelection(element: HTMLElement, type: AudioPlayerTypeEnum) {\r\n const textNodes = this.textNodesUnder(element);\r\n textNodes.forEach((textNode) => {\r\n const htmlNode = textNode.parentNode as HTMLElement;\r\n if (htmlNode.classList.contains('word') || htmlNode.classList.contains('space')) {\r\n if (type === AudioPlayerTypeEnum.Full) {\r\n htmlNode.classList.remove('full-highlight', 'full-paused');\r\n } else if (type === AudioPlayerTypeEnum.PartialDesktop) {\r\n htmlNode.classList.remove('partial', 'partial-highlight', 'partial-paused');\r\n }\r\n }\r\n });\r\n }\r\n\r\n private textNodesUnder(node: Node | null): Node[] {\r\n let all: Node[] = [];\r\n if (node?.firstChild) {\r\n for (node = node.firstChild; node; node = node.nextSibling) {\r\n if (\r\n (node.nodeType === 1 && node.nodeName === 'BR') ||\r\n (node.nodeType === 3 && node.nodeValue !== '\\n' && node.nodeValue !== '\\n\\n' && node.parentNode)\r\n ) {\r\n all.push(node);\r\n } else {\r\n all = all.concat(this.textNodesUnder(node));\r\n }\r\n }\r\n }\r\n return all;\r\n }\r\n\r\n iterate(element: HTMLElement) {\r\n let children = Array.from(element.childNodes);\r\n for (let i = 0; i < children.length; i++) {\r\n let child = children[i];\r\n if (child.nodeType === 1) {\r\n // html element\r\n this.iterate(child as HTMLElement);\r\n } else if (\r\n child.nodeType === 3 &&\r\n child.nodeValue &&\r\n child.nodeValue !== '\\n' &&\r\n child.nodeValue !== '\\n\\n' &&\r\n child.parentNode\r\n ) {\r\n // text element\r\n const newNode = document.createElement('SPAN');\r\n if (child.nodeValue === ' ') {\r\n newNode.classList.add('space');\r\n } else {\r\n newNode.classList.add('temp-words');\r\n }\r\n newNode.innerHTML = child.nodeValue;\r\n element.replaceChild(newNode, child);\r\n }\r\n }\r\n }\r\n\r\n prepareForSelection(element: HTMLElement) {\r\n if (element.getElementsByClassName('word').length) {\r\n return;\r\n }\r\n\r\n // 29\r\n\r\n // element.innerHTML = element.innerHTML.replace(\r\n // /(?]*|&[^;]*))([^\\s<]+)/g,\r\n // '$1$2'\r\n // );\r\n\r\n this.iterate(element);\r\n const tempWords = element.getElementsByClassName('temp-words');\r\n for (let i = tempWords.length - 1; i >= 0; i--) {\r\n const item = tempWords[i];\r\n let html: string[] = [];\r\n if (item.innerHTML) {\r\n const words = item.innerHTML.split(' ');\r\n words.forEach((word, index) => {\r\n if (word.length) {\r\n if (word === '-' || word === '–' || word.startsWith('!')) {\r\n html.push(`${word}`);\r\n } else {\r\n html.push(`${word}`);\r\n }\r\n } else {\r\n html.push(` `);\r\n }\r\n });\r\n }\r\n if (item.outerHTML) {\r\n item.outerHTML = html.join(' ');\r\n }\r\n }\r\n\r\n const shouldHaveBreak = Array.from(element.querySelectorAll('.rn_pagination,h1,h2,h3,h4,h5,h6,p,li,cite,a'))\r\n .map((i) => {\r\n const words1 = i.querySelectorAll('.word');\r\n return words1[words1.length - 1];\r\n })\r\n .filter((element) => {\r\n return element !== undefined;\r\n });\r\n\r\n const words = element.getElementsByClassName('word');\r\n\r\n for (var i = 0; i < words.length; i++) {\r\n const word = words[i];\r\n if (!word.closest('.sentence')) {\r\n word.parentElement?.classList.add('sentence');\r\n }\r\n if (word.innerHTML === word.parentElement?.title) {\r\n shouldHaveBreak.push(word);\r\n }\r\n }\r\n\r\n shouldHaveBreak.forEach((word) => {\r\n if (!['.', '!', '?'].some((char) => word.innerHTML.endsWith(char)) && !word.classList.contains('fixed')) {\r\n word.classList.add('fixed');\r\n word.innerHTML = `${word.innerHTML}!`;\r\n }\r\n });\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Meta, Title } from '@angular/platform-browser';\r\nimport { ApiService } from '@lru/felib';\r\nimport { IUmbMetaData } from '@portal-app/interfaces/umbraco/umb-meta-data.interface';\r\nimport { PageTypeEnum } from '../../enums/page-type.enum';\r\nimport { AppInitService } from './app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SeoService {\r\n constructor(\r\n private api: ApiService,\r\n private appInitService: AppInitService,\r\n private title: Title,\r\n private meta: Meta\r\n ) {}\r\n\r\n getMetaData(pageId: string) {\r\n return this.api.getUmbraco(\r\n `v4/alineaportal/getseometa/${pageId}/${this.appInitService.siteConfiguration.PortalId}`\r\n );\r\n }\r\n\r\n setMetaData(data: IUmbMetaData) {\r\n if (data.metaTitle) {\r\n if (data.pageType === PageTypeEnum.FrontPage) {\r\n this.title.setTitle(data.productName ? `${data.productName} - ${data.metaTitle}` : data.metaTitle);\r\n } else if (data.productName) {\r\n this.title.setTitle(`${data.metaTitle} - ${data.productName}`);\r\n } else {\r\n this.title.setTitle(data.metaTitle);\r\n }\r\n } else if (data.productName) {\r\n this.title.setTitle(data.productName);\r\n }\r\n\r\n let image = '';\r\n if (data.defaultImage) {\r\n image = data.defaultImage;\r\n } else if (data.logoImage) {\r\n image = data.logoImage;\r\n }\r\n\r\n data.metaTitle = data.metaTitle ?? '';\r\n data.metaDescription = data.metaDescription ?? '';\r\n\r\n this.meta.updateTag({\r\n name: 'keywords',\r\n content: data.keywords ? data.keywords.join(', ') : '',\r\n });\r\n this.meta.updateTag({ name: 'description', content: data.metaDescription });\r\n\r\n this.meta.updateTag({\r\n name: 'twitter:card',\r\n content: 'summary_large_image',\r\n });\r\n this.meta.updateTag({ name: 'twitter:title', content: data.metaTitle });\r\n this.meta.updateTag({\r\n name: 'twitter:text:title',\r\n content: data.metaTitle,\r\n });\r\n this.meta.updateTag({\r\n name: 'twitter:description',\r\n content: data.metaDescription,\r\n });\r\n this.meta.updateTag({ name: 'twitter:image', content: image });\r\n this.meta.updateTag({ name: 'twitter:image:alt', content: data.metaTitle });\r\n\r\n this.meta.updateTag({ property: 'og:url', content: window.location.href });\r\n this.meta.updateTag({ property: 'og:title', content: data.metaTitle });\r\n this.meta.updateTag({ property: 'og:image', content: image });\r\n this.meta.updateTag({\r\n property: 'og:image:alt',\r\n content: image ? data.metaTitle : '',\r\n });\r\n this.meta.updateTag({\r\n property: 'og:description',\r\n content: data.metaDescription,\r\n });\r\n\r\n this.meta.updateTag({\r\n name: 'robots',\r\n content: data.excludeFromSearchEngines ? 'noindex' : 'all',\r\n });\r\n }\r\n\r\n setGoogleVerificationId(id?: string) {\r\n if (id) {\r\n this.meta.updateTag({ property: 'google-site-verification', content: id });\r\n }\r\n }\r\n}\r\n","import { DimensionsEnum } from '@portal-app/enums/dimensions.enum';\r\n\r\nexport const environment = {\r\n production: true,\r\n fallbackLanguage: 'da',\r\n isRealProduction: () => {\r\n return window.location.hostname.toLocaleLowerCase().endsWith('.alinea.dk');\r\n },\r\n internalBackendUrl: () => {\r\n return window.location.origin + '/';\r\n },\r\n loginUsingMvcDotNet: true,\r\n apiLoungeBaseUrl: 'https://lounge.dev.alineadigital.dk/api/',\r\n apiNextBaseUrl: 'https://web-next-api-dev.azurewebsites.net/api/',\r\n apiNextSearchBaseUrl: 'https://nextsearch-dev.azurewebsites.net/api/',\r\n apIUmbBaseUrl: 'https://mitalineaumb.dev.alineadigital.dk/api/',\r\n assetBasePath: 'https://cdn.alinea.dk/',\r\n dimensions: DimensionsEnum,\r\n showPapertrailResponse: true,\r\n activityUrl: () => {\r\n return window.location.hostname === 'exploro.fagportal.dev.alineadigital.dk'\r\n ? 'https://exploroportal.dev.alineadigital.dk'\r\n : 'https://portal.dev.alineadigital.dk';\r\n },\r\n localHostName: 'dansk.fagportal.dev.alineadigital.dk',\r\n // localHostName: 'superreader.dev.alineadigital.dk',\r\n // localHostName: 'superbog.dev.alineadigital.dk',\r\n // localHostName: 'ps.dev.alineadigital.dk',\r\n};\r\n// The idnUrl must be the Internationalized Domain Name (IDN) for forstå.dk in production wich is https://xn--forst-qra.dk.\r\n","import { IDimensionRatio } from '@portal-app/interfaces/project/dimension.interface';\r\n\r\nexport const DimensionsEnum: IDimensionRatio[] = [\r\n {\r\n Ratio: 0.75,\r\n Dimensions: [\r\n {\r\n Width: 3840,\r\n Height: 2880,\r\n },\r\n {\r\n Width: 1920,\r\n Height: 1440,\r\n },\r\n {\r\n Width: 960,\r\n Height: 720,\r\n },\r\n {\r\n Width: 480,\r\n Height: 360,\r\n },\r\n ],\r\n },\r\n {\r\n Ratio: 1,\r\n Dimensions: [\r\n {\r\n Width: 600,\r\n Height: 600,\r\n },\r\n {\r\n Width: 300,\r\n Height: 300,\r\n },\r\n ],\r\n },\r\n {\r\n Ratio: 0.5625,\r\n Dimensions: [\r\n {\r\n Width: 3840,\r\n Height: 2160,\r\n },\r\n {\r\n Width: 1920,\r\n Height: 1080,\r\n },\r\n {\r\n Width: 960,\r\n Height: 540,\r\n },\r\n {\r\n Width: 480,\r\n Height: 270,\r\n },\r\n ],\r\n },\r\n {\r\n Ratio: 1.5,\r\n Dimensions: [\r\n {\r\n Width: 1920,\r\n Height: 2880,\r\n },\r\n {\r\n Width: 960,\r\n Height: 1440,\r\n },\r\n\r\n {\r\n Width: 480,\r\n Height: 720,\r\n },\r\n {\r\n Width: 240,\r\n Height: 360,\r\n },\r\n ],\r\n },\r\n];\r\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from './errors';\n\nconst LINE_START = '\\n - ';\n\nexport function invalidTimingValue(exp: string|number): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_TIMING_VALUE,\n ngDevMode && `The provided timing value \"${exp}\" is invalid.`);\n}\n\nexport function negativeStepValue(): Error {\n return new RuntimeError(\n RuntimeErrorCode.NEGATIVE_STEP_VALUE,\n ngDevMode && 'Duration values below 0 are not allowed for this animation step.');\n}\n\nexport function negativeDelayValue(): Error {\n return new RuntimeError(\n RuntimeErrorCode.NEGATIVE_DELAY_VALUE,\n ngDevMode && 'Delay values below 0 are not allowed for this animation step.');\n}\n\nexport function invalidStyleParams(varName: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_STYLE_PARAMS,\n ngDevMode &&\n `Unable to resolve the local animation param ${varName} in the given list of values`);\n}\n\nexport function invalidParamValue(varName: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_PARAM_VALUE,\n ngDevMode && `Please provide a value for the animation param ${varName}`);\n}\n\nexport function invalidNodeType(nodeType: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_NODE_TYPE,\n ngDevMode && `Unable to resolve animation metadata node #${nodeType}`);\n}\n\nexport function invalidCssUnitValue(userProvidedProperty: string, value: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_CSS_UNIT_VALUE,\n ngDevMode && `Please provide a CSS unit value for ${userProvidedProperty}:${value}`);\n}\n\nexport function invalidTrigger(): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_TRIGGER,\n ngDevMode &&\n 'animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\\'@foo\\', [...]))');\n}\n\nexport function invalidDefinition(): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_DEFINITION,\n ngDevMode && 'only state() and transition() definitions can sit inside of a trigger()');\n}\n\nexport function invalidState(metadataName: string, missingSubs: string[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_STATE,\n ngDevMode &&\n `state(\"${\n metadataName}\", ...) must define default values for all the following style substitutions: ${\n missingSubs.join(', ')}`);\n}\n\nexport function invalidStyleValue(value: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_STYLE_VALUE,\n ngDevMode && `The provided style string value ${value} is not allowed.`);\n}\n\nexport function invalidProperty(prop: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_PROPERTY,\n ngDevMode &&\n `The provided animation property \"${\n prop}\" is not a supported CSS property for animations`);\n}\n\nexport function invalidParallelAnimation(\n prop: string, firstStart: number, firstEnd: number, secondStart: number,\n secondEnd: number): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_PARALLEL_ANIMATION,\n ngDevMode &&\n `The CSS property \"${prop}\" that exists between the times of \"${firstStart}ms\" and \"${\n firstEnd}ms\" is also being animated in a parallel animation between the times of \"${\n secondStart}ms\" and \"${secondEnd}ms\"`);\n}\n\nexport function invalidKeyframes(): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_KEYFRAMES,\n ngDevMode && `keyframes() must be placed inside of a call to animate()`);\n}\n\nexport function invalidOffset(): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_OFFSET,\n ngDevMode && `Please ensure that all keyframe offsets are between 0 and 1`);\n}\n\nexport function keyframeOffsetsOutOfOrder(): Error {\n return new RuntimeError(\n RuntimeErrorCode.KEYFRAME_OFFSETS_OUT_OF_ORDER,\n ngDevMode && `Please ensure that all keyframe offsets are in order`);\n}\n\nexport function keyframesMissingOffsets(): Error {\n return new RuntimeError(\n RuntimeErrorCode.KEYFRAMES_MISSING_OFFSETS,\n ngDevMode && `Not all style() steps within the declared keyframes() contain offsets`);\n}\n\nexport function invalidStagger(): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_STAGGER,\n ngDevMode && `stagger() can only be used inside of query()`);\n}\n\nexport function invalidQuery(selector: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_QUERY,\n ngDevMode &&\n `\\`query(\"${selector}\")\\` returned zero elements. (Use \\`query(\"${\n selector}\", { optional: true })\\` if you wish to allow this.)`);\n}\n\nexport function invalidExpression(expr: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_EXPRESSION,\n ngDevMode && `The provided transition expression \"${expr}\" is not supported`);\n}\n\nexport function invalidTransitionAlias(alias: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_TRANSITION_ALIAS,\n ngDevMode && `The transition alias value \"${alias}\" is not supported`);\n}\n\nexport function validationFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.VALIDATION_FAILED,\n ngDevMode && `animation validation failed:\\n${errors.map(err => err.message).join('\\n')}`);\n}\n\nexport function buildingFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.BUILDING_FAILED,\n ngDevMode && `animation building failed:\\n${errors.map(err => err.message).join('\\n')}`);\n}\n\nexport function triggerBuildFailed(name: string, errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.TRIGGER_BUILD_FAILED,\n ngDevMode &&\n `The animation trigger \"${name}\" has failed to build due to the following errors:\\n - ${\n errors.map(err => err.message).join('\\n - ')}`);\n}\n\nexport function animationFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.ANIMATION_FAILED,\n ngDevMode &&\n `Unable to animate due to the following errors:${LINE_START}${\n errors.map(err => err.message).join(LINE_START)}`);\n}\n\nexport function registerFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.REGISTRATION_FAILED,\n ngDevMode &&\n `Unable to build the animation due to the following errors: ${\n errors.map(err => err.message).join('\\n')}`);\n}\n\nexport function missingOrDestroyedAnimation(): Error {\n return new RuntimeError(\n RuntimeErrorCode.MISSING_OR_DESTROYED_ANIMATION,\n ngDevMode && 'The requested animation doesn\\'t exist or has already been destroyed');\n}\n\nexport function createAnimationFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.CREATE_ANIMATION_FAILED,\n ngDevMode &&\n `Unable to create the animation due to the following errors:${\n errors.map(err => err.message).join('\\n')}`);\n}\n\nexport function missingPlayer(id: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.MISSING_PLAYER,\n ngDevMode && `Unable to find the timeline player referenced by ${id}`);\n}\n\nexport function missingTrigger(phase: string, name: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.MISSING_TRIGGER,\n ngDevMode &&\n `Unable to listen on the animation trigger event \"${\n phase}\" because the animation trigger \"${name}\" doesn\\'t exist!`);\n}\n\nexport function missingEvent(name: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.MISSING_EVENT,\n ngDevMode &&\n `Unable to listen on the animation trigger \"${\n name}\" because the provided event is undefined!`);\n}\n\nexport function unsupportedTriggerEvent(phase: string, name: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.UNSUPPORTED_TRIGGER_EVENT,\n ngDevMode &&\n `The provided animation trigger event \"${phase}\" for the animation trigger \"${\n name}\" is not supported!`);\n}\n\nexport function unregisteredTrigger(name: string): Error {\n return new RuntimeError(\n RuntimeErrorCode.UNREGISTERED_TRIGGER,\n ngDevMode && `The provided animation trigger \"${name}\" has not been registered!`);\n}\n\nexport function triggerTransitionsFailed(errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.TRIGGER_TRANSITIONS_FAILED,\n ngDevMode &&\n `Unable to process animations due to the following failed trigger transitions\\n ${\n errors.map(err => err.message).join('\\n')}`);\n}\n\nexport function triggerParsingFailed(name: string, errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.TRIGGER_PARSING_FAILED,\n ngDevMode &&\n `Animation parsing for the ${name} trigger have failed:${LINE_START}${\n errors.map(err => err.message).join(LINE_START)}`);\n}\n\nexport function transitionFailed(name: string, errors: Error[]): Error {\n return new RuntimeError(\n RuntimeErrorCode.TRANSITION_FAILED,\n ngDevMode && `@${name} has failed due to:\\n ${errors.map(err => err.message).join('\\n- ')}`);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationEvent, AnimationPlayer, AUTO_STYLE, NoopAnimationPlayer, ɵAnimationGroupPlayer, ɵPRE_STYLE as PRE_STYLE, ɵStyleDataMap} from '@angular/animations';\n\nimport {AnimationStyleNormalizer} from '../../src/dsl/style_normalization/animation_style_normalizer';\nimport {AnimationDriver} from '../../src/render/animation_driver';\nimport {animationFailed} from '../error_helpers';\n\nimport {ANIMATABLE_PROP_SET} from './web_animations/animatable_props_set';\n\n// We don't include ambient node types here since @angular/animations/browser\n// is meant to target the browser so technically it should not depend on node\n// types. `process` is just declared locally here as a result.\ndeclare const process: any;\n\nexport function isBrowser(): boolean {\n return (typeof window !== 'undefined' && typeof window.document !== 'undefined');\n}\n\nexport function isNode(): boolean {\n // Checking only for `process` isn't enough to identify whether or not we're in a Node\n // environment, because Webpack by default will polyfill the `process`. While we can discern\n // that Webpack polyfilled it by looking at `process.browser`, it's very Webpack-specific and\n // might not be future-proof. Instead we look at the stringified version of `process` which\n // is `[object process]` in Node and `[object Object]` when polyfilled.\n return typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';\n}\n\nexport function optimizeGroupPlayer(players: AnimationPlayer[]): AnimationPlayer {\n switch (players.length) {\n case 0:\n return new NoopAnimationPlayer();\n case 1:\n return players[0];\n default:\n return new ɵAnimationGroupPlayer(players);\n }\n}\n\nexport function normalizeKeyframes(\n driver: AnimationDriver, normalizer: AnimationStyleNormalizer, element: any,\n keyframes: Array<ɵStyleDataMap>, preStyles: ɵStyleDataMap = new Map(),\n postStyles: ɵStyleDataMap = new Map()): Array<ɵStyleDataMap> {\n const errors: Error[] = [];\n const normalizedKeyframes: Array<ɵStyleDataMap> = [];\n let previousOffset = -1;\n let previousKeyframe: ɵStyleDataMap|null = null;\n keyframes.forEach(kf => {\n const offset = kf.get('offset') as number;\n const isSameOffset = offset == previousOffset;\n const normalizedKeyframe: ɵStyleDataMap = (isSameOffset && previousKeyframe) || new Map();\n kf.forEach((val, prop) => {\n let normalizedProp = prop;\n let normalizedValue = val;\n if (prop !== 'offset') {\n normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors);\n switch (normalizedValue) {\n case PRE_STYLE:\n normalizedValue = preStyles.get(prop)!;\n break;\n\n case AUTO_STYLE:\n normalizedValue = postStyles.get(prop)!;\n break;\n\n default:\n normalizedValue =\n normalizer.normalizeStyleValue(prop, normalizedProp, normalizedValue, errors);\n break;\n }\n }\n normalizedKeyframe.set(normalizedProp, normalizedValue);\n });\n if (!isSameOffset) {\n normalizedKeyframes.push(normalizedKeyframe);\n }\n previousKeyframe = normalizedKeyframe;\n previousOffset = offset;\n });\n if (errors.length) {\n throw animationFailed(errors);\n }\n\n return normalizedKeyframes;\n}\n\nexport function listenOnPlayer(\n player: AnimationPlayer, eventName: string, event: AnimationEvent|undefined,\n callback: (event: any) => any) {\n switch (eventName) {\n case 'start':\n player.onStart(() => callback(event && copyAnimationEvent(event, 'start', player)));\n break;\n case 'done':\n player.onDone(() => callback(event && copyAnimationEvent(event, 'done', player)));\n break;\n case 'destroy':\n player.onDestroy(() => callback(event && copyAnimationEvent(event, 'destroy', player)));\n break;\n }\n}\n\nexport function copyAnimationEvent(\n e: AnimationEvent, phaseName: string, player: AnimationPlayer): AnimationEvent {\n const totalTime = player.totalTime;\n const disabled = (player as any).disabled ? true : false;\n const event = makeAnimationEvent(\n e.element, e.triggerName, e.fromState, e.toState, phaseName || e.phaseName,\n totalTime == undefined ? e.totalTime : totalTime, disabled);\n const data = (e as any)['_data'];\n if (data != null) {\n (event as any)['_data'] = data;\n }\n return event;\n}\n\nexport function makeAnimationEvent(\n element: any, triggerName: string, fromState: string, toState: string, phaseName: string = '',\n totalTime: number = 0, disabled?: boolean): AnimationEvent {\n return {element, triggerName, fromState, toState, phaseName, totalTime, disabled: !!disabled};\n}\n\nexport function getOrSetDefaultValue(map: Map, key: T, defaultValue: V) {\n let value = map.get(key);\n if (!value) {\n map.set(key, value = defaultValue);\n }\n return value;\n}\n\nexport function parseTimelineCommand(command: string): [string, string] {\n const separatorPos = command.indexOf(':');\n const id = command.substring(1, separatorPos);\n const action = command.slice(separatorPos + 1);\n return [id, action];\n}\n\nlet _contains: (elm1: any, elm2: any) => boolean = (elm1: any, elm2: any) => false;\nlet _query: (element: any, selector: string, multi: boolean) => any[] =\n (element: any, selector: string, multi: boolean) => {\n return [];\n };\nlet _documentElement: unknown|null = null;\n\nexport function getParentElement(element: any): unknown|null {\n const parent = element.parentNode || element.host; // consider host to support shadow DOM\n if (parent === _documentElement) {\n return null;\n }\n return parent;\n}\n\n// Define utility methods for browsers and platform-server(domino) where Element\n// and utility methods exist.\nconst _isNode = isNode();\nif (_isNode || typeof Element !== 'undefined') {\n if (!isBrowser()) {\n _contains = (elm1, elm2) => elm1.contains(elm2);\n } else {\n // Read the document element in an IIFE that's been marked pure to avoid a top-level property\n // read that may prevent tree-shaking.\n _documentElement = /* @__PURE__ */ (() => document.documentElement)();\n _contains = (elm1, elm2) => {\n while (elm2) {\n if (elm2 === elm1) {\n return true;\n }\n elm2 = getParentElement(elm2);\n }\n return false;\n };\n }\n\n _query = (element: any, selector: string, multi: boolean): any[] => {\n if (multi) {\n return Array.from(element.querySelectorAll(selector));\n }\n const elem = element.querySelector(selector);\n return elem ? [elem] : [];\n };\n}\n\nfunction containsVendorPrefix(prop: string): boolean {\n // Webkit is the only real popular vendor prefix nowadays\n // cc: http://shouldiprefix.com/\n return prop.substring(1, 6) == 'ebkit'; // webkit or Webkit\n}\n\nlet _CACHED_BODY: {style: any}|null = null;\nlet _IS_WEBKIT = false;\nexport function validateStyleProperty(prop: string): boolean {\n if (!_CACHED_BODY) {\n _CACHED_BODY = getBodyNode() || {};\n _IS_WEBKIT = _CACHED_BODY!.style ? ('WebkitAppearance' in _CACHED_BODY!.style) : false;\n }\n\n let result = true;\n if (_CACHED_BODY!.style && !containsVendorPrefix(prop)) {\n result = prop in _CACHED_BODY!.style;\n if (!result && _IS_WEBKIT) {\n const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.slice(1);\n result = camelProp in _CACHED_BODY!.style;\n }\n }\n\n return result;\n}\n\nexport function validateWebAnimatableStyleProperty(prop: string): boolean {\n return ANIMATABLE_PROP_SET.has(prop);\n}\n\nexport function getBodyNode(): any|null {\n if (typeof document != 'undefined') {\n return document.body;\n }\n return null;\n}\n\nexport const containsElement = _contains;\nexport const invokeQuery = _query;\n\nexport function hypenatePropsKeys(original: ɵStyleDataMap): ɵStyleDataMap {\n const newMap: ɵStyleDataMap = new Map();\n original.forEach((val, prop) => {\n const newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2');\n newMap.set(newProp, val);\n });\n return newMap;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationPlayer, NoopAnimationPlayer} from '@angular/animations';\nimport {Injectable} from '@angular/core';\n\nimport {containsElement, getParentElement, invokeQuery, validateStyleProperty} from './shared';\n\n/**\n * @publicApi\n */\n@Injectable()\nexport class NoopAnimationDriver implements AnimationDriver {\n validateStyleProperty(prop: string): boolean {\n return validateStyleProperty(prop);\n }\n\n matchesElement(_element: any, _selector: string): boolean {\n // This method is deprecated and no longer in use so we return false.\n return false;\n }\n\n containsElement(elm1: any, elm2: any): boolean {\n return containsElement(elm1, elm2);\n }\n\n getParentElement(element: unknown): unknown {\n return getParentElement(element);\n }\n\n query(element: any, selector: string, multi: boolean): any[] {\n return invokeQuery(element, selector, multi);\n }\n\n computeStyle(element: any, prop: string, defaultValue?: string): string {\n return defaultValue || '';\n }\n\n animate(\n element: any, keyframes: Array>, duration: number, delay: number,\n easing: string, previousPlayers: any[] = [],\n scrubberAccessRequested?: boolean): AnimationPlayer {\n return new NoopAnimationPlayer(duration, delay);\n }\n}\n\n/**\n * @publicApi\n */\nexport abstract class AnimationDriver {\n static NOOP: AnimationDriver = (/* @__PURE__ */ new NoopAnimationDriver());\n\n abstract validateStyleProperty(prop: string): boolean;\n\n abstract validateAnimatableStyleProperty?: (prop: string) => boolean;\n\n /**\n * @deprecated No longer in use. Will be removed.\n */\n abstract matchesElement(element: any, selector: string): boolean;\n\n abstract containsElement(elm1: any, elm2: any): boolean;\n\n /**\n * Obtains the parent element, if any. `null` is returned if the element does not have a parent.\n */\n abstract getParentElement(element: unknown): unknown;\n\n abstract query(element: any, selector: string, multi: boolean): any[];\n\n abstract computeStyle(element: any, prop: string, defaultValue?: string): string;\n\n abstract animate(\n element: any, keyframes: Array>, duration: number, delay: number,\n easing?: string|null, previousPlayers?: any[], scrubberAccessRequested?: boolean): any;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimateTimings, AnimationMetadata, AnimationMetadataType, AnimationOptions, sequence, ɵStyleData, ɵStyleDataMap} from '@angular/animations';\n\nimport {Ast as AnimationAst, AstVisitor as AnimationAstVisitor} from './dsl/animation_ast';\nimport {AnimationDslVisitor} from './dsl/animation_dsl_visitor';\nimport {invalidNodeType, invalidParamValue, invalidStyleParams, invalidTimingValue, negativeDelayValue, negativeStepValue} from './error_helpers';\nimport {isNode} from './render/shared';\n\nexport const ONE_SECOND = 1000;\n\nexport const SUBSTITUTION_EXPR_START = '{{';\nexport const SUBSTITUTION_EXPR_END = '}}';\nexport const ENTER_CLASSNAME = 'ng-enter';\nexport const LEAVE_CLASSNAME = 'ng-leave';\nexport const NG_TRIGGER_CLASSNAME = 'ng-trigger';\nexport const NG_TRIGGER_SELECTOR = '.ng-trigger';\nexport const NG_ANIMATING_CLASSNAME = 'ng-animating';\nexport const NG_ANIMATING_SELECTOR = '.ng-animating';\n\nexport function resolveTimingValue(value: string|number) {\n if (typeof value == 'number') return value;\n\n const matches = value.match(/^(-?[\\.\\d]+)(m?s)/);\n if (!matches || matches.length < 2) return 0;\n\n return _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);\n}\n\nfunction _convertTimeValueToMS(value: number, unit: string): number {\n switch (unit) {\n case 's':\n return value * ONE_SECOND;\n default: // ms or something else\n return value;\n }\n}\n\nexport function resolveTiming(\n timings: string|number|AnimateTimings, errors: Error[], allowNegativeValues?: boolean) {\n return timings.hasOwnProperty('duration') ?\n timings :\n parseTimeExpression(timings, errors, allowNegativeValues);\n}\n\nfunction parseTimeExpression(\n exp: string|number, errors: Error[], allowNegativeValues?: boolean): AnimateTimings {\n const regex = /^(-?[\\.\\d]+)(m?s)(?:\\s+(-?[\\.\\d]+)(m?s))?(?:\\s+([-a-z]+(?:\\(.+?\\))?))?$/i;\n let duration: number;\n let delay: number = 0;\n let easing: string = '';\n if (typeof exp === 'string') {\n const matches = exp.match(regex);\n if (matches === null) {\n errors.push(invalidTimingValue(exp));\n return {duration: 0, delay: 0, easing: ''};\n }\n\n duration = _convertTimeValueToMS(parseFloat(matches[1]), matches[2]);\n\n const delayMatch = matches[3];\n if (delayMatch != null) {\n delay = _convertTimeValueToMS(parseFloat(delayMatch), matches[4]);\n }\n\n const easingVal = matches[5];\n if (easingVal) {\n easing = easingVal;\n }\n } else {\n duration = exp;\n }\n\n if (!allowNegativeValues) {\n let containsErrors = false;\n let startIndex = errors.length;\n if (duration < 0) {\n errors.push(negativeStepValue());\n containsErrors = true;\n }\n if (delay < 0) {\n errors.push(negativeDelayValue());\n containsErrors = true;\n }\n if (containsErrors) {\n errors.splice(startIndex, 0, invalidTimingValue(exp));\n }\n }\n\n return {duration, delay, easing};\n}\n\nexport function copyObj(\n obj: {[key: string]: any}, destination: {[key: string]: any} = {}): {[key: string]: any} {\n Object.keys(obj).forEach(prop => {\n destination[prop] = obj[prop];\n });\n return destination;\n}\n\nexport function convertToMap(obj: ɵStyleData): ɵStyleDataMap {\n const styleMap: ɵStyleDataMap = new Map();\n Object.keys(obj).forEach(prop => {\n const val = obj[prop];\n styleMap.set(prop, val);\n });\n return styleMap;\n}\n\nexport function normalizeKeyframes(keyframes: Array<ɵStyleData>|\n Array<ɵStyleDataMap>): Array<ɵStyleDataMap> {\n if (!keyframes.length) {\n return [];\n }\n if (keyframes[0] instanceof Map) {\n return keyframes as Array<ɵStyleDataMap>;\n }\n return keyframes.map(kf => convertToMap(kf as ɵStyleData));\n}\n\nexport function normalizeStyles(styles: ɵStyleDataMap|Array<ɵStyleDataMap>): ɵStyleDataMap {\n const normalizedStyles: ɵStyleDataMap = new Map();\n if (Array.isArray(styles)) {\n styles.forEach(data => copyStyles(data, normalizedStyles));\n } else {\n copyStyles(styles, normalizedStyles);\n }\n return normalizedStyles;\n}\n\nexport function copyStyles(\n styles: ɵStyleDataMap, destination: ɵStyleDataMap = new Map(),\n backfill?: ɵStyleDataMap): ɵStyleDataMap {\n if (backfill) {\n for (let [prop, val] of backfill) {\n destination.set(prop, val);\n }\n }\n for (let [prop, val] of styles) {\n destination.set(prop, val);\n }\n return destination;\n}\n\nfunction getStyleAttributeString(element: any, key: string, value: string) {\n // Return the key-value pair string to be added to the style attribute for the\n // given CSS style key.\n if (value) {\n return key + ':' + value + ';';\n } else {\n return '';\n }\n}\n\nfunction writeStyleAttribute(element: any) {\n // Read the style property of the element and manually reflect it to the\n // style attribute. This is needed because Domino on platform-server doesn't\n // understand the full set of allowed CSS properties and doesn't reflect some\n // of them automatically.\n let styleAttrValue = '';\n for (let i = 0; i < element.style.length; i++) {\n const key = element.style.item(i);\n styleAttrValue += getStyleAttributeString(element, key, element.style.getPropertyValue(key));\n }\n for (const key in element.style) {\n // Skip internal Domino properties that don't need to be reflected.\n if (!element.style.hasOwnProperty(key) || key.startsWith('_')) {\n continue;\n }\n const dashKey = camelCaseToDashCase(key);\n styleAttrValue += getStyleAttributeString(element, dashKey, element.style[key]);\n }\n element.setAttribute('style', styleAttrValue);\n}\n\nexport function setStyles(element: any, styles: ɵStyleDataMap, formerStyles?: ɵStyleDataMap) {\n if (element['style']) {\n styles.forEach((val, prop) => {\n const camelProp = dashCaseToCamelCase(prop);\n if (formerStyles && !formerStyles.has(prop)) {\n formerStyles.set(prop, element.style[camelProp]);\n }\n element.style[camelProp] = val;\n });\n // On the server set the 'style' attribute since it's not automatically reflected.\n if (isNode()) {\n writeStyleAttribute(element);\n }\n }\n}\n\nexport function eraseStyles(element: any, styles: ɵStyleDataMap) {\n if (element['style']) {\n styles.forEach((_, prop) => {\n const camelProp = dashCaseToCamelCase(prop);\n element.style[camelProp] = '';\n });\n // On the server set the 'style' attribute since it's not automatically reflected.\n if (isNode()) {\n writeStyleAttribute(element);\n }\n }\n}\n\nexport function normalizeAnimationEntry(steps: AnimationMetadata|\n AnimationMetadata[]): AnimationMetadata {\n if (Array.isArray(steps)) {\n if (steps.length == 1) return steps[0];\n return sequence(steps);\n }\n return steps as AnimationMetadata;\n}\n\nexport function validateStyleParams(\n value: string|number|null|undefined, options: AnimationOptions, errors: Error[]) {\n const params = options.params || {};\n const matches = extractStyleParams(value);\n if (matches.length) {\n matches.forEach(varName => {\n if (!params.hasOwnProperty(varName)) {\n errors.push(invalidStyleParams(varName));\n }\n });\n }\n}\n\nconst PARAM_REGEX =\n new RegExp(`${SUBSTITUTION_EXPR_START}\\\\s*(.+?)\\\\s*${SUBSTITUTION_EXPR_END}`, 'g');\nexport function extractStyleParams(value: string|number|null|undefined): string[] {\n let params: string[] = [];\n if (typeof value === 'string') {\n let match: any;\n while (match = PARAM_REGEX.exec(value)) {\n params.push(match[1] as string);\n }\n PARAM_REGEX.lastIndex = 0;\n }\n return params;\n}\n\nexport function interpolateParams(\n value: string|number, params: {[name: string]: any}, errors: Error[]): string|number {\n const original = value.toString();\n const str = original.replace(PARAM_REGEX, (_, varName) => {\n let localVal = params[varName];\n // this means that the value was never overridden by the data passed in by the user\n if (localVal == null) {\n errors.push(invalidParamValue(varName));\n localVal = '';\n }\n return localVal.toString();\n });\n\n // we do this to assert that numeric values stay as they are\n return str == original ? value : str;\n}\n\nexport function iteratorToArray(iterator: any): any[] {\n const arr: any[] = [];\n let item = iterator.next();\n while (!item.done) {\n arr.push(item.value);\n item = iterator.next();\n }\n return arr;\n}\n\nconst DASH_CASE_REGEXP = /-+([a-z0-9])/g;\nexport function dashCaseToCamelCase(input: string): string {\n return input.replace(DASH_CASE_REGEXP, (...m: any[]) => m[1].toUpperCase());\n}\n\nexport function camelCaseToDashCase(input: string): string {\n return input.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nexport function allowPreviousPlayerStylesMerge(duration: number, delay: number) {\n return duration === 0 || delay === 0;\n}\n\nexport function balancePreviousStylesIntoKeyframes(\n element: any, keyframes: Array<ɵStyleDataMap>, previousStyles: ɵStyleDataMap) {\n if (previousStyles.size && keyframes.length) {\n let startingKeyframe = keyframes[0];\n let missingStyleProps: string[] = [];\n previousStyles.forEach((val, prop) => {\n if (!startingKeyframe.has(prop)) {\n missingStyleProps.push(prop);\n }\n startingKeyframe.set(prop, val);\n });\n\n if (missingStyleProps.length) {\n for (let i = 1; i < keyframes.length; i++) {\n let kf = keyframes[i];\n missingStyleProps.forEach(prop => kf.set(prop, computeStyle(element, prop)));\n }\n }\n }\n return keyframes;\n}\n\nexport function visitDslNode(\n visitor: AnimationDslVisitor, node: AnimationMetadata, context: any): any;\nexport function visitDslNode(\n visitor: AnimationAstVisitor, node: AnimationAst, context: any): any;\nexport function visitDslNode(visitor: any, node: any, context: any): any {\n switch (node.type) {\n case AnimationMetadataType.Trigger:\n return visitor.visitTrigger(node, context);\n case AnimationMetadataType.State:\n return visitor.visitState(node, context);\n case AnimationMetadataType.Transition:\n return visitor.visitTransition(node, context);\n case AnimationMetadataType.Sequence:\n return visitor.visitSequence(node, context);\n case AnimationMetadataType.Group:\n return visitor.visitGroup(node, context);\n case AnimationMetadataType.Animate:\n return visitor.visitAnimate(node, context);\n case AnimationMetadataType.Keyframes:\n return visitor.visitKeyframes(node, context);\n case AnimationMetadataType.Style:\n return visitor.visitStyle(node, context);\n case AnimationMetadataType.Reference:\n return visitor.visitReference(node, context);\n case AnimationMetadataType.AnimateChild:\n return visitor.visitAnimateChild(node, context);\n case AnimationMetadataType.AnimateRef:\n return visitor.visitAnimateRef(node, context);\n case AnimationMetadataType.Query:\n return visitor.visitQuery(node, context);\n case AnimationMetadataType.Stagger:\n return visitor.visitStagger(node, context);\n default:\n throw invalidNodeType(node.type);\n }\n}\n\nexport function computeStyle(element: any, prop: string): string {\n return (window.getComputedStyle(element))[prop];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {invalidExpression, invalidTransitionAlias} from '../error_helpers';\n\nexport const ANY_STATE = '*';\nexport declare type TransitionMatcherFn =\n (fromState: any, toState: any, element: any, params: {[key: string]: any}) => boolean;\n\nexport function parseTransitionExpr(\n transitionValue: string|TransitionMatcherFn, errors: Error[]): TransitionMatcherFn[] {\n const expressions: TransitionMatcherFn[] = [];\n if (typeof transitionValue == 'string') {\n transitionValue.split(/\\s*,\\s*/).forEach(\n str => parseInnerTransitionStr(str, expressions, errors));\n } else {\n expressions.push(transitionValue);\n }\n return expressions;\n}\n\nfunction parseInnerTransitionStr(\n eventStr: string, expressions: TransitionMatcherFn[], errors: Error[]) {\n if (eventStr[0] == ':') {\n const result = parseAnimationAlias(eventStr, errors);\n if (typeof result == 'function') {\n expressions.push(result);\n return;\n }\n eventStr = result;\n }\n\n const match = eventStr.match(/^(\\*|[-\\w]+)\\s*()\\s*(\\*|[-\\w]+)$/);\n if (match == null || match.length < 4) {\n errors.push(invalidExpression(eventStr));\n return expressions;\n }\n\n const fromState = match[1];\n const separator = match[2];\n const toState = match[3];\n expressions.push(makeLambdaFromStates(fromState, toState));\n\n const isFullAnyStateExpr = fromState == ANY_STATE && toState == ANY_STATE;\n if (separator[0] == '<' && !isFullAnyStateExpr) {\n expressions.push(makeLambdaFromStates(toState, fromState));\n }\n}\n\nfunction parseAnimationAlias(alias: string, errors: Error[]): string|TransitionMatcherFn {\n switch (alias) {\n case ':enter':\n return 'void => *';\n case ':leave':\n return '* => void';\n case ':increment':\n return (fromState: any, toState: any): boolean => parseFloat(toState) > parseFloat(fromState);\n case ':decrement':\n return (fromState: any, toState: any): boolean => parseFloat(toState) < parseFloat(fromState);\n default:\n errors.push(invalidTransitionAlias(alias));\n return '* => *';\n }\n}\n\n// DO NOT REFACTOR ... keep the follow set instantiations\n// with the values intact (closure compiler for some reason\n// removes follow-up lines that add the values outside of\n// the constructor...\nconst TRUE_BOOLEAN_VALUES = new Set(['true', '1']);\nconst FALSE_BOOLEAN_VALUES = new Set(['false', '0']);\n\nfunction makeLambdaFromStates(lhs: string, rhs: string): TransitionMatcherFn {\n const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs);\n const RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs);\n\n return (fromState: any, toState: any): boolean => {\n let lhsMatch = lhs == ANY_STATE || lhs == fromState;\n let rhsMatch = rhs == ANY_STATE || rhs == toState;\n\n if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') {\n lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs);\n }\n if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') {\n rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs);\n }\n\n return lhsMatch && rhsMatch;\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimateTimings, AnimationAnimateChildMetadata, AnimationAnimateMetadata, AnimationAnimateRefMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationMetadataType, AnimationOptions, AnimationQueryMetadata, AnimationQueryOptions, AnimationReferenceMetadata, AnimationSequenceMetadata, AnimationStaggerMetadata, AnimationStateMetadata, AnimationStyleMetadata, AnimationTransitionMetadata, AnimationTriggerMetadata, AUTO_STYLE, style, ɵStyleDataMap} from '@angular/animations';\n\nimport {invalidDefinition, invalidKeyframes, invalidOffset, invalidParallelAnimation, invalidProperty, invalidStagger, invalidState, invalidStyleValue, invalidTrigger, keyframeOffsetsOutOfOrder, keyframesMissingOffsets} from '../error_helpers';\nimport {AnimationDriver} from '../render/animation_driver';\nimport {getOrSetDefaultValue} from '../render/shared';\nimport {convertToMap, copyObj, extractStyleParams, iteratorToArray, NG_ANIMATING_SELECTOR, NG_TRIGGER_SELECTOR, normalizeAnimationEntry, resolveTiming, SUBSTITUTION_EXPR_START, validateStyleParams, visitDslNode} from '../util';\nimport {pushUnrecognizedPropertiesWarning} from '../warning_helpers';\n\nimport {AnimateAst, AnimateChildAst, AnimateRefAst, Ast, DynamicTimingAst, GroupAst, KeyframesAst, QueryAst, ReferenceAst, SequenceAst, StaggerAst, StateAst, StyleAst, TimingAst, TransitionAst, TriggerAst} from './animation_ast';\nimport {AnimationDslVisitor} from './animation_dsl_visitor';\nimport {parseTransitionExpr} from './animation_transition_expr';\n\nconst SELF_TOKEN = ':self';\nconst SELF_TOKEN_REGEX = new RegExp(`\\s*${SELF_TOKEN}\\s*,?`, 'g');\n\n/*\n * [Validation]\n * The visitor code below will traverse the animation AST generated by the animation verb functions\n * (the output is a tree of objects) and attempt to perform a series of validations on the data. The\n * following corner-cases will be validated:\n *\n * 1. Overlap of animations\n * Given that a CSS property cannot be animated in more than one place at the same time, it's\n * important that this behavior is detected and validated. The way in which this occurs is that\n * each time a style property is examined, a string-map containing the property will be updated with\n * the start and end times for when the property is used within an animation step.\n *\n * If there are two or more parallel animations that are currently running (these are invoked by the\n * group()) on the same element then the validator will throw an error. Since the start/end timing\n * values are collected for each property then if the current animation step is animating the same\n * property and its timing values fall anywhere into the window of time that the property is\n * currently being animated within then this is what causes an error.\n *\n * 2. Timing values\n * The validator will validate to see if a timing value of `duration delay easing` or\n * `durationNumber` is valid or not.\n *\n * (note that upon validation the code below will replace the timing data with an object containing\n * {duration,delay,easing}.\n *\n * 3. Offset Validation\n * Each of the style() calls are allowed to have an offset value when placed inside of keyframes().\n * Offsets within keyframes() are considered valid when:\n *\n * - No offsets are used at all\n * - Each style() entry contains an offset value\n * - Each offset is between 0 and 1\n * - Each offset is greater to or equal than the previous one\n *\n * Otherwise an error will be thrown.\n */\nexport function buildAnimationAst(\n driver: AnimationDriver, metadata: AnimationMetadata|AnimationMetadata[], errors: Error[],\n warnings: string[]): Ast {\n return new AnimationAstBuilderVisitor(driver).build(metadata, errors, warnings);\n}\n\nconst ROOT_SELECTOR = '';\n\nexport class AnimationAstBuilderVisitor implements AnimationDslVisitor {\n constructor(private _driver: AnimationDriver) {}\n\n build(metadata: AnimationMetadata|AnimationMetadata[], errors: Error[], warnings: string[]):\n Ast {\n const context = new AnimationAstBuilderContext(errors);\n this._resetContextStyleTimingState(context);\n const ast =\n >visitDslNode(this, normalizeAnimationEntry(metadata), context);\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (context.unsupportedCSSPropertiesFound.size) {\n pushUnrecognizedPropertiesWarning(\n warnings,\n [...context.unsupportedCSSPropertiesFound.keys()],\n );\n }\n }\n\n return ast;\n }\n\n private _resetContextStyleTimingState(context: AnimationAstBuilderContext) {\n context.currentQuerySelector = ROOT_SELECTOR;\n context.collectedStyles = new Map>();\n context.collectedStyles.set(ROOT_SELECTOR, new Map());\n context.currentTime = 0;\n }\n\n visitTrigger(metadata: AnimationTriggerMetadata, context: AnimationAstBuilderContext):\n TriggerAst {\n let queryCount = context.queryCount = 0;\n let depCount = context.depCount = 0;\n const states: StateAst[] = [];\n const transitions: TransitionAst[] = [];\n if (metadata.name.charAt(0) == '@') {\n context.errors.push(invalidTrigger());\n }\n\n metadata.definitions.forEach(def => {\n this._resetContextStyleTimingState(context);\n if (def.type == AnimationMetadataType.State) {\n const stateDef = def as AnimationStateMetadata;\n const name = stateDef.name;\n name.toString().split(/\\s*,\\s*/).forEach(n => {\n stateDef.name = n;\n states.push(this.visitState(stateDef, context));\n });\n stateDef.name = name;\n } else if (def.type == AnimationMetadataType.Transition) {\n const transition = this.visitTransition(def as AnimationTransitionMetadata, context);\n queryCount += transition.queryCount;\n depCount += transition.depCount;\n transitions.push(transition);\n } else {\n context.errors.push(invalidDefinition());\n }\n });\n\n return {\n type: AnimationMetadataType.Trigger,\n name: metadata.name,\n states,\n transitions,\n queryCount,\n depCount,\n options: null\n };\n }\n\n visitState(metadata: AnimationStateMetadata, context: AnimationAstBuilderContext): StateAst {\n const styleAst = this.visitStyle(metadata.styles, context);\n const astParams = (metadata.options && metadata.options.params) || null;\n if (styleAst.containsDynamicStyles) {\n const missingSubs = new Set();\n const params = astParams || {};\n styleAst.styles.forEach(style => {\n if (style instanceof Map) {\n style.forEach(value => {\n extractStyleParams(value).forEach(sub => {\n if (!params.hasOwnProperty(sub)) {\n missingSubs.add(sub);\n }\n });\n });\n }\n });\n if (missingSubs.size) {\n const missingSubsArr = iteratorToArray(missingSubs.values());\n context.errors.push(invalidState(metadata.name, missingSubsArr));\n }\n }\n\n return {\n type: AnimationMetadataType.State,\n name: metadata.name,\n style: styleAst,\n options: astParams ? {params: astParams} : null\n };\n }\n\n visitTransition(metadata: AnimationTransitionMetadata, context: AnimationAstBuilderContext):\n TransitionAst {\n context.queryCount = 0;\n context.depCount = 0;\n const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);\n const matchers = parseTransitionExpr(metadata.expr, context.errors);\n\n return {\n type: AnimationMetadataType.Transition,\n matchers,\n animation,\n queryCount: context.queryCount,\n depCount: context.depCount,\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitSequence(metadata: AnimationSequenceMetadata, context: AnimationAstBuilderContext):\n SequenceAst {\n return {\n type: AnimationMetadataType.Sequence,\n steps: metadata.steps.map(s => visitDslNode(this, s, context)),\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitGroup(metadata: AnimationGroupMetadata, context: AnimationAstBuilderContext): GroupAst {\n const currentTime = context.currentTime;\n let furthestTime = 0;\n const steps = metadata.steps.map(step => {\n context.currentTime = currentTime;\n const innerAst = visitDslNode(this, step, context);\n furthestTime = Math.max(furthestTime, context.currentTime);\n return innerAst;\n });\n\n context.currentTime = furthestTime;\n return {\n type: AnimationMetadataType.Group,\n steps,\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitAnimate(metadata: AnimationAnimateMetadata, context: AnimationAstBuilderContext):\n AnimateAst {\n const timingAst = constructTimingAst(metadata.timings, context.errors);\n context.currentAnimateTimings = timingAst;\n let styleAst: StyleAst|KeyframesAst;\n let styleMetadata: AnimationStyleMetadata|AnimationKeyframesSequenceMetadata =\n metadata.styles ? metadata.styles : style({});\n if (styleMetadata.type == AnimationMetadataType.Keyframes) {\n styleAst = this.visitKeyframes(styleMetadata as AnimationKeyframesSequenceMetadata, context);\n } else {\n let styleMetadata = metadata.styles as AnimationStyleMetadata;\n let isEmpty = false;\n if (!styleMetadata) {\n isEmpty = true;\n const newStyleData: {[prop: string]: string|number} = {};\n if (timingAst.easing) {\n newStyleData['easing'] = timingAst.easing;\n }\n styleMetadata = style(newStyleData);\n }\n context.currentTime += timingAst.duration + timingAst.delay;\n const _styleAst = this.visitStyle(styleMetadata, context);\n _styleAst.isEmptyStep = isEmpty;\n styleAst = _styleAst;\n }\n\n context.currentAnimateTimings = null;\n return {\n type: AnimationMetadataType.Animate,\n timings: timingAst,\n style: styleAst,\n options: null\n };\n }\n\n visitStyle(metadata: AnimationStyleMetadata, context: AnimationAstBuilderContext): StyleAst {\n const ast = this._makeStyleAst(metadata, context);\n this._validateStyleAst(ast, context);\n return ast;\n }\n\n private _makeStyleAst(metadata: AnimationStyleMetadata, context: AnimationAstBuilderContext):\n StyleAst {\n const styles: Array<(ɵStyleDataMap | string)> = [];\n const metadataStyles = Array.isArray(metadata.styles) ? metadata.styles : [metadata.styles];\n\n for (let styleTuple of metadataStyles) {\n if (typeof styleTuple === 'string') {\n if (styleTuple === AUTO_STYLE) {\n styles.push(styleTuple);\n } else {\n context.errors.push(invalidStyleValue(styleTuple));\n }\n } else {\n styles.push(convertToMap(styleTuple));\n }\n }\n\n let containsDynamicStyles = false;\n let collectedEasing: string|null = null;\n styles.forEach(styleData => {\n if (styleData instanceof Map) {\n if (styleData.has('easing')) {\n collectedEasing = styleData.get('easing') as string;\n styleData.delete('easing');\n }\n if (!containsDynamicStyles) {\n for (let value of styleData.values()) {\n if (value!.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) {\n containsDynamicStyles = true;\n break;\n }\n }\n }\n }\n });\n\n return {\n type: AnimationMetadataType.Style,\n styles,\n easing: collectedEasing,\n offset: metadata.offset,\n containsDynamicStyles,\n options: null\n };\n }\n\n private _validateStyleAst(ast: StyleAst, context: AnimationAstBuilderContext): void {\n const timings = context.currentAnimateTimings;\n let endTime = context.currentTime;\n let startTime = context.currentTime;\n if (timings && startTime > 0) {\n startTime -= timings.duration + timings.delay;\n }\n\n ast.styles.forEach(tuple => {\n if (typeof tuple === 'string') return;\n\n tuple.forEach((value, prop) => {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this._driver.validateStyleProperty(prop)) {\n tuple.delete(prop);\n context.unsupportedCSSPropertiesFound.add(prop);\n return;\n }\n }\n\n // This is guaranteed to have a defined Map at this querySelector location making it\n // safe to add the assertion here. It is set as a default empty map in prior methods.\n const collectedStyles = context.collectedStyles.get(context.currentQuerySelector!)!;\n const collectedEntry = collectedStyles.get(prop);\n let updateCollectedStyle = true;\n if (collectedEntry) {\n if (startTime != endTime && startTime >= collectedEntry.startTime &&\n endTime <= collectedEntry.endTime) {\n context.errors.push(invalidParallelAnimation(\n prop, collectedEntry.startTime, collectedEntry.endTime, startTime, endTime));\n updateCollectedStyle = false;\n }\n\n // we always choose the smaller start time value since we\n // want to have a record of the entire animation window where\n // the style property is being animated in between\n startTime = collectedEntry.startTime;\n }\n\n if (updateCollectedStyle) {\n collectedStyles.set(prop, {startTime, endTime});\n }\n\n if (context.options) {\n validateStyleParams(value, context.options, context.errors);\n }\n });\n });\n }\n\n visitKeyframes(metadata: AnimationKeyframesSequenceMetadata, context: AnimationAstBuilderContext):\n KeyframesAst {\n const ast: KeyframesAst = {type: AnimationMetadataType.Keyframes, styles: [], options: null};\n if (!context.currentAnimateTimings) {\n context.errors.push(invalidKeyframes());\n return ast;\n }\n\n const MAX_KEYFRAME_OFFSET = 1;\n\n let totalKeyframesWithOffsets = 0;\n const offsets: number[] = [];\n let offsetsOutOfOrder = false;\n let keyframesOutOfRange = false;\n let previousOffset: number = 0;\n\n const keyframes: StyleAst[] = metadata.steps.map(styles => {\n const style = this._makeStyleAst(styles, context);\n let offsetVal: number|null =\n style.offset != null ? style.offset : consumeOffset(style.styles);\n let offset: number = 0;\n if (offsetVal != null) {\n totalKeyframesWithOffsets++;\n offset = style.offset = offsetVal;\n }\n keyframesOutOfRange = keyframesOutOfRange || offset < 0 || offset > 1;\n offsetsOutOfOrder = offsetsOutOfOrder || offset < previousOffset;\n previousOffset = offset;\n offsets.push(offset);\n return style;\n });\n\n if (keyframesOutOfRange) {\n context.errors.push(invalidOffset());\n }\n\n if (offsetsOutOfOrder) {\n context.errors.push(keyframeOffsetsOutOfOrder());\n }\n\n const length = metadata.steps.length;\n let generatedOffset = 0;\n if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) {\n context.errors.push(keyframesMissingOffsets());\n } else if (totalKeyframesWithOffsets == 0) {\n generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1);\n }\n\n const limit = length - 1;\n const currentTime = context.currentTime;\n const currentAnimateTimings = context.currentAnimateTimings!;\n const animateDuration = currentAnimateTimings.duration;\n keyframes.forEach((kf, i) => {\n const offset = generatedOffset > 0 ? (i == limit ? 1 : (generatedOffset * i)) : offsets[i];\n const durationUpToThisFrame = offset * animateDuration;\n context.currentTime = currentTime + currentAnimateTimings.delay + durationUpToThisFrame;\n currentAnimateTimings.duration = durationUpToThisFrame;\n this._validateStyleAst(kf, context);\n kf.offset = offset;\n\n ast.styles.push(kf);\n });\n\n return ast;\n }\n\n visitReference(metadata: AnimationReferenceMetadata, context: AnimationAstBuilderContext):\n ReferenceAst {\n return {\n type: AnimationMetadataType.Reference,\n animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context),\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitAnimateChild(metadata: AnimationAnimateChildMetadata, context: AnimationAstBuilderContext):\n AnimateChildAst {\n context.depCount++;\n return {\n type: AnimationMetadataType.AnimateChild,\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitAnimateRef(metadata: AnimationAnimateRefMetadata, context: AnimationAstBuilderContext):\n AnimateRefAst {\n return {\n type: AnimationMetadataType.AnimateRef,\n animation: this.visitReference(metadata.animation, context),\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitQuery(metadata: AnimationQueryMetadata, context: AnimationAstBuilderContext): QueryAst {\n const parentSelector = context.currentQuerySelector!;\n const options = (metadata.options || {}) as AnimationQueryOptions;\n\n context.queryCount++;\n context.currentQuery = metadata;\n const [selector, includeSelf] = normalizeSelector(metadata.selector);\n context.currentQuerySelector =\n parentSelector.length ? (parentSelector + ' ' + selector) : selector;\n getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map());\n\n const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context);\n context.currentQuery = null;\n context.currentQuerySelector = parentSelector;\n\n return {\n type: AnimationMetadataType.Query,\n selector,\n limit: options.limit || 0,\n optional: !!options.optional,\n includeSelf,\n animation,\n originalSelector: metadata.selector,\n options: normalizeAnimationOptions(metadata.options)\n };\n }\n\n visitStagger(metadata: AnimationStaggerMetadata, context: AnimationAstBuilderContext):\n StaggerAst {\n if (!context.currentQuery) {\n context.errors.push(invalidStagger());\n }\n const timings = metadata.timings === 'full' ?\n {duration: 0, delay: 0, easing: 'full'} :\n resolveTiming(metadata.timings, context.errors, true);\n\n return {\n type: AnimationMetadataType.Stagger,\n animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context),\n timings,\n options: null\n };\n }\n}\n\nfunction normalizeSelector(selector: string): [string, boolean] {\n const hasAmpersand = selector.split(/\\s*,\\s*/).find(token => token == SELF_TOKEN) ? true : false;\n if (hasAmpersand) {\n selector = selector.replace(SELF_TOKEN_REGEX, '');\n }\n\n // Note: the :enter and :leave aren't normalized here since those\n // selectors are filled in at runtime during timeline building\n selector = selector.replace(/@\\*/g, NG_TRIGGER_SELECTOR)\n .replace(/@\\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.slice(1))\n .replace(/:animating/g, NG_ANIMATING_SELECTOR);\n\n return [selector, hasAmpersand];\n}\n\n\nfunction normalizeParams(obj: {[key: string]: any}|any): {[key: string]: any}|null {\n return obj ? copyObj(obj) : null;\n}\n\nexport type StyleTimeTuple = {\n startTime: number; endTime: number;\n};\n\nexport class AnimationAstBuilderContext {\n public queryCount: number = 0;\n public depCount: number = 0;\n public currentTransition: AnimationTransitionMetadata|null = null;\n public currentQuery: AnimationQueryMetadata|null = null;\n public currentQuerySelector: string|null = null;\n public currentAnimateTimings: TimingAst|null = null;\n public currentTime: number = 0;\n public collectedStyles = new Map>();\n public options: AnimationOptions|null = null;\n public unsupportedCSSPropertiesFound: Set = new Set();\n constructor(public errors: Error[]) {}\n}\n\ntype OffsetStyles = string|ɵStyleDataMap;\n\nfunction consumeOffset(styles: OffsetStyles|Array): number|null {\n if (typeof styles == 'string') return null;\n\n let offset: number|null = null;\n\n if (Array.isArray(styles)) {\n styles.forEach(styleTuple => {\n if (styleTuple instanceof Map && styleTuple.has('offset')) {\n const obj = styleTuple as ɵStyleDataMap;\n offset = parseFloat(obj.get('offset') as string);\n obj.delete('offset');\n }\n });\n } else if (styles instanceof Map && styles.has('offset')) {\n const obj = styles;\n offset = parseFloat(obj.get('offset') as string);\n obj.delete('offset');\n }\n return offset;\n}\n\nfunction constructTimingAst(value: string|number|AnimateTimings, errors: Error[]) {\n if (value.hasOwnProperty('duration')) {\n return value as AnimateTimings;\n }\n\n if (typeof value == 'number') {\n const duration = resolveTiming(value, errors).duration;\n return makeTimingAst(duration, 0, '');\n }\n\n const strValue = value as string;\n const isDynamic = strValue.split(/\\s+/).some(v => v.charAt(0) == '{' && v.charAt(1) == '{');\n if (isDynamic) {\n const ast = makeTimingAst(0, 0, '') as any;\n ast.dynamic = true;\n ast.strValue = strValue;\n return ast as DynamicTimingAst;\n }\n\n const timings = resolveTiming(strValue, errors);\n return makeTimingAst(timings.duration, timings.delay, timings.easing);\n}\n\nfunction normalizeAnimationOptions(options: AnimationOptions|null): AnimationOptions {\n if (options) {\n options = copyObj(options);\n if (options['params']) {\n options['params'] = normalizeParams(options['params'])!;\n }\n } else {\n options = {};\n }\n return options;\n}\n\nfunction makeTimingAst(duration: number, delay: number, easing: string|null): TimingAst {\n return {duration, delay, easing};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ɵStyleDataMap} from '@angular/animations';\n\nimport {AnimationEngineInstruction, AnimationTransitionInstructionType} from '../render/animation_engine_instruction';\n\nexport interface AnimationTimelineInstruction extends AnimationEngineInstruction {\n element: any;\n keyframes: Array<ɵStyleDataMap>;\n preStyleProps: string[];\n postStyleProps: string[];\n duration: number;\n delay: number;\n totalTime: number;\n easing: string|null;\n stretchStartingKeyframe?: boolean;\n subTimeline: boolean;\n}\n\nexport function createTimelineInstruction(\n element: any, keyframes: Array<ɵStyleDataMap>, preStyleProps: string[],\n postStyleProps: string[], duration: number, delay: number, easing: string|null = null,\n subTimeline: boolean = false): AnimationTimelineInstruction {\n return {\n type: AnimationTransitionInstructionType.TimelineAnimation,\n element,\n keyframes,\n preStyleProps,\n postStyleProps,\n duration,\n delay,\n totalTime: duration + delay,\n easing,\n subTimeline\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationTimelineInstruction} from './animation_timeline_instruction';\n\nexport class ElementInstructionMap {\n private _map = new Map();\n\n get(element: any): AnimationTimelineInstruction[] {\n return this._map.get(element) || [];\n }\n\n append(element: any, instructions: AnimationTimelineInstruction[]) {\n let existingInstructions = this._map.get(element);\n if (!existingInstructions) {\n this._map.set(element, existingInstructions = []);\n }\n existingInstructions.push(...instructions);\n }\n\n has(element: any): boolean {\n return this._map.has(element);\n }\n\n clear() {\n this._map.clear();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimateChildOptions, AnimateTimings, AnimationMetadataType, AnimationOptions, AnimationQueryOptions, AUTO_STYLE, ɵPRE_STYLE as PRE_STYLE, ɵStyleDataMap} from '@angular/animations';\n\nimport {invalidQuery} from '../error_helpers';\nimport {AnimationDriver} from '../render/animation_driver';\nimport {copyStyles, interpolateParams, iteratorToArray, resolveTiming, resolveTimingValue, visitDslNode} from '../util';\n\nimport {AnimateAst, AnimateChildAst, AnimateRefAst, Ast, AstVisitor, DynamicTimingAst, GroupAst, KeyframesAst, QueryAst, ReferenceAst, SequenceAst, StaggerAst, StateAst, StyleAst, TimingAst, TransitionAst, TriggerAst} from './animation_ast';\nimport {AnimationTimelineInstruction, createTimelineInstruction} from './animation_timeline_instruction';\nimport {ElementInstructionMap} from './element_instruction_map';\n\nconst ONE_FRAME_IN_MILLISECONDS = 1;\nconst ENTER_TOKEN = ':enter';\nconst ENTER_TOKEN_REGEX = new RegExp(ENTER_TOKEN, 'g');\nconst LEAVE_TOKEN = ':leave';\nconst LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g');\n\n/*\n * The code within this file aims to generate web-animations-compatible keyframes from Angular's\n * animation DSL code.\n *\n * The code below will be converted from:\n *\n * ```\n * sequence([\n * style({ opacity: 0 }),\n * animate(1000, style({ opacity: 0 }))\n * ])\n * ```\n *\n * To:\n * ```\n * keyframes = [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }]\n * duration = 1000\n * delay = 0\n * easing = ''\n * ```\n *\n * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a\n * combination of AST traversal and merge-sort-like algorithms are used.\n *\n * [AST Traversal]\n * Each of the animation verbs, when executed, will return an string-map object representing what\n * type of action it is (style, animate, group, etc...) and the data associated with it. This means\n * that when functional composition mix of these functions is evaluated (like in the example above)\n * then it will end up producing a tree of objects representing the animation itself.\n *\n * When this animation object tree is processed by the visitor code below it will visit each of the\n * verb statements within the visitor. And during each visit it will build the context of the\n * animation keyframes by interacting with the `TimelineBuilder`.\n *\n * [TimelineBuilder]\n * This class is responsible for tracking the styles and building a series of keyframe objects for a\n * timeline between a start and end time. The builder starts off with an initial timeline and each\n * time the AST comes across a `group()`, `keyframes()` or a combination of the two within a\n * `sequence()` then it will generate a sub timeline for each step as well as a new one after\n * they are complete.\n *\n * As the AST is traversed, the timing state on each of the timelines will be incremented. If a sub\n * timeline was created (based on one of the cases above) then the parent timeline will attempt to\n * merge the styles used within the sub timelines into itself (only with group() this will happen).\n * This happens with a merge operation (much like how the merge works in mergeSort) and it will only\n * copy the most recently used styles from the sub timelines into the parent timeline. This ensures\n * that if the styles are used later on in another phase of the animation then they will be the most\n * up-to-date values.\n *\n * [How Missing Styles Are Updated]\n * Each timeline has a `backFill` property which is responsible for filling in new styles into\n * already processed keyframes if a new style shows up later within the animation sequence.\n *\n * ```\n * sequence([\n * style({ width: 0 }),\n * animate(1000, style({ width: 100 })),\n * animate(1000, style({ width: 200 })),\n * animate(1000, style({ width: 300 }))\n * animate(1000, style({ width: 400, height: 400 })) // notice how `height` doesn't exist anywhere\n * else\n * ])\n * ```\n *\n * What is happening here is that the `height` value is added later in the sequence, but is missing\n * from all previous animation steps. Therefore when a keyframe is created it would also be missing\n * from all previous keyframes up until where it is first used. For the timeline keyframe generation\n * to properly fill in the style it will place the previous value (the value from the parent\n * timeline) or a default value of `*` into the backFill map. The `copyStyles` method in util.ts\n * handles propagating that backfill map to the styles object.\n *\n * When a sub-timeline is created it will have its own backFill property. This is done so that\n * styles present within the sub-timeline do not accidentally seep into the previous/future timeline\n * keyframes\n *\n * [Validation]\n * The code in this file is not responsible for validation. That functionality happens with within\n * the `AnimationValidatorVisitor` code.\n */\nexport function buildAnimationTimelines(\n driver: AnimationDriver, rootElement: any, ast: Ast,\n enterClassName: string, leaveClassName: string, startingStyles: ɵStyleDataMap = new Map(),\n finalStyles: ɵStyleDataMap = new Map(), options: AnimationOptions,\n subInstructions?: ElementInstructionMap, errors: Error[] = []): AnimationTimelineInstruction[] {\n return new AnimationTimelineBuilderVisitor().buildKeyframes(\n driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles,\n options, subInstructions, errors);\n}\n\nexport class AnimationTimelineBuilderVisitor implements AstVisitor {\n buildKeyframes(\n driver: AnimationDriver, rootElement: any, ast: Ast,\n enterClassName: string, leaveClassName: string, startingStyles: ɵStyleDataMap,\n finalStyles: ɵStyleDataMap, options: AnimationOptions,\n subInstructions?: ElementInstructionMap,\n errors: Error[] = []): AnimationTimelineInstruction[] {\n subInstructions = subInstructions || new ElementInstructionMap();\n const context = new AnimationTimelineContext(\n driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []);\n context.options = options;\n const delay = options.delay ? resolveTimingValue(options.delay) : 0;\n context.currentTimeline.delayNextStep(delay);\n context.currentTimeline.setStyles([startingStyles], null, context.errors, options);\n\n visitDslNode(this, ast, context);\n\n // this checks to see if an actual animation happened\n const timelines = context.timelines.filter(timeline => timeline.containsAnimation());\n\n // note: we just want to apply the final styles for the rootElement, so we do not\n // just apply the styles to the last timeline but the last timeline which\n // element is the root one (basically `*`-styles are replaced with the actual\n // state style values only for the root element)\n if (timelines.length && finalStyles.size) {\n let lastRootTimeline: TimelineBuilder|undefined;\n for (let i = timelines.length - 1; i >= 0; i--) {\n const timeline = timelines[i];\n if (timeline.element === rootElement) {\n lastRootTimeline = timeline;\n break;\n }\n }\n if (lastRootTimeline && !lastRootTimeline.allowOnlyTimelineStyles()) {\n lastRootTimeline.setStyles([finalStyles], null, context.errors, options);\n }\n }\n return timelines.length ?\n timelines.map(timeline => timeline.buildKeyframes()) :\n [createTimelineInstruction(rootElement, [], [], [], 0, delay, '', false)];\n }\n\n visitTrigger(ast: TriggerAst, context: AnimationTimelineContext): any {\n // these values are not visited in this AST\n }\n\n visitState(ast: StateAst, context: AnimationTimelineContext): any {\n // these values are not visited in this AST\n }\n\n visitTransition(ast: TransitionAst, context: AnimationTimelineContext): any {\n // these values are not visited in this AST\n }\n\n visitAnimateChild(ast: AnimateChildAst, context: AnimationTimelineContext): any {\n const elementInstructions = context.subInstructions.get(context.element);\n if (elementInstructions) {\n const innerContext = context.createSubContext(ast.options);\n const startTime = context.currentTimeline.currentTime;\n const endTime = this._visitSubInstructions(\n elementInstructions, innerContext, innerContext.options as AnimateChildOptions);\n if (startTime != endTime) {\n // we do this on the upper context because we created a sub context for\n // the sub child animations\n context.transformIntoNewTimeline(endTime);\n }\n }\n context.previousNode = ast;\n }\n\n visitAnimateRef(ast: AnimateRefAst, context: AnimationTimelineContext): any {\n const innerContext = context.createSubContext(ast.options);\n innerContext.transformIntoNewTimeline();\n this._applyAnimationRefDelays([ast.options, ast.animation.options], context, innerContext);\n this.visitReference(ast.animation, innerContext);\n context.transformIntoNewTimeline(innerContext.currentTimeline.currentTime);\n context.previousNode = ast;\n }\n\n private _applyAnimationRefDelays(\n animationsRefsOptions: (AnimationOptions|null)[], context: AnimationTimelineContext,\n innerContext: AnimationTimelineContext) {\n for (const animationRefOptions of animationsRefsOptions) {\n const animationDelay = animationRefOptions?.delay;\n if (animationDelay) {\n const animationDelayValue = typeof animationDelay === 'number' ?\n animationDelay :\n resolveTimingValue(interpolateParams(\n animationDelay, animationRefOptions?.params ?? {}, context.errors));\n innerContext.delayNextStep(animationDelayValue);\n }\n }\n }\n\n private _visitSubInstructions(\n instructions: AnimationTimelineInstruction[], context: AnimationTimelineContext,\n options: AnimateChildOptions): number {\n const startTime = context.currentTimeline.currentTime;\n let furthestTime = startTime;\n\n // this is a special-case for when a user wants to skip a sub\n // animation from being fired entirely.\n const duration = options.duration != null ? resolveTimingValue(options.duration) : null;\n const delay = options.delay != null ? resolveTimingValue(options.delay) : null;\n if (duration !== 0) {\n instructions.forEach(instruction => {\n const instructionTimings =\n context.appendInstructionToTimeline(instruction, duration, delay);\n furthestTime =\n Math.max(furthestTime, instructionTimings.duration + instructionTimings.delay);\n });\n }\n\n return furthestTime;\n }\n\n visitReference(ast: ReferenceAst, context: AnimationTimelineContext) {\n context.updateOptions(ast.options, true);\n visitDslNode(this, ast.animation, context);\n context.previousNode = ast;\n }\n\n visitSequence(ast: SequenceAst, context: AnimationTimelineContext) {\n const subContextCount = context.subContextCount;\n let ctx = context;\n const options = ast.options;\n\n if (options && (options.params || options.delay)) {\n ctx = context.createSubContext(options);\n ctx.transformIntoNewTimeline();\n\n if (options.delay != null) {\n if (ctx.previousNode.type == AnimationMetadataType.Style) {\n ctx.currentTimeline.snapshotCurrentStyles();\n ctx.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;\n }\n\n const delay = resolveTimingValue(options.delay);\n ctx.delayNextStep(delay);\n }\n }\n\n if (ast.steps.length) {\n ast.steps.forEach(s => visitDslNode(this, s, ctx));\n\n // this is here just in case the inner steps only contain or end with a style() call\n ctx.currentTimeline.applyStylesToKeyframe();\n\n // this means that some animation function within the sequence\n // ended up creating a sub timeline (which means the current\n // timeline cannot overlap with the contents of the sequence)\n if (ctx.subContextCount > subContextCount) {\n ctx.transformIntoNewTimeline();\n }\n }\n\n context.previousNode = ast;\n }\n\n visitGroup(ast: GroupAst, context: AnimationTimelineContext) {\n const innerTimelines: TimelineBuilder[] = [];\n let furthestTime = context.currentTimeline.currentTime;\n const delay = ast.options && ast.options.delay ? resolveTimingValue(ast.options.delay) : 0;\n\n ast.steps.forEach(s => {\n const innerContext = context.createSubContext(ast.options);\n if (delay) {\n innerContext.delayNextStep(delay);\n }\n\n visitDslNode(this, s, innerContext);\n furthestTime = Math.max(furthestTime, innerContext.currentTimeline.currentTime);\n innerTimelines.push(innerContext.currentTimeline);\n });\n\n // this operation is run after the AST loop because otherwise\n // if the parent timeline's collected styles were updated then\n // it would pass in invalid data into the new-to-be forked items\n innerTimelines.forEach(\n timeline => context.currentTimeline.mergeTimelineCollectedStyles(timeline));\n context.transformIntoNewTimeline(furthestTime);\n context.previousNode = ast;\n }\n\n private _visitTiming(ast: TimingAst, context: AnimationTimelineContext): AnimateTimings {\n if ((ast as DynamicTimingAst).dynamic) {\n const strValue = (ast as DynamicTimingAst).strValue;\n const timingValue =\n context.params ? interpolateParams(strValue, context.params, context.errors) : strValue;\n return resolveTiming(timingValue, context.errors);\n } else {\n return {duration: ast.duration, delay: ast.delay, easing: ast.easing};\n }\n }\n\n visitAnimate(ast: AnimateAst, context: AnimationTimelineContext) {\n const timings = context.currentAnimateTimings = this._visitTiming(ast.timings, context);\n const timeline = context.currentTimeline;\n if (timings.delay) {\n context.incrementTime(timings.delay);\n timeline.snapshotCurrentStyles();\n }\n\n const style = ast.style;\n if (style.type == AnimationMetadataType.Keyframes) {\n this.visitKeyframes(style, context);\n } else {\n context.incrementTime(timings.duration);\n this.visitStyle(style as StyleAst, context);\n timeline.applyStylesToKeyframe();\n }\n\n context.currentAnimateTimings = null;\n context.previousNode = ast;\n }\n\n visitStyle(ast: StyleAst, context: AnimationTimelineContext) {\n const timeline = context.currentTimeline;\n const timings = context.currentAnimateTimings!;\n\n // this is a special case for when a style() call\n // directly follows an animate() call (but not inside of an animate() call)\n if (!timings && timeline.hasCurrentStyleProperties()) {\n timeline.forwardFrame();\n }\n\n const easing = (timings && timings.easing) || ast.easing;\n if (ast.isEmptyStep) {\n timeline.applyEmptyStep(easing);\n } else {\n timeline.setStyles(ast.styles, easing, context.errors, context.options);\n }\n\n context.previousNode = ast;\n }\n\n visitKeyframes(ast: KeyframesAst, context: AnimationTimelineContext) {\n const currentAnimateTimings = context.currentAnimateTimings!;\n const startTime = (context.currentTimeline!).duration;\n const duration = currentAnimateTimings.duration;\n const innerContext = context.createSubContext();\n const innerTimeline = innerContext.currentTimeline;\n innerTimeline.easing = currentAnimateTimings.easing;\n\n ast.styles.forEach(step => {\n const offset: number = step.offset || 0;\n innerTimeline.forwardTime(offset * duration);\n innerTimeline.setStyles(step.styles, step.easing, context.errors, context.options);\n innerTimeline.applyStylesToKeyframe();\n });\n\n // this will ensure that the parent timeline gets all the styles from\n // the child even if the new timeline below is not used\n context.currentTimeline.mergeTimelineCollectedStyles(innerTimeline);\n\n // we do this because the window between this timeline and the sub timeline\n // should ensure that the styles within are exactly the same as they were before\n context.transformIntoNewTimeline(startTime + duration);\n context.previousNode = ast;\n }\n\n visitQuery(ast: QueryAst, context: AnimationTimelineContext) {\n // in the event that the first step before this is a style step we need\n // to ensure the styles are applied before the children are animated\n const startTime = context.currentTimeline.currentTime;\n const options = (ast.options || {}) as AnimationQueryOptions;\n const delay = options.delay ? resolveTimingValue(options.delay) : 0;\n\n if (delay &&\n (context.previousNode.type === AnimationMetadataType.Style ||\n (startTime == 0 && context.currentTimeline.hasCurrentStyleProperties()))) {\n context.currentTimeline.snapshotCurrentStyles();\n context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;\n }\n\n let furthestTime = startTime;\n const elms = context.invokeQuery(\n ast.selector, ast.originalSelector, ast.limit, ast.includeSelf,\n options.optional ? true : false, context.errors);\n\n context.currentQueryTotal = elms.length;\n let sameElementTimeline: TimelineBuilder|null = null;\n elms.forEach((element, i) => {\n context.currentQueryIndex = i;\n const innerContext = context.createSubContext(ast.options, element);\n if (delay) {\n innerContext.delayNextStep(delay);\n }\n\n if (element === context.element) {\n sameElementTimeline = innerContext.currentTimeline;\n }\n\n visitDslNode(this, ast.animation, innerContext);\n\n // this is here just incase the inner steps only contain or end\n // with a style() call (which is here to signal that this is a preparatory\n // call to style an element before it is animated again)\n innerContext.currentTimeline.applyStylesToKeyframe();\n\n const endTime = innerContext.currentTimeline.currentTime;\n furthestTime = Math.max(furthestTime, endTime);\n });\n\n context.currentQueryIndex = 0;\n context.currentQueryTotal = 0;\n context.transformIntoNewTimeline(furthestTime);\n\n if (sameElementTimeline) {\n context.currentTimeline.mergeTimelineCollectedStyles(sameElementTimeline);\n context.currentTimeline.snapshotCurrentStyles();\n }\n\n context.previousNode = ast;\n }\n\n visitStagger(ast: StaggerAst, context: AnimationTimelineContext) {\n const parentContext = context.parentContext!;\n const tl = context.currentTimeline;\n const timings = ast.timings;\n const duration = Math.abs(timings.duration);\n const maxTime = duration * (context.currentQueryTotal - 1);\n let delay = duration * context.currentQueryIndex;\n\n let staggerTransformer = timings.duration < 0 ? 'reverse' : timings.easing;\n switch (staggerTransformer) {\n case 'reverse':\n delay = maxTime - delay;\n break;\n case 'full':\n delay = parentContext.currentStaggerTime;\n break;\n }\n\n const timeline = context.currentTimeline;\n if (delay) {\n timeline.delayNextStep(delay);\n }\n\n const startingTime = timeline.currentTime;\n visitDslNode(this, ast.animation, context);\n context.previousNode = ast;\n\n // time = duration + delay\n // the reason why this computation is so complex is because\n // the inner timeline may either have a delay value or a stretched\n // keyframe depending on if a subtimeline is not used or is used.\n parentContext.currentStaggerTime =\n (tl.currentTime - startingTime) + (tl.startTime - parentContext.currentTimeline.startTime);\n }\n}\n\nexport declare type StyleAtTime = {\n time: number; value: string | number;\n};\n\nconst DEFAULT_NOOP_PREVIOUS_NODE = >{};\nexport class AnimationTimelineContext {\n public parentContext: AnimationTimelineContext|null = null;\n public currentTimeline: TimelineBuilder;\n public currentAnimateTimings: AnimateTimings|null = null;\n public previousNode: Ast = DEFAULT_NOOP_PREVIOUS_NODE;\n public subContextCount = 0;\n public options: AnimationOptions = {};\n public currentQueryIndex: number = 0;\n public currentQueryTotal: number = 0;\n public currentStaggerTime: number = 0;\n\n constructor(\n private _driver: AnimationDriver, public element: any,\n public subInstructions: ElementInstructionMap, private _enterClassName: string,\n private _leaveClassName: string, public errors: Error[], public timelines: TimelineBuilder[],\n initialTimeline?: TimelineBuilder) {\n this.currentTimeline = initialTimeline || new TimelineBuilder(this._driver, element, 0);\n timelines.push(this.currentTimeline);\n }\n\n get params() {\n return this.options.params;\n }\n\n updateOptions(options: AnimationOptions|null, skipIfExists?: boolean) {\n if (!options) return;\n\n const newOptions = options as any;\n let optionsToUpdate = this.options;\n\n // NOTE: this will get patched up when other animation methods support duration overrides\n if (newOptions.duration != null) {\n (optionsToUpdate as any).duration = resolveTimingValue(newOptions.duration);\n }\n\n if (newOptions.delay != null) {\n optionsToUpdate.delay = resolveTimingValue(newOptions.delay);\n }\n\n const newParams = newOptions.params;\n if (newParams) {\n let paramsToUpdate: {[name: string]: any} = optionsToUpdate.params!;\n if (!paramsToUpdate) {\n paramsToUpdate = this.options.params = {};\n }\n\n Object.keys(newParams).forEach(name => {\n if (!skipIfExists || !paramsToUpdate.hasOwnProperty(name)) {\n paramsToUpdate[name] = interpolateParams(newParams[name], paramsToUpdate, this.errors);\n }\n });\n }\n }\n\n private _copyOptions() {\n const options: AnimationOptions = {};\n if (this.options) {\n const oldParams = this.options.params;\n if (oldParams) {\n const params: {[name: string]: any} = options['params'] = {};\n Object.keys(oldParams).forEach(name => {\n params[name] = oldParams[name];\n });\n }\n }\n return options;\n }\n\n createSubContext(options: AnimationOptions|null = null, element?: any, newTime?: number):\n AnimationTimelineContext {\n const target = element || this.element;\n const context = new AnimationTimelineContext(\n this._driver, target, this.subInstructions, this._enterClassName, this._leaveClassName,\n this.errors, this.timelines, this.currentTimeline.fork(target, newTime || 0));\n context.previousNode = this.previousNode;\n context.currentAnimateTimings = this.currentAnimateTimings;\n\n context.options = this._copyOptions();\n context.updateOptions(options);\n\n context.currentQueryIndex = this.currentQueryIndex;\n context.currentQueryTotal = this.currentQueryTotal;\n context.parentContext = this;\n this.subContextCount++;\n return context;\n }\n\n transformIntoNewTimeline(newTime?: number) {\n this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE;\n this.currentTimeline = this.currentTimeline.fork(this.element, newTime);\n this.timelines.push(this.currentTimeline);\n return this.currentTimeline;\n }\n\n appendInstructionToTimeline(\n instruction: AnimationTimelineInstruction, duration: number|null,\n delay: number|null): AnimateTimings {\n const updatedTimings: AnimateTimings = {\n duration: duration != null ? duration : instruction.duration,\n delay: this.currentTimeline.currentTime + (delay != null ? delay : 0) + instruction.delay,\n easing: ''\n };\n const builder = new SubTimelineBuilder(\n this._driver, instruction.element, instruction.keyframes, instruction.preStyleProps,\n instruction.postStyleProps, updatedTimings, instruction.stretchStartingKeyframe);\n this.timelines.push(builder);\n return updatedTimings;\n }\n\n incrementTime(time: number) {\n this.currentTimeline.forwardTime(this.currentTimeline.duration + time);\n }\n\n delayNextStep(delay: number) {\n // negative delays are not yet supported\n if (delay > 0) {\n this.currentTimeline.delayNextStep(delay);\n }\n }\n\n invokeQuery(\n selector: string, originalSelector: string, limit: number, includeSelf: boolean,\n optional: boolean, errors: Error[]): any[] {\n let results: any[] = [];\n if (includeSelf) {\n results.push(this.element);\n }\n if (selector.length > 0) { // only if :self is used then the selector can be empty\n selector = selector.replace(ENTER_TOKEN_REGEX, '.' + this._enterClassName);\n selector = selector.replace(LEAVE_TOKEN_REGEX, '.' + this._leaveClassName);\n const multi = limit != 1;\n let elements = this._driver.query(this.element, selector, multi);\n if (limit !== 0) {\n elements = limit < 0 ? elements.slice(elements.length + limit, elements.length) :\n elements.slice(0, limit);\n }\n results.push(...elements);\n }\n\n if (!optional && results.length == 0) {\n errors.push(invalidQuery(originalSelector));\n }\n return results;\n }\n}\n\nexport class TimelineBuilder {\n public duration: number = 0;\n public easing: string|null = null;\n private _previousKeyframe: ɵStyleDataMap = new Map();\n private _currentKeyframe: ɵStyleDataMap = new Map();\n private _keyframes = new Map();\n private _styleSummary = new Map();\n private _localTimelineStyles: ɵStyleDataMap = new Map();\n private _globalTimelineStyles: ɵStyleDataMap;\n private _pendingStyles: ɵStyleDataMap = new Map();\n private _backFill: ɵStyleDataMap = new Map();\n private _currentEmptyStepKeyframe: ɵStyleDataMap|null = null;\n\n constructor(\n private _driver: AnimationDriver, public element: any, public startTime: number,\n private _elementTimelineStylesLookup?: Map) {\n if (!this._elementTimelineStylesLookup) {\n this._elementTimelineStylesLookup = new Map();\n }\n\n this._globalTimelineStyles = this._elementTimelineStylesLookup.get(element)!;\n if (!this._globalTimelineStyles) {\n this._globalTimelineStyles = this._localTimelineStyles;\n this._elementTimelineStylesLookup.set(element, this._localTimelineStyles);\n }\n this._loadKeyframe();\n }\n\n containsAnimation(): boolean {\n switch (this._keyframes.size) {\n case 0:\n return false;\n case 1:\n return this.hasCurrentStyleProperties();\n default:\n return true;\n }\n }\n\n hasCurrentStyleProperties(): boolean {\n return this._currentKeyframe.size > 0;\n }\n\n get currentTime() {\n return this.startTime + this.duration;\n }\n\n delayNextStep(delay: number) {\n // in the event that a style() step is placed right before a stagger()\n // and that style() step is the very first style() value in the animation\n // then we need to make a copy of the keyframe [0, copy, 1] so that the delay\n // properly applies the style() values to work with the stagger...\n const hasPreStyleStep = this._keyframes.size === 1 && this._pendingStyles.size;\n\n if (this.duration || hasPreStyleStep) {\n this.forwardTime(this.currentTime + delay);\n if (hasPreStyleStep) {\n this.snapshotCurrentStyles();\n }\n } else {\n this.startTime += delay;\n }\n }\n\n fork(element: any, currentTime?: number): TimelineBuilder {\n this.applyStylesToKeyframe();\n return new TimelineBuilder(\n this._driver, element, currentTime || this.currentTime, this._elementTimelineStylesLookup);\n }\n\n private _loadKeyframe() {\n if (this._currentKeyframe) {\n this._previousKeyframe = this._currentKeyframe;\n }\n this._currentKeyframe = this._keyframes.get(this.duration)!;\n if (!this._currentKeyframe) {\n this._currentKeyframe = new Map();\n this._keyframes.set(this.duration, this._currentKeyframe);\n }\n }\n\n forwardFrame() {\n this.duration += ONE_FRAME_IN_MILLISECONDS;\n this._loadKeyframe();\n }\n\n forwardTime(time: number) {\n this.applyStylesToKeyframe();\n this.duration = time;\n this._loadKeyframe();\n }\n\n private _updateStyle(prop: string, value: string|number) {\n this._localTimelineStyles.set(prop, value);\n this._globalTimelineStyles.set(prop, value);\n this._styleSummary.set(prop, {time: this.currentTime, value});\n }\n\n allowOnlyTimelineStyles() {\n return this._currentEmptyStepKeyframe !== this._currentKeyframe;\n }\n\n applyEmptyStep(easing: string|null) {\n if (easing) {\n this._previousKeyframe.set('easing', easing);\n }\n\n // special case for animate(duration):\n // all missing styles are filled with a `*` value then\n // if any destination styles are filled in later on the same\n // keyframe then they will override the overridden styles\n // We use `_globalTimelineStyles` here because there may be\n // styles in previous keyframes that are not present in this timeline\n for (let [prop, value] of this._globalTimelineStyles) {\n this._backFill.set(prop, value || AUTO_STYLE);\n this._currentKeyframe.set(prop, AUTO_STYLE);\n }\n this._currentEmptyStepKeyframe = this._currentKeyframe;\n }\n\n setStyles(\n input: Array<(ɵStyleDataMap | string)>, easing: string|null, errors: Error[],\n options?: AnimationOptions) {\n if (easing) {\n this._previousKeyframe.set('easing', easing);\n }\n const params = (options && options.params) || {};\n const styles = flattenStyles(input, this._globalTimelineStyles);\n for (let [prop, value] of styles) {\n const val = interpolateParams(value, params, errors);\n this._pendingStyles.set(prop, val);\n if (!this._localTimelineStyles.has(prop)) {\n this._backFill.set(prop, this._globalTimelineStyles.get(prop) ?? AUTO_STYLE);\n }\n this._updateStyle(prop, val);\n }\n }\n\n applyStylesToKeyframe() {\n if (this._pendingStyles.size == 0) return;\n\n this._pendingStyles.forEach((val, prop) => {\n this._currentKeyframe.set(prop, val);\n });\n this._pendingStyles.clear();\n\n this._localTimelineStyles.forEach((val, prop) => {\n if (!this._currentKeyframe.has(prop)) {\n this._currentKeyframe.set(prop, val);\n }\n });\n }\n\n snapshotCurrentStyles() {\n for (let [prop, val] of this._localTimelineStyles) {\n this._pendingStyles.set(prop, val);\n this._updateStyle(prop, val);\n }\n }\n\n getFinalKeyframe() {\n return this._keyframes.get(this.duration);\n }\n\n get properties() {\n const properties: string[] = [];\n for (let prop in this._currentKeyframe) {\n properties.push(prop);\n }\n return properties;\n }\n\n mergeTimelineCollectedStyles(timeline: TimelineBuilder) {\n timeline._styleSummary.forEach((details1, prop) => {\n const details0 = this._styleSummary.get(prop);\n if (!details0 || details1.time > details0.time) {\n this._updateStyle(prop, details1.value);\n }\n });\n }\n\n buildKeyframes(): AnimationTimelineInstruction {\n this.applyStylesToKeyframe();\n const preStyleProps = new Set();\n const postStyleProps = new Set();\n const isEmpty = this._keyframes.size === 1 && this.duration === 0;\n\n let finalKeyframes: Array<ɵStyleDataMap> = [];\n this._keyframes.forEach((keyframe, time) => {\n const finalKeyframe = copyStyles(keyframe, new Map(), this._backFill);\n finalKeyframe.forEach((value, prop) => {\n if (value === PRE_STYLE) {\n preStyleProps.add(prop);\n } else if (value === AUTO_STYLE) {\n postStyleProps.add(prop);\n }\n });\n if (!isEmpty) {\n finalKeyframe.set('offset', time / this.duration);\n }\n finalKeyframes.push(finalKeyframe);\n });\n\n const preProps: string[] = preStyleProps.size ? iteratorToArray(preStyleProps.values()) : [];\n const postProps: string[] = postStyleProps.size ? iteratorToArray(postStyleProps.values()) : [];\n\n // special case for a 0-second animation (which is designed just to place styles onscreen)\n if (isEmpty) {\n const kf0 = finalKeyframes[0];\n const kf1 = new Map(kf0);\n kf0.set('offset', 0);\n kf1.set('offset', 1);\n finalKeyframes = [kf0, kf1];\n }\n\n return createTimelineInstruction(\n this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime,\n this.easing, false);\n }\n}\n\nclass SubTimelineBuilder extends TimelineBuilder {\n public timings: AnimateTimings;\n\n constructor(\n driver: AnimationDriver, element: any, public keyframes: Array<ɵStyleDataMap>,\n public preStyleProps: string[], public postStyleProps: string[], timings: AnimateTimings,\n private _stretchStartingKeyframe: boolean = false) {\n super(driver, element, timings.delay);\n this.timings = {duration: timings.duration, delay: timings.delay, easing: timings.easing};\n }\n\n override containsAnimation(): boolean {\n return this.keyframes.length > 1;\n }\n\n override buildKeyframes(): AnimationTimelineInstruction {\n let keyframes = this.keyframes;\n let {delay, duration, easing} = this.timings;\n if (this._stretchStartingKeyframe && delay) {\n const newKeyframes: Array<ɵStyleDataMap> = [];\n const totalTime = duration + delay;\n const startingGap = delay / totalTime;\n\n // the original starting keyframe now starts once the delay is done\n const newFirstKeyframe = copyStyles(keyframes[0]);\n newFirstKeyframe.set('offset', 0);\n newKeyframes.push(newFirstKeyframe);\n\n const oldFirstKeyframe = copyStyles(keyframes[0]);\n oldFirstKeyframe.set('offset', roundOffset(startingGap));\n newKeyframes.push(oldFirstKeyframe);\n\n /*\n When the keyframe is stretched then it means that the delay before the animation\n starts is gone. Instead the first keyframe is placed at the start of the animation\n and it is then copied to where it starts when the original delay is over. This basically\n means nothing animates during that delay, but the styles are still rendered. For this\n to work the original offset values that exist in the original keyframes must be \"warped\"\n so that they can take the new keyframe + delay into account.\n\n delay=1000, duration=1000, keyframes = 0 .5 1\n\n turns into\n\n delay=0, duration=2000, keyframes = 0 .33 .66 1\n */\n\n // offsets between 1 ... n -1 are all warped by the keyframe stretch\n const limit = keyframes.length - 1;\n for (let i = 1; i <= limit; i++) {\n let kf = copyStyles(keyframes[i]);\n const oldOffset = kf.get('offset') as number;\n const timeAtKeyframe = delay + oldOffset * duration;\n kf.set('offset', roundOffset(timeAtKeyframe / totalTime));\n newKeyframes.push(kf);\n }\n\n // the new starting keyframe should be added at the start\n duration = totalTime;\n delay = 0;\n easing = '';\n\n keyframes = newKeyframes;\n }\n\n return createTimelineInstruction(\n this.element, keyframes, this.preStyleProps, this.postStyleProps, duration, delay, easing,\n true);\n }\n}\n\nfunction roundOffset(offset: number, decimalPoints = 3): number {\n const mult = Math.pow(10, decimalPoints - 1);\n return Math.round(offset * mult) / mult;\n}\n\nfunction flattenStyles(input: Array<(ɵStyleDataMap | string)>, allStyles: ɵStyleDataMap) {\n const styles: ɵStyleDataMap = new Map();\n let allProperties: string[]|IterableIterator;\n input.forEach(token => {\n if (token === '*') {\n allProperties = allProperties || allStyles.keys();\n for (let prop of allProperties) {\n styles.set(prop, AUTO_STYLE);\n }\n } else {\n copyStyles(token as ɵStyleDataMap, styles);\n }\n });\n return styles;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @publicApi\n */\nexport abstract class AnimationStyleNormalizer {\n abstract normalizePropertyName(propertyName: string, errors: Error[]): string;\n abstract normalizeStyleValue(\n userProvidedProperty: string, normalizedProperty: string, value: string|number,\n errors: Error[]): string;\n}\n\n/**\n * @publicApi\n */\nexport class NoopAnimationStyleNormalizer {\n normalizePropertyName(propertyName: string, errors: Error[]): string {\n return propertyName;\n }\n\n normalizeStyleValue(\n userProvidedProperty: string, normalizedProperty: string, value: string|number,\n errors: Error[]): string {\n return value;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {invalidCssUnitValue} from '../../error_helpers';\nimport {dashCaseToCamelCase} from '../../util';\n\nimport {AnimationStyleNormalizer} from './animation_style_normalizer';\n\nconst DIMENSIONAL_PROP_SET = new Set([\n 'width',\n 'height',\n 'minWidth',\n 'minHeight',\n 'maxWidth',\n 'maxHeight',\n 'left',\n 'top',\n 'bottom',\n 'right',\n 'fontSize',\n 'outlineWidth',\n 'outlineOffset',\n 'paddingTop',\n 'paddingLeft',\n 'paddingBottom',\n 'paddingRight',\n 'marginTop',\n 'marginLeft',\n 'marginBottom',\n 'marginRight',\n 'borderRadius',\n 'borderWidth',\n 'borderTopWidth',\n 'borderLeftWidth',\n 'borderRightWidth',\n 'borderBottomWidth',\n 'textIndent',\n 'perspective'\n]);\n\nexport class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer {\n override normalizePropertyName(propertyName: string, errors: Error[]): string {\n return dashCaseToCamelCase(propertyName);\n }\n\n override normalizeStyleValue(\n userProvidedProperty: string, normalizedProperty: string, value: string|number,\n errors: Error[]): string {\n let unit: string = '';\n const strVal = value.toString().trim();\n\n if (DIMENSIONAL_PROP_SET.has(normalizedProperty) && value !== 0 && value !== '0') {\n if (typeof value === 'number') {\n unit = 'px';\n } else {\n const valAndSuffixMatch = value.match(/^[+-]?[\\d\\.]+([a-z]*)$/);\n if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {\n errors.push(invalidCssUnitValue(userProvidedProperty, value));\n }\n }\n }\n return strVal + unit;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵStyleDataMap} from '@angular/animations';\n\nimport {AnimationEngineInstruction, AnimationTransitionInstructionType} from '../render/animation_engine_instruction';\n\nimport {AnimationTimelineInstruction} from './animation_timeline_instruction';\n\nexport interface AnimationTransitionInstruction extends AnimationEngineInstruction {\n element: any;\n triggerName: string;\n isRemovalTransition: boolean;\n fromState: string;\n fromStyles: ɵStyleDataMap;\n toState: string;\n toStyles: ɵStyleDataMap;\n timelines: AnimationTimelineInstruction[];\n queriedElements: any[];\n preStyleProps: Map>;\n postStyleProps: Map>;\n totalTime: number;\n errors?: Error[];\n}\n\nexport function createTransitionInstruction(\n element: any, triggerName: string, fromState: string, toState: string,\n isRemovalTransition: boolean, fromStyles: ɵStyleDataMap, toStyles: ɵStyleDataMap,\n timelines: AnimationTimelineInstruction[], queriedElements: any[],\n preStyleProps: Map>, postStyleProps: Map>, totalTime: number,\n errors?: Error[]): AnimationTransitionInstruction {\n return {\n type: AnimationTransitionInstructionType.TransitionAnimation,\n element,\n triggerName,\n isRemovalTransition,\n fromState,\n fromStyles,\n toState,\n toStyles,\n timelines,\n queriedElements,\n preStyleProps,\n postStyleProps,\n totalTime,\n errors\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationOptions, ɵStyleDataMap} from '@angular/animations';\n\nimport {AnimationDriver} from '../render/animation_driver';\nimport {getOrSetDefaultValue} from '../render/shared';\nimport {copyObj, interpolateParams, iteratorToArray} from '../util';\n\nimport {StyleAst, TransitionAst} from './animation_ast';\nimport {buildAnimationTimelines} from './animation_timeline_builder';\nimport {AnimationTimelineInstruction} from './animation_timeline_instruction';\nimport {TransitionMatcherFn} from './animation_transition_expr';\nimport {AnimationTransitionInstruction, createTransitionInstruction} from './animation_transition_instruction';\nimport {ElementInstructionMap} from './element_instruction_map';\nimport {AnimationStyleNormalizer} from './style_normalization/animation_style_normalizer';\n\nconst EMPTY_OBJECT = {};\n\nexport class AnimationTransitionFactory {\n constructor(\n private _triggerName: string, public ast: TransitionAst,\n private _stateStyles: Map) {}\n\n match(currentState: any, nextState: any, element: any, params: {[key: string]: any}): boolean {\n return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params);\n }\n\n buildStyles(stateName: string|boolean|undefined, params: {[key: string]: any}, errors: Error[]):\n ɵStyleDataMap {\n let styler = this._stateStyles.get('*');\n if (stateName !== undefined) {\n styler = this._stateStyles.get(stateName?.toString()) || styler;\n }\n return styler ? styler.buildStyles(params, errors) : new Map();\n }\n\n build(\n driver: AnimationDriver, element: any, currentState: any, nextState: any,\n enterClassName: string, leaveClassName: string, currentOptions?: AnimationOptions,\n nextOptions?: AnimationOptions, subInstructions?: ElementInstructionMap,\n skipAstBuild?: boolean): AnimationTransitionInstruction {\n const errors: Error[] = [];\n\n const transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT;\n const currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT;\n const currentStateStyles = this.buildStyles(currentState, currentAnimationParams, errors);\n const nextAnimationParams = nextOptions && nextOptions.params || EMPTY_OBJECT;\n const nextStateStyles = this.buildStyles(nextState, nextAnimationParams, errors);\n\n const queriedElements = new Set();\n const preStyleMap = new Map>();\n const postStyleMap = new Map>();\n const isRemoval = nextState === 'void';\n\n const animationOptions: AnimationOptions = {\n params: applyParamDefaults(nextAnimationParams, transitionAnimationParams),\n delay: this.ast.options?.delay,\n };\n\n const timelines = skipAstBuild ?\n [] :\n buildAnimationTimelines(\n driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles,\n nextStateStyles, animationOptions, subInstructions, errors);\n\n let totalTime = 0;\n timelines.forEach(tl => {\n totalTime = Math.max(tl.duration + tl.delay, totalTime);\n });\n\n if (errors.length) {\n return createTransitionInstruction(\n element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles,\n nextStateStyles, [], [], preStyleMap, postStyleMap, totalTime, errors);\n }\n\n timelines.forEach(tl => {\n const elm = tl.element;\n const preProps = getOrSetDefaultValue(preStyleMap, elm, new Set());\n tl.preStyleProps.forEach(prop => preProps.add(prop));\n\n const postProps = getOrSetDefaultValue(postStyleMap, elm, new Set());\n tl.postStyleProps.forEach(prop => postProps.add(prop));\n\n if (elm !== element) {\n queriedElements.add(elm);\n }\n });\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n checkNonAnimatableInTimelines(timelines, this._triggerName, driver);\n }\n\n const queriedElementsList = iteratorToArray(queriedElements.values());\n return createTransitionInstruction(\n element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles,\n nextStateStyles, timelines, queriedElementsList, preStyleMap, postStyleMap, totalTime);\n }\n}\n\n/**\n * Checks inside a set of timelines if they try to animate a css property which is not considered\n * animatable, in that case it prints a warning on the console.\n * Besides that the function doesn't have any other effect.\n *\n * Note: this check is done here after the timelines are built instead of doing on a lower level so\n * that we can make sure that the warning appears only once per instruction (we can aggregate here\n * all the issues instead of finding them separately).\n *\n * @param timelines The built timelines for the current instruction.\n * @param triggerName The name of the trigger for the current instruction.\n * @param driver Animation driver used to perform the check.\n *\n */\nfunction checkNonAnimatableInTimelines(\n timelines: AnimationTimelineInstruction[], triggerName: string, driver: AnimationDriver): void {\n if (!driver.validateAnimatableStyleProperty) {\n return;\n }\n\n const allowedNonAnimatableProps = new Set([\n // 'easing' is a utility/synthetic prop we use to represent\n // easing functions, it represents a property of the animation\n // which is not animatable but different values can be used\n // in different steps\n 'easing'\n ]);\n\n const invalidNonAnimatableProps = new Set();\n\n timelines.forEach(({keyframes}) => {\n const nonAnimatablePropsInitialValues = new Map();\n keyframes.forEach(keyframe => {\n const entriesToCheck =\n Array.from(keyframe.entries()).filter(([prop]) => !allowedNonAnimatableProps.has(prop));\n for (const [prop, value] of entriesToCheck) {\n if (!driver.validateAnimatableStyleProperty!(prop)) {\n if (nonAnimatablePropsInitialValues.has(prop) && !invalidNonAnimatableProps.has(prop)) {\n const propInitialValue = nonAnimatablePropsInitialValues.get(prop);\n if (propInitialValue !== value) {\n invalidNonAnimatableProps.add(prop);\n }\n } else {\n nonAnimatablePropsInitialValues.set(prop, value);\n }\n }\n }\n });\n });\n\n if (invalidNonAnimatableProps.size > 0) {\n console.warn(\n `Warning: The animation trigger \"${triggerName}\" is attempting to animate the following` +\n ' not animatable properties: ' + Array.from(invalidNonAnimatableProps).join(', ') + '\\n' +\n '(to check the list of all animatable properties visit https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties)');\n }\n}\n\nfunction oneOrMoreTransitionsMatch(\n matchFns: TransitionMatcherFn[], currentState: any, nextState: any, element: any,\n params: {[key: string]: any}): boolean {\n return matchFns.some(fn => fn(currentState, nextState, element, params));\n}\n\nfunction applyParamDefaults(userParams: Record, defaults: Record) {\n const result: Record = copyObj(defaults);\n\n for (const key in userParams) {\n if (userParams.hasOwnProperty(key) && userParams[key] != null) {\n result[key] = userParams[key];\n }\n }\n\n return result;\n}\n\nexport class AnimationStateStyles {\n constructor(\n private styles: StyleAst, private defaultParams: {[key: string]: any},\n private normalizer: AnimationStyleNormalizer) {}\n\n buildStyles(params: {[key: string]: any}, errors: Error[]): ɵStyleDataMap {\n const finalStyles: ɵStyleDataMap = new Map();\n const combinedParams = copyObj(this.defaultParams);\n Object.keys(params).forEach(key => {\n const value = params[key];\n if (value !== null) {\n combinedParams[key] = value;\n }\n });\n this.styles.styles.forEach(value => {\n if (typeof value !== 'string') {\n value.forEach((val, prop) => {\n if (val) {\n val = interpolateParams(val, combinedParams, errors);\n }\n const normalizedProp = this.normalizer.normalizePropertyName(prop, errors);\n val = this.normalizer.normalizeStyleValue(prop, normalizedProp, val, errors);\n finalStyles.set(prop, val);\n });\n }\n });\n return finalStyles;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationMetadataType, ɵStyleDataMap} from '@angular/animations';\n\nimport {SequenceAst, TransitionAst, TriggerAst} from './animation_ast';\nimport {AnimationStateStyles, AnimationTransitionFactory} from './animation_transition_factory';\nimport {AnimationStyleNormalizer} from './style_normalization/animation_style_normalizer';\n\n\n\nexport function buildTrigger(\n name: string, ast: TriggerAst, normalizer: AnimationStyleNormalizer): AnimationTrigger {\n return new AnimationTrigger(name, ast, normalizer);\n}\n\nexport class AnimationTrigger {\n public transitionFactories: AnimationTransitionFactory[] = [];\n public fallbackTransition: AnimationTransitionFactory;\n public states = new Map();\n\n constructor(\n public name: string, public ast: TriggerAst, private _normalizer: AnimationStyleNormalizer) {\n ast.states.forEach(ast => {\n const defaultParams = (ast.options && ast.options.params) || {};\n this.states.set(ast.name, new AnimationStateStyles(ast.style, defaultParams, _normalizer));\n });\n\n balanceProperties(this.states, 'true', '1');\n balanceProperties(this.states, 'false', '0');\n\n ast.transitions.forEach(ast => {\n this.transitionFactories.push(new AnimationTransitionFactory(name, ast, this.states));\n });\n this.fallbackTransition = createFallbackTransition(name, this.states, this._normalizer);\n }\n\n get containsQueries() {\n return this.ast.queryCount > 0;\n }\n\n matchTransition(currentState: any, nextState: any, element: any, params: {[key: string]: any}):\n AnimationTransitionFactory|null {\n const entry =\n this.transitionFactories.find(f => f.match(currentState, nextState, element, params));\n return entry || null;\n }\n\n matchStyles(currentState: any, params: {[key: string]: any}, errors: Error[]): ɵStyleDataMap {\n return this.fallbackTransition.buildStyles(currentState, params, errors);\n }\n}\n\nfunction createFallbackTransition(\n triggerName: string, states: Map,\n normalizer: AnimationStyleNormalizer): AnimationTransitionFactory {\n const matchers = [(fromState: any, toState: any) => true];\n const animation: SequenceAst = {type: AnimationMetadataType.Sequence, steps: [], options: null};\n const transition: TransitionAst = {\n type: AnimationMetadataType.Transition,\n animation,\n matchers,\n options: null,\n queryCount: 0,\n depCount: 0\n };\n return new AnimationTransitionFactory(triggerName, transition, states);\n}\n\nfunction balanceProperties(\n stateMap: Map, key1: string, key2: string) {\n if (stateMap.has(key1)) {\n if (!stateMap.has(key2)) {\n stateMap.set(key2, stateMap.get(key1)!);\n }\n } else if (stateMap.has(key2)) {\n stateMap.set(key1, stateMap.get(key2)!);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationMetadata, AnimationMetadataType, AnimationOptions, AnimationPlayer, AUTO_STYLE, ɵStyleDataMap} from '@angular/animations';\n\nimport {Ast} from '../dsl/animation_ast';\nimport {buildAnimationAst} from '../dsl/animation_ast_builder';\nimport {buildAnimationTimelines} from '../dsl/animation_timeline_builder';\nimport {AnimationTimelineInstruction} from '../dsl/animation_timeline_instruction';\nimport {ElementInstructionMap} from '../dsl/element_instruction_map';\nimport {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';\nimport {createAnimationFailed, missingOrDestroyedAnimation, missingPlayer, registerFailed} from '../error_helpers';\nimport {ENTER_CLASSNAME, LEAVE_CLASSNAME} from '../util';\nimport {warnRegister} from '../warning_helpers';\n\nimport {AnimationDriver} from './animation_driver';\nimport {getOrSetDefaultValue, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';\n\nconst EMPTY_INSTRUCTION_MAP = new ElementInstructionMap();\n\nexport class TimelineAnimationEngine {\n private _animations = new Map>();\n private _playersById = new Map();\n public players: AnimationPlayer[] = [];\n\n constructor(\n public bodyNode: any, private _driver: AnimationDriver,\n private _normalizer: AnimationStyleNormalizer) {}\n\n register(id: string, metadata: AnimationMetadata|AnimationMetadata[]) {\n const errors: Error[] = [];\n const warnings: string[] = [];\n const ast = buildAnimationAst(this._driver, metadata, errors, warnings);\n if (errors.length) {\n throw registerFailed(errors);\n } else {\n if (warnings.length) {\n warnRegister(warnings);\n }\n this._animations.set(id, ast);\n }\n }\n\n private _buildPlayer(\n i: AnimationTimelineInstruction, preStyles: ɵStyleDataMap,\n postStyles?: ɵStyleDataMap): AnimationPlayer {\n const element = i.element;\n const keyframes = normalizeKeyframes(\n this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles);\n return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true);\n }\n\n create(id: string, element: any, options: AnimationOptions = {}): AnimationPlayer {\n const errors: Error[] = [];\n const ast = this._animations.get(id);\n let instructions: AnimationTimelineInstruction[];\n\n const autoStylesMap = new Map();\n\n if (ast) {\n instructions = buildAnimationTimelines(\n this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, new Map(), new Map(),\n options, EMPTY_INSTRUCTION_MAP, errors);\n instructions.forEach(inst => {\n const styles = getOrSetDefaultValue(\n autoStylesMap, inst.element, new Map());\n inst.postStyleProps.forEach(prop => styles.set(prop, null));\n });\n } else {\n errors.push(missingOrDestroyedAnimation());\n instructions = [];\n }\n\n if (errors.length) {\n throw createAnimationFailed(errors);\n }\n\n autoStylesMap.forEach((styles, element) => {\n styles.forEach((_, prop) => {\n styles.set(prop, this._driver.computeStyle(element, prop, AUTO_STYLE));\n });\n });\n\n const players = instructions.map(i => {\n const styles = autoStylesMap.get(i.element);\n return this._buildPlayer(i, new Map(), styles);\n });\n const player = optimizeGroupPlayer(players);\n this._playersById.set(id, player);\n player.onDestroy(() => this.destroy(id));\n\n this.players.push(player);\n return player;\n }\n\n destroy(id: string) {\n const player = this._getPlayer(id);\n player.destroy();\n this._playersById.delete(id);\n const index = this.players.indexOf(player);\n if (index >= 0) {\n this.players.splice(index, 1);\n }\n }\n\n private _getPlayer(id: string): AnimationPlayer {\n const player = this._playersById.get(id);\n if (!player) {\n throw missingPlayer(id);\n }\n return player;\n }\n\n listen(id: string, element: string, eventName: string, callback: (event: any) => any):\n () => void {\n // triggerName, fromState, toState are all ignored for timeline animations\n const baseEvent = makeAnimationEvent(element, '', '', '');\n listenOnPlayer(this._getPlayer(id), eventName, baseEvent, callback);\n return () => {};\n }\n\n command(id: string, element: any, command: string, args: any[]): void {\n if (command == 'register') {\n this.register(id, args[0] as AnimationMetadata | AnimationMetadata[]);\n return;\n }\n\n if (command == 'create') {\n const options = (args[0] || {}) as AnimationOptions;\n this.create(id, element, options);\n return;\n }\n\n const player = this._getPlayer(id);\n switch (command) {\n case 'play':\n player.play();\n break;\n case 'pause':\n player.pause();\n break;\n case 'reset':\n player.reset();\n break;\n case 'restart':\n player.restart();\n break;\n case 'finish':\n player.finish();\n break;\n case 'init':\n player.init();\n break;\n case 'setPosition':\n player.setPosition(parseFloat(args[0] as string));\n break;\n case 'destroy':\n this.destroy(id);\n break;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationOptions, AnimationPlayer, AUTO_STYLE, NoopAnimationPlayer, ɵAnimationGroupPlayer as AnimationGroupPlayer, ɵPRE_STYLE as PRE_STYLE, ɵStyleDataMap} from '@angular/animations';\n\nimport {AnimationTimelineInstruction} from '../dsl/animation_timeline_instruction';\nimport {AnimationTransitionFactory} from '../dsl/animation_transition_factory';\nimport {AnimationTransitionInstruction} from '../dsl/animation_transition_instruction';\nimport {AnimationTrigger} from '../dsl/animation_trigger';\nimport {ElementInstructionMap} from '../dsl/element_instruction_map';\nimport {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';\nimport {missingEvent, missingTrigger, transitionFailed, triggerTransitionsFailed, unregisteredTrigger, unsupportedTriggerEvent} from '../error_helpers';\nimport {copyObj, ENTER_CLASSNAME, eraseStyles, LEAVE_CLASSNAME, NG_ANIMATING_CLASSNAME, NG_ANIMATING_SELECTOR, NG_TRIGGER_CLASSNAME, NG_TRIGGER_SELECTOR, setStyles} from '../util';\n\nimport {AnimationDriver} from './animation_driver';\nimport {getOrSetDefaultValue, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';\n\nconst QUEUED_CLASSNAME = 'ng-animate-queued';\nconst QUEUED_SELECTOR = '.ng-animate-queued';\nconst DISABLED_CLASSNAME = 'ng-animate-disabled';\nconst DISABLED_SELECTOR = '.ng-animate-disabled';\nconst STAR_CLASSNAME = 'ng-star-inserted';\nconst STAR_SELECTOR = '.ng-star-inserted';\n\nconst EMPTY_PLAYER_ARRAY: TransitionAnimationPlayer[] = [];\nconst NULL_REMOVAL_STATE: ElementAnimationState = {\n namespaceId: '',\n setForRemoval: false,\n setForMove: false,\n hasAnimation: false,\n removedBeforeQueried: false\n};\nconst NULL_REMOVED_QUERIED_STATE: ElementAnimationState = {\n namespaceId: '',\n setForMove: false,\n setForRemoval: false,\n hasAnimation: false,\n removedBeforeQueried: true\n};\n\ninterface TriggerListener {\n name: string;\n phase: string;\n callback: (event: any) => any;\n}\n\nexport interface QueueInstruction {\n element: any;\n triggerName: string;\n fromState: StateValue;\n toState: StateValue;\n transition: AnimationTransitionFactory;\n player: TransitionAnimationPlayer;\n isFallbackTransition: boolean;\n}\n\nexport const REMOVAL_FLAG = '__ng_removed';\n\nexport interface ElementAnimationState {\n setForRemoval: boolean;\n setForMove: boolean;\n hasAnimation: boolean;\n namespaceId: string;\n removedBeforeQueried: boolean;\n previousTriggersValues?: Map;\n}\n\nexport class StateValue {\n public value: string;\n public options: AnimationOptions;\n\n get params(): {[key: string]: any} {\n return this.options.params as {[key: string]: any};\n }\n\n constructor(input: any, public namespaceId: string = '') {\n const isObj = input && input.hasOwnProperty('value');\n const value = isObj ? input['value'] : input;\n this.value = normalizeTriggerValue(value);\n if (isObj) {\n const options = copyObj(input as any);\n delete options['value'];\n this.options = options as AnimationOptions;\n } else {\n this.options = {};\n }\n if (!this.options.params) {\n this.options.params = {};\n }\n }\n\n absorbOptions(options: AnimationOptions) {\n const newParams = options.params;\n if (newParams) {\n const oldParams = this.options.params!;\n Object.keys(newParams).forEach(prop => {\n if (oldParams[prop] == null) {\n oldParams[prop] = newParams[prop];\n }\n });\n }\n }\n}\n\nexport const VOID_VALUE = 'void';\nexport const DEFAULT_STATE_VALUE = new StateValue(VOID_VALUE);\n\nexport class AnimationTransitionNamespace {\n public players: TransitionAnimationPlayer[] = [];\n\n private _triggers = new Map();\n private _queue: QueueInstruction[] = [];\n\n private _elementListeners = new Map();\n\n private _hostClassName: string;\n\n constructor(\n public id: string, public hostElement: any, private _engine: TransitionAnimationEngine) {\n this._hostClassName = 'ng-tns-' + id;\n addClass(hostElement, this._hostClassName);\n }\n\n listen(element: any, name: string, phase: string, callback: (event: any) => boolean): () => any {\n if (!this._triggers.has(name)) {\n throw missingTrigger(phase, name);\n }\n\n if (phase == null || phase.length == 0) {\n throw missingEvent(name);\n }\n\n if (!isTriggerEventValid(phase)) {\n throw unsupportedTriggerEvent(phase, name);\n }\n\n const listeners = getOrSetDefaultValue(this._elementListeners, element, []);\n const data = {name, phase, callback};\n listeners.push(data);\n\n const triggersWithStates =\n getOrSetDefaultValue(this._engine.statesByElement, element, new Map());\n if (!triggersWithStates.has(name)) {\n addClass(element, NG_TRIGGER_CLASSNAME);\n addClass(element, NG_TRIGGER_CLASSNAME + '-' + name);\n triggersWithStates.set(name, DEFAULT_STATE_VALUE);\n }\n\n return () => {\n // the event listener is removed AFTER the flush has occurred such\n // that leave animations callbacks can fire (otherwise if the node\n // is removed in between then the listeners would be deregistered)\n this._engine.afterFlush(() => {\n const index = listeners.indexOf(data);\n if (index >= 0) {\n listeners.splice(index, 1);\n }\n\n if (!this._triggers.has(name)) {\n triggersWithStates.delete(name);\n }\n });\n };\n }\n\n register(name: string, ast: AnimationTrigger): boolean {\n if (this._triggers.has(name)) {\n // throw\n return false;\n } else {\n this._triggers.set(name, ast);\n return true;\n }\n }\n\n private _getTrigger(name: string) {\n const trigger = this._triggers.get(name);\n if (!trigger) {\n throw unregisteredTrigger(name);\n }\n return trigger;\n }\n\n trigger(element: any, triggerName: string, value: any, defaultToFallback: boolean = true):\n TransitionAnimationPlayer|undefined {\n const trigger = this._getTrigger(triggerName);\n const player = new TransitionAnimationPlayer(this.id, triggerName, element);\n\n let triggersWithStates = this._engine.statesByElement.get(element);\n if (!triggersWithStates) {\n addClass(element, NG_TRIGGER_CLASSNAME);\n addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName);\n this._engine.statesByElement.set(element, triggersWithStates = new Map());\n }\n\n let fromState = triggersWithStates.get(triggerName);\n const toState = new StateValue(value, this.id);\n const isObj = value && value.hasOwnProperty('value');\n if (!isObj && fromState) {\n toState.absorbOptions(fromState.options);\n }\n\n triggersWithStates.set(triggerName, toState);\n\n if (!fromState) {\n fromState = DEFAULT_STATE_VALUE;\n }\n\n const isRemoval = toState.value === VOID_VALUE;\n\n // normally this isn't reached by here, however, if an object expression\n // is passed in then it may be a new object each time. Comparing the value\n // is important since that will stay the same despite there being a new object.\n // The removal arc here is special cased because the same element is triggered\n // twice in the event that it contains animations on the outer/inner portions\n // of the host container\n if (!isRemoval && fromState.value === toState.value) {\n // this means that despite the value not changing, some inner params\n // have changed which means that the animation final styles need to be applied\n if (!objEquals(fromState.params, toState.params)) {\n const errors: Error[] = [];\n const fromStyles = trigger.matchStyles(fromState.value, fromState.params, errors);\n const toStyles = trigger.matchStyles(toState.value, toState.params, errors);\n if (errors.length) {\n this._engine.reportError(errors);\n } else {\n this._engine.afterFlush(() => {\n eraseStyles(element, fromStyles);\n setStyles(element, toStyles);\n });\n }\n }\n return;\n }\n\n const playersOnElement: TransitionAnimationPlayer[] =\n getOrSetDefaultValue(this._engine.playersByElement, element, []);\n playersOnElement.forEach(player => {\n // only remove the player if it is queued on the EXACT same trigger/namespace\n // we only also deal with queued players here because if the animation has\n // started then we want to keep the player alive until the flush happens\n // (which is where the previousPlayers are passed into the new player)\n if (player.namespaceId == this.id && player.triggerName == triggerName && player.queued) {\n player.destroy();\n }\n });\n\n let transition =\n trigger.matchTransition(fromState.value, toState.value, element, toState.params);\n let isFallbackTransition = false;\n if (!transition) {\n if (!defaultToFallback) return;\n transition = trigger.fallbackTransition;\n isFallbackTransition = true;\n }\n\n this._engine.totalQueuedPlayers++;\n this._queue.push(\n {element, triggerName, transition, fromState, toState, player, isFallbackTransition});\n\n if (!isFallbackTransition) {\n addClass(element, QUEUED_CLASSNAME);\n player.onStart(() => {\n removeClass(element, QUEUED_CLASSNAME);\n });\n }\n\n player.onDone(() => {\n let index = this.players.indexOf(player);\n if (index >= 0) {\n this.players.splice(index, 1);\n }\n\n const players = this._engine.playersByElement.get(element);\n if (players) {\n let index = players.indexOf(player);\n if (index >= 0) {\n players.splice(index, 1);\n }\n }\n });\n\n this.players.push(player);\n playersOnElement.push(player);\n\n return player;\n }\n\n deregister(name: string) {\n this._triggers.delete(name);\n\n this._engine.statesByElement.forEach(stateMap => stateMap.delete(name));\n\n this._elementListeners.forEach((listeners, element) => {\n this._elementListeners.set(element, listeners.filter(entry => {\n return entry.name != name;\n }));\n });\n }\n\n clearElementCache(element: any) {\n this._engine.statesByElement.delete(element);\n this._elementListeners.delete(element);\n const elementPlayers = this._engine.playersByElement.get(element);\n if (elementPlayers) {\n elementPlayers.forEach(player => player.destroy());\n this._engine.playersByElement.delete(element);\n }\n }\n\n private _signalRemovalForInnerTriggers(rootElement: any, context: any) {\n const elements = this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true);\n\n // emulate a leave animation for all inner nodes within this node.\n // If there are no animations found for any of the nodes then clear the cache\n // for the element.\n elements.forEach(elm => {\n // this means that an inner remove() operation has already kicked off\n // the animation on this element...\n if (elm[REMOVAL_FLAG]) return;\n\n const namespaces = this._engine.fetchNamespacesByElement(elm);\n if (namespaces.size) {\n namespaces.forEach(ns => ns.triggerLeaveAnimation(elm, context, false, true));\n } else {\n this.clearElementCache(elm);\n }\n });\n\n // If the child elements were removed along with the parent, their animations might not\n // have completed. Clear all the elements from the cache so we don't end up with a memory leak.\n this._engine.afterFlushAnimationsDone(\n () => elements.forEach(elm => this.clearElementCache(elm)));\n }\n\n triggerLeaveAnimation(\n element: any, context: any, destroyAfterComplete?: boolean,\n defaultToFallback?: boolean): boolean {\n const triggerStates = this._engine.statesByElement.get(element);\n const previousTriggersValues = new Map();\n if (triggerStates) {\n const players: TransitionAnimationPlayer[] = [];\n triggerStates.forEach((state, triggerName) => {\n previousTriggersValues.set(triggerName, state.value);\n // this check is here in the event that an element is removed\n // twice (both on the host level and the component level)\n if (this._triggers.has(triggerName)) {\n const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback);\n if (player) {\n players.push(player);\n }\n }\n });\n\n if (players.length) {\n this._engine.markElementAsRemoved(this.id, element, true, context, previousTriggersValues);\n if (destroyAfterComplete) {\n optimizeGroupPlayer(players).onDone(() => this._engine.processLeaveNode(element));\n }\n return true;\n }\n }\n return false;\n }\n\n prepareLeaveAnimationListeners(element: any) {\n const listeners = this._elementListeners.get(element);\n const elementStates = this._engine.statesByElement.get(element);\n\n // if this statement fails then it means that the element was picked up\n // by an earlier flush (or there are no listeners at all to track the leave).\n if (listeners && elementStates) {\n const visitedTriggers = new Set();\n listeners.forEach(listener => {\n const triggerName = listener.name;\n if (visitedTriggers.has(triggerName)) return;\n visitedTriggers.add(triggerName);\n\n const trigger = this._triggers.get(triggerName)!;\n const transition = trigger.fallbackTransition;\n const fromState = elementStates.get(triggerName) || DEFAULT_STATE_VALUE;\n const toState = new StateValue(VOID_VALUE);\n const player = new TransitionAnimationPlayer(this.id, triggerName, element);\n\n this._engine.totalQueuedPlayers++;\n this._queue.push({\n element,\n triggerName,\n transition,\n fromState,\n toState,\n player,\n isFallbackTransition: true\n });\n });\n }\n }\n\n removeNode(element: any, context: any): void {\n const engine = this._engine;\n if (element.childElementCount) {\n this._signalRemovalForInnerTriggers(element, context);\n }\n\n // this means that a * => VOID animation was detected and kicked off\n if (this.triggerLeaveAnimation(element, context, true)) return;\n\n // find the player that is animating and make sure that the\n // removal is delayed until that player has completed\n let containsPotentialParentTransition = false;\n if (engine.totalAnimations) {\n const currentPlayers =\n engine.players.length ? engine.playersByQueriedElement.get(element) : [];\n\n // when this `if statement` does not continue forward it means that\n // a previous animation query has selected the current element and\n // is animating it. In this situation want to continue forwards and\n // allow the element to be queued up for animation later.\n if (currentPlayers && currentPlayers.length) {\n containsPotentialParentTransition = true;\n } else {\n let parent = element;\n while (parent = parent.parentNode) {\n const triggers = engine.statesByElement.get(parent);\n if (triggers) {\n containsPotentialParentTransition = true;\n break;\n }\n }\n }\n }\n\n // at this stage we know that the element will either get removed\n // during flush or will be picked up by a parent query. Either way\n // we need to fire the listeners for this element when it DOES get\n // removed (once the query parent animation is done or after flush)\n this.prepareLeaveAnimationListeners(element);\n\n // whether or not a parent has an animation we need to delay the deferral of the leave\n // operation until we have more information (which we do after flush() has been called)\n if (containsPotentialParentTransition) {\n engine.markElementAsRemoved(this.id, element, false, context);\n } else {\n const removalFlag = element[REMOVAL_FLAG];\n if (!removalFlag || removalFlag === NULL_REMOVAL_STATE) {\n // we do this after the flush has occurred such\n // that the callbacks can be fired\n engine.afterFlush(() => this.clearElementCache(element));\n engine.destroyInnerAnimations(element);\n engine._onRemovalComplete(element, context);\n }\n }\n }\n\n insertNode(element: any, parent: any): void {\n addClass(element, this._hostClassName);\n }\n\n drainQueuedTransitions(microtaskId: number): QueueInstruction[] {\n const instructions: QueueInstruction[] = [];\n this._queue.forEach(entry => {\n const player = entry.player;\n if (player.destroyed) return;\n\n const element = entry.element;\n const listeners = this._elementListeners.get(element);\n if (listeners) {\n listeners.forEach((listener: TriggerListener) => {\n if (listener.name == entry.triggerName) {\n const baseEvent = makeAnimationEvent(\n element, entry.triggerName, entry.fromState.value, entry.toState.value);\n (baseEvent as any)['_data'] = microtaskId;\n listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback);\n }\n });\n }\n\n if (player.markedForDestroy) {\n this._engine.afterFlush(() => {\n // now we can destroy the element properly since the event listeners have\n // been bound to the player\n player.destroy();\n });\n } else {\n instructions.push(entry);\n }\n });\n\n this._queue = [];\n\n return instructions.sort((a, b) => {\n // if depCount == 0 them move to front\n // otherwise if a contains b then move back\n const d0 = a.transition.ast.depCount;\n const d1 = b.transition.ast.depCount;\n if (d0 == 0 || d1 == 0) {\n return d0 - d1;\n }\n return this._engine.driver.containsElement(a.element, b.element) ? 1 : -1;\n });\n }\n\n destroy(context: any) {\n this.players.forEach(p => p.destroy());\n this._signalRemovalForInnerTriggers(this.hostElement, context);\n }\n\n elementContainsData(element: any): boolean {\n let containsData = false;\n if (this._elementListeners.has(element)) containsData = true;\n containsData =\n (this._queue.find(entry => entry.element === element) ? true : false) || containsData;\n return containsData;\n }\n}\n\nexport interface QueuedTransition {\n element: any;\n instruction: AnimationTransitionInstruction;\n player: TransitionAnimationPlayer;\n}\n\nexport class TransitionAnimationEngine {\n public players: TransitionAnimationPlayer[] = [];\n public newHostElements = new Map();\n public playersByElement = new Map();\n public playersByQueriedElement = new Map();\n public statesByElement = new Map>();\n public disabledNodes = new Set();\n\n public totalAnimations = 0;\n public totalQueuedPlayers = 0;\n\n private _namespaceLookup: {[id: string]: AnimationTransitionNamespace} = {};\n private _namespaceList: AnimationTransitionNamespace[] = [];\n private _flushFns: (() => any)[] = [];\n private _whenQuietFns: (() => any)[] = [];\n\n public namespacesByHostElement = new Map();\n public collectedEnterElements: any[] = [];\n public collectedLeaveElements: any[] = [];\n\n // this method is designed to be overridden by the code that uses this engine\n public onRemovalComplete = (element: any, context: any) => {};\n\n /** @internal */\n _onRemovalComplete(element: any, context: any) {\n this.onRemovalComplete(element, context);\n }\n\n constructor(\n public bodyNode: any, public driver: AnimationDriver,\n private _normalizer: AnimationStyleNormalizer) {}\n\n get queuedPlayers(): TransitionAnimationPlayer[] {\n const players: TransitionAnimationPlayer[] = [];\n this._namespaceList.forEach(ns => {\n ns.players.forEach(player => {\n if (player.queued) {\n players.push(player);\n }\n });\n });\n return players;\n }\n\n createNamespace(namespaceId: string, hostElement: any) {\n const ns = new AnimationTransitionNamespace(namespaceId, hostElement, this);\n if (this.bodyNode && this.driver.containsElement(this.bodyNode, hostElement)) {\n this._balanceNamespaceList(ns, hostElement);\n } else {\n // defer this later until flush during when the host element has\n // been inserted so that we know exactly where to place it in\n // the namespace list\n this.newHostElements.set(hostElement, ns);\n\n // given that this host element is a part of the animation code, it\n // may or may not be inserted by a parent node that is of an\n // animation renderer type. If this happens then we can still have\n // access to this item when we query for :enter nodes. If the parent\n // is a renderer then the set data-structure will normalize the entry\n this.collectEnterElement(hostElement);\n }\n return this._namespaceLookup[namespaceId] = ns;\n }\n\n private _balanceNamespaceList(ns: AnimationTransitionNamespace, hostElement: any) {\n const namespaceList = this._namespaceList;\n const namespacesByHostElement = this.namespacesByHostElement;\n const limit = namespaceList.length - 1;\n if (limit >= 0) {\n let found = false;\n // Find the closest ancestor with an existing namespace so we can then insert `ns` after it,\n // establishing a top-down ordering of namespaces in `this._namespaceList`.\n let ancestor = this.driver.getParentElement(hostElement);\n while (ancestor) {\n const ancestorNs = namespacesByHostElement.get(ancestor);\n if (ancestorNs) {\n // An animation namespace has been registered for this ancestor, so we insert `ns`\n // right after it to establish top-down ordering of animation namespaces.\n const index = namespaceList.indexOf(ancestorNs);\n namespaceList.splice(index + 1, 0, ns);\n found = true;\n break;\n }\n ancestor = this.driver.getParentElement(ancestor);\n }\n if (!found) {\n // No namespace exists that is an ancestor of `ns`, so `ns` is inserted at the front to\n // ensure that any existing descendants are ordered after `ns`, retaining the desired\n // top-down ordering.\n namespaceList.unshift(ns);\n }\n } else {\n namespaceList.push(ns);\n }\n\n namespacesByHostElement.set(hostElement, ns);\n return ns;\n }\n\n register(namespaceId: string, hostElement: any) {\n let ns = this._namespaceLookup[namespaceId];\n if (!ns) {\n ns = this.createNamespace(namespaceId, hostElement);\n }\n return ns;\n }\n\n registerTrigger(namespaceId: string, name: string, trigger: AnimationTrigger) {\n let ns = this._namespaceLookup[namespaceId];\n if (ns && ns.register(name, trigger)) {\n this.totalAnimations++;\n }\n }\n\n destroy(namespaceId: string, context: any) {\n if (!namespaceId) return;\n\n const ns = this._fetchNamespace(namespaceId);\n\n this.afterFlush(() => {\n this.namespacesByHostElement.delete(ns.hostElement);\n delete this._namespaceLookup[namespaceId];\n const index = this._namespaceList.indexOf(ns);\n if (index >= 0) {\n this._namespaceList.splice(index, 1);\n }\n });\n\n this.afterFlushAnimationsDone(() => ns.destroy(context));\n }\n\n private _fetchNamespace(id: string) {\n return this._namespaceLookup[id];\n }\n\n fetchNamespacesByElement(element: any): Set {\n // normally there should only be one namespace per element, however\n // if @triggers are placed on both the component element and then\n // its host element (within the component code) then there will be\n // two namespaces returned. We use a set here to simply deduplicate\n // the namespaces in case (for the reason described above) there are multiple triggers\n const namespaces = new Set();\n const elementStates = this.statesByElement.get(element);\n if (elementStates) {\n for (let stateValue of elementStates.values()) {\n if (stateValue.namespaceId) {\n const ns = this._fetchNamespace(stateValue.namespaceId);\n if (ns) {\n namespaces.add(ns);\n }\n }\n }\n }\n return namespaces;\n }\n\n trigger(namespaceId: string, element: any, name: string, value: any): boolean {\n if (isElementNode(element)) {\n const ns = this._fetchNamespace(namespaceId);\n if (ns) {\n ns.trigger(element, name, value);\n return true;\n }\n }\n return false;\n }\n\n insertNode(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {\n if (!isElementNode(element)) return;\n\n // special case for when an element is removed and reinserted (move operation)\n // when this occurs we do not want to use the element for deletion later\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n if (details && details.setForRemoval) {\n details.setForRemoval = false;\n details.setForMove = true;\n const index = this.collectedLeaveElements.indexOf(element);\n if (index >= 0) {\n this.collectedLeaveElements.splice(index, 1);\n }\n }\n\n // in the event that the namespaceId is blank then the caller\n // code does not contain any animation code in it, but it is\n // just being called so that the node is marked as being inserted\n if (namespaceId) {\n const ns = this._fetchNamespace(namespaceId);\n // This if-statement is a workaround for router issue #21947.\n // The router sometimes hits a race condition where while a route\n // is being instantiated a new navigation arrives, triggering leave\n // animation of DOM that has not been fully initialized, until this\n // is resolved, we need to handle the scenario when DOM is not in a\n // consistent state during the animation.\n if (ns) {\n ns.insertNode(element, parent);\n }\n }\n\n // only *directives and host elements are inserted before\n if (insertBefore) {\n this.collectEnterElement(element);\n }\n }\n\n collectEnterElement(element: any) {\n this.collectedEnterElements.push(element);\n }\n\n markElementAsDisabled(element: any, value: boolean) {\n if (value) {\n if (!this.disabledNodes.has(element)) {\n this.disabledNodes.add(element);\n addClass(element, DISABLED_CLASSNAME);\n }\n } else if (this.disabledNodes.has(element)) {\n this.disabledNodes.delete(element);\n removeClass(element, DISABLED_CLASSNAME);\n }\n }\n\n removeNode(namespaceId: string, element: any, isHostElement: boolean, context: any): void {\n if (isElementNode(element)) {\n const ns = namespaceId ? this._fetchNamespace(namespaceId) : null;\n if (ns) {\n ns.removeNode(element, context);\n } else {\n this.markElementAsRemoved(namespaceId, element, false, context);\n }\n\n if (isHostElement) {\n const hostNS = this.namespacesByHostElement.get(element);\n if (hostNS && hostNS.id !== namespaceId) {\n hostNS.removeNode(element, context);\n }\n }\n } else {\n this._onRemovalComplete(element, context);\n }\n }\n\n markElementAsRemoved(\n namespaceId: string, element: any, hasAnimation?: boolean, context?: any,\n previousTriggersValues?: Map) {\n this.collectedLeaveElements.push(element);\n element[REMOVAL_FLAG] = {\n namespaceId,\n setForRemoval: context,\n hasAnimation,\n removedBeforeQueried: false,\n previousTriggersValues\n };\n }\n\n listen(\n namespaceId: string, element: any, name: string, phase: string,\n callback: (event: any) => boolean): () => any {\n if (isElementNode(element)) {\n return this._fetchNamespace(namespaceId).listen(element, name, phase, callback);\n }\n return () => {};\n }\n\n private _buildInstruction(\n entry: QueueInstruction, subTimelines: ElementInstructionMap, enterClassName: string,\n leaveClassName: string, skipBuildAst?: boolean) {\n return entry.transition.build(\n this.driver, entry.element, entry.fromState.value, entry.toState.value, enterClassName,\n leaveClassName, entry.fromState.options, entry.toState.options, subTimelines, skipBuildAst);\n }\n\n destroyInnerAnimations(containerElement: any) {\n let elements = this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true);\n elements.forEach(element => this.destroyActiveAnimationsForElement(element));\n\n if (this.playersByQueriedElement.size == 0) return;\n\n elements = this.driver.query(containerElement, NG_ANIMATING_SELECTOR, true);\n elements.forEach(element => this.finishActiveQueriedAnimationOnElement(element));\n }\n\n destroyActiveAnimationsForElement(element: any) {\n const players = this.playersByElement.get(element);\n if (players) {\n players.forEach(player => {\n // special case for when an element is set for destruction, but hasn't started.\n // in this situation we want to delay the destruction until the flush occurs\n // so that any event listeners attached to the player are triggered.\n if (player.queued) {\n player.markedForDestroy = true;\n } else {\n player.destroy();\n }\n });\n }\n }\n\n finishActiveQueriedAnimationOnElement(element: any) {\n const players = this.playersByQueriedElement.get(element);\n if (players) {\n players.forEach(player => player.finish());\n }\n }\n\n whenRenderingDone(): Promise {\n return new Promise(resolve => {\n if (this.players.length) {\n return optimizeGroupPlayer(this.players).onDone(() => resolve());\n } else {\n resolve();\n }\n });\n }\n\n processLeaveNode(element: any) {\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n if (details && details.setForRemoval) {\n // this will prevent it from removing it twice\n element[REMOVAL_FLAG] = NULL_REMOVAL_STATE;\n if (details.namespaceId) {\n this.destroyInnerAnimations(element);\n const ns = this._fetchNamespace(details.namespaceId);\n if (ns) {\n ns.clearElementCache(element);\n }\n }\n this._onRemovalComplete(element, details.setForRemoval);\n }\n\n if (element.classList?.contains(DISABLED_CLASSNAME)) {\n this.markElementAsDisabled(element, false);\n }\n\n this.driver.query(element, DISABLED_SELECTOR, true).forEach(node => {\n this.markElementAsDisabled(node, false);\n });\n }\n\n flush(microtaskId: number = -1) {\n let players: AnimationPlayer[] = [];\n if (this.newHostElements.size) {\n this.newHostElements.forEach((ns, element) => this._balanceNamespaceList(ns, element));\n this.newHostElements.clear();\n }\n\n if (this.totalAnimations && this.collectedEnterElements.length) {\n for (let i = 0; i < this.collectedEnterElements.length; i++) {\n const elm = this.collectedEnterElements[i];\n addClass(elm, STAR_CLASSNAME);\n }\n }\n\n if (this._namespaceList.length &&\n (this.totalQueuedPlayers || this.collectedLeaveElements.length)) {\n const cleanupFns: Function[] = [];\n try {\n players = this._flushAnimations(cleanupFns, microtaskId);\n } finally {\n for (let i = 0; i < cleanupFns.length; i++) {\n cleanupFns[i]();\n }\n }\n } else {\n for (let i = 0; i < this.collectedLeaveElements.length; i++) {\n const element = this.collectedLeaveElements[i];\n this.processLeaveNode(element);\n }\n }\n\n this.totalQueuedPlayers = 0;\n this.collectedEnterElements.length = 0;\n this.collectedLeaveElements.length = 0;\n this._flushFns.forEach(fn => fn());\n this._flushFns = [];\n\n if (this._whenQuietFns.length) {\n // we move these over to a variable so that\n // if any new callbacks are registered in another\n // flush they do not populate the existing set\n const quietFns = this._whenQuietFns;\n this._whenQuietFns = [];\n\n if (players.length) {\n optimizeGroupPlayer(players).onDone(() => {\n quietFns.forEach(fn => fn());\n });\n } else {\n quietFns.forEach(fn => fn());\n }\n }\n }\n\n reportError(errors: Error[]) {\n throw triggerTransitionsFailed(errors);\n }\n\n private _flushAnimations(cleanupFns: Function[], microtaskId: number):\n TransitionAnimationPlayer[] {\n const subTimelines = new ElementInstructionMap();\n const skippedPlayers: TransitionAnimationPlayer[] = [];\n const skippedPlayersMap = new Map();\n const queuedInstructions: QueuedTransition[] = [];\n const queriedElements = new Map();\n const allPreStyleElements = new Map>();\n const allPostStyleElements = new Map>();\n\n const disabledElementsSet = new Set();\n this.disabledNodes.forEach(node => {\n disabledElementsSet.add(node);\n const nodesThatAreDisabled = this.driver.query(node, QUEUED_SELECTOR, true);\n for (let i = 0; i < nodesThatAreDisabled.length; i++) {\n disabledElementsSet.add(nodesThatAreDisabled[i]);\n }\n });\n\n const bodyNode = this.bodyNode;\n const allTriggerElements = Array.from(this.statesByElement.keys());\n const enterNodeMap = buildRootMap(allTriggerElements, this.collectedEnterElements);\n\n // this must occur before the instructions are built below such that\n // the :enter queries match the elements (since the timeline queries\n // are fired during instruction building).\n const enterNodeMapIds = new Map();\n let i = 0;\n enterNodeMap.forEach((nodes, root) => {\n const className = ENTER_CLASSNAME + i++;\n enterNodeMapIds.set(root, className);\n nodes.forEach(node => addClass(node, className));\n });\n\n const allLeaveNodes: any[] = [];\n const mergedLeaveNodes = new Set();\n const leaveNodesWithoutAnimations = new Set();\n for (let i = 0; i < this.collectedLeaveElements.length; i++) {\n const element = this.collectedLeaveElements[i];\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n if (details && details.setForRemoval) {\n allLeaveNodes.push(element);\n mergedLeaveNodes.add(element);\n if (details.hasAnimation) {\n this.driver.query(element, STAR_SELECTOR, true).forEach(elm => mergedLeaveNodes.add(elm));\n } else {\n leaveNodesWithoutAnimations.add(element);\n }\n }\n }\n\n const leaveNodeMapIds = new Map();\n const leaveNodeMap = buildRootMap(allTriggerElements, Array.from(mergedLeaveNodes));\n leaveNodeMap.forEach((nodes, root) => {\n const className = LEAVE_CLASSNAME + i++;\n leaveNodeMapIds.set(root, className);\n nodes.forEach(node => addClass(node, className));\n });\n\n cleanupFns.push(() => {\n enterNodeMap.forEach((nodes, root) => {\n const className = enterNodeMapIds.get(root)!;\n nodes.forEach(node => removeClass(node, className));\n });\n\n leaveNodeMap.forEach((nodes, root) => {\n const className = leaveNodeMapIds.get(root)!;\n nodes.forEach(node => removeClass(node, className));\n });\n\n allLeaveNodes.forEach(element => {\n this.processLeaveNode(element);\n });\n });\n\n const allPlayers: TransitionAnimationPlayer[] = [];\n const erroneousTransitions: AnimationTransitionInstruction[] = [];\n for (let i = this._namespaceList.length - 1; i >= 0; i--) {\n const ns = this._namespaceList[i];\n ns.drainQueuedTransitions(microtaskId).forEach(entry => {\n const player = entry.player;\n const element = entry.element;\n allPlayers.push(player);\n\n if (this.collectedEnterElements.length) {\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n // animations for move operations (elements being removed and reinserted,\n // e.g. when the order of an *ngFor list changes) are currently not supported\n if (details && details.setForMove) {\n if (details.previousTriggersValues &&\n details.previousTriggersValues.has(entry.triggerName)) {\n const previousValue = details.previousTriggersValues.get(entry.triggerName) as string;\n\n // we need to restore the previous trigger value since the element has\n // only been moved and hasn't actually left the DOM\n const triggersWithStates = this.statesByElement.get(entry.element);\n if (triggersWithStates && triggersWithStates.has(entry.triggerName)) {\n const state = triggersWithStates.get(entry.triggerName)!;\n state.value = previousValue;\n triggersWithStates.set(entry.triggerName, state);\n }\n }\n\n player.destroy();\n return;\n }\n }\n\n const nodeIsOrphaned = !bodyNode || !this.driver.containsElement(bodyNode, element);\n const leaveClassName = leaveNodeMapIds.get(element)!;\n const enterClassName = enterNodeMapIds.get(element)!;\n const instruction = this._buildInstruction(\n entry, subTimelines, enterClassName, leaveClassName, nodeIsOrphaned)!;\n if (instruction.errors && instruction.errors.length) {\n erroneousTransitions.push(instruction);\n return;\n }\n\n // even though the element may not be in the DOM, it may still\n // be added at a later point (due to the mechanics of content\n // projection and/or dynamic component insertion) therefore it's\n // important to still style the element.\n if (nodeIsOrphaned) {\n player.onStart(() => eraseStyles(element, instruction.fromStyles));\n player.onDestroy(() => setStyles(element, instruction.toStyles));\n skippedPlayers.push(player);\n return;\n }\n\n // if an unmatched transition is queued and ready to go\n // then it SHOULD NOT render an animation and cancel the\n // previously running animations.\n if (entry.isFallbackTransition) {\n player.onStart(() => eraseStyles(element, instruction.fromStyles));\n player.onDestroy(() => setStyles(element, instruction.toStyles));\n skippedPlayers.push(player);\n return;\n }\n\n // this means that if a parent animation uses this animation as a sub-trigger\n // then it will instruct the timeline builder not to add a player delay, but\n // instead stretch the first keyframe gap until the animation starts. This is\n // important in order to prevent extra initialization styles from being\n // required by the user for the animation.\n const timelines: AnimationTimelineInstruction[] = [];\n instruction.timelines.forEach(tl => {\n tl.stretchStartingKeyframe = true;\n if (!this.disabledNodes.has(tl.element)) {\n timelines.push(tl);\n }\n });\n instruction.timelines = timelines;\n\n subTimelines.append(element, instruction.timelines);\n\n const tuple = {instruction, player, element};\n\n queuedInstructions.push(tuple);\n\n instruction.queriedElements.forEach(\n element => getOrSetDefaultValue(queriedElements, element, []).push(player));\n\n instruction.preStyleProps.forEach((stringMap, element) => {\n if (stringMap.size) {\n let setVal: Set = allPreStyleElements.get(element)!;\n if (!setVal) {\n allPreStyleElements.set(element, setVal = new Set());\n }\n stringMap.forEach((_, prop) => setVal.add(prop));\n }\n });\n\n instruction.postStyleProps.forEach((stringMap, element) => {\n let setVal: Set = allPostStyleElements.get(element)!;\n if (!setVal) {\n allPostStyleElements.set(element, setVal = new Set());\n }\n stringMap.forEach((_, prop) => setVal.add(prop));\n });\n });\n }\n\n if (erroneousTransitions.length) {\n const errors: Error[] = [];\n erroneousTransitions.forEach(instruction => {\n errors.push(transitionFailed(instruction.triggerName, instruction.errors!));\n });\n\n allPlayers.forEach(player => player.destroy());\n this.reportError(errors);\n }\n\n const allPreviousPlayersMap = new Map();\n // this map tells us which element in the DOM tree is contained by\n // which animation. Further down this map will get populated once\n // the players are built and in doing so we can use it to efficiently\n // figure out if a sub player is skipped due to a parent player having priority.\n const animationElementMap = new Map();\n queuedInstructions.forEach(entry => {\n const element = entry.element;\n if (subTimelines.has(element)) {\n animationElementMap.set(element, element);\n this._beforeAnimationBuild(\n entry.player.namespaceId, entry.instruction, allPreviousPlayersMap);\n }\n });\n\n skippedPlayers.forEach(player => {\n const element = player.element;\n const previousPlayers =\n this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);\n previousPlayers.forEach(prevPlayer => {\n getOrSetDefaultValue(allPreviousPlayersMap, element, []).push(prevPlayer);\n prevPlayer.destroy();\n });\n });\n\n // this is a special case for nodes that will be removed either by\n // having their own leave animations or by being queried in a container\n // that will be removed once a parent animation is complete. The idea\n // here is that * styles must be identical to ! styles because of\n // backwards compatibility (* is also filled in by default in many places).\n // Otherwise * styles will return an empty value or \"auto\" since the element\n // passed to getComputedStyle will not be visible (since * === destination)\n const replaceNodes = allLeaveNodes.filter(node => {\n return replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements);\n });\n\n // POST STAGE: fill the * styles\n const postStylesMap = new Map();\n const allLeaveQueriedNodes = cloakAndComputeStyles(\n postStylesMap, this.driver, leaveNodesWithoutAnimations, allPostStyleElements, AUTO_STYLE);\n\n allLeaveQueriedNodes.forEach(node => {\n if (replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements)) {\n replaceNodes.push(node);\n }\n });\n\n // PRE STAGE: fill the ! styles\n const preStylesMap = new Map();\n enterNodeMap.forEach((nodes, root) => {\n cloakAndComputeStyles(\n preStylesMap, this.driver, new Set(nodes), allPreStyleElements, PRE_STYLE);\n });\n\n replaceNodes.forEach(node => {\n const post = postStylesMap.get(node);\n const pre = preStylesMap.get(node);\n postStylesMap.set(\n node,\n new Map([...Array.from(post?.entries() ?? []), ...Array.from(pre?.entries() ?? [])]));\n });\n\n const rootPlayers: TransitionAnimationPlayer[] = [];\n const subPlayers: TransitionAnimationPlayer[] = [];\n const NO_PARENT_ANIMATION_ELEMENT_DETECTED = {};\n queuedInstructions.forEach(entry => {\n const {element, player, instruction} = entry;\n // this means that it was never consumed by a parent animation which\n // means that it is independent and therefore should be set for animation\n if (subTimelines.has(element)) {\n if (disabledElementsSet.has(element)) {\n player.onDestroy(() => setStyles(element, instruction.toStyles));\n player.disabled = true;\n player.overrideTotalTime(instruction.totalTime);\n skippedPlayers.push(player);\n return;\n }\n\n // this will flow up the DOM and query the map to figure out\n // if a parent animation has priority over it. In the situation\n // that a parent is detected then it will cancel the loop. If\n // nothing is detected, or it takes a few hops to find a parent,\n // then it will fill in the missing nodes and signal them as having\n // a detected parent (or a NO_PARENT value via a special constant).\n let parentWithAnimation: any = NO_PARENT_ANIMATION_ELEMENT_DETECTED;\n if (animationElementMap.size > 1) {\n let elm = element;\n const parentsToAdd: any[] = [];\n while (elm = elm.parentNode) {\n const detectedParent = animationElementMap.get(elm);\n if (detectedParent) {\n parentWithAnimation = detectedParent;\n break;\n }\n parentsToAdd.push(elm);\n }\n parentsToAdd.forEach(parent => animationElementMap.set(parent, parentWithAnimation));\n }\n\n const innerPlayer = this._buildAnimation(\n player.namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap,\n postStylesMap);\n\n player.setRealPlayer(innerPlayer);\n\n if (parentWithAnimation === NO_PARENT_ANIMATION_ELEMENT_DETECTED) {\n rootPlayers.push(player);\n } else {\n const parentPlayers = this.playersByElement.get(parentWithAnimation);\n if (parentPlayers && parentPlayers.length) {\n player.parentPlayer = optimizeGroupPlayer(parentPlayers);\n }\n skippedPlayers.push(player);\n }\n } else {\n eraseStyles(element, instruction.fromStyles);\n player.onDestroy(() => setStyles(element, instruction.toStyles));\n // there still might be a ancestor player animating this\n // element therefore we will still add it as a sub player\n // even if its animation may be disabled\n subPlayers.push(player);\n if (disabledElementsSet.has(element)) {\n skippedPlayers.push(player);\n }\n }\n });\n\n // find all of the sub players' corresponding inner animation players\n subPlayers.forEach(player => {\n // even if no players are found for a sub animation it\n // will still complete itself after the next tick since it's Noop\n const playersForElement = skippedPlayersMap.get(player.element);\n if (playersForElement && playersForElement.length) {\n const innerPlayer = optimizeGroupPlayer(playersForElement);\n player.setRealPlayer(innerPlayer);\n }\n });\n\n // the reason why we don't actually play the animation is\n // because all that a skipped player is designed to do is to\n // fire the start/done transition callback events\n skippedPlayers.forEach(player => {\n if (player.parentPlayer) {\n player.syncPlayerEvents(player.parentPlayer);\n } else {\n player.destroy();\n }\n });\n\n // run through all of the queued removals and see if they\n // were picked up by a query. If not then perform the removal\n // operation right away unless a parent animation is ongoing.\n for (let i = 0; i < allLeaveNodes.length; i++) {\n const element = allLeaveNodes[i];\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n removeClass(element, LEAVE_CLASSNAME);\n\n // this means the element has a removal animation that is being\n // taken care of and therefore the inner elements will hang around\n // until that animation is over (or the parent queried animation)\n if (details && details.hasAnimation) continue;\n\n let players: TransitionAnimationPlayer[] = [];\n\n // if this element is queried or if it contains queried children\n // then we want for the element not to be removed from the page\n // until the queried animations have finished\n if (queriedElements.size) {\n let queriedPlayerResults = queriedElements.get(element);\n if (queriedPlayerResults && queriedPlayerResults.length) {\n players.push(...queriedPlayerResults);\n }\n\n let queriedInnerElements = this.driver.query(element, NG_ANIMATING_SELECTOR, true);\n for (let j = 0; j < queriedInnerElements.length; j++) {\n let queriedPlayers = queriedElements.get(queriedInnerElements[j]);\n if (queriedPlayers && queriedPlayers.length) {\n players.push(...queriedPlayers);\n }\n }\n }\n\n const activePlayers = players.filter(p => !p.destroyed);\n if (activePlayers.length) {\n removeNodesAfterAnimationDone(this, element, activePlayers);\n } else {\n this.processLeaveNode(element);\n }\n }\n\n // this is required so the cleanup method doesn't remove them\n allLeaveNodes.length = 0;\n\n rootPlayers.forEach(player => {\n this.players.push(player);\n player.onDone(() => {\n player.destroy();\n\n const index = this.players.indexOf(player);\n this.players.splice(index, 1);\n });\n player.play();\n });\n\n return rootPlayers;\n }\n\n elementContainsData(namespaceId: string, element: any) {\n let containsData = false;\n const details = element[REMOVAL_FLAG] as ElementAnimationState;\n if (details && details.setForRemoval) containsData = true;\n if (this.playersByElement.has(element)) containsData = true;\n if (this.playersByQueriedElement.has(element)) containsData = true;\n if (this.statesByElement.has(element)) containsData = true;\n return this._fetchNamespace(namespaceId).elementContainsData(element) || containsData;\n }\n\n afterFlush(callback: () => any) {\n this._flushFns.push(callback);\n }\n\n afterFlushAnimationsDone(callback: () => any) {\n this._whenQuietFns.push(callback);\n }\n\n private _getPreviousPlayers(\n element: string, isQueriedElement: boolean, namespaceId?: string, triggerName?: string,\n toStateValue?: any): TransitionAnimationPlayer[] {\n let players: TransitionAnimationPlayer[] = [];\n if (isQueriedElement) {\n const queriedElementPlayers = this.playersByQueriedElement.get(element);\n if (queriedElementPlayers) {\n players = queriedElementPlayers;\n }\n } else {\n const elementPlayers = this.playersByElement.get(element);\n if (elementPlayers) {\n const isRemovalAnimation = !toStateValue || toStateValue == VOID_VALUE;\n elementPlayers.forEach(player => {\n if (player.queued) return;\n if (!isRemovalAnimation && player.triggerName != triggerName) return;\n players.push(player);\n });\n }\n }\n if (namespaceId || triggerName) {\n players = players.filter(player => {\n if (namespaceId && namespaceId != player.namespaceId) return false;\n if (triggerName && triggerName != player.triggerName) return false;\n return true;\n });\n }\n return players;\n }\n\n private _beforeAnimationBuild(\n namespaceId: string, instruction: AnimationTransitionInstruction,\n allPreviousPlayersMap: Map) {\n const triggerName = instruction.triggerName;\n const rootElement = instruction.element;\n\n // when a removal animation occurs, ALL previous players are collected\n // and destroyed (even if they are outside of the current namespace)\n const targetNameSpaceId: string|undefined =\n instruction.isRemovalTransition ? undefined : namespaceId;\n const targetTriggerName: string|undefined =\n instruction.isRemovalTransition ? undefined : triggerName;\n\n for (const timelineInstruction of instruction.timelines) {\n const element = timelineInstruction.element;\n const isQueriedElement = element !== rootElement;\n const players = getOrSetDefaultValue(allPreviousPlayersMap, element, []);\n const previousPlayers = this._getPreviousPlayers(\n element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);\n previousPlayers.forEach(player => {\n const realPlayer = (player as TransitionAnimationPlayer).getRealPlayer() as any;\n if (realPlayer.beforeDestroy) {\n realPlayer.beforeDestroy();\n }\n player.destroy();\n players.push(player);\n });\n }\n\n // this needs to be done so that the PRE/POST styles can be\n // computed properly without interfering with the previous animation\n eraseStyles(rootElement, instruction.fromStyles);\n }\n\n private _buildAnimation(\n namespaceId: string, instruction: AnimationTransitionInstruction,\n allPreviousPlayersMap: Map,\n skippedPlayersMap: Map, preStylesMap: Map,\n postStylesMap: Map): AnimationPlayer {\n const triggerName = instruction.triggerName;\n const rootElement = instruction.element;\n\n // we first run this so that the previous animation player\n // data can be passed into the successive animation players\n const allQueriedPlayers: TransitionAnimationPlayer[] = [];\n const allConsumedElements = new Set();\n const allSubElements = new Set();\n const allNewPlayers = instruction.timelines.map(timelineInstruction => {\n const element = timelineInstruction.element;\n allConsumedElements.add(element);\n\n // FIXME (matsko): make sure to-be-removed animations are removed properly\n const details = element[REMOVAL_FLAG];\n if (details && details.removedBeforeQueried)\n return new NoopAnimationPlayer(timelineInstruction.duration, timelineInstruction.delay);\n const isQueriedElement = element !== rootElement;\n const previousPlayers =\n flattenGroupPlayers((allPreviousPlayersMap.get(element) || EMPTY_PLAYER_ARRAY)\n .map(p => p.getRealPlayer()))\n .filter(p => {\n // the `element` is not apart of the AnimationPlayer definition, but\n // Mock/WebAnimations\n // use the element within their implementation. This will be added in Angular5 to\n // AnimationPlayer\n const pp = p as any;\n return pp.element ? pp.element === element : false;\n });\n\n const preStyles = preStylesMap.get(element);\n const postStyles = postStylesMap.get(element);\n\n const keyframes = normalizeKeyframes(\n this.driver, this._normalizer, element, timelineInstruction.keyframes, preStyles,\n postStyles);\n const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers);\n\n // this means that this particular player belongs to a sub trigger. It is\n // important that we match this player up with the corresponding (@trigger.listener)\n if (timelineInstruction.subTimeline && skippedPlayersMap) {\n allSubElements.add(element);\n }\n\n if (isQueriedElement) {\n const wrappedPlayer = new TransitionAnimationPlayer(namespaceId, triggerName, element);\n wrappedPlayer.setRealPlayer(player);\n allQueriedPlayers.push(wrappedPlayer);\n }\n\n return player;\n });\n\n allQueriedPlayers.forEach(player => {\n getOrSetDefaultValue(this.playersByQueriedElement, player.element, []).push(player);\n player.onDone(() => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player));\n });\n\n allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME));\n const player = optimizeGroupPlayer(allNewPlayers);\n player.onDestroy(() => {\n allConsumedElements.forEach(element => removeClass(element, NG_ANIMATING_CLASSNAME));\n setStyles(rootElement, instruction.toStyles);\n });\n\n // this basically makes all of the callbacks for sub element animations\n // be dependent on the upper players for when they finish\n allSubElements.forEach(element => {\n getOrSetDefaultValue(skippedPlayersMap, element, []).push(player);\n });\n\n return player;\n }\n\n private _buildPlayer(\n instruction: AnimationTimelineInstruction, keyframes: Array<ɵStyleDataMap>,\n previousPlayers: AnimationPlayer[]): AnimationPlayer {\n if (keyframes.length > 0) {\n return this.driver.animate(\n instruction.element, keyframes, instruction.duration, instruction.delay,\n instruction.easing, previousPlayers);\n }\n\n // special case for when an empty transition|definition is provided\n // ... there is no point in rendering an empty animation\n return new NoopAnimationPlayer(instruction.duration, instruction.delay);\n }\n}\n\nexport class TransitionAnimationPlayer implements AnimationPlayer {\n private _player: AnimationPlayer = new NoopAnimationPlayer();\n private _containsRealPlayer = false;\n\n private _queuedCallbacks = new Map any)[]>();\n public readonly destroyed = false;\n public parentPlayer: AnimationPlayer|null = null;\n\n public markedForDestroy: boolean = false;\n public disabled = false;\n\n readonly queued: boolean = true;\n public readonly totalTime: number = 0;\n\n constructor(public namespaceId: string, public triggerName: string, public element: any) {}\n\n setRealPlayer(player: AnimationPlayer) {\n if (this._containsRealPlayer) return;\n\n this._player = player;\n this._queuedCallbacks.forEach((callbacks, phase) => {\n callbacks.forEach(callback => listenOnPlayer(player, phase, undefined, callback));\n });\n\n this._queuedCallbacks.clear();\n this._containsRealPlayer = true;\n this.overrideTotalTime(player.totalTime);\n (this as {queued: boolean}).queued = false;\n }\n\n getRealPlayer() {\n return this._player;\n }\n\n overrideTotalTime(totalTime: number) {\n (this as any).totalTime = totalTime;\n }\n\n syncPlayerEvents(player: AnimationPlayer) {\n const p = this._player as any;\n if (p.triggerCallback) {\n player.onStart(() => p.triggerCallback!('start'));\n }\n player.onDone(() => this.finish());\n player.onDestroy(() => this.destroy());\n }\n\n private _queueEvent(name: string, callback: (event: any) => any): void {\n getOrSetDefaultValue(this._queuedCallbacks, name, []).push(callback);\n }\n\n onDone(fn: () => void): void {\n if (this.queued) {\n this._queueEvent('done', fn);\n }\n this._player.onDone(fn);\n }\n\n onStart(fn: () => void): void {\n if (this.queued) {\n this._queueEvent('start', fn);\n }\n this._player.onStart(fn);\n }\n\n onDestroy(fn: () => void): void {\n if (this.queued) {\n this._queueEvent('destroy', fn);\n }\n this._player.onDestroy(fn);\n }\n\n init(): void {\n this._player.init();\n }\n\n hasStarted(): boolean {\n return this.queued ? false : this._player.hasStarted();\n }\n\n play(): void {\n !this.queued && this._player.play();\n }\n\n pause(): void {\n !this.queued && this._player.pause();\n }\n\n restart(): void {\n !this.queued && this._player.restart();\n }\n\n finish(): void {\n this._player.finish();\n }\n\n destroy(): void {\n (this as {destroyed: boolean}).destroyed = true;\n this._player.destroy();\n }\n\n reset(): void {\n !this.queued && this._player.reset();\n }\n\n setPosition(p: any): void {\n if (!this.queued) {\n this._player.setPosition(p);\n }\n }\n\n getPosition(): number {\n return this.queued ? 0 : this._player.getPosition();\n }\n\n /** @internal */\n triggerCallback(phaseName: string): void {\n const p = this._player as any;\n if (p.triggerCallback) {\n p.triggerCallback(phaseName);\n }\n }\n}\n\nfunction deleteOrUnsetInMap(map: Map, key: T, value: V) {\n let currentValues = map.get(key);\n if (currentValues) {\n if (currentValues.length) {\n const index = currentValues.indexOf(value);\n currentValues.splice(index, 1);\n }\n if (currentValues.length == 0) {\n map.delete(key);\n }\n }\n return currentValues;\n}\n\nfunction normalizeTriggerValue(value: any): any {\n // we use `!= null` here because it's the most simple\n // way to test against a \"falsy\" value without mixing\n // in empty strings or a zero value. DO NOT OPTIMIZE.\n return value != null ? value : null;\n}\n\nfunction isElementNode(node: any) {\n return node && node['nodeType'] === 1;\n}\n\nfunction isTriggerEventValid(eventName: string): boolean {\n return eventName == 'start' || eventName == 'done';\n}\n\nfunction cloakElement(element: any, value?: string) {\n const oldValue = element.style.display;\n element.style.display = value != null ? value : 'none';\n return oldValue;\n}\n\nfunction cloakAndComputeStyles(\n valuesMap: Map, driver: AnimationDriver, elements: Set,\n elementPropsMap: Map>, defaultStyle: string): any[] {\n const cloakVals: string[] = [];\n elements.forEach(element => cloakVals.push(cloakElement(element)));\n\n const failedElements: any[] = [];\n\n elementPropsMap.forEach((props: Set, element: any) => {\n const styles: ɵStyleDataMap = new Map();\n props.forEach(prop => {\n const value = driver.computeStyle(element, prop, defaultStyle);\n styles.set(prop, value);\n\n // there is no easy way to detect this because a sub element could be removed\n // by a parent animation element being detached.\n if (!value || value.length == 0) {\n element[REMOVAL_FLAG] = NULL_REMOVED_QUERIED_STATE;\n failedElements.push(element);\n }\n });\n valuesMap.set(element, styles);\n });\n\n // we use a index variable here since Set.forEach(a, i) does not return\n // an index value for the closure (but instead just the value)\n let i = 0;\n elements.forEach(element => cloakElement(element, cloakVals[i++]));\n\n return failedElements;\n}\n\n/*\nSince the Angular renderer code will return a collection of inserted\nnodes in all areas of a DOM tree, it's up to this algorithm to figure\nout which nodes are roots for each animation @trigger.\n\nBy placing each inserted node into a Set and traversing upwards, it\nis possible to find the @trigger elements and well any direct *star\ninsertion nodes, if a @trigger root is found then the enter element\nis placed into the Map[@trigger] spot.\n */\nfunction buildRootMap(roots: any[], nodes: any[]): Map {\n const rootMap = new Map();\n roots.forEach(root => rootMap.set(root, []));\n\n if (nodes.length == 0) return rootMap;\n\n const NULL_NODE = 1;\n const nodeSet = new Set(nodes);\n const localRootMap = new Map();\n\n function getRoot(node: any): any {\n if (!node) return NULL_NODE;\n\n let root = localRootMap.get(node);\n if (root) return root;\n\n const parent = node.parentNode;\n if (rootMap.has(parent)) { // ngIf inside @trigger\n root = parent;\n } else if (nodeSet.has(parent)) { // ngIf inside ngIf\n root = NULL_NODE;\n } else { // recurse upwards\n root = getRoot(parent);\n }\n\n localRootMap.set(node, root);\n return root;\n }\n\n nodes.forEach(node => {\n const root = getRoot(node);\n if (root !== NULL_NODE) {\n rootMap.get(root)!.push(node);\n }\n });\n\n return rootMap;\n}\n\nfunction addClass(element: any, className: string) {\n element.classList?.add(className);\n}\n\nfunction removeClass(element: any, className: string) {\n element.classList?.remove(className);\n}\n\nfunction removeNodesAfterAnimationDone(\n engine: TransitionAnimationEngine, element: any, players: AnimationPlayer[]) {\n optimizeGroupPlayer(players).onDone(() => engine.processLeaveNode(element));\n}\n\nfunction flattenGroupPlayers(players: AnimationPlayer[]): AnimationPlayer[] {\n const finalPlayers: AnimationPlayer[] = [];\n _flattenGroupPlayersRecur(players, finalPlayers);\n return finalPlayers;\n}\n\nfunction _flattenGroupPlayersRecur(players: AnimationPlayer[], finalPlayers: AnimationPlayer[]) {\n for (let i = 0; i < players.length; i++) {\n const player = players[i];\n if (player instanceof AnimationGroupPlayer) {\n _flattenGroupPlayersRecur(player.players, finalPlayers);\n } else {\n finalPlayers.push(player);\n }\n }\n}\n\nfunction objEquals(a: {[key: string]: any}, b: {[key: string]: any}): boolean {\n const k1 = Object.keys(a);\n const k2 = Object.keys(b);\n if (k1.length != k2.length) return false;\n for (let i = 0; i < k1.length; i++) {\n const prop = k1[i];\n if (!b.hasOwnProperty(prop) || a[prop] !== b[prop]) return false;\n }\n return true;\n}\n\nfunction replacePostStylesAsPre(\n element: any, allPreStyleElements: Map>,\n allPostStyleElements: Map>): boolean {\n const postEntry = allPostStyleElements.get(element);\n if (!postEntry) return false;\n\n let preEntry = allPreStyleElements.get(element);\n if (preEntry) {\n postEntry.forEach(data => preEntry!.add(data));\n } else {\n allPreStyleElements.set(element, postEntry);\n }\n\n allPostStyleElements.delete(element);\n return true;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationMetadata, AnimationPlayer, AnimationTriggerMetadata} from '@angular/animations';\n\nimport {TriggerAst} from '../dsl/animation_ast';\nimport {buildAnimationAst} from '../dsl/animation_ast_builder';\nimport {AnimationTrigger, buildTrigger} from '../dsl/animation_trigger';\nimport {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';\nimport {triggerBuildFailed} from '../error_helpers';\nimport {warnTriggerBuild} from '../warning_helpers';\n\nimport {AnimationDriver} from './animation_driver';\nimport {parseTimelineCommand} from './shared';\nimport {TimelineAnimationEngine} from './timeline_animation_engine';\nimport {TransitionAnimationEngine} from './transition_animation_engine';\n\nexport class AnimationEngine {\n private _transitionEngine: TransitionAnimationEngine;\n private _timelineEngine: TimelineAnimationEngine;\n\n private _triggerCache: {[key: string]: AnimationTrigger} = {};\n\n // this method is designed to be overridden by the code that uses this engine\n public onRemovalComplete = (element: any, context: any) => {};\n\n constructor(\n private bodyNode: any, private _driver: AnimationDriver,\n private _normalizer: AnimationStyleNormalizer) {\n this._transitionEngine = new TransitionAnimationEngine(bodyNode, _driver, _normalizer);\n this._timelineEngine = new TimelineAnimationEngine(bodyNode, _driver, _normalizer);\n\n this._transitionEngine.onRemovalComplete = (element: any, context: any) =>\n this.onRemovalComplete(element, context);\n }\n\n registerTrigger(\n componentId: string, namespaceId: string, hostElement: any, name: string,\n metadata: AnimationTriggerMetadata): void {\n const cacheKey = componentId + '-' + name;\n let trigger = this._triggerCache[cacheKey];\n if (!trigger) {\n const errors: Error[] = [];\n const warnings: string[] = [];\n const ast = buildAnimationAst(\n this._driver, metadata as AnimationMetadata, errors, warnings) as TriggerAst;\n if (errors.length) {\n throw triggerBuildFailed(name, errors);\n }\n if (warnings.length) {\n warnTriggerBuild(name, warnings);\n }\n trigger = buildTrigger(name, ast, this._normalizer);\n this._triggerCache[cacheKey] = trigger;\n }\n this._transitionEngine.registerTrigger(namespaceId, name, trigger);\n }\n\n register(namespaceId: string, hostElement: any) {\n this._transitionEngine.register(namespaceId, hostElement);\n }\n\n destroy(namespaceId: string, context: any) {\n this._transitionEngine.destroy(namespaceId, context);\n }\n\n onInsert(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {\n this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore);\n }\n\n onRemove(namespaceId: string, element: any, context: any, isHostElement?: boolean): void {\n this._transitionEngine.removeNode(namespaceId, element, isHostElement || false, context);\n }\n\n disableAnimations(element: any, disable: boolean) {\n this._transitionEngine.markElementAsDisabled(element, disable);\n }\n\n process(namespaceId: string, element: any, property: string, value: any) {\n if (property.charAt(0) == '@') {\n const [id, action] = parseTimelineCommand(property);\n const args = value as any[];\n this._timelineEngine.command(id, element, action, args);\n } else {\n this._transitionEngine.trigger(namespaceId, element, property, value);\n }\n }\n\n listen(\n namespaceId: string, element: any, eventName: string, eventPhase: string,\n callback: (event: any) => any): () => any {\n // @@listen\n if (eventName.charAt(0) == '@') {\n const [id, action] = parseTimelineCommand(eventName);\n return this._timelineEngine.listen(id, element, action, callback);\n }\n return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);\n }\n\n flush(microtaskId: number = -1): void {\n this._transitionEngine.flush(microtaskId);\n }\n\n get players(): AnimationPlayer[] {\n return (this._transitionEngine.players as AnimationPlayer[])\n .concat(this._timelineEngine.players as AnimationPlayer[]);\n }\n\n whenRenderingDone(): Promise {\n return this._transitionEngine.whenRenderingDone();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ɵStyleDataMap} from '@angular/animations';\n\nimport {eraseStyles, setStyles} from '../util';\n\n/**\n * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are\n * detected.\n *\n * In CSS there exist properties that cannot be animated within a keyframe animation\n * (whether it be via CSS keyframes or web-animations) and the animation implementation\n * will ignore them. This function is designed to detect those special cased styles and\n * return a container that will be executed at the start and end of the animation.\n *\n * @returns an instance of `SpecialCasedStyles` if any special styles are detected otherwise `null`\n */\nexport function packageNonAnimatableStyles(\n element: any, styles: ɵStyleDataMap|Array<ɵStyleDataMap>): SpecialCasedStyles|null {\n let startStyles: ɵStyleDataMap|null = null;\n let endStyles: ɵStyleDataMap|null = null;\n if (Array.isArray(styles) && styles.length) {\n startStyles = filterNonAnimatableStyles(styles[0]);\n if (styles.length > 1) {\n endStyles = filterNonAnimatableStyles(styles[styles.length - 1]);\n }\n } else if (styles instanceof Map) {\n startStyles = filterNonAnimatableStyles(styles);\n }\n\n return (startStyles || endStyles) ? new SpecialCasedStyles(element, startStyles, endStyles) :\n null;\n}\n\n/**\n * Designed to be executed during a keyframe-based animation to apply any special-cased styles.\n *\n * When started (when the `start()` method is run) then the provided `startStyles`\n * will be applied. When finished (when the `finish()` method is called) the\n * `endStyles` will be applied as well any any starting styles. Finally when\n * `destroy()` is called then all styles will be removed.\n */\nexport class SpecialCasedStyles {\n static initialStylesByElement = (/* @__PURE__ */ new WeakMap());\n\n private _state = SpecialCasedStylesState.Pending;\n private _initialStyles!: ɵStyleDataMap;\n\n constructor(\n private _element: any, private _startStyles: ɵStyleDataMap|null,\n private _endStyles: ɵStyleDataMap|null) {\n let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element);\n if (!initialStyles) {\n SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = new Map());\n }\n this._initialStyles = initialStyles;\n }\n\n start() {\n if (this._state < SpecialCasedStylesState.Started) {\n if (this._startStyles) {\n setStyles(this._element, this._startStyles, this._initialStyles);\n }\n this._state = SpecialCasedStylesState.Started;\n }\n }\n\n finish() {\n this.start();\n if (this._state < SpecialCasedStylesState.Finished) {\n setStyles(this._element, this._initialStyles);\n if (this._endStyles) {\n setStyles(this._element, this._endStyles);\n this._endStyles = null;\n }\n this._state = SpecialCasedStylesState.Started;\n }\n }\n\n destroy() {\n this.finish();\n if (this._state < SpecialCasedStylesState.Destroyed) {\n SpecialCasedStyles.initialStylesByElement.delete(this._element);\n if (this._startStyles) {\n eraseStyles(this._element, this._startStyles);\n this._endStyles = null;\n }\n if (this._endStyles) {\n eraseStyles(this._element, this._endStyles);\n this._endStyles = null;\n }\n setStyles(this._element, this._initialStyles);\n this._state = SpecialCasedStylesState.Destroyed;\n }\n }\n}\n\n/**\n * An enum of states reflective of what the status of `SpecialCasedStyles` is.\n *\n * Depending on how `SpecialCasedStyles` is interacted with, the start and end\n * styles may not be applied in the same way. This enum ensures that if and when\n * the ending styles are applied then the starting styles are applied. It is\n * also used to reflect what the current status of the special cased styles are\n * which helps prevent the starting/ending styles not be applied twice. It is\n * also used to cleanup the styles once `SpecialCasedStyles` is destroyed.\n */\nconst enum SpecialCasedStylesState {\n Pending = 0,\n Started = 1,\n Finished = 2,\n Destroyed = 3,\n}\n\nfunction filterNonAnimatableStyles(styles: ɵStyleDataMap): ɵStyleDataMap|null {\n let result: ɵStyleDataMap|null = null;\n styles.forEach((val, prop) => {\n if (isNonAnimatableStyle(prop)) {\n result = result || new Map();\n result.set(prop, val);\n }\n });\n return result;\n}\n\nfunction isNonAnimatableStyle(prop: string) {\n return prop === 'display' || prop === 'position';\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationPlayer, ɵStyleDataMap} from '@angular/animations';\n\nimport {computeStyle} from '../../util';\nimport {SpecialCasedStyles} from '../special_cased_styles';\n\nimport {DOMAnimation} from './dom_animation';\n\nexport class WebAnimationsPlayer implements AnimationPlayer {\n private _onDoneFns: Function[] = [];\n private _onStartFns: Function[] = [];\n private _onDestroyFns: Function[] = [];\n private _duration: number;\n private _delay: number;\n private _initialized = false;\n private _finished = false;\n private _started = false;\n private _destroyed = false;\n private _finalKeyframe?: ɵStyleDataMap;\n\n // the following original fns are persistent copies of the _onStartFns and _onDoneFns\n // and are used to reset the fns to their original values upon reset()\n // (since the _onStartFns and _onDoneFns get deleted after they are called)\n private _originalOnDoneFns: Function[] = [];\n private _originalOnStartFns: Function[] = [];\n\n // using non-null assertion because it's re(set) by init();\n public readonly domPlayer!: DOMAnimation;\n public time = 0;\n\n public parentPlayer: AnimationPlayer|null = null;\n public currentSnapshot: ɵStyleDataMap = new Map();\n\n constructor(\n public element: any, public keyframes: Array<ɵStyleDataMap>,\n public options: {[key: string]: string|number},\n private _specialStyles?: SpecialCasedStyles|null) {\n this._duration = options['duration'];\n this._delay = options['delay'] || 0;\n this.time = this._duration + this._delay;\n }\n\n private _onFinish() {\n if (!this._finished) {\n this._finished = true;\n this._onDoneFns.forEach(fn => fn());\n this._onDoneFns = [];\n }\n }\n\n init(): void {\n this._buildPlayer();\n this._preparePlayerBeforeStart();\n }\n\n private _buildPlayer(): void {\n if (this._initialized) return;\n this._initialized = true;\n\n const keyframes = this.keyframes;\n // @ts-expect-error overwriting a readonly property\n this.domPlayer = this._triggerWebAnimation(this.element, keyframes, this.options);\n this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map();\n this.domPlayer.addEventListener('finish', () => this._onFinish());\n }\n\n private _preparePlayerBeforeStart() {\n // this is required so that the player doesn't start to animate right away\n if (this._delay) {\n this._resetDomPlayerState();\n } else {\n this.domPlayer.pause();\n }\n }\n\n private _convertKeyframesToObject(keyframes: Array<ɵStyleDataMap>): any[] {\n const kfs: any[] = [];\n keyframes.forEach(frame => {\n kfs.push(Object.fromEntries(frame));\n });\n return kfs;\n }\n\n /** @internal */\n _triggerWebAnimation(element: any, keyframes: Array<ɵStyleDataMap>, options: any): DOMAnimation {\n // jscompiler doesn't seem to know animate is a native property because it's not fully\n // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929]\n return element['animate'](this._convertKeyframesToObject(keyframes), options) as DOMAnimation;\n }\n\n onStart(fn: () => void): void {\n this._originalOnStartFns.push(fn);\n this._onStartFns.push(fn);\n }\n\n onDone(fn: () => void): void {\n this._originalOnDoneFns.push(fn);\n this._onDoneFns.push(fn);\n }\n\n onDestroy(fn: () => void): void {\n this._onDestroyFns.push(fn);\n }\n\n play(): void {\n this._buildPlayer();\n if (!this.hasStarted()) {\n this._onStartFns.forEach(fn => fn());\n this._onStartFns = [];\n this._started = true;\n if (this._specialStyles) {\n this._specialStyles.start();\n }\n }\n this.domPlayer.play();\n }\n\n pause(): void {\n this.init();\n this.domPlayer.pause();\n }\n\n finish(): void {\n this.init();\n if (this._specialStyles) {\n this._specialStyles.finish();\n }\n this._onFinish();\n this.domPlayer.finish();\n }\n\n reset(): void {\n this._resetDomPlayerState();\n this._destroyed = false;\n this._finished = false;\n this._started = false;\n this._onStartFns = this._originalOnStartFns;\n this._onDoneFns = this._originalOnDoneFns;\n }\n\n private _resetDomPlayerState() {\n if (this.domPlayer) {\n this.domPlayer.cancel();\n }\n }\n\n restart(): void {\n this.reset();\n this.play();\n }\n\n hasStarted(): boolean {\n return this._started;\n }\n\n destroy(): void {\n if (!this._destroyed) {\n this._destroyed = true;\n this._resetDomPlayerState();\n this._onFinish();\n if (this._specialStyles) {\n this._specialStyles.destroy();\n }\n this._onDestroyFns.forEach(fn => fn());\n this._onDestroyFns = [];\n }\n }\n\n setPosition(p: number): void {\n if (this.domPlayer === undefined) {\n this.init();\n }\n this.domPlayer.currentTime = p * this.time;\n }\n\n getPosition(): number {\n return this.domPlayer.currentTime / this.time;\n }\n\n get totalTime(): number {\n return this._delay + this._duration;\n }\n\n beforeDestroy() {\n const styles: ɵStyleDataMap = new Map();\n if (this.hasStarted()) {\n // note: this code is invoked only when the `play` function was called prior to this\n // (thus `hasStarted` returns true), this implies that the code that initializes\n // `_finalKeyframe` has also been executed and the non-null assertion can be safely used here\n const finalKeyframe = this._finalKeyframe!;\n finalKeyframe.forEach((val, prop) => {\n if (prop !== 'offset') {\n styles.set(prop, this._finished ? val : computeStyle(this.element, prop));\n }\n });\n }\n\n this.currentSnapshot = styles;\n }\n\n /** @internal */\n triggerCallback(phaseName: string): void {\n const methods = phaseName === 'start' ? this._onStartFns : this._onDoneFns;\n methods.forEach(fn => fn());\n methods.length = 0;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationPlayer, ɵStyleDataMap} from '@angular/animations';\n\nimport {allowPreviousPlayerStylesMerge, balancePreviousStylesIntoKeyframes, camelCaseToDashCase, copyStyles, normalizeKeyframes} from '../../util';\nimport {AnimationDriver} from '../animation_driver';\nimport {containsElement, getParentElement, invokeQuery, validateStyleProperty, validateWebAnimatableStyleProperty} from '../shared';\nimport {packageNonAnimatableStyles} from '../special_cased_styles';\n\nimport {WebAnimationsPlayer} from './web_animations_player';\n\nexport class WebAnimationsDriver implements AnimationDriver {\n validateStyleProperty(prop: string): boolean {\n // Perform actual validation in dev mode only, in prod mode this check is a noop.\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n return validateStyleProperty(prop);\n }\n return true;\n }\n\n validateAnimatableStyleProperty(prop: string): boolean {\n // Perform actual validation in dev mode only, in prod mode this check is a noop.\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n const cssProp = camelCaseToDashCase(prop);\n return validateWebAnimatableStyleProperty(cssProp);\n }\n return true;\n }\n\n matchesElement(_element: any, _selector: string): boolean {\n // This method is deprecated and no longer in use so we return false.\n return false;\n }\n\n containsElement(elm1: any, elm2: any): boolean {\n return containsElement(elm1, elm2);\n }\n\n getParentElement(element: unknown): unknown {\n return getParentElement(element);\n }\n\n query(element: any, selector: string, multi: boolean): any[] {\n return invokeQuery(element, selector, multi);\n }\n\n computeStyle(element: any, prop: string, defaultValue?: string): string {\n return (window.getComputedStyle(element) as any)[prop] as string;\n }\n\n animate(\n element: any, keyframes: Array>, duration: number, delay: number,\n easing: string, previousPlayers: AnimationPlayer[] = []): AnimationPlayer {\n const fill = delay == 0 ? 'both' : 'forwards';\n const playerOptions: {[key: string]: string|number} = {duration, delay, fill};\n // we check for this to avoid having a null|undefined value be present\n // for the easing (which results in an error for certain browsers #9752)\n if (easing) {\n playerOptions['easing'] = easing;\n }\n\n const previousStyles: ɵStyleDataMap = new Map();\n const previousWebAnimationPlayers = previousPlayers.filter(\n player => player instanceof WebAnimationsPlayer);\n if (allowPreviousPlayerStylesMerge(duration, delay)) {\n previousWebAnimationPlayers.forEach(player => {\n player.currentSnapshot.forEach((val, prop) => previousStyles.set(prop, val));\n });\n }\n\n let _keyframes = normalizeKeyframes(keyframes).map(styles => copyStyles(styles));\n _keyframes = balancePreviousStylesIntoKeyframes(element, _keyframes, previousStyles);\n const specialStyles = packageNonAnimatableStyles(element, _keyframes);\n return new WebAnimationsPlayer(element, _keyframes, playerOptions, specialStyles);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationBuilder, AnimationFactory, AnimationMetadata, AnimationOptions, AnimationPlayer, sequence} from '@angular/animations';\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, RendererFactory2, RendererType2, ViewEncapsulation} from '@angular/core';\n\nimport {AnimationRenderer} from './animation_renderer';\n\n@Injectable()\nexport class BrowserAnimationBuilder extends AnimationBuilder {\n private _nextAnimationId = 0;\n private _renderer: AnimationRenderer;\n\n constructor(rootRenderer: RendererFactory2, @Inject(DOCUMENT) doc: any) {\n super();\n const typeData =\n {id: '0', encapsulation: ViewEncapsulation.None, styles: [], data: {animation: []}} as\n RendererType2;\n this._renderer = rootRenderer.createRenderer(doc.body, typeData) as AnimationRenderer;\n }\n\n override build(animation: AnimationMetadata|AnimationMetadata[]): AnimationFactory {\n const id = this._nextAnimationId.toString();\n this._nextAnimationId++;\n const entry = Array.isArray(animation) ? sequence(animation) : animation;\n issueAnimationCommand(this._renderer, null, id, 'register', [entry]);\n return new BrowserAnimationFactory(id, this._renderer);\n }\n}\n\nexport class BrowserAnimationFactory extends AnimationFactory {\n constructor(private _id: string, private _renderer: AnimationRenderer) {\n super();\n }\n\n override create(element: any, options?: AnimationOptions): AnimationPlayer {\n return new RendererAnimationPlayer(this._id, element, options || {}, this._renderer);\n }\n}\n\nexport class RendererAnimationPlayer implements AnimationPlayer {\n public parentPlayer: AnimationPlayer|null = null;\n private _started = false;\n\n constructor(\n public id: string, public element: any, options: AnimationOptions,\n private _renderer: AnimationRenderer) {\n this._command('create', options);\n }\n\n private _listen(eventName: string, callback: (event: any) => any): () => void {\n return this._renderer.listen(this.element, `@@${this.id}:${eventName}`, callback);\n }\n\n private _command(command: string, ...args: any[]) {\n return issueAnimationCommand(this._renderer, this.element, this.id, command, args);\n }\n\n onDone(fn: () => void): void {\n this._listen('done', fn);\n }\n\n onStart(fn: () => void): void {\n this._listen('start', fn);\n }\n\n onDestroy(fn: () => void): void {\n this._listen('destroy', fn);\n }\n\n init(): void {\n this._command('init');\n }\n\n hasStarted(): boolean {\n return this._started;\n }\n\n play(): void {\n this._command('play');\n this._started = true;\n }\n\n pause(): void {\n this._command('pause');\n }\n\n restart(): void {\n this._command('restart');\n }\n\n finish(): void {\n this._command('finish');\n }\n\n destroy(): void {\n this._command('destroy');\n }\n\n reset(): void {\n this._command('reset');\n this._started = false;\n }\n\n setPosition(p: number): void {\n this._command('setPosition', p);\n }\n\n getPosition(): number {\n return this._renderer.engine.players[+this.id]?.getPosition() ?? 0;\n }\n\n public totalTime = 0;\n}\n\nfunction issueAnimationCommand(\n renderer: AnimationRenderer, element: any, id: string, command: string, args: any[]): any {\n return renderer.setProperty(element, `@@${id}:${command}`, args);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationTriggerMetadata} from '@angular/animations';\nimport {ɵAnimationEngine as AnimationEngine} from '@angular/animations/browser';\nimport {Injectable, NgZone, Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '@angular/core';\n\nconst ANIMATION_PREFIX = '@';\nconst DISABLE_ANIMATIONS_FLAG = '@.disabled';\n\n// Define a recursive type to allow for nested arrays of `AnimationTriggerMetadata`. Note that an\n// interface declaration is used as TypeScript prior to 3.7 does not support recursive type\n// references, see https://github.com/microsoft/TypeScript/pull/33050 for details.\ntype NestedAnimationTriggerMetadata = AnimationTriggerMetadata|RecursiveAnimationTriggerMetadata;\ninterface RecursiveAnimationTriggerMetadata extends Array {}\n\n@Injectable()\nexport class AnimationRendererFactory implements RendererFactory2 {\n private _currentId: number = 0;\n private _microtaskId: number = 1;\n private _animationCallbacksBuffer: [(e: any) => any, any][] = [];\n private _rendererCache = new Map();\n private _cdRecurDepth = 0;\n private promise: Promise = Promise.resolve(0);\n\n constructor(\n private delegate: RendererFactory2, private engine: AnimationEngine, private _zone: NgZone) {\n engine.onRemovalComplete = (element: any, delegate: Renderer2) => {\n // Note: if a component element has a leave animation, and a host leave animation,\n // the view engine will call `removeChild` for the parent\n // component renderer as well as for the child component renderer.\n // Therefore, we need to check if we already removed the element.\n const parentNode = delegate?.parentNode(element);\n if (parentNode) {\n delegate.removeChild(parentNode, element);\n }\n };\n }\n\n createRenderer(hostElement: any, type: RendererType2): Renderer2 {\n const EMPTY_NAMESPACE_ID = '';\n\n // cache the delegates to find out which cached delegate can\n // be used by which cached renderer\n const delegate = this.delegate.createRenderer(hostElement, type);\n if (!hostElement || !type || !type.data || !type.data['animation']) {\n let renderer: BaseAnimationRenderer|undefined = this._rendererCache.get(delegate);\n if (!renderer) {\n // Ensure that the renderer is removed from the cache on destroy\n // since it may contain references to detached DOM nodes.\n const onRendererDestroy = () => this._rendererCache.delete(delegate);\n renderer =\n new BaseAnimationRenderer(EMPTY_NAMESPACE_ID, delegate, this.engine, onRendererDestroy);\n // only cache this result when the base renderer is used\n this._rendererCache.set(delegate, renderer);\n }\n return renderer;\n }\n\n const componentId = type.id;\n const namespaceId = type.id + '-' + this._currentId;\n this._currentId++;\n\n this.engine.register(namespaceId, hostElement);\n\n const registerTrigger = (trigger: NestedAnimationTriggerMetadata) => {\n if (Array.isArray(trigger)) {\n trigger.forEach(registerTrigger);\n } else {\n this.engine.registerTrigger(componentId, namespaceId, hostElement, trigger.name, trigger);\n }\n };\n const animationTriggers = type.data['animation'] as NestedAnimationTriggerMetadata[];\n animationTriggers.forEach(registerTrigger);\n\n return new AnimationRenderer(this, namespaceId, delegate, this.engine);\n }\n\n begin() {\n this._cdRecurDepth++;\n if (this.delegate.begin) {\n this.delegate.begin();\n }\n }\n\n private _scheduleCountTask() {\n // always use promise to schedule microtask instead of use Zone\n this.promise.then(() => {\n this._microtaskId++;\n });\n }\n\n /** @internal */\n scheduleListenerCallback(count: number, fn: (e: any) => any, data: any) {\n if (count >= 0 && count < this._microtaskId) {\n this._zone.run(() => fn(data));\n return;\n }\n\n if (this._animationCallbacksBuffer.length == 0) {\n Promise.resolve(null).then(() => {\n this._zone.run(() => {\n this._animationCallbacksBuffer.forEach(tuple => {\n const [fn, data] = tuple;\n fn(data);\n });\n this._animationCallbacksBuffer = [];\n });\n });\n }\n\n this._animationCallbacksBuffer.push([fn, data]);\n }\n\n end() {\n this._cdRecurDepth--;\n\n // this is to prevent animations from running twice when an inner\n // component does CD when a parent component instead has inserted it\n if (this._cdRecurDepth == 0) {\n this._zone.runOutsideAngular(() => {\n this._scheduleCountTask();\n this.engine.flush(this._microtaskId);\n });\n }\n if (this.delegate.end) {\n this.delegate.end();\n }\n }\n\n whenRenderingDone(): Promise {\n return this.engine.whenRenderingDone();\n }\n}\n\nexport class BaseAnimationRenderer implements Renderer2 {\n constructor(\n protected namespaceId: string, public delegate: Renderer2, public engine: AnimationEngine,\n private _onDestroy?: () => void) {\n this.destroyNode = this.delegate.destroyNode ? (n) => delegate.destroyNode!(n) : null;\n }\n\n get data() {\n return this.delegate.data;\n }\n\n destroyNode: ((n: any) => void)|null;\n\n destroy(): void {\n this.engine.destroy(this.namespaceId, this.delegate);\n this.delegate.destroy();\n this._onDestroy?.();\n }\n\n createElement(name: string, namespace?: string|null|undefined) {\n return this.delegate.createElement(name, namespace);\n }\n\n createComment(value: string) {\n return this.delegate.createComment(value);\n }\n\n createText(value: string) {\n return this.delegate.createText(value);\n }\n\n appendChild(parent: any, newChild: any): void {\n this.delegate.appendChild(parent, newChild);\n this.engine.onInsert(this.namespaceId, newChild, parent, false);\n }\n\n insertBefore(parent: any, newChild: any, refChild: any, isMove: boolean = true): void {\n this.delegate.insertBefore(parent, newChild, refChild);\n // If `isMove` true than we should animate this insert.\n this.engine.onInsert(this.namespaceId, newChild, parent, isMove);\n }\n\n removeChild(parent: any, oldChild: any, isHostElement: boolean): void {\n this.engine.onRemove(this.namespaceId, oldChild, this.delegate, isHostElement);\n }\n\n selectRootElement(selectorOrNode: any, preserveContent?: boolean) {\n return this.delegate.selectRootElement(selectorOrNode, preserveContent);\n }\n\n parentNode(node: any) {\n return this.delegate.parentNode(node);\n }\n\n nextSibling(node: any) {\n return this.delegate.nextSibling(node);\n }\n\n setAttribute(el: any, name: string, value: string, namespace?: string|null|undefined): void {\n this.delegate.setAttribute(el, name, value, namespace);\n }\n\n removeAttribute(el: any, name: string, namespace?: string|null|undefined): void {\n this.delegate.removeAttribute(el, name, namespace);\n }\n\n addClass(el: any, name: string): void {\n this.delegate.addClass(el, name);\n }\n\n removeClass(el: any, name: string): void {\n this.delegate.removeClass(el, name);\n }\n\n setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2|undefined): void {\n this.delegate.setStyle(el, style, value, flags);\n }\n\n removeStyle(el: any, style: string, flags?: RendererStyleFlags2|undefined): void {\n this.delegate.removeStyle(el, style, flags);\n }\n\n setProperty(el: any, name: string, value: any): void {\n if (name.charAt(0) == ANIMATION_PREFIX && name == DISABLE_ANIMATIONS_FLAG) {\n this.disableAnimations(el, !!value);\n } else {\n this.delegate.setProperty(el, name, value);\n }\n }\n\n setValue(node: any, value: string): void {\n this.delegate.setValue(node, value);\n }\n\n listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void {\n return this.delegate.listen(target, eventName, callback);\n }\n\n protected disableAnimations(element: any, value: boolean) {\n this.engine.disableAnimations(element, value);\n }\n}\n\nexport class AnimationRenderer extends BaseAnimationRenderer implements Renderer2 {\n constructor(\n public factory: AnimationRendererFactory, namespaceId: string, delegate: Renderer2,\n engine: AnimationEngine, onDestroy?: () => void) {\n super(namespaceId, delegate, engine, onDestroy);\n this.namespaceId = namespaceId;\n }\n\n override setProperty(el: any, name: string, value: any): void {\n if (name.charAt(0) == ANIMATION_PREFIX) {\n if (name.charAt(1) == '.' && name == DISABLE_ANIMATIONS_FLAG) {\n value = value === undefined ? true : !!value;\n this.disableAnimations(el, value as boolean);\n } else {\n this.engine.process(this.namespaceId, el, name.slice(1), value);\n }\n } else {\n this.delegate.setProperty(el, name, value);\n }\n }\n\n override listen(\n target: 'window'|'document'|'body'|any, eventName: string,\n callback: (event: any) => any): () => void {\n if (eventName.charAt(0) == ANIMATION_PREFIX) {\n const element = resolveElementFromTarget(target);\n let name = eventName.slice(1);\n let phase = '';\n // @listener.phase is for trigger animation callbacks\n // @@listener is for animation builder callbacks\n if (name.charAt(0) != ANIMATION_PREFIX) {\n [name, phase] = parseTriggerCallbackName(name);\n }\n return this.engine.listen(this.namespaceId, element, name, phase, event => {\n const countId = (event as any)['_data'] || -1;\n this.factory.scheduleListenerCallback(countId, callback, event);\n });\n }\n return this.delegate.listen(target, eventName, callback);\n }\n}\n\nfunction resolveElementFromTarget(target: 'window'|'document'|'body'|any): any {\n switch (target) {\n case 'body':\n return document.body;\n case 'document':\n return document;\n case 'window':\n return window;\n default:\n return target;\n }\n}\n\nfunction parseTriggerCallbackName(triggerName: string) {\n const dotIndex = triggerName.indexOf('.');\n const trigger = triggerName.substring(0, dotIndex);\n const phase = triggerName.slice(dotIndex + 1);\n return [trigger, phase];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AnimationBuilder} from '@angular/animations';\nimport {AnimationDriver, ɵAnimationEngine as AnimationEngine, ɵAnimationStyleNormalizer as AnimationStyleNormalizer, ɵNoopAnimationDriver as NoopAnimationDriver, ɵWebAnimationsDriver as WebAnimationsDriver, ɵWebAnimationsStyleNormalizer as WebAnimationsStyleNormalizer} from '@angular/animations/browser';\nimport {DOCUMENT} from '@angular/common';\nimport {ANIMATION_MODULE_TYPE, ApplicationRef, Inject, Injectable, NgZone, OnDestroy, Provider, RendererFactory2} from '@angular/core';\nimport {ɵDomRendererFactory2 as DomRendererFactory2} from '@angular/platform-browser';\n\nimport {BrowserAnimationBuilder} from './animation_builder';\nimport {AnimationRendererFactory} from './animation_renderer';\n\n@Injectable()\nexport class InjectableAnimationEngine extends AnimationEngine implements OnDestroy {\n // The `ApplicationRef` is injected here explicitly to force the dependency ordering.\n // Since the `ApplicationRef` should be created earlier before the `AnimationEngine`, they\n // both have `ngOnDestroy` hooks and `flush()` must be called after all views are destroyed.\n constructor(\n @Inject(DOCUMENT) doc: any, driver: AnimationDriver, normalizer: AnimationStyleNormalizer,\n appRef: ApplicationRef) {\n super(doc.body, driver, normalizer);\n }\n\n ngOnDestroy(): void {\n this.flush();\n }\n}\n\nexport function instantiateDefaultStyleNormalizer() {\n return new WebAnimationsStyleNormalizer();\n}\n\nexport function instantiateRendererFactory(\n renderer: DomRendererFactory2, engine: AnimationEngine, zone: NgZone) {\n return new AnimationRendererFactory(renderer, engine, zone);\n}\n\nconst SHARED_ANIMATION_PROVIDERS: Provider[] = [\n {provide: AnimationBuilder, useClass: BrowserAnimationBuilder},\n {provide: AnimationStyleNormalizer, useFactory: instantiateDefaultStyleNormalizer},\n {provide: AnimationEngine, useClass: InjectableAnimationEngine}, {\n provide: RendererFactory2,\n useFactory: instantiateRendererFactory,\n deps: [DomRendererFactory2, AnimationEngine, NgZone]\n }\n];\n\n/**\n * Separate providers from the actual module so that we can do a local modification in Google3 to\n * include them in the BrowserModule.\n */\nexport const BROWSER_ANIMATIONS_PROVIDERS: Provider[] = [\n {provide: AnimationDriver, useFactory: () => new WebAnimationsDriver()},\n {provide: ANIMATION_MODULE_TYPE, useValue: 'BrowserAnimations'}, ...SHARED_ANIMATION_PROVIDERS\n];\n\n/**\n * Separate providers from the actual module so that we can do a local modification in Google3 to\n * include them in the BrowserTestingModule.\n */\nexport const BROWSER_NOOP_ANIMATIONS_PROVIDERS: Provider[] = [\n {provide: AnimationDriver, useClass: NoopAnimationDriver},\n {provide: ANIMATION_MODULE_TYPE, useValue: 'NoopAnimations'}, ...SHARED_ANIMATION_PROVIDERS\n];\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ModuleWithProviders, NgModule, Provider} from '@angular/core';\nimport {BrowserModule} from '@angular/platform-browser';\n\nimport {BROWSER_ANIMATIONS_PROVIDERS, BROWSER_NOOP_ANIMATIONS_PROVIDERS} from './providers';\n\n/**\n * Object used to configure the behavior of {@link BrowserAnimationsModule}\n * @publicApi\n */\nexport interface BrowserAnimationsModuleConfig {\n /**\n * Whether animations should be disabled. Passing this is identical to providing the\n * `NoopAnimationsModule`, but it can be controlled based on a runtime value.\n */\n disableAnimations?: boolean;\n}\n\n/**\n * Exports `BrowserModule` with additional [dependency-injection providers](guide/glossary#provider)\n * for use with animations. See [Animations](guide/animations).\n * @publicApi\n */\n@NgModule({\n exports: [BrowserModule],\n providers: BROWSER_ANIMATIONS_PROVIDERS,\n})\nexport class BrowserAnimationsModule {\n /**\n * Configures the module based on the specified object.\n *\n * @param config Object used to configure the behavior of the `BrowserAnimationsModule`.\n * @see `BrowserAnimationsModuleConfig`\n *\n * @usageNotes\n * When registering the `BrowserAnimationsModule`, you can use the `withConfig`\n * function as follows:\n * ```\n * @NgModule({\n * imports: [BrowserAnimationsModule.withConfig(config)]\n * })\n * class MyNgModule {}\n * ```\n */\n static withConfig(config: BrowserAnimationsModuleConfig):\n ModuleWithProviders {\n return {\n ngModule: BrowserAnimationsModule,\n providers: config.disableAnimations ? BROWSER_NOOP_ANIMATIONS_PROVIDERS :\n BROWSER_ANIMATIONS_PROVIDERS\n };\n }\n}\n\n/**\n * Returns the set of [dependency-injection providers](guide/glossary#provider)\n * to enable animations in an application. See [animations guide](guide/animations)\n * to learn more about animations in Angular.\n *\n * @usageNotes\n *\n * The function is useful when you want to enable animations in an application\n * bootstrapped using the `bootstrapApplication` function. In this scenario there\n * is no need to import the `BrowserAnimationsModule` NgModule at all, just add\n * providers returned by this function to the `providers` list as show below.\n *\n * ```typescript\n * bootstrapApplication(RootComponent, {\n * providers: [\n * provideAnimations()\n * ]\n * });\n * ```\n *\n * @publicApi\n */\nexport function provideAnimations(): Provider[] {\n // Return a copy to prevent changes to the original array in case any in-place\n // alterations are performed to the `provideAnimations` call results in app code.\n return [...BROWSER_ANIMATIONS_PROVIDERS];\n}\n\n/**\n * A null player that must be imported to allow disabling of animations.\n * @publicApi\n */\n@NgModule({\n exports: [BrowserModule],\n providers: BROWSER_NOOP_ANIMATIONS_PROVIDERS,\n})\nexport class NoopAnimationsModule {\n}\n\n/**\n * Returns the set of [dependency-injection providers](guide/glossary#provider)\n * to disable animations in an application. See [animations guide](guide/animations)\n * to learn more about animations in Angular.\n *\n * @usageNotes\n *\n * The function is useful when you want to bootstrap an application using\n * the `bootstrapApplication` function, but you need to disable animations\n * (for example, when running tests).\n *\n * ```typescript\n * bootstrapApplication(RootComponent, {\n * providers: [\n * provideNoopAnimations()\n * ]\n * });\n * ```\n *\n * @publicApi\n */\nexport function provideNoopAnimations(): Provider[] {\n // Return a copy to prevent changes to the original array in case any in-place\n // alterations are performed to the `provideNoopAnimations` call results in app code.\n return [...BROWSER_NOOP_ANIMATIONS_PROVIDERS];\n}\n","class TranslateHttpLoader {\r\n constructor(http, prefix = \"/assets/i18n/\", suffix = \".json\") {\r\n this.http = http;\r\n this.prefix = prefix;\r\n this.suffix = suffix;\r\n }\r\n /**\r\n * Gets the translations from the server\r\n */\r\n getTranslation(lang) {\r\n return this.http.get(`${this.prefix}${lang}${this.suffix}`);\r\n }\r\n}\n\n/**\r\n * Generated bundle index. Do not edit.\r\n */\n\nexport { TranslateHttpLoader };\n","import { Injectable } from '@angular/core';\r\nimport { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';\r\nimport { GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { PageService } from '@portal-app/services/shared/page/page.service';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { PageTypeEnum } from '../enums/page-type.enum';\r\nimport { AppInitService } from '../services/shared/app-init.service';\r\nimport { NavbarService } from '../services/shared/navbar.service';\r\nimport { SeoService } from '../services/shared/seo.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class RouteHasPage implements CanActivate {\r\n constructor(\r\n private pageService: PageService,\r\n private seoService: SeoService,\r\n private userService: UserService,\r\n private navbarService: NavbarService,\r\n private router: Router,\r\n private appInitService: AppInitService,\r\n private googleTagManagerService: GoogleTagManagerService\r\n ) {}\r\n\r\n async canActivate(route: ActivatedRouteSnapshot) {\r\n const pageSettings = await firstValueFrom(this.pageService.pageSettings$);\r\n\r\n if (pageSettings) {\r\n const metaData = await firstValueFrom(this.seoService.getMetaData(pageSettings.pageId));\r\n this.seoService.setMetaData(metaData);\r\n\r\n if (\r\n this.appInitService.shouldUseTagManager &&\r\n this.appInitService.siteConfiguration.GoogleTagManagerId &&\r\n pageSettings.pageUrl\r\n ) {\r\n this.googleTagManagerService.setId(this.appInitService.siteConfiguration.GoogleTagManagerId);\r\n\r\n const gtmTag = {\r\n event: GTMEvent.Page,\r\n pageName: decodeURI(pageSettings.pageUrl),\r\n visitorType: this.userService.userType,\r\n };\r\n this.googleTagManagerService.pushTag(gtmTag);\r\n }\r\n\r\n return true;\r\n } else {\r\n // this is to redirect old urls to new urls\r\n if (route.data.pageType === PageTypeEnum.Error503) {\r\n return true;\r\n } else if (\r\n route.data.pageType === PageTypeEnum.BookLibrary ||\r\n route.data.pageType === PageTypeEnum.CourseLibrary ||\r\n route.data.pageType === PageTypeEnum.PsAssignmentLibrary ||\r\n route.data.pageType === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n const libraryUrl = await firstValueFrom(this.navbarService.libraryUrl$);\r\n this.router.navigate([libraryUrl], { queryParams: route.queryParams });\r\n } else if (route.data.pageType === PageTypeEnum.CourseStudentAnswers) {\r\n if (window.location.pathname.replace('/', '') === PageTypeEnum.CourseStudentAnswers) {\r\n const courseStudentAnswersUrl = await firstValueFrom(this.navbarService.courseStudentAnswersUrl$);\r\n this.router.navigate([courseStudentAnswersUrl], { queryParams: route.queryParams });\r\n } else {\r\n return true;\r\n }\r\n } else if (\r\n route.data.pageType === PageTypeEnum.CourseFavorites ||\r\n route.data.pageType === PageTypeEnum.BookFavorites\r\n ) {\r\n const favoritesUrl = await firstValueFrom(this.navbarService.favoritesUrl$);\r\n this.router.navigate([favoritesUrl], { queryParams: route.queryParams });\r\n } else if (route.data.pageType === PageTypeEnum.CourseAnnualPlan) {\r\n const courseAnnualPlanUrl = await firstValueFrom(this.navbarService.courseAnnualPlanUrl$);\r\n this.router.navigate([courseAnnualPlanUrl], { queryParams: route.queryParams });\r\n } else {\r\n this.pageService.showError(window.location.pathname, 404);\r\n }\r\n return false;\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';\r\nimport { GoogleTagManagerService, UserService } from '@lru/felib';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\nimport { GTMTag } from '@portal-app/interfaces/project/gtm-tag.interface';\r\nimport { AppInitService } from '../services/shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SetGTMForRoute implements CanActivate {\r\n constructor(\r\n private userService: UserService,\r\n private appInitService: AppInitService,\r\n private googleTagManagerService: GoogleTagManagerService\r\n ) {}\r\n\r\n canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {\r\n if (this.appInitService.shouldUseTagManager && this.appInitService.siteConfiguration.GoogleTagManagerId) {\r\n this.googleTagManagerService.setId(this.appInitService.siteConfiguration.GoogleTagManagerId);\r\n const gtmTag: GTMTag = {\r\n event: GTMEvent.Page,\r\n pageName: decodeURI(state.url),\r\n visitorType: this.userService.userType,\r\n };\r\n this.googleTagManagerService.pushTag(gtmTag);\r\n }\r\n return true;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';\r\nimport { HeroMenuItem } from '@portal-app/modules/shared/hero/components/hero/interfaces/hero-menu-item.interface';\r\nimport { PageService } from '@portal-app/services/shared/page/page.service';\r\nimport { AppInitService } from '../services/shared/app-init.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SetPageForRoute implements CanActivate {\r\n constructor(private pageService: PageService, private appInitService: AppInitService, private router: Router) {}\r\n\r\n canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {\r\n if (this.appInitService.siteConfiguration) {\r\n const url = state.url.split('/');\r\n let id = url[url.length - 1].split('?')[0];\r\n const localStorageValue = localStorage.getItem('frontpageLevel');\r\n\r\n const frontpageLevel = localStorageValue ? (JSON.parse(localStorageValue) as HeroMenuItem) : '';\r\n\r\n if (this.appInitService.isFagportal && frontpageLevel && !id && frontpageLevel.Url !== id) {\r\n this.router.navigate([frontpageLevel.Url]);\r\n return false;\r\n }\r\n\r\n if (!id) {\r\n if (this.appInitService.siteConfiguration.FrontpageId) {\r\n id = this.appInitService.siteConfiguration.FrontpageId.toString();\r\n } else {\r\n this.pageService.showError(id, 404);\r\n }\r\n }\r\n\r\n this.pageService.setPageSettings({\r\n pageId: id,\r\n pageUrl: id,\r\n fromError: false,\r\n });\r\n }\r\n return true;\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { RouterModule, Routes } from '@angular/router';\r\nimport { PageTypeEnum } from './enums/page-type.enum';\r\nimport { RouteHasPage } from './guards/route-has-page.guard';\r\nimport { SetGTMForRoute } from './guards/set-gtm-for-route.guard';\r\nimport { SetPageForRoute } from './guards/set-page-for-route.guard';\r\nconst routes: Routes = [\r\n // ps related\r\n {\r\n path: PageTypeEnum.PsArticle,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-article/ps-article.module').then((module) => module.PsArticleModule),\r\n data: { pageType: PageTypeEnum.PsArticle },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.PsAssignment,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-assignment/ps-assignment.module').then(\r\n (module) => module.PsAssignmentModule\r\n ),\r\n data: { pageType: PageTypeEnum.PsAssignment },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.PrintbarAssignment,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/printbar-assignment/printbar-assignment.module').then(\r\n (module) => module.PrintbarAssignmentModule\r\n ),\r\n data: { pageType: PageTypeEnum.PrintbarAssignment },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.PsArticleLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-library/ps-library.module').then((module) => module.PsLibraryModule),\r\n data: { pageType: PageTypeEnum.PsArticleLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.PsAssignmentLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-library/ps-library.module').then((module) => module.PsLibraryModule),\r\n data: { pageType: PageTypeEnum.PsAssignmentLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.PsThemeLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-library/ps-library.module').then((module) => module.PsLibraryModule),\r\n data: { pageType: PageTypeEnum.PsThemeLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n // printbar related\r\n {\r\n path: PageTypeEnum.PrintbarAssignmentLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/printbar-library/printbar-library.module').then(\r\n (module) => module.PrintbarLibraryModule\r\n ),\r\n data: { pageType: PageTypeEnum.PrintbarAssignmentLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.PsThemeLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/ps-library/ps-library.module').then((module) => module.PsLibraryModule),\r\n data: { pageType: PageTypeEnum.PsThemeLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n // book related\r\n {\r\n path: PageTypeEnum.BookInfo + '/:id',\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-info/book-info.module').then((module) => module.BookInfoModule),\r\n data: { pageType: PageTypeEnum.BookInfo },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.BookTag + '/:tag/:id',\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-tag/book-tag.module').then((module) => module.BookTagModule),\r\n data: { pageType: PageTypeEnum.BookTag },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.BookTag + '/:tag/:id/:title',\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-tag/book-tag.module').then((module) => module.BookTagModule),\r\n data: { pageType: PageTypeEnum.BookTag },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.Book + '/:id',\r\n loadChildren: () => import('@portal-app/modules/routes/book/book.module').then((module) => module.BookModule),\r\n data: { pageType: PageTypeEnum.Book },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.BookCollection,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-collection/book-collection.module').then(\r\n (module) => module.BookCollectionModule\r\n ),\r\n data: { pageType: PageTypeEnum.BookCollection },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.BookFavorites,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-favorites/book-favorites.module').then(\r\n (module) => module.BookFavoritesModule\r\n ),\r\n data: { pageType: PageTypeEnum.BookFavorites },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.BookLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-library/book-library.module').then((module) => module.BookLibraryModule),\r\n data: { pageType: PageTypeEnum.BookLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.BookTeacherDashboard,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/book-teacher-dashboard/book-teacher-dashboard.module').then(\r\n (module) => module.BookTeacherDashboardModule\r\n ),\r\n data: { pageType: PageTypeEnum.BookTeacherDashboard },\r\n canActivate: [RouteHasPage],\r\n },\r\n // course related\r\n {\r\n path: PageTypeEnum.CourseFavorites,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/course-favorites/course-favorites.module').then(\r\n (module) => module.CourseFavoritesModule\r\n ),\r\n data: { pageType: PageTypeEnum.CourseFavorites },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n {\r\n path: PageTypeEnum.CourseLibrary,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/course-library/course-library.module').then(\r\n (module) => module.CourseLibraryModule\r\n ),\r\n data: { pageType: PageTypeEnum.CourseLibrary },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.CourseStudentAnswers,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/course-student-answers/course-student-answers.module').then(\r\n (module) => module.CourseStudentAnswersModule\r\n ),\r\n data: { pageType: PageTypeEnum.CourseStudentAnswers },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.CourseAnnualPlan,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/course-annual-plan/course-annual-plan.module').then(\r\n (module) => module.CourseAnnualPlanModule\r\n ),\r\n data: { pageType: PageTypeEnum.CourseAnnualPlan },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.CourseFrontpage + '/:id',\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/course-frontpage/course-frontpage.module').then(\r\n (module) => module.CourseFrontpageModule\r\n ),\r\n data: { pageType: PageTypeEnum.CourseFrontpage },\r\n canActivate: [SetGTMForRoute],\r\n },\r\n // lounge related\r\n {\r\n path: PageTypeEnum.LoungeTeamAdmin,\r\n loadChildren: () =>\r\n import('@portal-app/modules/routes/lounge-proxy/lounge-proxy.module').then((module) => module.LoungeProxyModule),\r\n data: { pageType: PageTypeEnum.LoungeTeamAdmin },\r\n canActivate: [RouteHasPage],\r\n },\r\n // general stuff\r\n {\r\n path: PageTypeEnum.ContentPage,\r\n loadChildren: () => import('@portal-app/modules/routes/page/page.module').then((module) => module.PageModule),\r\n data: { pageType: PageTypeEnum.ContentPage },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: PageTypeEnum.Error503,\r\n loadChildren: () => import('@portal-app/modules/routes/page/page.module').then((module) => module.PageModule),\r\n data: { pageType: PageTypeEnum.Error503 },\r\n canActivate: [RouteHasPage],\r\n },\r\n {\r\n path: '**',\r\n loadChildren: () => import('@portal-app/modules/routes/empty/empty.module').then((module) => module.EmptyModule),\r\n canActivate: [SetPageForRoute],\r\n },\r\n];\r\n\r\n@NgModule({\r\n imports: [\r\n RouterModule.forRoot(routes, {\r\n scrollPositionRestoration: 'top', // Always start scroll 0 on route change\r\n enableTracing: false, // Debugging purpose only, enable to debug routing\r\n }),\r\n ],\r\n providers: [SetPageForRoute, RouteHasPage, SetGTMForRoute],\r\n exports: [RouterModule],\r\n})\r\nexport class AppRoutingModule {}\r\n","export enum HeaderTypeEnum {\r\n Default = 'default',\r\n Book = 'book',\r\n Course = 'course',\r\n}\r\n","import { Injectable, OnDestroy } from '@angular/core';\r\nimport { LoadingService, MouseKeyboardService } from '@lru/felib';\r\nimport { LoadingKey } from '@portal-app/enums/loading-keys.enum';\r\nimport { IDropdown } from '@portal-app/interfaces/project/dropdown.interface';\r\nimport { take } from 'rxjs/operators';\r\nimport { DropdownService } from './dropdown.service';\r\nimport { ExtendedDialogService } from './extended-dialog.service';\r\nimport { LayoutAudioService } from './layout-audio.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class MouseAndKeyboardService implements OnDestroy {\r\n loaded = false;\r\n private header?: HTMLElement;\r\n private focus?: HTMLElement;\r\n private hover?: HTMLElement;\r\n private isLoading = false;\r\n private dropdownOpen?: IDropdown;\r\n private validElements = '[tabindex=\"0\"], a:not([tabindex=\"-1\"]), button:not([tabindex=\"-1\"])';\r\n\r\n private loadingSubscription = this.loadingService\r\n .loading$(LoadingKey.Page)\r\n .subscribe((data) => (this.isLoading = data));\r\n private dropDownSubscription = this.dropdownService.open$.subscribe((data) => {\r\n this.dropdownOpen = data;\r\n });\r\n\r\n constructor(\r\n private dropdownService: DropdownService,\r\n private extendedDialogService: ExtendedDialogService,\r\n private layoutAudioService: LayoutAudioService,\r\n private mouseKeyboardService: MouseKeyboardService,\r\n private loadingService: LoadingService\r\n ) {}\r\n\r\n init() {\r\n this.header = document.getElementById('header') || undefined;\r\n this.loaded = true;\r\n }\r\n\r\n handleKeyup(e: KeyboardEvent) {\r\n let target = e.target as HTMLElement | null;\r\n if (target && e.key === 'Tab') {\r\n this.mouseKeyboardService.removeHover();\r\n if (\r\n !target.closest('#nav') &&\r\n (target.closest('.dropdown')?.id !== this.dropdownOpen?.Id || !target.closest('.dropdown'))\r\n ) {\r\n this.dropdownService.closeDropdown();\r\n }\r\n if (\r\n (target.closest('.caption .canvas button') && document.body.querySelector('.lightbox')) ||\r\n target.closest('.lightbox')\r\n ) {\r\n target = document.querySelector('.lb-closeContainer .lb-close');\r\n } else {\r\n this.fixTabOffset(target);\r\n }\r\n if (target) {\r\n this.mouseKeyboardService.addFocus(target);\r\n }\r\n }\r\n }\r\n\r\n handleKeydown(e: KeyboardEvent) {\r\n const target = e.target as HTMLElement;\r\n\r\n if (this.isLoading) {\r\n if (e.key === 'Tab' || (e.ctrlKey && e.key === 'a')) {\r\n e.preventDefault();\r\n }\r\n this.mouseKeyboardService.removeHover();\r\n } else {\r\n const tabs = (target.closest('.tabs') || this.hover?.closest('.tabs')) as HTMLElement;\r\n const pagination = (target.closest('.pagination') || this.hover?.closest('.pagination')) as HTMLElement;\r\n\r\n if (e.key === 'Enter') {\r\n if (this.hover) {\r\n e.preventDefault();\r\n this.hover.click();\r\n } else if (this.focus) {\r\n if (!target.closest('a') && !target.closest('button')) {\r\n this.focus.click();\r\n }\r\n this.mouseKeyboardService.addFocus(target);\r\n } else {\r\n if (target.classList.contains('checkbox') || target.classList.contains('toggle')) {\r\n target.click();\r\n }\r\n }\r\n } else if (this.dropdownOpen || target.closest('portal-library-search')) {\r\n this.handleDropdown(e, target);\r\n } else if (tabs) {\r\n this.handleArrow(e, tabs);\r\n } else if (pagination) {\r\n this.handleArrow(e, pagination);\r\n } else if (e.key === 'Tab') {\r\n if (\r\n (target.closest('.caption .canvas button') && document.body.querySelector('.lightbox')) ||\r\n target.closest('.lightbox')\r\n ) {\r\n e.preventDefault();\r\n }\r\n }\r\n }\r\n }\r\n\r\n documentClick(target: HTMLElement) {\r\n this.mouseKeyboardService.removeFocus();\r\n this.mouseKeyboardService.removeHover();\r\n if (target.classList.contains('cdk-overlay-container')) {\r\n this.extendedDialogService.closeAll();\r\n } else if (this.dropdownOpen) {\r\n if (\r\n !target.closest('#nav') &&\r\n (target.closest('.dropdown')?.id !== this.dropdownOpen?.Id || !target.closest('.dropdown'))\r\n ) {\r\n this.dropdownService.closeDropdown();\r\n }\r\n }\r\n this.layoutAudioService.data$.pipe(take(1)).subscribe((data) => {\r\n if (data.Full?.Enabled && !target.closest('.audio-element.full')) {\r\n this.layoutAudioService.resetFull();\r\n }\r\n if (data.Partial && !target.closest('.audio-element.partial')) {\r\n this.layoutAudioService.removePartial();\r\n }\r\n });\r\n }\r\n\r\n private handleDropdown(e: KeyboardEvent, target: HTMLElement) {\r\n if (e.key === 'Escape') {\r\n e.stopPropagation();\r\n this.dropdownService.closeDropdown();\r\n } else if (\r\n this.isArrowDown(e.key) ||\r\n this.isArrowLeft(e.key) ||\r\n this.isArrowRight(e.key) ||\r\n this.isArrowUp(e.key)\r\n ) {\r\n if (target.closest('input[type=\"text\"]') && (this.isArrowLeft(e.key) || this.isArrowRight(e.key))) {\r\n // allow to go left/right in text input\r\n } else {\r\n e.preventDefault();\r\n if (!(target.nodeName.toLowerCase() === 'input' && target.getAttribute('type') === 'text')) {\r\n this.mouseKeyboardService.removeFocus();\r\n }\r\n const dropdown = this.dropdownOpen?.Id ? document.getElementById(this.dropdownOpen.Id) : undefined;\r\n const container = dropdown ? dropdown : target.closest('portal-library-search');\r\n if (container) {\r\n const items = container.querySelector('.dropdown-content')?.querySelectorAll(this.validElements);\r\n\r\n if (items) {\r\n if (this.isArrowDown(e.key) || this.isArrowRight(e.key)) {\r\n if (\r\n this.hover === undefined ||\r\n (this.hover && this.hover.closest('.toggle-dropdown')) ||\r\n (target.closest('.toggle-dropdown') &&\r\n (!this.hover || (this.hover && this.hover.closest('.toggle-dropdown'))))\r\n ) {\r\n if (items?.length) {\r\n const element = items[0] as HTMLElement;\r\n this.mouseKeyboardService.addHover(element, true);\r\n }\r\n } else {\r\n const element = this.mouseKeyboardService.selectNext(Array.from(items) as HTMLElement[], true);\r\n\r\n if (element) {\r\n this.mouseKeyboardService.addHover(element, true);\r\n }\r\n }\r\n } else if (this.isArrowUp(e.key) || this.isArrowLeft(e.key)) {\r\n const element = this.mouseKeyboardService.selectPrev(Array.from(items) as HTMLElement[], false);\r\n\r\n if (element) {\r\n this.mouseKeyboardService.addHover(element, true);\r\n } else {\r\n const button = container.querySelector('.toggle-dropdown');\r\n if (button) {\r\n this.mouseKeyboardService.addHover(button, true);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private handleArrow(e: KeyboardEvent, container: HTMLElement) {\r\n if (this.isArrowDown(e.key) || this.isArrowLeft(e.key) || this.isArrowRight(e.key) || this.isArrowUp(e.key)) {\r\n e.preventDefault();\r\n\r\n this.mouseKeyboardService.removeFocus();\r\n\r\n let element: HTMLElement | undefined;\r\n const items = container.querySelectorAll(this.validElements);\r\n if (items) {\r\n if (this.isArrowDown(e.key) || this.isArrowRight(e.key)) {\r\n element = this.mouseKeyboardService.selectNext(Array.from(items) as HTMLElement[], true);\r\n } else if (this.isArrowUp(e.key) || this.isArrowLeft(e.key)) {\r\n element = this.mouseKeyboardService.selectPrev(Array.from(items) as HTMLElement[], true);\r\n }\r\n }\r\n\r\n if (element) {\r\n this.mouseKeyboardService.addHover(element);\r\n }\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.loadingSubscription?.unsubscribe();\r\n this.dropDownSubscription?.unsubscribe();\r\n }\r\n\r\n private fixTabOffset(target: HTMLElement) {\r\n if (this.header) {\r\n const correctDistanceFromTop = this.header.clientHeight + 10;\r\n const top = target.getBoundingClientRect().top - correctDistanceFromTop - 10;\r\n if (top < 0) {\r\n window.scrollBy(0, top);\r\n }\r\n }\r\n }\r\n\r\n private isArrowDown(key: string) {\r\n return key === 'ArrowDown';\r\n }\r\n\r\n private isArrowUp(key: string) {\r\n return key === 'ArrowUp';\r\n }\r\n\r\n private isArrowLeft(key: string) {\r\n return key === 'ArrowLeft';\r\n }\r\n\r\n private isArrowRight(key: string) {\r\n return key === 'ArrowRight';\r\n }\r\n}\r\n","import { DOCUMENT, isPlatformBrowser } from '@angular/common';\r\nimport { Inject, Injectable, PLATFORM_ID } from '@angular/core';\r\nimport { EMPTY, fromEvent } from 'rxjs';\r\nimport { map, share, startWith } from 'rxjs/operators';\r\n\r\n@Injectable()\r\nexport class WindowScrollService {\r\n constructor(@Inject(DOCUMENT) private document: Document, @Inject(PLATFORM_ID) private platformId: object) {}\r\n\r\n getScrollY() {\r\n if (isPlatformBrowser(this.platformId)) {\r\n return fromEvent(window, 'scroll').pipe(\r\n startWith(0),\r\n map((event) => {\r\n return window.scrollY || this.document.documentElement.scrollTop;\r\n }),\r\n share()\r\n );\r\n } else {\r\n // in non-browser environments, provide an empty observable so you can safely subscribe to scroll$\r\n return EMPTY;\r\n }\r\n }\r\n}\r\n","export enum LinkTypeEnum {\r\n External = 'link-external',\r\n Internal = 'link-content',\r\n Module = 'internal-module',\r\n Dropdown = 'dropdown',\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { LinkTypeEnum } from '@portal-app/enums/link-type.enum';\r\nimport { PageTypeEnum } from '@portal-app/enums/page-type.enum';\r\nimport { INavbarItem } from '@portal-app/interfaces/project/navbar.interface';\r\nimport { IUmbNavbar, IUmbNavbarItem } from '@portal-app/interfaces/umbraco/umb-navbar.interface';\r\nimport { NavbarService } from '@portal-app/services/shared/navbar.service';\r\nimport { HelperService } from '../../services/shared/helper.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class NavbarMapper {\r\n constructor(private navbarService: NavbarService, private helperService: HelperService) {}\r\n\r\n pushItemToArray(item: IUmbNavbarItem, items: INavbarItem[], array: INavbarItem[], dropdownIndex?: number) {\r\n if (!item.isActive) {\r\n // dont add items that are not active\r\n return;\r\n }\r\n\r\n const url = this.helperService.getCustomUrl(item.customUrl || item.url);\r\n\r\n if (item.pageType === PageTypeEnum.CourseLibrary || item.pageType === PageTypeEnum.BookLibrary) {\r\n this.navbarService.setLibrary(url);\r\n } else if (item.pageType === PageTypeEnum.CourseFavorites || item.pageType === PageTypeEnum.BookFavorites) {\r\n this.navbarService.setFavorites(url);\r\n } else if (item.pageType === PageTypeEnum.CourseStudentAnswers) {\r\n this.navbarService.setCourseStudentAnswers(url);\r\n } else if (item.pageType === PageTypeEnum.CourseAnnualPlan) {\r\n this.navbarService.setCourseAnnualPlan(url);\r\n } else if (item.pageType === PageTypeEnum.PsArticleLibrary) {\r\n this.navbarService.setPsArticleLibrary(url);\r\n } else if (\r\n item.pageType === PageTypeEnum.PsAssignmentLibrary ||\r\n item.pageType === PageTypeEnum.PrintbarAssignmentLibrary\r\n ) {\r\n this.navbarService.setPsAssignmentLibrary(url);\r\n }\r\n\r\n if (item.isHidden) {\r\n return;\r\n }\r\n\r\n if (item.type === LinkTypeEnum.External) {\r\n item.url = item.url;\r\n } else if (item.contentTypeAlias === PageTypeEnum.FrontPage) {\r\n item.url = '/';\r\n } else if (item.customUrl) {\r\n item.url = url;\r\n }\r\n\r\n array.push({\r\n Id: item.type === LinkTypeEnum.Dropdown && dropdownIndex !== null ? dropdownIndex : item.id,\r\n Items: items,\r\n Title: item.name,\r\n Type: item.type,\r\n Target: item.target,\r\n Url: item.url,\r\n });\r\n }\r\n\r\n mapNavbarFromApi(navbar: IUmbNavbar): INavbarItem[] {\r\n const result: INavbarItem[] = [];\r\n\r\n for (const row of navbar.rows) {\r\n for (const column of row.columns) {\r\n if (column.value) {\r\n const items: IUmbNavbarItem[] = [];\r\n column.value.items.forEach((item) => {\r\n items.push(item);\r\n });\r\n items.forEach((item, index) => {\r\n const navbarItems: INavbarItem[] = [];\r\n if (item.type === LinkTypeEnum.Dropdown) {\r\n for (const child of item.items) {\r\n this.pushItemToArray(child, [], navbarItems);\r\n }\r\n }\r\n this.pushItemToArray(item, navbarItems, result, index);\r\n });\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n isLinkActive(url: string) {\r\n return url === window.location.pathname;\r\n }\r\n\r\n isDropdownActive(urls: string[]) {\r\n return urls.find((elem) => elem === window.location.pathname) ? true : false;\r\n }\r\n}\r\n","\r\n
    \r\n \r\n \r\n
  • \r\n \r\n \r\n {{ item.Title }}\r\n \r\n \r\n
      \r\n
    • \r\n \r\n {{ child.Title }}\r\n \r\n \r\n {{ child.Title }}\r\n \r\n
    • \r\n
    \r\n
    \r\n \r\n
  • \r\n
    \r\n \r\n
  • \r\n \r\n {{ item.Title }}\r\n \r\n {{ item.Title }}\r\n
  • \r\n
    \r\n
    \r\n
\r\n
\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { Component, OnInit } from '@angular/core';\r\nimport { LinkTypeEnum } from '@portal-app/enums/link-type.enum';\r\nimport { INavbarItem } from '@portal-app/interfaces/project/navbar.interface';\r\nimport { NavbarMapper } from '@portal-app/mapper/shared/navbar.mapper';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { BreakpointsService } from '@portal-app/services/shared/breakpoints.service';\r\nimport { NavbarService } from '@portal-app/services/shared/navbar.service';\r\nimport { PageService } from '@portal-app/services/shared/page/page.service';\r\nimport { take } from 'rxjs/operators';\r\n\r\n@Component({\r\n selector: 'portal-navbar',\r\n templateUrl: './navbar.component.html',\r\n styleUrls: ['./navbar.component.scss'],\r\n})\r\nexport class NavbarComponent implements OnInit {\r\n isLoading = true;\r\n navbar?: INavbarItem[];\r\n dropdownsEnabled?: boolean;\r\n\r\n constructor(\r\n private appInitService: AppInitService,\r\n private navbarService: NavbarService,\r\n private navbarMapper: NavbarMapper,\r\n private breakpointsService: BreakpointsService,\r\n private pageService: PageService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.breakpointsService.large$.subscribe((data) => {\r\n this.dropdownsEnabled = data;\r\n });\r\n\r\n const menuId = this.appInitService.siteConfiguration.NavbarId;\r\n if (menuId) {\r\n this.navbarService\r\n .getNavbar(menuId)\r\n .pipe(take(1))\r\n .subscribe(\r\n (navbar) => {\r\n this.navbar = this.navbarMapper.mapNavbarFromApi(navbar);\r\n this.isLoading = false;\r\n },\r\n (error: HttpErrorResponse) => {\r\n this.pageService.showError(window.location.pathname, error.status);\r\n }\r\n );\r\n }\r\n }\r\n\r\n get LinkTypeEnum() {\r\n return LinkTypeEnum;\r\n }\r\n\r\n isLinkActive(item: INavbarItem) {\r\n return item.Url === window.location.pathname;\r\n }\r\n\r\n isDropdownActive(items: INavbarItem[]) {\r\n return items.map((elem) => elem.Url).find((elem) => elem === window.location.pathname) ? true : false;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ApiService } from '@lru/felib';\r\nimport { IUmbNavbar } from '@portal-app/interfaces/umbraco/umb-navbar.interface';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class MegaMenuService {\r\n constructor(private api: ApiService) {}\r\n\r\n getMegaMenu(menuId: number) {\r\n return this.api.getUmbraco(`alineaportal/menu/fetch/${menuId}`);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { LinkTypeEnum } from '@portal-app/enums/link-type.enum';\r\nimport { IMegaMenu, IMegaMenuTab } from '@portal-app/interfaces/project/mega-menu.interface';\r\nimport { IUmbNavbar } from '@portal-app/interfaces/umbraco/umb-navbar.interface';\r\nimport { HtmlService } from '@portal-app/services/shared/html.service';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class MegaMenuMapper {\r\n constructor(private htmlService: HtmlService) {}\r\n\r\n mapMegaMenuFromApi(navbar: IUmbNavbar): IMegaMenu {\r\n const result: IMegaMenu = {\r\n Tabs: [],\r\n };\r\n\r\n const css: string[] = [];\r\n\r\n navbar.rows.forEach((row, i) => {\r\n row.columns.forEach((column, j) => {\r\n if (column.value?.items) {\r\n column.value?.items.forEach((item, k) => {\r\n if (item.type === LinkTypeEnum.Dropdown) {\r\n const dropdown: IMegaMenuTab = {\r\n Title: item.name,\r\n Label: item.label,\r\n Items: [],\r\n };\r\n item.items.forEach((child, l) => {\r\n const className = `hover-${i}-${j}-${k}-${l}`;\r\n if (child.hoverColor) {\r\n css.push(\r\n `portal-mega-menu .${className}:hover { background-color: ${child.hoverColor} !important; }`\r\n );\r\n }\r\n\r\n dropdown.Items.push({\r\n Icon: child.iconUrl,\r\n Title: child.name,\r\n Label: child.label,\r\n Url: child.url ? `${child.url}?portalclick=megamenu` : '',\r\n Target: child.target ?? '_blank',\r\n Description: this.htmlService.fixHtml(child.description),\r\n Hover: child.hoverColor\r\n ? {\r\n ClassName: className,\r\n Color: child.hoverColor,\r\n }\r\n : undefined,\r\n });\r\n });\r\n result.Tabs.push(dropdown);\r\n } else if (item.type === LinkTypeEnum.External) {\r\n result.Link = {\r\n Title: item.name,\r\n Url: item.url ? `${item.url}?portalclick=megamenu` : '',\r\n };\r\n }\r\n });\r\n }\r\n });\r\n });\r\n if (result) {\r\n if (css) {\r\n const style = document.createElement('style');\r\n style.appendChild(document.createTextNode(css.join('')));\r\n document.getElementsByTagName('head')[0].appendChild(style);\r\n }\r\n result.CurrentTab = result.Tabs[0];\r\n }\r\n return result;\r\n }\r\n}\r\n","\r\n
\r\n
    \r\n
  • \r\n \r\n \r\n \r\n \r\n \r\n
  • \r\n
\r\n \r\n {{ megaMenu.Link.Title }}\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n\r\n\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { IMegaMenu, IMegaMenuTab } from '@portal-app/interfaces/project/mega-menu.interface';\r\nimport { MegaMenuMapper } from '@portal-app/mapper/shared/mega-menu.mapper';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { MegaMenuService } from '@portal-app/services/shared/mega-menu.service';\r\n\r\n@Component({\r\n selector: 'portal-mega-menu',\r\n templateUrl: './mega-menu.component.html',\r\n styleUrls: ['./mega-menu.component.scss'],\r\n})\r\nexport class MegaMenuComponent implements OnInit {\r\n megaMenu?: IMegaMenu;\r\n\r\n constructor(\r\n private megaMenuService: MegaMenuService,\r\n private megaMenuMapper: MegaMenuMapper,\r\n private appInitService: AppInitService\r\n ) {}\r\n\r\n ngOnInit() {\r\n const menuId = this.appInitService.siteConfiguration.MegaMenuId;\r\n if (menuId) {\r\n this.megaMenuService.getMegaMenu(menuId).subscribe((megaMenu) => {\r\n this.megaMenu = this.megaMenuMapper.mapMegaMenuFromApi(megaMenu);\r\n });\r\n }\r\n }\r\n\r\n changeTab(tab: IMegaMenuTab) {\r\n if (this.megaMenu) {\r\n this.megaMenu.CurrentTab = tab;\r\n\r\n if (this.megaMenu.ActivelyOpenedTab === tab) {\r\n this.megaMenu.ActivelyOpenedTab = undefined;\r\n } else {\r\n this.megaMenu.ActivelyOpenedTab = tab;\r\n }\r\n }\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\nimport { IUser } from '@lru/felib/lib/services/core/user/interfaces/user.interface';\r\n\r\n@Component({\r\n selector: 'portal-user',\r\n templateUrl: './user.component.html',\r\n styleUrls: ['./user.component.scss'],\r\n})\r\nexport class UserComponent implements OnInit {\r\n user?: IUser;\r\n\r\n constructor(private userService: UserService) {}\r\n\r\n ngOnInit() {\r\n this.user = this.userService.user;\r\n }\r\n\r\n onLogout() {\r\n this.userService.logout();\r\n }\r\n}\r\n","\r\n \r\n {{ user?.initials }}\r\n \r\n \r\n
    \r\n
  • \r\n \r\n
  • \r\n
\r\n
\r\n\r\n","
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n
\r\n
\r\n \r\n
\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n
\r\n","import { Component, Input, OnInit } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\nimport { ProjectTypeEnum } from '@portal-app/enums/project-type.enum';\r\nimport { IDropdown } from '@portal-app/interfaces/project/dropdown.interface';\r\nimport { ISiteLoge } from '@portal-app/interfaces/project/site-configuration.interface';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { WindowScrollService } from '@portal-app/services/shared/window-scroll.service';\r\nimport { PageTypeEnum } from '../../../../../enums/page-type.enum';\r\nimport { BreakpointsService } from '../../../../../services/shared/breakpoints.service';\r\nimport { DropdownService } from '../../../../../services/shared/dropdown.service';\r\nimport { NavbarService } from '../../../../../services/shared/navbar.service';\r\n\r\n@Component({\r\n selector: 'portal-header-default[pageType]',\r\n templateUrl: './header-default.component.html',\r\n styleUrls: ['./header-default.component.scss'],\r\n})\r\nexport class HeaderDefaultComponent implements OnInit {\r\n @Input() pageType!: string;\r\n\r\n scrolled?: boolean;\r\n isLoggedIn?: boolean;\r\n dropdownOpen?: IDropdown;\r\n siteName?: string;\r\n hasMegaMenu?: boolean;\r\n isFagportal?: boolean;\r\n isSuperBogOrReader?: boolean;\r\n favoriteUrl?: string;\r\n large?: boolean;\r\n libraryUrl?: string;\r\n logo?: ISiteLoge;\r\n showLogin: boolean = false;\r\n\r\n constructor(\r\n private windowScrollService: WindowScrollService,\r\n private appInitService: AppInitService,\r\n private userService: UserService,\r\n private navbarService: NavbarService,\r\n private breakpointsService: BreakpointsService,\r\n private dropdownService: DropdownService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.logo = this.appInitService.siteConfiguration.logo;\r\n this.showLogin = this.appInitService.siteConfiguration.ProjectType !== ProjectTypeEnum.Other;\r\n\r\n this.isLoggedIn = this.userService.isLoggedIn;\r\n this.hasMegaMenu = this.appInitService.siteConfiguration.MegaMenuId ? true : false;\r\n this.isFagportal = this.appInitService.isFagportal;\r\n this.isSuperBogOrReader = this.appInitService.isSuperbog || this.appInitService.isSuperreader;\r\n\r\n this.dropdownService.open$.subscribe((value) => {\r\n this.dropdownOpen = value;\r\n });\r\n\r\n this.navbarService.favoritesUrl$.subscribe((url) => {\r\n this.favoriteUrl = url;\r\n });\r\n\r\n this.breakpointsService.large$.subscribe((data) => {\r\n this.large = data;\r\n });\r\n\r\n this.navbarService.libraryUrl$.subscribe((url) => {\r\n this.libraryUrl = url;\r\n });\r\n\r\n this.siteName = this.appInitService.siteConfiguration.Title;\r\n\r\n this.windowScrollService.getScrollY().subscribe((pos) => {\r\n if (!window.scrollLocked) {\r\n this.setScrolled(pos);\r\n }\r\n });\r\n }\r\n\r\n onLogin() {\r\n this.userService.login();\r\n }\r\n\r\n get PageTypeEnum() {\r\n return PageTypeEnum;\r\n }\r\n\r\n private setScrolled(verticalOffset: number) {\r\n const maxScrollVal = 1;\r\n\r\n this.scrolled = verticalOffset >= maxScrollVal;\r\n }\r\n}\r\n","\r\n","import { Component, Input, OnInit } from '@angular/core';\r\nimport { ILink } from '../../../../../interfaces/project/link.interface';\r\nimport { BreadcrumbsService } from '../../../../../services/shared/breadcrumbs.service';\r\nimport { BreakpointsService } from '../../../../../services/shared/breakpoints.service';\r\n\r\n@Component({\r\n selector: 'portal-breadcrumbs',\r\n templateUrl: './breadcrumbs.component.html',\r\n styleUrls: ['./breadcrumbs.component.scss'],\r\n})\r\nexport class BreadcrumbsComponent implements OnInit {\r\n medium = false;\r\n items: ILink[] = [];\r\n @Input() isHeader = false;\r\n\r\n constructor(private breadcrumbsService: BreadcrumbsService, private breakpointsService: BreakpointsService) {}\r\n\r\n ngOnInit() {\r\n this.breadcrumbsService.data$.subscribe((data) => {\r\n this.items = data;\r\n });\r\n this.breakpointsService.medium$.subscribe((data) => {\r\n this.medium = data;\r\n });\r\n }\r\n\r\n getRootUrl() {\r\n if (!this.medium && this.items.length) {\r\n const item = this.items[this.items.length - 1];\r\n if (item.Url) {\r\n return item.Url;\r\n }\r\n }\r\n return '/';\r\n }\r\n}\r\n","// see https://tools.ietf.org/html/rfc1808\n\n(function (root) {\n var URL_REGEX =\n /^(?=((?:[a-zA-Z0-9+\\-.]+:)?))\\1(?=((?:\\/\\/[^\\/?#]*)?))\\2(?=((?:(?:[^?#\\/]*\\/)*[^;?#\\/]*)?))\\3((?:;[^?#]*)?)(\\?[^#]*)?(#[^]*)?$/;\n var FIRST_SEGMENT_REGEX = /^(?=([^\\/?#]*))\\1([^]*)$/;\n var SLASH_DOT_REGEX = /(?:\\/|^)\\.(?=\\/)/g;\n var SLASH_DOT_DOT_REGEX = /(?:\\/|^)\\.\\.\\/(?!\\.\\.\\/)[^\\/]*(?=\\/)/g;\n\n var URLToolkit = {\n // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //\n // E.g\n // With opts.alwaysNormalize = false (default, spec compliant)\n // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g\n // With opts.alwaysNormalize = true (not spec compliant)\n // http://a.com/b/cd + /e/f/../g => http://a.com/e/g\n buildAbsoluteURL: function (baseURL, relativeURL, opts) {\n opts = opts || {};\n // remove any remaining space and CRLF\n baseURL = baseURL.trim();\n relativeURL = relativeURL.trim();\n if (!relativeURL) {\n // 2a) If the embedded URL is entirely empty, it inherits the\n // entire base URL (i.e., is set equal to the base URL)\n // and we are done.\n if (!opts.alwaysNormalize) {\n return baseURL;\n }\n var basePartsForNormalise = URLToolkit.parseURL(baseURL);\n if (!basePartsForNormalise) {\n throw new Error('Error trying to parse base URL.');\n }\n basePartsForNormalise.path = URLToolkit.normalizePath(\n basePartsForNormalise.path\n );\n return URLToolkit.buildURLFromParts(basePartsForNormalise);\n }\n var relativeParts = URLToolkit.parseURL(relativeURL);\n if (!relativeParts) {\n throw new Error('Error trying to parse relative URL.');\n }\n if (relativeParts.scheme) {\n // 2b) If the embedded URL starts with a scheme name, it is\n // interpreted as an absolute URL and we are done.\n if (!opts.alwaysNormalize) {\n return relativeURL;\n }\n relativeParts.path = URLToolkit.normalizePath(relativeParts.path);\n return URLToolkit.buildURLFromParts(relativeParts);\n }\n var baseParts = URLToolkit.parseURL(baseURL);\n if (!baseParts) {\n throw new Error('Error trying to parse base URL.');\n }\n if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {\n // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc\n // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'\n var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);\n baseParts.netLoc = pathParts[1];\n baseParts.path = pathParts[2];\n }\n if (baseParts.netLoc && !baseParts.path) {\n baseParts.path = '/';\n }\n var builtParts = {\n // 2c) Otherwise, the embedded URL inherits the scheme of\n // the base URL.\n scheme: baseParts.scheme,\n netLoc: relativeParts.netLoc,\n path: null,\n params: relativeParts.params,\n query: relativeParts.query,\n fragment: relativeParts.fragment,\n };\n if (!relativeParts.netLoc) {\n // 3) If the embedded URL's is non-empty, we skip to\n // Step 7. Otherwise, the embedded URL inherits the \n // (if any) of the base URL.\n builtParts.netLoc = baseParts.netLoc;\n // 4) If the embedded URL path is preceded by a slash \"/\", the\n // path is not relative and we skip to Step 7.\n if (relativeParts.path[0] !== '/') {\n if (!relativeParts.path) {\n // 5) If the embedded URL path is empty (and not preceded by a\n // slash), then the embedded URL inherits the base URL path\n builtParts.path = baseParts.path;\n // 5a) if the embedded URL's is non-empty, we skip to\n // step 7; otherwise, it inherits the of the base\n // URL (if any) and\n if (!relativeParts.params) {\n builtParts.params = baseParts.params;\n // 5b) if the embedded URL's is non-empty, we skip to\n // step 7; otherwise, it inherits the of the base\n // URL (if any) and we skip to step 7.\n if (!relativeParts.query) {\n builtParts.query = baseParts.query;\n }\n }\n } else {\n // 6) The last segment of the base URL's path (anything\n // following the rightmost slash \"/\", or the entire path if no\n // slash is present) is removed and the embedded URL's path is\n // appended in its place.\n var baseURLPath = baseParts.path;\n var newPath =\n baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) +\n relativeParts.path;\n builtParts.path = URLToolkit.normalizePath(newPath);\n }\n }\n }\n if (builtParts.path === null) {\n builtParts.path = opts.alwaysNormalize\n ? URLToolkit.normalizePath(relativeParts.path)\n : relativeParts.path;\n }\n return URLToolkit.buildURLFromParts(builtParts);\n },\n parseURL: function (url) {\n var parts = URL_REGEX.exec(url);\n if (!parts) {\n return null;\n }\n return {\n scheme: parts[1] || '',\n netLoc: parts[2] || '',\n path: parts[3] || '',\n params: parts[4] || '',\n query: parts[5] || '',\n fragment: parts[6] || '',\n };\n },\n normalizePath: function (path) {\n // The following operations are\n // then applied, in order, to the new path:\n // 6a) All occurrences of \"./\", where \".\" is a complete path\n // segment, are removed.\n // 6b) If the path ends with \".\" as a complete path segment,\n // that \".\" is removed.\n path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');\n // 6c) All occurrences of \"/../\", where is a\n // complete path segment not equal to \"..\", are removed.\n // Removal of these path segments is performed iteratively,\n // removing the leftmost matching pattern on each iteration,\n // until no matching pattern remains.\n // 6d) If the path ends with \"/..\", where is a\n // complete path segment not equal to \"..\", that\n // \"/..\" is removed.\n while (\n path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length\n ) {}\n return path.split('').reverse().join('');\n },\n buildURLFromParts: function (parts) {\n return (\n parts.scheme +\n parts.netLoc +\n parts.path +\n parts.params +\n parts.query +\n parts.fragment\n );\n },\n };\n\n if (typeof exports === 'object' && typeof module === 'object')\n module.exports = URLToolkit;\n else if (typeof define === 'function' && define.amd)\n define([], function () {\n return URLToolkit;\n });\n else if (typeof exports === 'object') exports['URLToolkit'] = URLToolkit;\n else root['URLToolkit'] = URLToolkit;\n})(this);\n","export const isFiniteNumber =\n Number.isFinite ||\n function (value) {\n return typeof value === 'number' && isFinite(value);\n };\n\nexport const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;\n","import {\n ManifestLoadedData,\n ManifestLoadingData,\n MediaAttachedData,\n MediaAttachingData,\n LevelLoadingData,\n LevelLoadedData,\n ManifestParsedData,\n LevelUpdatedData,\n LevelsUpdatedData,\n FragParsingUserdataData,\n FragDecryptedData,\n FragLoadedData,\n InitPTSFoundData,\n CuesParsedData,\n SubtitleFragProcessedData,\n NonNativeTextTracksData,\n FragLoadingData,\n AudioTrackLoadedData,\n SubtitleTrackLoadedData,\n ErrorData,\n AudioTrackSwitchingData,\n AudioTrackSwitchedData,\n KeyLoadedData,\n KeyLoadingData,\n SubtitleTrackSwitchData,\n SubtitleTracksUpdatedData,\n LevelSwitchedData,\n FragChangedData,\n BufferAppendingData,\n BufferCodecsData,\n FragParsingMetadataData,\n FragParsingInitSegmentData,\n FragBufferedData,\n BufferFlushingData,\n BufferEOSData,\n LevelSwitchingData,\n FPSDropLevelCappingData,\n FPSDropData,\n BufferCreatedData,\n BufferAppendedData,\n LevelPTSUpdatedData,\n FragParsedData,\n AudioTracksUpdatedData,\n FragLoadEmergencyAbortedData,\n BackBufferData,\n LiveBackBufferData,\n TrackLoadingData,\n BufferFlushedData,\n} from './types/events';\n\nexport enum Events {\n // Fired before MediaSource is attaching to media element\n MEDIA_ATTACHING = 'hlsMediaAttaching',\n // Fired when MediaSource has been successfully attached to media element\n MEDIA_ATTACHED = 'hlsMediaAttached',\n // Fired before detaching MediaSource from media element\n MEDIA_DETACHING = 'hlsMediaDetaching',\n // Fired when MediaSource has been detached from media element\n MEDIA_DETACHED = 'hlsMediaDetached',\n // Fired when the buffer is going to be reset\n BUFFER_RESET = 'hlsBufferReset',\n // Fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}\n BUFFER_CODECS = 'hlsBufferCodecs',\n // fired when sourcebuffers have been created - data: { tracks : tracks }\n BUFFER_CREATED = 'hlsBufferCreated',\n // fired when we append a segment to the buffer - data: { segment: segment object }\n BUFFER_APPENDING = 'hlsBufferAppending',\n // fired when we are done with appending a media segment to the buffer - data : { parent : segment parent that triggered BUFFER_APPENDING, pending : nb of segments waiting for appending for this segment parent}\n BUFFER_APPENDED = 'hlsBufferAppended',\n // fired when the stream is finished and we want to notify the media buffer that there will be no more data - data: { }\n BUFFER_EOS = 'hlsBufferEos',\n // fired when the media buffer should be flushed - data { startOffset, endOffset }\n BUFFER_FLUSHING = 'hlsBufferFlushing',\n // fired when the media buffer has been flushed - data: { }\n BUFFER_FLUSHED = 'hlsBufferFlushed',\n // fired to signal that a manifest loading starts - data: { url : manifestURL}\n MANIFEST_LOADING = 'hlsManifestLoading',\n // fired after manifest has been loaded - data: { levels : [available quality levels], audioTracks : [ available audio tracks ], url : manifestURL, stats : LoaderStats }\n MANIFEST_LOADED = 'hlsManifestLoaded',\n // fired after manifest has been parsed - data: { levels : [available quality levels], firstLevel : index of first quality level appearing in Manifest}\n MANIFEST_PARSED = 'hlsManifestParsed',\n // fired when a level switch is requested - data: { level : id of new level }\n LEVEL_SWITCHING = 'hlsLevelSwitching',\n // fired when a level switch is effective - data: { level : id of new level }\n LEVEL_SWITCHED = 'hlsLevelSwitched',\n // fired when a level playlist loading starts - data: { url : level URL, level : id of level being loaded}\n LEVEL_LOADING = 'hlsLevelLoading',\n // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : LoaderStats }\n LEVEL_LOADED = 'hlsLevelLoaded',\n // fired when a level's details have been updated based on previous details, after it has been loaded - data: { details : levelDetails object, level : id of updated level }\n LEVEL_UPDATED = 'hlsLevelUpdated',\n // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment }\n LEVEL_PTS_UPDATED = 'hlsLevelPtsUpdated',\n // fired to notify that levels have changed after removing a level - data: { levels : [available quality levels] }\n LEVELS_UPDATED = 'hlsLevelsUpdated',\n // fired to notify that audio track lists has been updated - data: { audioTracks : audioTracks }\n AUDIO_TRACKS_UPDATED = 'hlsAudioTracksUpdated',\n // fired when an audio track switching is requested - data: { id : audio track id }\n AUDIO_TRACK_SWITCHING = 'hlsAudioTrackSwitching',\n // fired when an audio track switch actually occurs - data: { id : audio track id }\n AUDIO_TRACK_SWITCHED = 'hlsAudioTrackSwitched',\n // fired when an audio track loading starts - data: { url : audio track URL, id : audio track id }\n AUDIO_TRACK_LOADING = 'hlsAudioTrackLoading',\n // fired when an audio track loading finishes - data: { details : levelDetails object, id : audio track id, stats : LoaderStats }\n AUDIO_TRACK_LOADED = 'hlsAudioTrackLoaded',\n // fired to notify that subtitle track lists has been updated - data: { subtitleTracks : subtitleTracks }\n SUBTITLE_TRACKS_UPDATED = 'hlsSubtitleTracksUpdated',\n // fired to notify that subtitle tracks were cleared as a result of stopping the media\n SUBTITLE_TRACKS_CLEARED = 'hlsSubtitleTracksCleared',\n // fired when an subtitle track switch occurs - data: { id : subtitle track id }\n SUBTITLE_TRACK_SWITCH = 'hlsSubtitleTrackSwitch',\n // fired when a subtitle track loading starts - data: { url : subtitle track URL, id : subtitle track id }\n SUBTITLE_TRACK_LOADING = 'hlsSubtitleTrackLoading',\n // fired when a subtitle track loading finishes - data: { details : levelDetails object, id : subtitle track id, stats : LoaderStats }\n SUBTITLE_TRACK_LOADED = 'hlsSubtitleTrackLoaded',\n // fired when a subtitle fragment has been processed - data: { success : boolean, frag : the processed frag }\n SUBTITLE_FRAG_PROCESSED = 'hlsSubtitleFragProcessed',\n // fired when a set of VTTCues to be managed externally has been parsed - data: { type: string, track: string, cues: [ VTTCue ] }\n CUES_PARSED = 'hlsCuesParsed',\n // fired when a text track to be managed externally is found - data: { tracks: [ { label: string, kind: string, default: boolean } ] }\n NON_NATIVE_TEXT_TRACKS_FOUND = 'hlsNonNativeTextTracksFound',\n // fired when the first timestamp is found - data: { id : demuxer id, initPTS: initPTS, timescale: timescale, frag : fragment object }\n INIT_PTS_FOUND = 'hlsInitPtsFound',\n // fired when a fragment loading starts - data: { frag : fragment object }\n FRAG_LOADING = 'hlsFragLoading',\n // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded } }\n // FRAG_LOAD_PROGRESS = 'hlsFragLoadProgress',\n // Identifier for fragment load aborting for emergency switch down - data: { frag : fragment object }\n FRAG_LOAD_EMERGENCY_ABORTED = 'hlsFragLoadEmergencyAborted',\n // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : LoaderStats }\n FRAG_LOADED = 'hlsFragLoaded',\n // fired when a fragment has finished decrypting - data: { id : demuxer id, frag: fragment object, payload : fragment payload, stats : { tstart, tdecrypt } }\n FRAG_DECRYPTED = 'hlsFragDecrypted',\n // fired when Init Segment has been extracted from fragment - data: { id : demuxer id, frag: fragment object, moov : moov MP4 box, codecs : codecs found while parsing fragment }\n FRAG_PARSING_INIT_SEGMENT = 'hlsFragParsingInitSegment',\n // fired when parsing sei text is completed - data: { id : demuxer id, frag: fragment object, samples : [ sei samples pes ] }\n FRAG_PARSING_USERDATA = 'hlsFragParsingUserdata',\n // fired when parsing id3 is completed - data: { id : demuxer id, frag: fragment object, samples : [ id3 samples pes ] }\n FRAG_PARSING_METADATA = 'hlsFragParsingMetadata',\n // fired when data have been extracted from fragment - data: { id : demuxer id, frag: fragment object, data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null}\n // FRAG_PARSING_DATA = 'hlsFragParsingData',\n // fired when fragment parsing is completed - data: { id : demuxer id, frag: fragment object }\n FRAG_PARSED = 'hlsFragParsed',\n // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { id : demuxer id, frag : fragment object, stats : LoaderStats }\n FRAG_BUFFERED = 'hlsFragBuffered',\n // fired when fragment matching with current media position is changing - data : { id : demuxer id, frag : fragment object }\n FRAG_CHANGED = 'hlsFragChanged',\n // Identifier for a FPS drop event - data: { currentDropped, currentDecoded, totalDroppedFrames }\n FPS_DROP = 'hlsFpsDrop',\n // triggered when FPS drop triggers auto level capping - data: { level, droppedLevel }\n FPS_DROP_LEVEL_CAPPING = 'hlsFpsDropLevelCapping',\n // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data }\n ERROR = 'hlsError',\n // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - data: { }\n DESTROYING = 'hlsDestroying',\n // fired when a decrypt key loading starts - data: { frag : fragment object }\n KEY_LOADING = 'hlsKeyLoading',\n // fired when a decrypt key loading is completed - data: { frag : fragment object, keyInfo : KeyLoaderInfo }\n KEY_LOADED = 'hlsKeyLoaded',\n // deprecated; please use BACK_BUFFER_REACHED - data : { bufferEnd: number }\n LIVE_BACK_BUFFER_REACHED = 'hlsLiveBackBufferReached',\n // fired when the back buffer is reached as defined by the backBufferLength config option - data : { bufferEnd: number }\n BACK_BUFFER_REACHED = 'hlsBackBufferReached',\n}\n\n/**\n * Defines each Event type and payload by Event name. Used in {@link hls.js#HlsEventEmitter} to strongly type the event listener API.\n */\nexport interface HlsListeners {\n [Events.MEDIA_ATTACHING]: (\n event: Events.MEDIA_ATTACHING,\n data: MediaAttachingData\n ) => void;\n [Events.MEDIA_ATTACHED]: (\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ) => void;\n [Events.MEDIA_DETACHING]: (event: Events.MEDIA_DETACHING) => void;\n [Events.MEDIA_DETACHED]: (event: Events.MEDIA_DETACHED) => void;\n [Events.BUFFER_RESET]: (event: Events.BUFFER_RESET) => void;\n [Events.BUFFER_CODECS]: (\n event: Events.BUFFER_CODECS,\n data: BufferCodecsData\n ) => void;\n [Events.BUFFER_CREATED]: (\n event: Events.BUFFER_CREATED,\n data: BufferCreatedData\n ) => void;\n [Events.BUFFER_APPENDING]: (\n event: Events.BUFFER_APPENDING,\n data: BufferAppendingData\n ) => void;\n [Events.BUFFER_APPENDED]: (\n event: Events.BUFFER_APPENDED,\n data: BufferAppendedData\n ) => void;\n [Events.BUFFER_EOS]: (event: Events.BUFFER_EOS, data: BufferEOSData) => void;\n [Events.BUFFER_FLUSHING]: (\n event: Events.BUFFER_FLUSHING,\n data: BufferFlushingData\n ) => void;\n [Events.BUFFER_FLUSHED]: (\n event: Events.BUFFER_FLUSHED,\n data: BufferFlushedData\n ) => void;\n [Events.MANIFEST_LOADING]: (\n event: Events.MANIFEST_LOADING,\n data: ManifestLoadingData\n ) => void;\n [Events.MANIFEST_LOADED]: (\n event: Events.MANIFEST_LOADED,\n data: ManifestLoadedData\n ) => void;\n [Events.MANIFEST_PARSED]: (\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ) => void;\n [Events.LEVEL_SWITCHING]: (\n event: Events.LEVEL_SWITCHING,\n data: LevelSwitchingData\n ) => void;\n [Events.LEVEL_SWITCHED]: (\n event: Events.LEVEL_SWITCHED,\n data: LevelSwitchedData\n ) => void;\n [Events.LEVEL_LOADING]: (\n event: Events.LEVEL_LOADING,\n data: LevelLoadingData\n ) => void;\n [Events.LEVEL_LOADED]: (\n event: Events.LEVEL_LOADED,\n data: LevelLoadedData\n ) => void;\n [Events.LEVEL_UPDATED]: (\n event: Events.LEVEL_UPDATED,\n data: LevelUpdatedData\n ) => void;\n [Events.LEVEL_PTS_UPDATED]: (\n event: Events.LEVEL_PTS_UPDATED,\n data: LevelPTSUpdatedData\n ) => void;\n [Events.LEVELS_UPDATED]: (\n event: Events.LEVELS_UPDATED,\n data: LevelsUpdatedData\n ) => void;\n [Events.AUDIO_TRACKS_UPDATED]: (\n event: Events.AUDIO_TRACKS_UPDATED,\n data: AudioTracksUpdatedData\n ) => void;\n [Events.AUDIO_TRACK_SWITCHING]: (\n event: Events.AUDIO_TRACK_SWITCHING,\n data: AudioTrackSwitchingData\n ) => void;\n [Events.AUDIO_TRACK_SWITCHED]: (\n event: Events.AUDIO_TRACK_SWITCHED,\n data: AudioTrackSwitchedData\n ) => void;\n [Events.AUDIO_TRACK_LOADING]: (\n event: Events.AUDIO_TRACK_LOADING,\n data: TrackLoadingData\n ) => void;\n [Events.AUDIO_TRACK_LOADED]: (\n event: Events.AUDIO_TRACK_LOADED,\n data: AudioTrackLoadedData\n ) => void;\n [Events.SUBTITLE_TRACKS_UPDATED]: (\n event: Events.SUBTITLE_TRACKS_UPDATED,\n data: SubtitleTracksUpdatedData\n ) => void;\n [Events.SUBTITLE_TRACKS_CLEARED]: (\n event: Events.SUBTITLE_TRACKS_CLEARED\n ) => void;\n [Events.SUBTITLE_TRACK_SWITCH]: (\n event: Events.SUBTITLE_TRACK_SWITCH,\n data: SubtitleTrackSwitchData\n ) => void;\n [Events.SUBTITLE_TRACK_LOADING]: (\n event: Events.SUBTITLE_TRACK_LOADING,\n data: TrackLoadingData\n ) => void;\n [Events.SUBTITLE_TRACK_LOADED]: (\n event: Events.SUBTITLE_TRACK_LOADED,\n data: SubtitleTrackLoadedData\n ) => void;\n [Events.SUBTITLE_FRAG_PROCESSED]: (\n event: Events.SUBTITLE_FRAG_PROCESSED,\n data: SubtitleFragProcessedData\n ) => void;\n [Events.CUES_PARSED]: (\n event: Events.CUES_PARSED,\n data: CuesParsedData\n ) => void;\n [Events.NON_NATIVE_TEXT_TRACKS_FOUND]: (\n event: Events.NON_NATIVE_TEXT_TRACKS_FOUND,\n data: NonNativeTextTracksData\n ) => void;\n [Events.INIT_PTS_FOUND]: (\n event: Events.INIT_PTS_FOUND,\n data: InitPTSFoundData\n ) => void;\n [Events.FRAG_LOADING]: (\n event: Events.FRAG_LOADING,\n data: FragLoadingData\n ) => void;\n // [Events.FRAG_LOAD_PROGRESS]: TodoEventType\n [Events.FRAG_LOAD_EMERGENCY_ABORTED]: (\n event: Events.FRAG_LOAD_EMERGENCY_ABORTED,\n data: FragLoadEmergencyAbortedData\n ) => void;\n [Events.FRAG_LOADED]: (\n event: Events.FRAG_LOADED,\n data: FragLoadedData\n ) => void;\n [Events.FRAG_DECRYPTED]: (\n event: Events.FRAG_DECRYPTED,\n data: FragDecryptedData\n ) => void;\n [Events.FRAG_PARSING_INIT_SEGMENT]: (\n event: Events.FRAG_PARSING_INIT_SEGMENT,\n data: FragParsingInitSegmentData\n ) => void;\n [Events.FRAG_PARSING_USERDATA]: (\n event: Events.FRAG_PARSING_USERDATA,\n data: FragParsingUserdataData\n ) => void;\n [Events.FRAG_PARSING_METADATA]: (\n event: Events.FRAG_PARSING_METADATA,\n data: FragParsingMetadataData\n ) => void;\n // [Events.FRAG_PARSING_DATA]: TodoEventType\n [Events.FRAG_PARSED]: (\n event: Events.FRAG_PARSED,\n data: FragParsedData\n ) => void;\n [Events.FRAG_BUFFERED]: (\n event: Events.FRAG_BUFFERED,\n data: FragBufferedData\n ) => void;\n [Events.FRAG_CHANGED]: (\n event: Events.FRAG_CHANGED,\n data: FragChangedData\n ) => void;\n [Events.FPS_DROP]: (event: Events.FPS_DROP, data: FPSDropData) => void;\n [Events.FPS_DROP_LEVEL_CAPPING]: (\n event: Events.FPS_DROP_LEVEL_CAPPING,\n data: FPSDropLevelCappingData\n ) => void;\n [Events.ERROR]: (event: Events.ERROR, data: ErrorData) => void;\n [Events.DESTROYING]: (event: Events.DESTROYING) => void;\n [Events.KEY_LOADING]: (\n event: Events.KEY_LOADING,\n data: KeyLoadingData\n ) => void;\n [Events.KEY_LOADED]: (event: Events.KEY_LOADED, data: KeyLoadedData) => void;\n [Events.LIVE_BACK_BUFFER_REACHED]: (\n event: Events.LIVE_BACK_BUFFER_REACHED,\n data: LiveBackBufferData\n ) => void;\n [Events.BACK_BUFFER_REACHED]: (\n event: Events.BACK_BUFFER_REACHED,\n data: BackBufferData\n ) => void;\n}\nexport interface HlsEventEmitter {\n on(\n event: E,\n listener: HlsListeners[E],\n context?: Context\n ): void;\n once(\n event: E,\n listener: HlsListeners[E],\n context?: Context\n ): void;\n\n removeAllListeners(event?: E): void;\n off(\n event: E,\n listener?: HlsListeners[E],\n context?: Context,\n once?: boolean\n ): void;\n\n listeners(event: E): HlsListeners[E][];\n emit(\n event: E,\n name: E,\n eventObject: Parameters[1]\n ): boolean;\n listenerCount(event: E): number;\n}\n","export enum ErrorTypes {\n // Identifier for a network error (loading error / timeout ...)\n NETWORK_ERROR = 'networkError',\n // Identifier for a media Error (video/parsing/mediasource error)\n MEDIA_ERROR = 'mediaError',\n // EME (encrypted media extensions) errors\n KEY_SYSTEM_ERROR = 'keySystemError',\n // Identifier for a mux Error (demuxing/remuxing)\n MUX_ERROR = 'muxError',\n // Identifier for all other errors\n OTHER_ERROR = 'otherError',\n}\n\nexport enum ErrorDetails {\n KEY_SYSTEM_NO_KEYS = 'keySystemNoKeys',\n KEY_SYSTEM_NO_ACCESS = 'keySystemNoAccess',\n KEY_SYSTEM_NO_SESSION = 'keySystemNoSession',\n KEY_SYSTEM_NO_CONFIGURED_LICENSE = 'keySystemNoConfiguredLicense',\n KEY_SYSTEM_LICENSE_REQUEST_FAILED = 'keySystemLicenseRequestFailed',\n KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED = 'keySystemServerCertificateRequestFailed',\n KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED = 'keySystemServerCertificateUpdateFailed',\n KEY_SYSTEM_SESSION_UPDATE_FAILED = 'keySystemSessionUpdateFailed',\n KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED = 'keySystemStatusOutputRestricted',\n KEY_SYSTEM_STATUS_INTERNAL_ERROR = 'keySystemStatusInternalError',\n // Identifier for a manifest load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n MANIFEST_LOAD_ERROR = 'manifestLoadError',\n // Identifier for a manifest load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n MANIFEST_LOAD_TIMEOUT = 'manifestLoadTimeOut',\n // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}\n MANIFEST_PARSING_ERROR = 'manifestParsingError',\n // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}\n MANIFEST_INCOMPATIBLE_CODECS_ERROR = 'manifestIncompatibleCodecsError',\n // Identifier for a level which contains no fragments - data: { url: faulty URL, reason: \"no fragments found in level\", level: index of the bad level }\n LEVEL_EMPTY_ERROR = 'levelEmptyError',\n // Identifier for a level load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n LEVEL_LOAD_ERROR = 'levelLoadError',\n // Identifier for a level load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n LEVEL_LOAD_TIMEOUT = 'levelLoadTimeOut',\n // Identifier for a level parse error - data: { url : faulty URL, error: Error, reason: error message }\n LEVEL_PARSING_ERROR = 'levelParsingError',\n // Identifier for a level switch error - data: { level : faulty level Id, event : error description}\n LEVEL_SWITCH_ERROR = 'levelSwitchError',\n // Identifier for an audio track load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n AUDIO_TRACK_LOAD_ERROR = 'audioTrackLoadError',\n // Identifier for an audio track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n AUDIO_TRACK_LOAD_TIMEOUT = 'audioTrackLoadTimeOut',\n // Identifier for a subtitle track load error - data: { url : faulty URL, response : { code: error code, text: error text }}\n SUBTITLE_LOAD_ERROR = 'subtitleTrackLoadError',\n // Identifier for a subtitle track load timeout - data: { url : faulty URL, response : { code: error code, text: error text }}\n SUBTITLE_TRACK_LOAD_TIMEOUT = 'subtitleTrackLoadTimeOut',\n // Identifier for fragment load error - data: { frag : fragment object, response : { code: error code, text: error text }}\n FRAG_LOAD_ERROR = 'fragLoadError',\n // Identifier for fragment load timeout error - data: { frag : fragment object}\n FRAG_LOAD_TIMEOUT = 'fragLoadTimeOut',\n // Identifier for a fragment decryption error event - data: {id : demuxer Id,frag: fragment object, reason : parsing error description }\n FRAG_DECRYPT_ERROR = 'fragDecryptError',\n // Identifier for a fragment parsing error event - data: { id : demuxer Id, reason : parsing error description }\n // will be renamed DEMUX_PARSING_ERROR and switched to MUX_ERROR in the next major release\n FRAG_PARSING_ERROR = 'fragParsingError',\n // Identifier for a fragment or part load skipped because of a GAP tag or attribute\n FRAG_GAP = 'fragGap',\n // Identifier for a remux alloc error event - data: { id : demuxer Id, frag : fragment object, bytes : nb of bytes on which allocation failed , reason : error text }\n REMUX_ALLOC_ERROR = 'remuxAllocError',\n // Identifier for decrypt key load error - data: { frag : fragment object, response : { code: error code, text: error text }}\n KEY_LOAD_ERROR = 'keyLoadError',\n // Identifier for decrypt key load timeout error - data: { frag : fragment object}\n KEY_LOAD_TIMEOUT = 'keyLoadTimeOut',\n // Triggered when an exception occurs while adding a sourceBuffer to MediaSource - data : { error : exception , mimeType : mimeType }\n BUFFER_ADD_CODEC_ERROR = 'bufferAddCodecError',\n // Triggered when source buffer(s) could not be created using level (manifest CODECS attribute), parsed media, or best guess codec(s) - data: { reason : error reason }\n BUFFER_INCOMPATIBLE_CODECS_ERROR = 'bufferIncompatibleCodecsError',\n // Identifier for a buffer append error - data: append error description\n BUFFER_APPEND_ERROR = 'bufferAppendError',\n // Identifier for a buffer appending error event - data: appending error description\n BUFFER_APPENDING_ERROR = 'bufferAppendingError',\n // Identifier for a buffer stalled error event\n BUFFER_STALLED_ERROR = 'bufferStalledError',\n // Identifier for a buffer full event\n BUFFER_FULL_ERROR = 'bufferFullError',\n // Identifier for a buffer seek over hole event\n BUFFER_SEEK_OVER_HOLE = 'bufferSeekOverHole',\n // Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area)\n BUFFER_NUDGE_ON_STALL = 'bufferNudgeOnStall',\n // Identifier for an internal exception happening inside hls.js while handling an event\n INTERNAL_EXCEPTION = 'internalException',\n // Identifier for an internal call to abort a loader\n INTERNAL_ABORTED = 'aborted',\n // Uncategorized error\n UNKNOWN = 'unknown',\n}\n","export interface ILogFunction {\n (message?: any, ...optionalParams: any[]): void;\n}\n\nexport interface ILogger {\n trace: ILogFunction;\n debug: ILogFunction;\n log: ILogFunction;\n warn: ILogFunction;\n info: ILogFunction;\n error: ILogFunction;\n}\n\nconst noop: ILogFunction = function () {};\n\nconst fakeLogger: ILogger = {\n trace: noop,\n debug: noop,\n log: noop,\n warn: noop,\n info: noop,\n error: noop,\n};\n\nlet exportedLogger: ILogger = fakeLogger;\n\n// let lastCallTime;\n// function formatMsgWithTimeInfo(type, msg) {\n// const now = Date.now();\n// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';\n// lastCallTime = now;\n// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';\n// return msg;\n// }\n\nfunction consolePrintFn(type: string): ILogFunction {\n const func: ILogFunction = self.console[type];\n if (func) {\n return func.bind(self.console, `[${type}] >`);\n }\n return noop;\n}\n\nfunction exportLoggerFunctions(\n debugConfig: boolean | ILogger,\n ...functions: string[]\n): void {\n functions.forEach(function (type) {\n exportedLogger[type] = debugConfig[type]\n ? debugConfig[type].bind(debugConfig)\n : consolePrintFn(type);\n });\n}\n\nexport function enableLogs(debugConfig: boolean | ILogger, id: string): void {\n // check that console is available\n if (\n (self.console && debugConfig === true) ||\n typeof debugConfig === 'object'\n ) {\n exportLoggerFunctions(\n debugConfig,\n // Remove out from list here to hard-disable a log-level\n // 'trace',\n 'debug',\n 'log',\n 'info',\n 'warn',\n 'error'\n );\n // Some browsers don't allow to use bind on console object anyway\n // fallback to default if needed\n try {\n exportedLogger.log(\n `Debug logs enabled for \"${id}\" in hls.js version ${__VERSION__}`\n );\n } catch (e) {\n exportedLogger = fakeLogger;\n }\n } else {\n exportedLogger = fakeLogger;\n }\n}\n\nexport const logger: ILogger = exportedLogger;\n","const DECIMAL_RESOLUTION_REGEX = /^(\\d+)x(\\d+)$/;\nconst ATTR_LIST_REGEX = /(.+?)=(\".*?\"|.*?)(?:,|$)/g;\n\n// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js\nexport class AttrList {\n [key: string]: any;\n\n constructor(attrs: string | Record) {\n if (typeof attrs === 'string') {\n attrs = AttrList.parseAttrList(attrs);\n }\n\n for (const attr in attrs) {\n if (attrs.hasOwnProperty(attr)) {\n if (attr.substring(0, 2) === 'X-') {\n this.clientAttrs = this.clientAttrs || [];\n this.clientAttrs.push(attr);\n }\n this[attr] = attrs[attr];\n }\n }\n }\n\n decimalInteger(attrName: string): number {\n const intValue = parseInt(this[attrName], 10);\n if (intValue > Number.MAX_SAFE_INTEGER) {\n return Infinity;\n }\n\n return intValue;\n }\n\n hexadecimalInteger(attrName: string) {\n if (this[attrName]) {\n let stringValue = (this[attrName] || '0x').slice(2);\n stringValue = (stringValue.length & 1 ? '0' : '') + stringValue;\n\n const value = new Uint8Array(stringValue.length / 2);\n for (let i = 0; i < stringValue.length / 2; i++) {\n value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);\n }\n\n return value;\n } else {\n return null;\n }\n }\n\n hexadecimalIntegerAsNumber(attrName: string): number {\n const intValue = parseInt(this[attrName], 16);\n if (intValue > Number.MAX_SAFE_INTEGER) {\n return Infinity;\n }\n\n return intValue;\n }\n\n decimalFloatingPoint(attrName: string): number {\n return parseFloat(this[attrName]);\n }\n\n optionalFloat(attrName: string, defaultValue: number): number {\n const value = this[attrName];\n return value ? parseFloat(value) : defaultValue;\n }\n\n enumeratedString(attrName: string): string | undefined {\n return this[attrName];\n }\n\n bool(attrName: string): boolean {\n return this[attrName] === 'YES';\n }\n\n decimalResolution(attrName: string):\n | {\n width: number;\n height: number;\n }\n | undefined {\n const res = DECIMAL_RESOLUTION_REGEX.exec(this[attrName]);\n if (res === null) {\n return undefined;\n }\n\n return {\n width: parseInt(res[1], 10),\n height: parseInt(res[2], 10),\n };\n }\n\n static parseAttrList(input: string): Record {\n let match;\n const attrs = {};\n const quote = '\"';\n ATTR_LIST_REGEX.lastIndex = 0;\n while ((match = ATTR_LIST_REGEX.exec(input)) !== null) {\n let value = match[2];\n\n if (\n value.indexOf(quote) === 0 &&\n value.lastIndexOf(quote) === value.length - 1\n ) {\n value = value.slice(1, -1);\n }\n const name = match[1].trim();\n attrs[name] = value;\n }\n return attrs;\n }\n}\n","import { AttrList } from '../utils/attr-list';\nimport { logger } from '../utils/logger';\n\n// Avoid exporting const enum so that these values can be inlined\nconst enum DateRangeAttribute {\n ID = 'ID',\n CLASS = 'CLASS',\n START_DATE = 'START-DATE',\n DURATION = 'DURATION',\n END_DATE = 'END-DATE',\n END_ON_NEXT = 'END-ON-NEXT',\n PLANNED_DURATION = 'PLANNED-DURATION',\n SCTE35_OUT = 'SCTE35-OUT',\n SCTE35_IN = 'SCTE35-IN',\n}\n\nexport function isDateRangeCueAttribute(attrName: string): boolean {\n return (\n attrName !== DateRangeAttribute.ID &&\n attrName !== DateRangeAttribute.CLASS &&\n attrName !== DateRangeAttribute.START_DATE &&\n attrName !== DateRangeAttribute.DURATION &&\n attrName !== DateRangeAttribute.END_DATE &&\n attrName !== DateRangeAttribute.END_ON_NEXT\n );\n}\n\nexport function isSCTE35Attribute(attrName: string): boolean {\n return (\n attrName === DateRangeAttribute.SCTE35_OUT ||\n attrName === DateRangeAttribute.SCTE35_IN\n );\n}\n\nexport class DateRange {\n public attr: AttrList;\n private _startDate: Date;\n private _endDate?: Date;\n private _badValueForSameId?: string;\n\n constructor(dateRangeAttr: AttrList, dateRangeWithSameId?: DateRange) {\n if (dateRangeWithSameId) {\n const previousAttr = dateRangeWithSameId.attr;\n for (const key in previousAttr) {\n if (\n Object.prototype.hasOwnProperty.call(dateRangeAttr, key) &&\n dateRangeAttr[key] !== previousAttr[key]\n ) {\n logger.warn(\n `DATERANGE tag attribute: \"${key}\" does not match for tags with ID: \"${dateRangeAttr.ID}\"`\n );\n this._badValueForSameId = key;\n break;\n }\n }\n // Merge DateRange tags with the same ID\n dateRangeAttr = Object.assign(\n new AttrList({}),\n previousAttr,\n dateRangeAttr\n );\n }\n this.attr = dateRangeAttr;\n this._startDate = new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);\n if (DateRangeAttribute.END_DATE in this.attr) {\n const endDate = new Date(this.attr[DateRangeAttribute.END_DATE]);\n if (Number.isFinite(endDate.getTime())) {\n this._endDate = endDate;\n }\n }\n }\n\n get id(): string {\n return this.attr.ID;\n }\n\n get class(): string {\n return this.attr.CLASS;\n }\n\n get startDate(): Date {\n return this._startDate;\n }\n\n get endDate(): Date | null {\n if (this._endDate) {\n return this._endDate;\n }\n const duration = this.duration;\n if (duration !== null) {\n return new Date(this._startDate.getTime() + duration * 1000);\n }\n return null;\n }\n\n get duration(): number | null {\n if (DateRangeAttribute.DURATION in this.attr) {\n const duration = this.attr.decimalFloatingPoint(\n DateRangeAttribute.DURATION\n );\n if (Number.isFinite(duration)) {\n return duration;\n }\n } else if (this._endDate) {\n return (this._endDate.getTime() - this._startDate.getTime()) / 1000;\n }\n return null;\n }\n\n get plannedDuration(): number | null {\n if (DateRangeAttribute.PLANNED_DURATION in this.attr) {\n return this.attr.decimalFloatingPoint(\n DateRangeAttribute.PLANNED_DURATION\n );\n }\n return null;\n }\n\n get endOnNext(): boolean {\n return this.attr.bool(DateRangeAttribute.END_ON_NEXT);\n }\n\n get isValid(): boolean {\n return (\n !!this.id &&\n !this._badValueForSameId &&\n Number.isFinite(this.startDate.getTime()) &&\n (this.duration === null || this.duration >= 0) &&\n (!this.endOnNext || !!this.class)\n );\n }\n}\n","import type {\n HlsPerformanceTiming,\n HlsProgressivePerformanceTiming,\n LoaderStats,\n} from '../types/loader';\n\nexport class LoadStats implements LoaderStats {\n aborted: boolean = false;\n loaded: number = 0;\n retry: number = 0;\n total: number = 0;\n chunkCount: number = 0;\n bwEstimate: number = 0;\n loading: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };\n parsing: HlsPerformanceTiming = { start: 0, end: 0 };\n buffering: HlsProgressivePerformanceTiming = { start: 0, first: 0, end: 0 };\n}\n","import { buildAbsoluteURL } from 'url-toolkit';\nimport { LevelKey } from './level-key';\nimport { LoadStats } from './load-stats';\nimport { AttrList } from '../utils/attr-list';\nimport type {\n FragmentLoaderContext,\n KeyLoaderContext,\n Loader,\n PlaylistLevelType,\n} from '../types/loader';\nimport type { KeySystemFormats } from '../utils/mediakeys-helper';\n\nexport const enum ElementaryStreamTypes {\n AUDIO = 'audio',\n VIDEO = 'video',\n AUDIOVIDEO = 'audiovideo',\n}\n\nexport interface ElementaryStreamInfo {\n startPTS: number;\n endPTS: number;\n startDTS: number;\n endDTS: number;\n partial?: boolean;\n}\n\nexport type ElementaryStreams = Record<\n ElementaryStreamTypes,\n ElementaryStreamInfo | null\n>;\n\nexport class BaseSegment {\n private _byteRange: number[] | null = null;\n private _url: string | null = null;\n\n // baseurl is the URL to the playlist\n public readonly baseurl: string;\n // relurl is the portion of the URL that comes from inside the playlist.\n public relurl?: string;\n // Holds the types of data this fragment supports\n public elementaryStreams: ElementaryStreams = {\n [ElementaryStreamTypes.AUDIO]: null,\n [ElementaryStreamTypes.VIDEO]: null,\n [ElementaryStreamTypes.AUDIOVIDEO]: null,\n };\n\n constructor(baseurl: string) {\n this.baseurl = baseurl;\n }\n\n // setByteRange converts a EXT-X-BYTERANGE attribute into a two element array\n setByteRange(value: string, previous?: BaseSegment) {\n const params = value.split('@', 2);\n const byteRange: number[] = [];\n if (params.length === 1) {\n byteRange[0] = previous ? previous.byteRangeEndOffset : 0;\n } else {\n byteRange[0] = parseInt(params[1]);\n }\n byteRange[1] = parseInt(params[0]) + byteRange[0];\n this._byteRange = byteRange;\n }\n\n get byteRange(): number[] {\n if (!this._byteRange) {\n return [];\n }\n\n return this._byteRange;\n }\n\n get byteRangeStartOffset(): number {\n return this.byteRange[0];\n }\n\n get byteRangeEndOffset(): number {\n return this.byteRange[1];\n }\n\n get url(): string {\n if (!this._url && this.baseurl && this.relurl) {\n this._url = buildAbsoluteURL(this.baseurl, this.relurl, {\n alwaysNormalize: true,\n });\n }\n return this._url || '';\n }\n\n set url(value: string) {\n this._url = value;\n }\n}\n\n/**\n * Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.\n */\nexport class Fragment extends BaseSegment {\n private _decryptdata: LevelKey | null = null;\n\n public rawProgramDateTime: string | null = null;\n public programDateTime: number | null = null;\n public tagList: Array = [];\n\n // EXTINF has to be present for a m3u8 to be considered valid\n public duration: number = 0;\n // sn notates the sequence number for a segment, and if set to a string can be 'initSegment'\n public sn: number | 'initSegment' = 0;\n // levelkeys are the EXT-X-KEY tags that apply to this segment for decryption\n // core difference from the private field _decryptdata is the lack of the initialized IV\n // _decryptdata will set the IV for this segment based on the segment number in the fragment\n public levelkeys?: { [key: string]: LevelKey };\n // A string representing the fragment type\n public readonly type: PlaylistLevelType;\n // A reference to the loader. Set while the fragment is loading, and removed afterwards. Used to abort fragment loading\n public loader: Loader | null = null;\n // A reference to the key loader. Set while the key is loading, and removed afterwards. Used to abort key loading\n public keyLoader: Loader | null = null;\n // The level/track index to which the fragment belongs\n public level: number = -1;\n // The continuity counter of the fragment\n public cc: number = 0;\n // The starting Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.\n public startPTS?: number;\n // The ending Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.\n public endPTS?: number;\n // The starting Decode Time Stamp (DTS) of the fragment. Set after transmux complete.\n public startDTS!: number;\n // The ending Decode Time Stamp (DTS) of the fragment. Set after transmux complete.\n public endDTS!: number;\n // The start time of the fragment, as listed in the manifest. Updated after transmux complete.\n public start: number = 0;\n // Set by `updateFragPTSDTS` in level-helper\n public deltaPTS?: number;\n // The maximum starting Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete.\n public maxStartPTS?: number;\n // The minimum ending Presentation Time Stamp (audio/video PTS) of the fragment. Set after transmux complete.\n public minEndPTS?: number;\n // Load/parse timing information\n public stats: LoadStats = new LoadStats();\n public urlId: number = 0;\n public data?: Uint8Array;\n // A flag indicating whether the segment was downloaded in order to test bitrate, and was not buffered\n public bitrateTest: boolean = false;\n // #EXTINF segment title\n public title: string | null = null;\n // The Media Initialization Section for this segment\n public initSegment: Fragment | null = null;\n // Fragment is the last fragment in the media playlist\n public endList?: boolean;\n // Fragment is marked by an EXT-X-GAP tag indicating that it does not contain media data and should not be loaded\n public gap?: boolean;\n\n constructor(type: PlaylistLevelType, baseurl: string) {\n super(baseurl);\n this.type = type;\n }\n\n get decryptdata(): LevelKey | null {\n const { levelkeys } = this;\n if (!levelkeys && !this._decryptdata) {\n return null;\n }\n\n if (!this._decryptdata && this.levelkeys && !this.levelkeys.NONE) {\n const key = this.levelkeys.identity;\n if (key) {\n this._decryptdata = key.getDecryptData(this.sn);\n } else {\n const keyFormats = Object.keys(this.levelkeys);\n if (keyFormats.length === 1) {\n return (this._decryptdata = this.levelkeys[\n keyFormats[0]\n ].getDecryptData(this.sn));\n } else {\n // Multiple keys. key-loader to call Fragment.setKeyFormat based on selected key-system.\n }\n }\n }\n\n return this._decryptdata;\n }\n\n get end(): number {\n return this.start + this.duration;\n }\n\n get endProgramDateTime() {\n if (this.programDateTime === null) {\n return null;\n }\n\n if (!Number.isFinite(this.programDateTime)) {\n return null;\n }\n\n const duration = !Number.isFinite(this.duration) ? 0 : this.duration;\n\n return this.programDateTime + duration * 1000;\n }\n\n get encrypted() {\n // At the m3u8-parser level we need to add support for manifest signalled keyformats\n // when we want the fragment to start reporting that it is encrypted.\n // Currently, keyFormat will only be set for identity keys\n if (this._decryptdata?.encrypted) {\n return true;\n } else if (this.levelkeys) {\n const keyFormats = Object.keys(this.levelkeys);\n const len = keyFormats.length;\n if (len > 1 || (len === 1 && this.levelkeys[keyFormats[0]].encrypted)) {\n return true;\n }\n }\n\n return false;\n }\n\n setKeyFormat(keyFormat: KeySystemFormats) {\n if (this.levelkeys) {\n const key = this.levelkeys[keyFormat];\n if (key && !this._decryptdata) {\n this._decryptdata = key.getDecryptData(this.sn);\n }\n }\n }\n\n abortRequests(): void {\n this.loader?.abort();\n this.keyLoader?.abort();\n }\n\n setElementaryStreamInfo(\n type: ElementaryStreamTypes,\n startPTS: number,\n endPTS: number,\n startDTS: number,\n endDTS: number,\n partial: boolean = false\n ) {\n const { elementaryStreams } = this;\n const info = elementaryStreams[type];\n if (!info) {\n elementaryStreams[type] = {\n startPTS,\n endPTS,\n startDTS,\n endDTS,\n partial,\n };\n return;\n }\n\n info.startPTS = Math.min(info.startPTS, startPTS);\n info.endPTS = Math.max(info.endPTS, endPTS);\n info.startDTS = Math.min(info.startDTS, startDTS);\n info.endDTS = Math.max(info.endDTS, endDTS);\n }\n\n clearElementaryStreamInfo() {\n const { elementaryStreams } = this;\n elementaryStreams[ElementaryStreamTypes.AUDIO] = null;\n elementaryStreams[ElementaryStreamTypes.VIDEO] = null;\n elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO] = null;\n }\n}\n\n/**\n * Object representing parsed data from an HLS Partial Segment. Found in {@link hls.js#LevelDetails.partList}.\n */\nexport class Part extends BaseSegment {\n public readonly fragOffset: number = 0;\n public readonly duration: number = 0;\n public readonly gap: boolean = false;\n public readonly independent: boolean = false;\n public readonly relurl: string;\n public readonly fragment: Fragment;\n public readonly index: number;\n public stats: LoadStats = new LoadStats();\n\n constructor(\n partAttrs: AttrList,\n frag: Fragment,\n baseurl: string,\n index: number,\n previous?: Part\n ) {\n super(baseurl);\n this.duration = partAttrs.decimalFloatingPoint('DURATION');\n this.gap = partAttrs.bool('GAP');\n this.independent = partAttrs.bool('INDEPENDENT');\n this.relurl = partAttrs.enumeratedString('URI') as string;\n this.fragment = frag;\n this.index = index;\n const byteRange = partAttrs.enumeratedString('BYTERANGE');\n if (byteRange) {\n this.setByteRange(byteRange, previous);\n }\n if (previous) {\n this.fragOffset = previous.fragOffset + previous.duration;\n }\n }\n\n get start(): number {\n return this.fragment.start + this.fragOffset;\n }\n\n get end(): number {\n return this.start + this.duration;\n }\n\n get loaded(): boolean {\n const { elementaryStreams } = this;\n return !!(\n elementaryStreams.audio ||\n elementaryStreams.video ||\n elementaryStreams.audiovideo\n );\n }\n}\n","import { Part } from './fragment';\nimport type { Fragment } from './fragment';\nimport type { AttrList } from '../utils/attr-list';\nimport type { DateRange } from './date-range';\nimport type { VariableMap } from '../types/level';\n\nconst DEFAULT_TARGET_DURATION = 10;\n\n/**\n * Object representing parsed data from an HLS Media Playlist. Found in {@link hls.js#Level.details}.\n */\nexport class LevelDetails {\n public PTSKnown: boolean = false;\n public alignedSliding: boolean = false;\n public averagetargetduration?: number;\n public endCC: number = 0;\n public endSN: number = 0;\n public fragments: Fragment[];\n public fragmentHint?: Fragment;\n public partList: Part[] | null = null;\n public dateRanges: Record;\n public live: boolean = true;\n public ageHeader: number = 0;\n public advancedDateTime?: number;\n public updated: boolean = true;\n public advanced: boolean = true;\n public availabilityDelay?: number; // Manifest reload synchronization\n public misses: number = 0;\n public startCC: number = 0;\n public startSN: number = 0;\n public startTimeOffset: number | null = null;\n public targetduration: number = 0;\n public totalduration: number = 0;\n public type: string | null = null;\n public url: string;\n public m3u8: string = '';\n public version: number | null = null;\n public canBlockReload: boolean = false;\n public canSkipUntil: number = 0;\n public canSkipDateRanges: boolean = false;\n public skippedSegments: number = 0;\n public recentlyRemovedDateranges?: string[];\n public partHoldBack: number = 0;\n public holdBack: number = 0;\n public partTarget: number = 0;\n public preloadHint?: AttrList;\n public renditionReports?: AttrList[];\n public tuneInGoal: number = 0;\n public deltaUpdateFailed?: boolean;\n public driftStartTime: number = 0;\n public driftEndTime: number = 0;\n public driftStart: number = 0;\n public driftEnd: number = 0;\n public encryptedFragments: Fragment[];\n public playlistParsingError: Error | null = null;\n public variableList: VariableMap | null = null;\n public hasVariableRefs = false;\n\n constructor(baseUrl) {\n this.fragments = [];\n this.encryptedFragments = [];\n this.dateRanges = {};\n this.url = baseUrl;\n }\n\n reloaded(previous: LevelDetails | undefined) {\n if (!previous) {\n this.advanced = true;\n this.updated = true;\n return;\n }\n const partSnDiff = this.lastPartSn - previous.lastPartSn;\n const partIndexDiff = this.lastPartIndex - previous.lastPartIndex;\n this.updated =\n this.endSN !== previous.endSN || !!partIndexDiff || !!partSnDiff;\n this.advanced =\n this.endSN > previous.endSN ||\n partSnDiff > 0 ||\n (partSnDiff === 0 && partIndexDiff > 0);\n if (this.updated || this.advanced) {\n this.misses = Math.floor(previous.misses * 0.6);\n } else {\n this.misses = previous.misses + 1;\n }\n this.availabilityDelay = previous.availabilityDelay;\n }\n\n get hasProgramDateTime(): boolean {\n if (this.fragments.length) {\n return Number.isFinite(\n this.fragments[this.fragments.length - 1].programDateTime as number\n );\n }\n return false;\n }\n\n get levelTargetDuration(): number {\n return (\n this.averagetargetduration ||\n this.targetduration ||\n DEFAULT_TARGET_DURATION\n );\n }\n\n get drift(): number {\n const runTime = this.driftEndTime - this.driftStartTime;\n if (runTime > 0) {\n const runDuration = this.driftEnd - this.driftStart;\n return (runDuration * 1000) / runTime;\n }\n return 1;\n }\n\n get edge(): number {\n return this.partEnd || this.fragmentEnd;\n }\n\n get partEnd(): number {\n if (this.partList?.length) {\n return this.partList[this.partList.length - 1].end;\n }\n return this.fragmentEnd;\n }\n\n get fragmentEnd(): number {\n if (this.fragments?.length) {\n return this.fragments[this.fragments.length - 1].end;\n }\n return 0;\n }\n\n get age(): number {\n if (this.advancedDateTime) {\n return Math.max(Date.now() - this.advancedDateTime, 0) / 1000;\n }\n return 0;\n }\n\n get lastPartIndex(): number {\n if (this.partList?.length) {\n return this.partList[this.partList.length - 1].index;\n }\n return -1;\n }\n\n get lastPartSn(): number {\n if (this.partList?.length) {\n return this.partList[this.partList.length - 1].fragment.sn as number;\n }\n return this.endSN;\n }\n}\n","export function base64ToBase64Url(base64encodedStr: string): string {\n return base64encodedStr\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\nexport function strToBase64Encode(str: string): string {\n return btoa(str);\n}\n\nexport function base64DecodeToStr(str: string): string {\n return atob(str);\n}\n\nexport function base64Encode(input: Uint8Array): string {\n return btoa(String.fromCharCode(...input));\n}\n\nexport function base64UrlEncode(input: Uint8Array): string {\n return base64ToBase64Url(base64Encode(input));\n}\n\nexport function base64Decode(base64encodedStr: string): Uint8Array {\n return Uint8Array.from(atob(base64encodedStr), (c) => c.charCodeAt(0));\n}\n","import { base64Decode } from './numeric-encoding-utils';\n\nfunction getKeyIdBytes(str: string): Uint8Array {\n const keyIdbytes = strToUtf8array(str).subarray(0, 16);\n const paddedkeyIdbytes = new Uint8Array(16);\n paddedkeyIdbytes.set(keyIdbytes, 16 - keyIdbytes.length);\n return paddedkeyIdbytes;\n}\n\nexport function changeEndianness(keyId: Uint8Array) {\n const swap = function (array: Uint8Array, from: number, to: number) {\n const cur = array[from];\n array[from] = array[to];\n array[to] = cur;\n };\n\n swap(keyId, 0, 3);\n swap(keyId, 1, 2);\n swap(keyId, 4, 5);\n swap(keyId, 6, 7);\n}\n\nexport function convertDataUriToArrayBytes(uri: string): Uint8Array | null {\n // data:[\n const colonsplit = uri.split(':');\n let keydata: Uint8Array | null = null;\n if (colonsplit[0] === 'data' && colonsplit.length === 2) {\n const semicolonsplit = colonsplit[1].split(';');\n const commasplit = semicolonsplit[semicolonsplit.length - 1].split(',');\n if (commasplit.length === 2) {\n const isbase64 = commasplit[0] === 'base64';\n const data = commasplit[1];\n if (isbase64) {\n semicolonsplit.splice(-1, 1); // remove from processing\n keydata = base64Decode(data);\n } else {\n keydata = getKeyIdBytes(data);\n }\n }\n }\n return keydata;\n}\n\nexport function strToUtf8array(str: string): Uint8Array {\n return Uint8Array.from(unescape(encodeURIComponent(str)), (c) =>\n c.charCodeAt(0)\n );\n}\n","import type { DRMSystemOptions, EMEControllerConfig } from '../config';\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess\n */\nexport const enum KeySystems {\n CLEARKEY = 'org.w3.clearkey',\n FAIRPLAY = 'com.apple.fps',\n PLAYREADY = 'com.microsoft.playready',\n WIDEVINE = 'com.widevine.alpha',\n}\n\n// Playlist #EXT-X-KEY KEYFORMAT values\nexport const enum KeySystemFormats {\n CLEARKEY = 'org.w3.clearkey',\n FAIRPLAY = 'com.apple.streamingkeydelivery',\n PLAYREADY = 'com.microsoft.playready',\n WIDEVINE = 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',\n}\n\nexport function keySystemFormatToKeySystemDomain(\n format: KeySystemFormats\n): KeySystems | undefined {\n switch (format) {\n case KeySystemFormats.FAIRPLAY:\n return KeySystems.FAIRPLAY;\n case KeySystemFormats.PLAYREADY:\n return KeySystems.PLAYREADY;\n case KeySystemFormats.WIDEVINE:\n return KeySystems.WIDEVINE;\n case KeySystemFormats.CLEARKEY:\n return KeySystems.CLEARKEY;\n }\n}\n\n// System IDs for which we can extract a key ID from \"encrypted\" event PSSH\nexport const enum KeySystemIds {\n // CENC = '1077efecc0b24d02ace33c1e52e2fb4b'\n // CLEARKEY = 'e2719d58a985b3c9781ab030af78d30e',\n // FAIRPLAY = '94ce86fb07ff4f43adb893d2fa968ca2',\n // PLAYREADY = '9a04f07998404286ab92e65be0885f95',\n WIDEVINE = 'edef8ba979d64acea3c827dcd51d21ed',\n}\n\nexport function keySystemIdToKeySystemDomain(\n systemId: KeySystemIds\n): KeySystems | undefined {\n if (systemId === KeySystemIds.WIDEVINE) {\n return KeySystems.WIDEVINE;\n // } else if (systemId === KeySystemIds.PLAYREADY) {\n // return KeySystems.PLAYREADY;\n // } else if (systemId === KeySystemIds.CENC || systemId === KeySystemIds.CLEARKEY) {\n // return KeySystems.CLEARKEY;\n }\n}\n\nexport function keySystemDomainToKeySystemFormat(\n keySystem: KeySystems\n): KeySystemFormats | undefined {\n switch (keySystem) {\n case KeySystems.FAIRPLAY:\n return KeySystemFormats.FAIRPLAY;\n case KeySystems.PLAYREADY:\n return KeySystemFormats.PLAYREADY;\n case KeySystems.WIDEVINE:\n return KeySystemFormats.WIDEVINE;\n case KeySystems.CLEARKEY:\n return KeySystemFormats.CLEARKEY;\n }\n}\n\nexport function getKeySystemsForConfig(\n config: EMEControllerConfig\n): KeySystems[] {\n const { drmSystems, widevineLicenseUrl } = config;\n const keySystemsToAttempt: KeySystems[] = drmSystems\n ? [\n KeySystems.FAIRPLAY,\n KeySystems.WIDEVINE,\n KeySystems.PLAYREADY,\n KeySystems.CLEARKEY,\n ].filter((keySystem) => !!drmSystems[keySystem])\n : [];\n if (!keySystemsToAttempt[KeySystems.WIDEVINE] && widevineLicenseUrl) {\n keySystemsToAttempt.push(KeySystems.WIDEVINE);\n }\n return keySystemsToAttempt;\n}\n\nexport type MediaKeyFunc = (\n keySystem: KeySystems,\n supportedConfigurations: MediaKeySystemConfiguration[]\n) => Promise;\n\nexport const requestMediaKeySystemAccess = (function (): MediaKeyFunc | null {\n if (\n typeof self !== 'undefined' &&\n self.navigator &&\n self.navigator.requestMediaKeySystemAccess\n ) {\n return self.navigator.requestMediaKeySystemAccess.bind(self.navigator);\n } else {\n return null;\n }\n})();\n\n/**\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemConfiguration\n */\nexport function getSupportedMediaKeySystemConfigurations(\n keySystem: KeySystems,\n audioCodecs: string[],\n videoCodecs: string[],\n drmSystemOptions: DRMSystemOptions\n): MediaKeySystemConfiguration[] {\n let initDataTypes: string[];\n switch (keySystem) {\n case KeySystems.FAIRPLAY:\n initDataTypes = ['cenc', 'sinf'];\n break;\n case KeySystems.WIDEVINE:\n case KeySystems.PLAYREADY:\n initDataTypes = ['cenc'];\n break;\n case KeySystems.CLEARKEY:\n initDataTypes = ['cenc', 'keyids'];\n break;\n default:\n throw new Error(`Unknown key-system: ${keySystem}`);\n }\n return createMediaKeySystemConfigurations(\n initDataTypes,\n audioCodecs,\n videoCodecs,\n drmSystemOptions\n );\n}\n\nfunction createMediaKeySystemConfigurations(\n initDataTypes: string[],\n audioCodecs: string[],\n videoCodecs: string[],\n drmSystemOptions: DRMSystemOptions\n): MediaKeySystemConfiguration[] {\n const baseConfig: MediaKeySystemConfiguration = {\n initDataTypes: initDataTypes,\n persistentState: drmSystemOptions.persistentState || 'not-allowed',\n distinctiveIdentifier:\n drmSystemOptions.distinctiveIdentifier || 'not-allowed',\n sessionTypes: drmSystemOptions.sessionTypes || [\n drmSystemOptions.sessionType || 'temporary',\n ],\n audioCapabilities: audioCodecs.map((codec) => ({\n contentType: `audio/mp4; codecs=\"${codec}\"`,\n robustness: drmSystemOptions.audioRobustness || '',\n encryptionScheme: drmSystemOptions.audioEncryptionScheme || null,\n })),\n videoCapabilities: videoCodecs.map((codec) => ({\n contentType: `video/mp4; codecs=\"${codec}\"`,\n robustness: drmSystemOptions.videoRobustness || '',\n encryptionScheme: drmSystemOptions.videoEncryptionScheme || null,\n })),\n };\n\n return [baseConfig];\n}\n","export function sliceUint8(\n array: Uint8Array,\n start?: number,\n end?: number\n): Uint8Array {\n // @ts-expect-error This polyfills IE11 usage of Uint8Array slice.\n // It always exists in the TypeScript definition so fails, but it fails at runtime on IE11.\n return Uint8Array.prototype.slice\n ? array.slice(start, end)\n : new Uint8Array(Array.prototype.slice.call(array, start, end));\n}\n","type RawFrame = { type: string; size: number; data: Uint8Array };\n\n// breaking up those two types in order to clarify what is happening in the decoding path.\ntype DecodedFrame = { key: string; data: T; info?: any };\nexport type Frame = DecodedFrame;\n\n/**\n * Returns true if an ID3 header can be found at offset in data\n * @param data - The data to search\n * @param offset - The offset at which to start searching\n */\nexport const isHeader = (data: Uint8Array, offset: number): boolean => {\n /*\n * http://id3.org/id3v2.3.0\n * [0] = 'I'\n * [1] = 'D'\n * [2] = '3'\n * [3,4] = {Version}\n * [5] = {Flags}\n * [6-9] = {ID3 Size}\n *\n * An ID3v2 tag can be detected with the following pattern:\n * $49 44 33 yy yy xx zz zz zz zz\n * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80\n */\n if (offset + 10 <= data.length) {\n // look for 'ID3' identifier\n if (\n data[offset] === 0x49 &&\n data[offset + 1] === 0x44 &&\n data[offset + 2] === 0x33\n ) {\n // check version is within range\n if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {\n // check size is within range\n if (\n data[offset + 6] < 0x80 &&\n data[offset + 7] < 0x80 &&\n data[offset + 8] < 0x80 &&\n data[offset + 9] < 0x80\n ) {\n return true;\n }\n }\n }\n }\n\n return false;\n};\n\n/**\n * Returns true if an ID3 footer can be found at offset in data\n * @param data - The data to search\n * @param offset - The offset at which to start searching\n */\nexport const isFooter = (data: Uint8Array, offset: number): boolean => {\n /*\n * The footer is a copy of the header, but with a different identifier\n */\n if (offset + 10 <= data.length) {\n // look for '3DI' identifier\n if (\n data[offset] === 0x33 &&\n data[offset + 1] === 0x44 &&\n data[offset + 2] === 0x49\n ) {\n // check version is within range\n if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {\n // check size is within range\n if (\n data[offset + 6] < 0x80 &&\n data[offset + 7] < 0x80 &&\n data[offset + 8] < 0x80 &&\n data[offset + 9] < 0x80\n ) {\n return true;\n }\n }\n }\n }\n\n return false;\n};\n\n/**\n * Returns any adjacent ID3 tags found in data starting at offset, as one block of data\n * @param data - The data to search in\n * @param offset - The offset at which to start searching\n * @returns the block of data containing any ID3 tags found\n * or *undefined* if no header is found at the starting offset\n */\nexport const getID3Data = (\n data: Uint8Array,\n offset: number\n): Uint8Array | undefined => {\n const front = offset;\n let length = 0;\n\n while (isHeader(data, offset)) {\n // ID3 header is 10 bytes\n length += 10;\n\n const size = readSize(data, offset + 6);\n length += size;\n\n if (isFooter(data, offset + 10)) {\n // ID3 footer is 10 bytes\n length += 10;\n }\n\n offset += length;\n }\n\n if (length > 0) {\n return data.subarray(front, front + length);\n }\n\n return undefined;\n};\n\nconst readSize = (data: Uint8Array, offset: number): number => {\n let size = 0;\n size = (data[offset] & 0x7f) << 21;\n size |= (data[offset + 1] & 0x7f) << 14;\n size |= (data[offset + 2] & 0x7f) << 7;\n size |= data[offset + 3] & 0x7f;\n return size;\n};\n\nexport const canParse = (data: Uint8Array, offset: number): boolean => {\n return (\n isHeader(data, offset) &&\n readSize(data, offset + 6) + 10 <= data.length - offset\n );\n};\n\n/**\n * Searches for the Elementary Stream timestamp found in the ID3 data chunk\n * @param data - Block of data containing one or more ID3 tags\n */\nexport const getTimeStamp = (data: Uint8Array): number | undefined => {\n const frames: Frame[] = getID3Frames(data);\n\n for (let i = 0; i < frames.length; i++) {\n const frame = frames[i];\n\n if (isTimeStampFrame(frame)) {\n return readTimeStamp(frame as DecodedFrame);\n }\n }\n\n return undefined;\n};\n\n/**\n * Returns true if the ID3 frame is an Elementary Stream timestamp frame\n */\nexport const isTimeStampFrame = (frame: Frame): boolean => {\n return (\n frame &&\n frame.key === 'PRIV' &&\n frame.info === 'com.apple.streaming.transportStreamTimestamp'\n );\n};\n\nconst getFrameData = (data: Uint8Array): RawFrame => {\n /*\n Frame ID $xx xx xx xx (four characters)\n Size $xx xx xx xx\n Flags $xx xx\n */\n const type: string = String.fromCharCode(data[0], data[1], data[2], data[3]);\n const size: number = readSize(data, 4);\n\n // skip frame id, size, and flags\n const offset = 10;\n\n return { type, size, data: data.subarray(offset, offset + size) };\n};\n\n/**\n * Returns an array of ID3 frames found in all the ID3 tags in the id3Data\n * @param id3Data - The ID3 data containing one or more ID3 tags\n */\nexport const getID3Frames = (id3Data: Uint8Array): Frame[] => {\n let offset = 0;\n const frames: Frame[] = [];\n\n while (isHeader(id3Data, offset)) {\n const size = readSize(id3Data, offset + 6);\n // skip past ID3 header\n offset += 10;\n const end = offset + size;\n // loop through frames in the ID3 tag\n while (offset + 8 < end) {\n const frameData: RawFrame = getFrameData(id3Data.subarray(offset));\n const frame: Frame | undefined = decodeFrame(frameData);\n if (frame) {\n frames.push(frame);\n }\n\n // skip frame header and frame data\n offset += frameData.size + 10;\n }\n\n if (isFooter(id3Data, offset)) {\n offset += 10;\n }\n }\n\n return frames;\n};\n\nexport const decodeFrame = (frame: RawFrame): Frame | undefined => {\n if (frame.type === 'PRIV') {\n return decodePrivFrame(frame);\n } else if (frame.type[0] === 'W') {\n return decodeURLFrame(frame);\n }\n\n return decodeTextFrame(frame);\n};\n\nconst decodePrivFrame = (\n frame: RawFrame\n): DecodedFrame | undefined => {\n /*\n Format: \\0\n */\n if (frame.size < 2) {\n return undefined;\n }\n\n const owner = utf8ArrayToStr(frame.data, true);\n const privateData = new Uint8Array(frame.data.subarray(owner.length + 1));\n\n return { key: frame.type, info: owner, data: privateData.buffer };\n};\n\nconst decodeTextFrame = (frame: RawFrame): DecodedFrame | undefined => {\n if (frame.size < 2) {\n return undefined;\n }\n\n if (frame.type === 'TXXX') {\n /*\n Format:\n [0] = {Text Encoding}\n [1-?] = {Description}\\0{Value}\n */\n let index = 1;\n const description = utf8ArrayToStr(frame.data.subarray(index), true);\n\n index += description.length + 1;\n const value = utf8ArrayToStr(frame.data.subarray(index));\n\n return { key: frame.type, info: description, data: value };\n }\n /*\n Format:\n [0] = {Text Encoding}\n [1-?] = {Value}\n */\n const text = utf8ArrayToStr(frame.data.subarray(1));\n return { key: frame.type, data: text };\n};\n\nconst decodeURLFrame = (frame: RawFrame): DecodedFrame | undefined => {\n if (frame.type === 'WXXX') {\n /*\n Format:\n [0] = {Text Encoding}\n [1-?] = {Description}\\0{URL}\n */\n if (frame.size < 2) {\n return undefined;\n }\n\n let index = 1;\n const description: string = utf8ArrayToStr(\n frame.data.subarray(index),\n true\n );\n\n index += description.length + 1;\n const value: string = utf8ArrayToStr(frame.data.subarray(index));\n\n return { key: frame.type, info: description, data: value };\n }\n /*\n Format:\n [0-?] = {URL}\n */\n const url: string = utf8ArrayToStr(frame.data);\n return { key: frame.type, data: url };\n};\n\nconst readTimeStamp = (\n timeStampFrame: DecodedFrame\n): number | undefined => {\n if (timeStampFrame.data.byteLength === 8) {\n const data = new Uint8Array(timeStampFrame.data);\n // timestamp is 33 bit expressed as a big-endian eight-octet number,\n // with the upper 31 bits set to zero.\n const pts33Bit = data[3] & 0x1;\n let timestamp =\n (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];\n timestamp /= 45;\n\n if (pts33Bit) {\n timestamp += 47721858.84;\n } // 2^32 / 90\n\n return Math.round(timestamp);\n }\n\n return undefined;\n};\n\n// http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197\n// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt\n/* utf.js - UTF-8 <=> UTF-16 convertion\n *\n * Copyright (C) 1999 Masanao Izumo \n * Version: 1.0\n * LastModified: Dec 25 1999\n * This library is free. You can redistribute it and/or modify it.\n */\nexport const utf8ArrayToStr = (\n array: Uint8Array,\n exitOnNull: boolean = false\n): string => {\n const decoder = getTextDecoder();\n if (decoder) {\n const decoded = decoder.decode(array);\n\n if (exitOnNull) {\n // grab up to the first null\n const idx = decoded.indexOf('\\0');\n return idx !== -1 ? decoded.substring(0, idx) : decoded;\n }\n\n // remove any null characters\n return decoded.replace(/\\0/g, '');\n }\n\n const len = array.length;\n let c;\n let char2;\n let char3;\n let out = '';\n let i = 0;\n while (i < len) {\n c = array[i++];\n if (c === 0x00 && exitOnNull) {\n return out;\n } else if (c === 0x00 || c === 0x03) {\n // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it\n continue;\n }\n switch (c >> 4) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n // 0xxxxxxx\n out += String.fromCharCode(c);\n break;\n case 12:\n case 13:\n // 110x xxxx 10xx xxxx\n char2 = array[i++];\n out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));\n break;\n case 14:\n // 1110 xxxx 10xx xxxx 10xx xxxx\n char2 = array[i++];\n char3 = array[i++];\n out += String.fromCharCode(\n ((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0)\n );\n break;\n default:\n }\n }\n return out;\n};\n\nexport const testables = {\n decodeTextFrame: decodeTextFrame,\n};\n\nlet decoder: TextDecoder;\n\nfunction getTextDecoder() {\n if (!decoder && typeof self.TextDecoder !== 'undefined') {\n decoder = new self.TextDecoder('utf-8');\n }\n\n return decoder;\n}\n","/**\n * hex dump helper class\n */\n\nconst Hex = {\n hexDump: function (array: Uint8Array) {\n let str = '';\n for (let i = 0; i < array.length; i++) {\n let h = array[i].toString(16);\n if (h.length < 2) {\n h = '0' + h;\n }\n\n str += h;\n }\n return str;\n },\n};\n\nexport default Hex;\n","import { ElementaryStreamTypes } from '../loader/fragment';\nimport { sliceUint8 } from './typed-array';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport { logger } from '../utils/logger';\nimport Hex from './hex';\nimport type { PassthroughTrack, UserdataSample } from '../types/demuxer';\nimport type { DecryptData } from '../loader/level-key';\n\nconst UINT32_MAX = Math.pow(2, 32) - 1;\nconst push = [].push;\n\n// We are using fixed track IDs for driving the MP4 remuxer\n// instead of following the TS PIDs.\n// There is no reason not to do this and some browsers/SourceBuffer-demuxers\n// may not like if there are TrackID \"switches\"\n// See https://github.com/video-dev/hls.js/issues/1331\n// Here we are mapping our internal track types to constant MP4 track IDs\n// With MSE currently one can only have one track of each, and we are muxing\n// whatever video/audio rendition in them.\nexport const RemuxerTrackIdConfig = {\n video: 1,\n audio: 2,\n id3: 3,\n text: 4,\n};\n\nexport function bin2str(data: Uint8Array): string {\n return String.fromCharCode.apply(null, data);\n}\n\nexport function readUint16(buffer: Uint8Array, offset: number): number {\n const val = (buffer[offset] << 8) | buffer[offset + 1];\n return val < 0 ? 65536 + val : val;\n}\n\nexport function readUint32(buffer: Uint8Array, offset: number): number {\n const val = readSint32(buffer, offset);\n return val < 0 ? 4294967296 + val : val;\n}\n\nexport function readSint32(buffer: Uint8Array, offset: number): number {\n return (\n (buffer[offset] << 24) |\n (buffer[offset + 1] << 16) |\n (buffer[offset + 2] << 8) |\n buffer[offset + 3]\n );\n}\n\nexport function writeUint32(buffer: Uint8Array, offset: number, value: number) {\n buffer[offset] = value >> 24;\n buffer[offset + 1] = (value >> 16) & 0xff;\n buffer[offset + 2] = (value >> 8) & 0xff;\n buffer[offset + 3] = value & 0xff;\n}\n\n// Find the data for a box specified by its path\nexport function findBox(data: Uint8Array, path: string[]): Uint8Array[] {\n const results = [] as Uint8Array[];\n if (!path.length) {\n // short-circuit the search for empty paths\n return results;\n }\n const end = data.byteLength;\n\n for (let i = 0; i < end; ) {\n const size = readUint32(data, i);\n const type = bin2str(data.subarray(i + 4, i + 8));\n const endbox = size > 1 ? i + size : end;\n\n if (type === path[0]) {\n if (path.length === 1) {\n // this is the end of the path and we've found the box we were\n // looking for\n results.push(data.subarray(i + 8, endbox));\n } else {\n // recursively search for the next box along the path\n const subresults = findBox(data.subarray(i + 8, endbox), path.slice(1));\n if (subresults.length) {\n push.apply(results, subresults);\n }\n }\n }\n i = endbox;\n }\n\n // we've finished searching all of data\n return results;\n}\n\ntype SidxInfo = {\n earliestPresentationTime: number;\n timescale: number;\n version: number;\n referencesCount: number;\n references: any[];\n};\n\nexport function parseSegmentIndex(sidx: Uint8Array): SidxInfo | null {\n const references: any[] = [];\n\n const version = sidx[0];\n\n // set initial offset, we skip the reference ID (not needed)\n let index = 8;\n\n const timescale = readUint32(sidx, index);\n index += 4;\n\n // TODO: parse earliestPresentationTime and firstOffset\n // usually zero in our case\n const earliestPresentationTime = 0;\n const firstOffset = 0;\n\n if (version === 0) {\n index += 8;\n } else {\n index += 16;\n }\n\n // skip reserved\n index += 2;\n\n let startByte = sidx.length + firstOffset;\n\n const referencesCount = readUint16(sidx, index);\n index += 2;\n\n for (let i = 0; i < referencesCount; i++) {\n let referenceIndex = index;\n\n const referenceInfo = readUint32(sidx, referenceIndex);\n referenceIndex += 4;\n\n const referenceSize = referenceInfo & 0x7fffffff;\n const referenceType = (referenceInfo & 0x80000000) >>> 31;\n\n if (referenceType === 1) {\n logger.warn('SIDX has hierarchical references (not supported)');\n return null;\n }\n\n const subsegmentDuration = readUint32(sidx, referenceIndex);\n referenceIndex += 4;\n\n references.push({\n referenceSize,\n subsegmentDuration, // unscaled\n info: {\n duration: subsegmentDuration / timescale,\n start: startByte,\n end: startByte + referenceSize - 1,\n },\n });\n\n startByte += referenceSize;\n\n // Skipping 1 bit for |startsWithSap|, 3 bits for |sapType|, and 28 bits\n // for |sapDelta|.\n referenceIndex += 4;\n\n // skip to next ref\n index = referenceIndex;\n }\n\n return {\n earliestPresentationTime,\n timescale,\n version,\n referencesCount,\n references,\n };\n}\n\n/**\n * Parses an MP4 initialization segment and extracts stream type and\n * timescale values for any declared tracks. Timescale values indicate the\n * number of clock ticks per second to assume for time-based values\n * elsewhere in the MP4.\n *\n * To determine the start time of an MP4, you need two pieces of\n * information: the timescale unit and the earliest base media decode\n * time. Multiple timescales can be specified within an MP4 but the\n * base media decode time is always expressed in the timescale from\n * the media header box for the track:\n * ```\n * moov > trak > mdia > mdhd.timescale\n * moov > trak > mdia > hdlr\n * ```\n * @param initSegment the bytes of the init segment\n * @returns a hash of track type to timescale values or null if\n * the init segment is malformed.\n */\n\nexport interface InitDataTrack {\n timescale: number;\n id: number;\n codec: string;\n}\n\ntype HdlrType = ElementaryStreamTypes.AUDIO | ElementaryStreamTypes.VIDEO;\n\nexport interface InitData extends Array {\n [index: number]:\n | {\n timescale: number;\n type: HdlrType;\n default?: {\n duration: number;\n flags: number;\n };\n }\n | undefined;\n audio?: InitDataTrack;\n video?: InitDataTrack;\n caption?: InitDataTrack;\n}\n\nexport function parseInitSegment(initSegment: Uint8Array): InitData {\n const result: InitData = [];\n const traks = findBox(initSegment, ['moov', 'trak']);\n for (let i = 0; i < traks.length; i++) {\n const trak = traks[i];\n const tkhd = findBox(trak, ['tkhd'])[0];\n if (tkhd) {\n let version = tkhd[0];\n let index = version === 0 ? 12 : 20;\n const trackId = readUint32(tkhd, index);\n const mdhd = findBox(trak, ['mdia', 'mdhd'])[0];\n if (mdhd) {\n version = mdhd[0];\n index = version === 0 ? 12 : 20;\n const timescale = readUint32(mdhd, index);\n const hdlr = findBox(trak, ['mdia', 'hdlr'])[0];\n if (hdlr) {\n const hdlrType = bin2str(hdlr.subarray(8, 12));\n const type: HdlrType | undefined = {\n soun: ElementaryStreamTypes.AUDIO as const,\n vide: ElementaryStreamTypes.VIDEO as const,\n }[hdlrType];\n if (type) {\n // Parse codec details\n const stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0];\n let codec;\n if (stsd) {\n codec = bin2str(stsd.subarray(12, 16));\n // TODO: Parse codec details to be able to build MIME type.\n // stsd.start += 8;\n // const codecBox = findBox(stsd, [codec])[0];\n // if (codecBox) {\n // TODO: Codec parsing support for avc1, mp4a, hevc, av01...\n // }\n }\n result[trackId] = { timescale, type };\n result[type] = { timescale, id: trackId, codec };\n }\n }\n }\n }\n }\n\n const trex = findBox(initSegment, ['moov', 'mvex', 'trex']);\n trex.forEach((trex) => {\n const trackId = readUint32(trex, 4);\n const track = result[trackId];\n if (track) {\n track.default = {\n duration: readUint32(trex, 12),\n flags: readUint32(trex, 20),\n };\n }\n });\n\n return result;\n}\n\nexport function patchEncyptionData(\n initSegment: Uint8Array | undefined,\n decryptdata: DecryptData | null\n): Uint8Array | undefined {\n if (!initSegment || !decryptdata) {\n return initSegment;\n }\n const keyId = decryptdata.keyId;\n if (keyId && decryptdata.isCommonEncryption) {\n const traks = findBox(initSegment, ['moov', 'trak']);\n traks.forEach((trak) => {\n const stsd = findBox(trak, ['mdia', 'minf', 'stbl', 'stsd'])[0];\n\n // skip the sample entry count\n const sampleEntries = stsd.subarray(8);\n let encBoxes = findBox(sampleEntries, ['enca']);\n const isAudio = encBoxes.length > 0;\n if (!isAudio) {\n encBoxes = findBox(sampleEntries, ['encv']);\n }\n encBoxes.forEach((enc) => {\n const encBoxChildren = isAudio ? enc.subarray(28) : enc.subarray(78);\n const sinfBoxes = findBox(encBoxChildren, ['sinf']);\n sinfBoxes.forEach((sinf) => {\n const tenc = parseSinf(sinf);\n if (tenc) {\n // Look for default key id (keyID offset is always 8 within the tenc box):\n const tencKeyId = tenc.subarray(8, 24);\n if (!tencKeyId.some((b) => b !== 0)) {\n logger.log(\n `[eme] Patching keyId in 'enc${\n isAudio ? 'a' : 'v'\n }>sinf>>tenc' box: ${Hex.hexDump(tencKeyId)} -> ${Hex.hexDump(\n keyId\n )}`\n );\n tenc.set(keyId, 8);\n }\n }\n });\n });\n });\n }\n\n return initSegment;\n}\n\nexport function parseSinf(sinf: Uint8Array): Uint8Array | null {\n const schm = findBox(sinf, ['schm'])[0];\n if (schm) {\n const scheme = bin2str(schm.subarray(4, 8));\n if (scheme === 'cbcs' || scheme === 'cenc') {\n return findBox(sinf, ['schi', 'tenc'])[0];\n }\n }\n logger.error(`[eme] missing 'schm' box`);\n return null;\n}\n\n/**\n * Determine the base media decode start time, in seconds, for an MP4\n * fragment. If multiple fragments are specified, the earliest time is\n * returned.\n *\n * The base media decode time can be parsed from track fragment\n * metadata:\n * ```\n * moof > traf > tfdt.baseMediaDecodeTime\n * ```\n * It requires the timescale value from the mdhd to interpret.\n *\n * @param initData - a hash of track type to timescale values\n * @param fmp4 - the bytes of the mp4 fragment\n * @returns the earliest base media decode start time for the\n * fragment, in seconds\n */\nexport function getStartDTS(\n initData: InitData,\n fmp4: Uint8Array\n): number | null {\n // we need info from two children of each track fragment box\n return findBox(fmp4, ['moof', 'traf']).reduce(\n (result: number | null, traf) => {\n const tfdt = findBox(traf, ['tfdt'])[0];\n const version = tfdt[0];\n const start = findBox(traf, ['tfhd']).reduce(\n (result: number | null, tfhd) => {\n // get the track id from the tfhd\n const id = readUint32(tfhd, 4);\n const track = initData[id];\n if (track) {\n let baseTime = readUint32(tfdt, 4);\n if (version === 1) {\n // If value is too large, assume signed 64-bit. Negative track fragment decode times are invalid, but they exist in the wild.\n // This prevents large values from being used for initPTS, which can cause playlist sync issues.\n // https://github.com/video-dev/hls.js/issues/5303\n if (baseTime === UINT32_MAX) {\n logger.warn(\n `[mp4-demuxer]: Ignoring assumed invalid signed 64-bit track fragment decode time`\n );\n return result;\n }\n baseTime *= UINT32_MAX + 1;\n baseTime += readUint32(tfdt, 8);\n }\n // assume a 90kHz clock if no timescale was specified\n const scale = track.timescale || 90e3;\n // convert base time to seconds\n const startTime = baseTime / scale;\n if (\n isFinite(startTime) &&\n (result === null || startTime < result)\n ) {\n return startTime;\n }\n }\n return result;\n },\n null\n );\n if (\n start !== null &&\n isFinite(start) &&\n (result === null || start < result)\n ) {\n return start;\n }\n return result;\n },\n null\n );\n}\n\n/*\n For Reference:\n aligned(8) class TrackFragmentHeaderBox\n extends FullBox(‘tfhd’, 0, tf_flags){\n unsigned int(32) track_ID;\n // all the following are optional fields\n unsigned int(64) base_data_offset;\n unsigned int(32) sample_description_index;\n unsigned int(32) default_sample_duration;\n unsigned int(32) default_sample_size;\n unsigned int(32) default_sample_flags\n }\n */\nexport function getDuration(data: Uint8Array, initData: InitData) {\n let rawDuration = 0;\n let videoDuration = 0;\n let audioDuration = 0;\n const trafs = findBox(data, ['moof', 'traf']);\n for (let i = 0; i < trafs.length; i++) {\n const traf = trafs[i];\n // There is only one tfhd & trun per traf\n // This is true for CMAF style content, and we should perhaps check the ftyp\n // and only look for a single trun then, but for ISOBMFF we should check\n // for multiple track runs.\n const tfhd = findBox(traf, ['tfhd'])[0];\n // get the track id from the tfhd\n const id = readUint32(tfhd, 4);\n const track = initData[id];\n if (!track) {\n continue;\n }\n const trackDefault = track.default;\n const tfhdFlags = readUint32(tfhd, 0) | trackDefault?.flags!;\n let sampleDuration: number | undefined = trackDefault?.duration;\n if (tfhdFlags & 0x000008) {\n // 0x000008 indicates the presence of the default_sample_duration field\n if (tfhdFlags & 0x000002) {\n // 0x000002 indicates the presence of the sample_description_index field, which precedes default_sample_duration\n // If present, the default_sample_duration exists at byte offset 12\n sampleDuration = readUint32(tfhd, 12);\n } else {\n // Otherwise, the duration is at byte offset 8\n sampleDuration = readUint32(tfhd, 8);\n }\n }\n // assume a 90kHz clock if no timescale was specified\n const timescale = track.timescale || 90e3;\n const truns = findBox(traf, ['trun']);\n for (let j = 0; j < truns.length; j++) {\n rawDuration = computeRawDurationFromSamples(truns[j]);\n if (!rawDuration && sampleDuration) {\n const sampleCount = readUint32(truns[j], 4);\n rawDuration = sampleDuration * sampleCount;\n }\n if (track.type === ElementaryStreamTypes.VIDEO) {\n videoDuration += rawDuration / timescale;\n } else if (track.type === ElementaryStreamTypes.AUDIO) {\n audioDuration += rawDuration / timescale;\n }\n }\n }\n if (videoDuration === 0 && audioDuration === 0) {\n // If duration samples are not available in the traf use sidx subsegment_duration\n let sidxDuration = 0;\n const sidxs = findBox(data, ['sidx']);\n for (let i = 0; i < sidxs.length; i++) {\n const sidx = parseSegmentIndex(sidxs[i]);\n if (sidx?.references) {\n sidxDuration += sidx.references.reduce(\n (dur, ref) => dur + ref.info.duration || 0,\n 0\n );\n }\n }\n\n return sidxDuration;\n }\n if (videoDuration) {\n return videoDuration;\n }\n return audioDuration;\n}\n\n/*\n For Reference:\n aligned(8) class TrackRunBox\n extends FullBox(‘trun’, version, tr_flags) {\n unsigned int(32) sample_count;\n // the following are optional fields\n signed int(32) data_offset;\n unsigned int(32) first_sample_flags;\n // all fields in the following array are optional\n {\n unsigned int(32) sample_duration;\n unsigned int(32) sample_size;\n unsigned int(32) sample_flags\n if (version == 0)\n { unsigned int(32)\n else\n { signed int(32)\n }[ sample_count ]\n }\n */\nexport function computeRawDurationFromSamples(trun): number {\n const flags = readUint32(trun, 0);\n // Flags are at offset 0, non-optional sample_count is at offset 4. Therefore we start 8 bytes in.\n // Each field is an int32, which is 4 bytes\n let offset = 8;\n // data-offset-present flag\n if (flags & 0x000001) {\n offset += 4;\n }\n // first-sample-flags-present flag\n if (flags & 0x000004) {\n offset += 4;\n }\n\n let duration = 0;\n const sampleCount = readUint32(trun, 4);\n for (let i = 0; i < sampleCount; i++) {\n // sample-duration-present flag\n if (flags & 0x000100) {\n const sampleDuration = readUint32(trun, offset);\n duration += sampleDuration;\n offset += 4;\n }\n // sample-size-present flag\n if (flags & 0x000200) {\n offset += 4;\n }\n // sample-flags-present flag\n if (flags & 0x000400) {\n offset += 4;\n }\n // sample-composition-time-offsets-present flag\n if (flags & 0x000800) {\n offset += 4;\n }\n }\n return duration;\n}\n\nexport function offsetStartDTS(\n initData: InitData,\n fmp4: Uint8Array,\n timeOffset: number\n) {\n findBox(fmp4, ['moof', 'traf']).forEach((traf) => {\n findBox(traf, ['tfhd']).forEach((tfhd) => {\n // get the track id from the tfhd\n const id = readUint32(tfhd, 4);\n const track = initData[id];\n if (!track) {\n return;\n }\n // assume a 90kHz clock if no timescale was specified\n const timescale = track.timescale || 90e3;\n // get the base media decode time from the tfdt\n findBox(traf, ['tfdt']).forEach((tfdt) => {\n const version = tfdt[0];\n let baseMediaDecodeTime = readUint32(tfdt, 4);\n\n if (version === 0) {\n baseMediaDecodeTime -= timeOffset * timescale;\n baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);\n writeUint32(tfdt, 4, baseMediaDecodeTime);\n } else {\n baseMediaDecodeTime *= Math.pow(2, 32);\n baseMediaDecodeTime += readUint32(tfdt, 8);\n baseMediaDecodeTime -= timeOffset * timescale;\n baseMediaDecodeTime = Math.max(baseMediaDecodeTime, 0);\n const upper = Math.floor(baseMediaDecodeTime / (UINT32_MAX + 1));\n const lower = Math.floor(baseMediaDecodeTime % (UINT32_MAX + 1));\n writeUint32(tfdt, 4, upper);\n writeUint32(tfdt, 8, lower);\n }\n });\n });\n });\n}\n\n// TODO: Check if the last moof+mdat pair is part of the valid range\nexport function segmentValidRange(data: Uint8Array): SegmentedRange {\n const segmentedRange: SegmentedRange = {\n valid: null,\n remainder: null,\n };\n\n const moofs = findBox(data, ['moof']);\n if (!moofs) {\n return segmentedRange;\n } else if (moofs.length < 2) {\n segmentedRange.remainder = data;\n return segmentedRange;\n }\n const last = moofs[moofs.length - 1];\n // Offset by 8 bytes; findBox offsets the start by as much\n segmentedRange.valid = sliceUint8(data, 0, last.byteOffset - 8);\n segmentedRange.remainder = sliceUint8(data, last.byteOffset - 8);\n return segmentedRange;\n}\n\nexport interface SegmentedRange {\n valid: Uint8Array | null;\n remainder: Uint8Array | null;\n}\n\nexport function appendUint8Array(\n data1: Uint8Array,\n data2: Uint8Array\n): Uint8Array {\n const temp = new Uint8Array(data1.length + data2.length);\n temp.set(data1);\n temp.set(data2, data1.length);\n\n return temp;\n}\n\nexport interface IEmsgParsingData {\n schemeIdUri: string;\n value: string;\n timeScale: number;\n presentationTimeDelta?: number;\n presentationTime?: number;\n eventDuration: number;\n id: number;\n payload: Uint8Array;\n}\n\nexport function parseSamples(\n timeOffset: number,\n track: PassthroughTrack\n): UserdataSample[] {\n const seiSamples = [] as UserdataSample[];\n const videoData = track.samples;\n const timescale = track.timescale;\n const trackId = track.id;\n let isHEVCFlavor = false;\n\n const moofs = findBox(videoData, ['moof']);\n moofs.map((moof) => {\n const moofOffset = moof.byteOffset - 8;\n const trafs = findBox(moof, ['traf']);\n trafs.map((traf) => {\n // get the base media decode time from the tfdt\n const baseTime = findBox(traf, ['tfdt']).map((tfdt) => {\n const version = tfdt[0];\n let result = readUint32(tfdt, 4);\n if (version === 1) {\n result *= Math.pow(2, 32);\n result += readUint32(tfdt, 8);\n }\n return result / timescale;\n })[0];\n\n if (baseTime !== undefined) {\n timeOffset = baseTime;\n }\n\n return findBox(traf, ['tfhd']).map((tfhd) => {\n const id = readUint32(tfhd, 4);\n const tfhdFlags = readUint32(tfhd, 0) & 0xffffff;\n const baseDataOffsetPresent = (tfhdFlags & 0x000001) !== 0;\n const sampleDescriptionIndexPresent = (tfhdFlags & 0x000002) !== 0;\n const defaultSampleDurationPresent = (tfhdFlags & 0x000008) !== 0;\n let defaultSampleDuration = 0;\n const defaultSampleSizePresent = (tfhdFlags & 0x000010) !== 0;\n let defaultSampleSize = 0;\n const defaultSampleFlagsPresent = (tfhdFlags & 0x000020) !== 0;\n let tfhdOffset = 8;\n\n if (id === trackId) {\n if (baseDataOffsetPresent) {\n tfhdOffset += 8;\n }\n if (sampleDescriptionIndexPresent) {\n tfhdOffset += 4;\n }\n if (defaultSampleDurationPresent) {\n defaultSampleDuration = readUint32(tfhd, tfhdOffset);\n tfhdOffset += 4;\n }\n if (defaultSampleSizePresent) {\n defaultSampleSize = readUint32(tfhd, tfhdOffset);\n tfhdOffset += 4;\n }\n if (defaultSampleFlagsPresent) {\n tfhdOffset += 4;\n }\n if (track.type === 'video') {\n isHEVCFlavor = isHEVC(track.codec);\n }\n\n findBox(traf, ['trun']).map((trun) => {\n const version = trun[0];\n const flags = readUint32(trun, 0) & 0xffffff;\n const dataOffsetPresent = (flags & 0x000001) !== 0;\n let dataOffset = 0;\n const firstSampleFlagsPresent = (flags & 0x000004) !== 0;\n const sampleDurationPresent = (flags & 0x000100) !== 0;\n let sampleDuration = 0;\n const sampleSizePresent = (flags & 0x000200) !== 0;\n let sampleSize = 0;\n const sampleFlagsPresent = (flags & 0x000400) !== 0;\n const sampleCompositionOffsetsPresent = (flags & 0x000800) !== 0;\n let compositionOffset = 0;\n const sampleCount = readUint32(trun, 4);\n let trunOffset = 8; // past version, flags, and sample count\n\n if (dataOffsetPresent) {\n dataOffset = readUint32(trun, trunOffset);\n trunOffset += 4;\n }\n if (firstSampleFlagsPresent) {\n trunOffset += 4;\n }\n\n let sampleOffset = dataOffset + moofOffset;\n\n for (let ix = 0; ix < sampleCount; ix++) {\n if (sampleDurationPresent) {\n sampleDuration = readUint32(trun, trunOffset);\n trunOffset += 4;\n } else {\n sampleDuration = defaultSampleDuration;\n }\n if (sampleSizePresent) {\n sampleSize = readUint32(trun, trunOffset);\n trunOffset += 4;\n } else {\n sampleSize = defaultSampleSize;\n }\n if (sampleFlagsPresent) {\n trunOffset += 4;\n }\n if (sampleCompositionOffsetsPresent) {\n if (version === 0) {\n compositionOffset = readUint32(trun, trunOffset);\n } else {\n compositionOffset = readSint32(trun, trunOffset);\n }\n trunOffset += 4;\n }\n if (track.type === ElementaryStreamTypes.VIDEO) {\n let naluTotalSize = 0;\n while (naluTotalSize < sampleSize) {\n const naluSize = readUint32(videoData, sampleOffset);\n sampleOffset += 4;\n if (isSEIMessage(isHEVCFlavor, videoData[sampleOffset])) {\n const data = videoData.subarray(\n sampleOffset,\n sampleOffset + naluSize\n );\n parseSEIMessageFromNALu(\n data,\n isHEVCFlavor ? 2 : 1,\n timeOffset + compositionOffset / timescale,\n seiSamples\n );\n }\n sampleOffset += naluSize;\n naluTotalSize += naluSize + 4;\n }\n }\n\n timeOffset += sampleDuration / timescale;\n }\n });\n }\n });\n });\n });\n return seiSamples;\n}\n\nfunction isHEVC(codec: string) {\n if (!codec) {\n return false;\n }\n const delimit = codec.indexOf('.');\n const baseCodec = delimit < 0 ? codec : codec.substring(0, delimit);\n return (\n baseCodec === 'hvc1' ||\n baseCodec === 'hev1' ||\n // Dolby Vision\n baseCodec === 'dvh1' ||\n baseCodec === 'dvhe'\n );\n}\n\nfunction isSEIMessage(isHEVCFlavor: boolean, naluHeader: number) {\n if (isHEVCFlavor) {\n const naluType = (naluHeader >> 1) & 0x3f;\n return naluType === 39 || naluType === 40;\n } else {\n const naluType = naluHeader & 0x1f;\n return naluType === 6;\n }\n}\n\nexport function parseSEIMessageFromNALu(\n unescapedData: Uint8Array,\n headerSize: number,\n pts: number,\n samples: UserdataSample[]\n) {\n const data = discardEPB(unescapedData);\n let seiPtr = 0;\n // skip nal header\n seiPtr += headerSize;\n let payloadType = 0;\n let payloadSize = 0;\n let endOfCaptions = false;\n let b = 0;\n\n while (seiPtr < data.length) {\n payloadType = 0;\n do {\n if (seiPtr >= data.length) {\n break;\n }\n b = data[seiPtr++];\n payloadType += b;\n } while (b === 0xff);\n\n // Parse payload size.\n payloadSize = 0;\n do {\n if (seiPtr >= data.length) {\n break;\n }\n b = data[seiPtr++];\n payloadSize += b;\n } while (b === 0xff);\n\n const leftOver = data.length - seiPtr;\n\n if (!endOfCaptions && payloadType === 4 && seiPtr < data.length) {\n endOfCaptions = true;\n\n const countryCode = data[seiPtr++];\n if (countryCode === 181) {\n const providerCode = readUint16(data, seiPtr);\n seiPtr += 2;\n\n if (providerCode === 49) {\n const userStructure = readUint32(data, seiPtr);\n seiPtr += 4;\n\n if (userStructure === 0x47413934) {\n const userDataType = data[seiPtr++];\n\n // Raw CEA-608 bytes wrapped in CEA-708 packet\n if (userDataType === 3) {\n const firstByte = data[seiPtr++];\n const totalCCs = 0x1f & firstByte;\n const enabled = 0x40 & firstByte;\n const totalBytes = enabled ? 2 + totalCCs * 3 : 0;\n const byteArray = new Uint8Array(totalBytes);\n if (enabled) {\n byteArray[0] = firstByte;\n for (let i = 1; i < totalBytes; i++) {\n byteArray[i] = data[seiPtr++];\n }\n }\n\n samples.push({\n type: userDataType,\n payloadType,\n pts,\n bytes: byteArray,\n });\n }\n }\n }\n }\n } else if (payloadType === 5 && payloadSize < leftOver) {\n endOfCaptions = true;\n\n if (payloadSize > 16) {\n const uuidStrArray: Array = [];\n for (let i = 0; i < 16; i++) {\n const b = data[seiPtr++].toString(16);\n uuidStrArray.push(b.length == 1 ? '0' + b : b);\n\n if (i === 3 || i === 5 || i === 7 || i === 9) {\n uuidStrArray.push('-');\n }\n }\n const length = payloadSize - 16;\n const userDataBytes = new Uint8Array(length);\n for (let i = 0; i < length; i++) {\n userDataBytes[i] = data[seiPtr++];\n }\n\n samples.push({\n payloadType,\n pts,\n uuid: uuidStrArray.join(''),\n userData: utf8ArrayToStr(userDataBytes),\n userDataBytes,\n });\n }\n } else if (payloadSize < leftOver) {\n seiPtr += payloadSize;\n } else if (payloadSize > leftOver) {\n break;\n }\n }\n}\n\n/**\n * remove Emulation Prevention bytes from a RBSP\n */\nexport function discardEPB(data: Uint8Array): Uint8Array {\n const length = data.byteLength;\n const EPBPositions = [] as Array;\n let i = 1;\n\n // Find all `Emulation Prevention Bytes`\n while (i < length - 2) {\n if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) {\n EPBPositions.push(i + 2);\n i += 2;\n } else {\n i++;\n }\n }\n\n // If no Emulation Prevention Bytes were found just return the original\n // array\n if (EPBPositions.length === 0) {\n return data;\n }\n\n // Create a new array to hold the NAL unit data\n const newLength = length - EPBPositions.length;\n const newData = new Uint8Array(newLength);\n let sourceIndex = 0;\n\n for (i = 0; i < newLength; sourceIndex++, i++) {\n if (sourceIndex === EPBPositions[0]) {\n // Skip this byte\n sourceIndex++;\n // Remove this position index\n EPBPositions.shift();\n }\n newData[i] = data[sourceIndex];\n }\n return newData;\n}\n\nexport function parseEmsg(data: Uint8Array): IEmsgParsingData {\n const version = data[0];\n let schemeIdUri: string = '';\n let value: string = '';\n let timeScale: number = 0;\n let presentationTimeDelta: number = 0;\n let presentationTime: number = 0;\n let eventDuration: number = 0;\n let id: number = 0;\n let offset: number = 0;\n\n if (version === 0) {\n while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n }\n\n schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n\n while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n value += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n }\n\n value += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n\n timeScale = readUint32(data, 12);\n presentationTimeDelta = readUint32(data, 16);\n eventDuration = readUint32(data, 20);\n id = readUint32(data, 24);\n offset = 28;\n } else if (version === 1) {\n offset += 4;\n timeScale = readUint32(data, offset);\n offset += 4;\n const leftPresentationTime = readUint32(data, offset);\n offset += 4;\n const rightPresentationTime = readUint32(data, offset);\n offset += 4;\n presentationTime = 2 ** 32 * leftPresentationTime + rightPresentationTime;\n if (!Number.isSafeInteger(presentationTime)) {\n presentationTime = Number.MAX_SAFE_INTEGER;\n logger.warn(\n 'Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box'\n );\n }\n\n eventDuration = readUint32(data, offset);\n offset += 4;\n id = readUint32(data, offset);\n offset += 4;\n\n while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n }\n\n schemeIdUri += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n\n while (bin2str(data.subarray(offset, offset + 1)) !== '\\0') {\n value += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n }\n\n value += bin2str(data.subarray(offset, offset + 1));\n offset += 1;\n }\n const payload = data.subarray(offset, data.byteLength);\n\n return {\n schemeIdUri,\n value,\n timeScale,\n presentationTime,\n presentationTimeDelta,\n eventDuration,\n id,\n payload,\n };\n}\n\nexport function mp4Box(type: ArrayLike, ...payload: Uint8Array[]) {\n const len = payload.length;\n let size = 8;\n let i = len;\n while (i--) {\n size += payload[i].byteLength;\n }\n const result = new Uint8Array(size);\n result[0] = (size >> 24) & 0xff;\n result[1] = (size >> 16) & 0xff;\n result[2] = (size >> 8) & 0xff;\n result[3] = size & 0xff;\n result.set(type, 4);\n for (i = 0, size = 8; i < len; i++) {\n result.set(payload[i], size);\n size += payload[i].byteLength;\n }\n return result;\n}\n\nexport function mp4pssh(\n systemId: Uint8Array,\n keyids: Array | null,\n data: Uint8Array\n) {\n if (systemId.byteLength !== 16) {\n throw new RangeError('Invalid system id');\n }\n let version;\n let kids;\n if (keyids) {\n version = 1;\n kids = new Uint8Array(keyids.length * 16);\n for (let ix = 0; ix < keyids.length; ix++) {\n const k = keyids[ix]; // uint8array\n if (k.byteLength !== 16) {\n throw new RangeError('Invalid key');\n }\n kids.set(k, ix * 16);\n }\n } else {\n version = 0;\n kids = new Uint8Array();\n }\n let kidCount;\n if (version > 0) {\n kidCount = new Uint8Array(4);\n if (keyids!.length > 0) {\n new DataView(kidCount.buffer).setUint32(0, keyids!.length, false);\n }\n } else {\n kidCount = new Uint8Array();\n }\n const dataSize = new Uint8Array(4);\n if (data && data.byteLength > 0) {\n new DataView(dataSize.buffer).setUint32(0, data.byteLength, false);\n }\n return mp4Box(\n [112, 115, 115, 104],\n new Uint8Array([\n version,\n 0x00,\n 0x00,\n 0x00, // Flags\n ]),\n systemId, // 16 bytes\n kidCount,\n kids,\n dataSize,\n data || new Uint8Array()\n );\n}\n\nexport function parsePssh(initData: ArrayBuffer) {\n if (!(initData instanceof ArrayBuffer) || initData.byteLength < 32) {\n return null;\n }\n const result = {\n version: 0,\n systemId: '',\n kids: null as null | Uint8Array[],\n data: null as null | Uint8Array,\n };\n const view = new DataView(initData);\n const boxSize = view.getUint32(0);\n if (initData.byteLength !== boxSize && boxSize > 44) {\n return null;\n }\n const type = view.getUint32(4);\n if (type !== 0x70737368) {\n return null;\n }\n result.version = view.getUint32(8) >>> 24;\n if (result.version > 1) {\n return null;\n }\n result.systemId = Hex.hexDump(new Uint8Array(initData, 12, 16));\n const dataSizeOrKidCount = view.getUint32(28);\n if (result.version === 0) {\n if (boxSize - 32 < dataSizeOrKidCount) {\n return null;\n }\n result.data = new Uint8Array(initData, 32, dataSizeOrKidCount);\n } else if (result.version === 1) {\n result.kids = [];\n for (let i = 0; i < dataSizeOrKidCount; i++) {\n result.kids.push(new Uint8Array(initData, 32 + i * 16, 16));\n }\n }\n return result;\n}\n","import {\n changeEndianness,\n convertDataUriToArrayBytes,\n} from '../utils/keysystem-util';\nimport { KeySystemFormats } from '../utils/mediakeys-helper';\nimport { mp4pssh } from '../utils/mp4-tools';\nimport { logger } from '../utils/logger';\nimport { base64Decode } from '../utils/numeric-encoding-utils';\n\nlet keyUriToKeyIdMap: { [uri: string]: Uint8Array } = {};\n\nexport interface DecryptData {\n uri: string;\n method: string;\n keyFormat: string;\n keyFormatVersions: number[];\n iv: Uint8Array | null;\n key: Uint8Array | null;\n keyId: Uint8Array | null;\n pssh: Uint8Array | null;\n encrypted: boolean;\n isCommonEncryption: boolean;\n}\n\nexport class LevelKey implements DecryptData {\n public readonly uri: string;\n public readonly method: string;\n public readonly keyFormat: string;\n public readonly keyFormatVersions: number[];\n public readonly encrypted: boolean;\n public readonly isCommonEncryption: boolean;\n public iv: Uint8Array | null = null;\n public key: Uint8Array | null = null;\n public keyId: Uint8Array | null = null;\n public pssh: Uint8Array | null = null;\n\n static clearKeyUriToKeyIdMap() {\n keyUriToKeyIdMap = {};\n }\n\n constructor(\n method: string,\n uri: string,\n format: string,\n formatversions: number[] = [1],\n iv: Uint8Array | null = null\n ) {\n this.method = method;\n this.uri = uri;\n this.keyFormat = format;\n this.keyFormatVersions = formatversions;\n this.iv = iv;\n this.encrypted = method ? method !== 'NONE' : false;\n this.isCommonEncryption = this.encrypted && method !== 'AES-128';\n }\n\n public isSupported(): boolean {\n // If it's Segment encryption or No encryption, just select that key system\n if (this.method) {\n if (this.method === 'AES-128' || this.method === 'NONE') {\n return true;\n }\n if (this.keyFormat === 'identity') {\n // Maintain support for clear SAMPLE-AES with MPEG-3 TS\n return this.method === 'SAMPLE-AES';\n } else if (__USE_EME_DRM__) {\n switch (this.keyFormat) {\n case KeySystemFormats.FAIRPLAY:\n case KeySystemFormats.WIDEVINE:\n case KeySystemFormats.PLAYREADY:\n case KeySystemFormats.CLEARKEY:\n return (\n [\n 'ISO-23001-7',\n 'SAMPLE-AES',\n 'SAMPLE-AES-CENC',\n 'SAMPLE-AES-CTR',\n ].indexOf(this.method) !== -1\n );\n }\n }\n }\n return false;\n }\n\n public getDecryptData(sn: number | 'initSegment'): LevelKey | null {\n if (!this.encrypted || !this.uri) {\n return null;\n }\n\n if (this.method === 'AES-128' && this.uri && !this.iv) {\n if (typeof sn !== 'number') {\n // We are fetching decryption data for a initialization segment\n // If the segment was encrypted with AES-128\n // It must have an IV defined. We cannot substitute the Segment Number in.\n if (this.method === 'AES-128' && !this.iv) {\n logger.warn(\n `missing IV for initialization segment with method=\"${this.method}\" - compliance issue`\n );\n }\n // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.\n sn = 0;\n }\n const iv = createInitializationVector(sn);\n const decryptdata = new LevelKey(\n this.method,\n this.uri,\n 'identity',\n this.keyFormatVersions,\n iv\n );\n return decryptdata;\n }\n\n if (!__USE_EME_DRM__) {\n return this;\n }\n\n // Initialize keyId if possible\n const keyBytes = convertDataUriToArrayBytes(this.uri);\n if (keyBytes) {\n switch (this.keyFormat) {\n case KeySystemFormats.WIDEVINE:\n this.pssh = keyBytes;\n // In case of widevine keyID is embedded in PSSH box. Read Key ID.\n if (keyBytes.length >= 22) {\n this.keyId = keyBytes.subarray(\n keyBytes.length - 22,\n keyBytes.length - 6\n );\n }\n break;\n case KeySystemFormats.PLAYREADY: {\n const PlayReadyKeySystemUUID = new Uint8Array([\n 0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xab, 0x92, 0xe6,\n 0x5b, 0xe0, 0x88, 0x5f, 0x95,\n ]);\n\n this.pssh = mp4pssh(PlayReadyKeySystemUUID, null, keyBytes);\n\n const keyBytesUtf16 = new Uint16Array(\n keyBytes.buffer,\n keyBytes.byteOffset,\n keyBytes.byteLength / 2\n );\n const keyByteStr = String.fromCharCode.apply(\n null,\n Array.from(keyBytesUtf16)\n );\n\n // Parse Playready WRMHeader XML\n const xmlKeyBytes = keyByteStr.substring(\n keyByteStr.indexOf('<'),\n keyByteStr.length\n );\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlKeyBytes, 'text/xml');\n const keyData = xmlDoc.getElementsByTagName('KID')[0];\n if (keyData) {\n const keyId = keyData.childNodes[0]\n ? keyData.childNodes[0].nodeValue\n : keyData.getAttribute('VALUE');\n if (keyId) {\n const keyIdArray = base64Decode(keyId).subarray(0, 16);\n // KID value in PRO is a base64-encoded little endian GUID interpretation of UUID\n // KID value in ‘tenc’ is a big endian UUID GUID interpretation of UUID\n changeEndianness(keyIdArray);\n this.keyId = keyIdArray;\n }\n }\n break;\n }\n default: {\n let keydata = keyBytes.subarray(0, 16);\n if (keydata.length !== 16) {\n const padded = new Uint8Array(16);\n padded.set(keydata, 16 - keydata.length);\n keydata = padded;\n }\n this.keyId = keydata;\n break;\n }\n }\n }\n\n // Default behavior: assign a new keyId for each uri\n if (!this.keyId || this.keyId.byteLength !== 16) {\n let keyId = keyUriToKeyIdMap[this.uri];\n if (!keyId) {\n const val =\n Object.keys(keyUriToKeyIdMap).length % Number.MAX_SAFE_INTEGER;\n keyId = new Uint8Array(16);\n const dv = new DataView(keyId.buffer, 12, 4); // Just set the last 4 bytes\n dv.setUint32(0, val);\n keyUriToKeyIdMap[this.uri] = keyId;\n }\n this.keyId = keyId;\n }\n\n return this;\n }\n}\n\nfunction createInitializationVector(segmentNumber: number): Uint8Array {\n const uint8View = new Uint8Array(16);\n for (let i = 12; i < 16; i++) {\n uint8View[i] = (segmentNumber >> (8 * (15 - i))) & 0xff;\n }\n return uint8View;\n}\n","import type { AttrList } from './attr-list';\nimport type { ParsedMultivariantPlaylist } from '../loader/m3u8-parser';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { VariableMap } from '../types/level';\n\nconst VARIABLE_REPLACEMENT_REGEX = /\\{\\$([a-zA-Z0-9-_]+)\\}/g;\n\nexport function hasVariableReferences(str: string): boolean {\n return VARIABLE_REPLACEMENT_REGEX.test(str);\n}\n\nexport function substituteVariablesInAttributes(\n parsed: Pick<\n ParsedMultivariantPlaylist | LevelDetails,\n 'variableList' | 'hasVariableRefs' | 'playlistParsingError'\n >,\n attr: AttrList,\n attributeNames: string[]\n) {\n if (parsed.variableList !== null || parsed.hasVariableRefs) {\n for (let i = attributeNames.length; i--; ) {\n const name = attributeNames[i];\n const value = attr[name];\n if (value) {\n attr[name] = substituteVariables(parsed, value);\n }\n }\n }\n}\n\nexport function substituteVariables(\n parsed: Pick<\n ParsedMultivariantPlaylist | LevelDetails,\n 'variableList' | 'hasVariableRefs' | 'playlistParsingError'\n >,\n value: string\n): string {\n if (parsed.variableList !== null || parsed.hasVariableRefs) {\n const variableList = parsed.variableList;\n return value.replace(\n VARIABLE_REPLACEMENT_REGEX,\n (variableReference: string) => {\n const variableName = variableReference.substring(\n 2,\n variableReference.length - 1\n );\n const variableValue = variableList?.[variableName];\n if (variableValue === undefined) {\n parsed.playlistParsingError ||= new Error(\n `Missing preceding EXT-X-DEFINE tag for Variable Reference: \"${variableName}\"`\n );\n return variableReference;\n }\n return variableValue;\n }\n );\n }\n return value;\n}\n\nexport function addVariableDefinition(\n parsed: Pick<\n ParsedMultivariantPlaylist | LevelDetails,\n 'variableList' | 'playlistParsingError'\n >,\n attr: AttrList,\n parentUrl: string\n) {\n let variableList = parsed.variableList;\n if (!variableList) {\n parsed.variableList = variableList = {};\n }\n let NAME: string;\n let VALUE;\n if ('QUERYPARAM' in attr) {\n NAME = attr.QUERYPARAM;\n try {\n const searchParams = new self.URL(parentUrl).searchParams;\n if (searchParams.has(NAME)) {\n VALUE = searchParams.get(NAME);\n } else {\n throw new Error(\n `\"${NAME}\" does not match any query parameter in URI: \"${parentUrl}\"`\n );\n }\n } catch (error) {\n parsed.playlistParsingError ||= new Error(\n `EXT-X-DEFINE QUERYPARAM: ${error.message}`\n );\n }\n } else {\n NAME = attr.NAME;\n VALUE = attr.VALUE;\n }\n if (NAME in variableList) {\n parsed.playlistParsingError ||= new Error(\n `EXT-X-DEFINE duplicate Variable Name declarations: \"${NAME}\"`\n );\n } else {\n variableList[NAME] = VALUE || '';\n }\n}\n\nexport function importVariableDefinition(\n parsed: Pick<\n ParsedMultivariantPlaylist | LevelDetails,\n 'variableList' | 'playlistParsingError'\n >,\n attr: AttrList,\n sourceVariableList: VariableMap | null\n) {\n const IMPORT = attr.IMPORT;\n if (sourceVariableList && IMPORT in sourceVariableList) {\n let variableList = parsed.variableList;\n if (!variableList) {\n parsed.variableList = variableList = {};\n }\n variableList[IMPORT] = sourceVariableList[IMPORT];\n } else {\n parsed.playlistParsingError ||= new Error(\n `EXT-X-DEFINE IMPORT attribute not found in Multivariant Playlist: \"${IMPORT}\"`\n );\n }\n}\n","/**\n * MediaSource helper\n */\n\nexport function getMediaSource(): typeof MediaSource | undefined {\n if (typeof self === 'undefined') return undefined;\n return self.MediaSource || ((self as any).WebKitMediaSource as MediaSource);\n}\n","import { getMediaSource } from './mediasource-helper';\n\n// from http://mp4ra.org/codecs.html\nconst sampleEntryCodesISO = {\n audio: {\n a3ds: true,\n 'ac-3': true,\n 'ac-4': true,\n alac: true,\n alaw: true,\n dra1: true,\n 'dts+': true,\n 'dts-': true,\n dtsc: true,\n dtse: true,\n dtsh: true,\n 'ec-3': true,\n enca: true,\n g719: true,\n g726: true,\n m4ae: true,\n mha1: true,\n mha2: true,\n mhm1: true,\n mhm2: true,\n mlpa: true,\n mp4a: true,\n 'raw ': true,\n Opus: true,\n opus: true, // browsers expect this to be lowercase despite MP4RA says 'Opus'\n samr: true,\n sawb: true,\n sawp: true,\n sevc: true,\n sqcp: true,\n ssmv: true,\n twos: true,\n ulaw: true,\n },\n video: {\n avc1: true,\n avc2: true,\n avc3: true,\n avc4: true,\n avcp: true,\n av01: true,\n drac: true,\n dva1: true,\n dvav: true,\n dvh1: true,\n dvhe: true,\n encv: true,\n hev1: true,\n hvc1: true,\n mjp2: true,\n mp4v: true,\n mvc1: true,\n mvc2: true,\n mvc3: true,\n mvc4: true,\n resv: true,\n rv60: true,\n s263: true,\n svc1: true,\n svc2: true,\n 'vc-1': true,\n vp08: true,\n vp09: true,\n },\n text: {\n stpp: true,\n wvtt: true,\n },\n};\n\nconst MediaSource = getMediaSource();\n\nexport type CodecType = 'audio' | 'video';\n\nexport function isCodecType(codec: string, type: CodecType): boolean {\n const typeCodes = sampleEntryCodesISO[type];\n return !!typeCodes && typeCodes[codec.slice(0, 4)] === true;\n}\n\nexport function isCodecSupportedInMp4(codec: string, type: CodecType): boolean {\n return (\n MediaSource?.isTypeSupported(`${type || 'video'}/mp4;codecs=\"${codec}\"`) ??\n false\n );\n}\n","import { buildAbsoluteURL } from 'url-toolkit';\nimport { DateRange } from './date-range';\nimport { Fragment, Part } from './fragment';\nimport { LevelDetails } from './level-details';\nimport { LevelKey } from './level-key';\nimport { AttrList } from '../utils/attr-list';\nimport { logger } from '../utils/logger';\nimport {\n addVariableDefinition,\n hasVariableReferences,\n importVariableDefinition,\n substituteVariables,\n substituteVariablesInAttributes,\n} from '../utils/variable-substitution';\nimport { isCodecType } from '../utils/codecs';\nimport type { CodecType } from '../utils/codecs';\nimport type {\n MediaPlaylist,\n AudioGroup,\n MediaPlaylistType,\n MediaAttributes,\n} from '../types/media-playlist';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { LevelAttributes, LevelParsed, VariableMap } from '../types/level';\nimport type { ContentSteeringOptions } from '../types/events';\n\ntype M3U8ParserFragments = Array;\n\nexport type ParsedMultivariantPlaylist = {\n contentSteering: ContentSteeringOptions | null;\n levels: LevelParsed[];\n playlistParsingError: Error | null;\n sessionData: Record | null;\n sessionKeys: LevelKey[] | null;\n startTimeOffset: number | null;\n variableList: VariableMap | null;\n hasVariableRefs: boolean;\n};\n\ntype ParsedMultivariantMediaOptions = {\n AUDIO?: MediaPlaylist[];\n SUBTITLES?: MediaPlaylist[];\n 'CLOSED-CAPTIONS'?: MediaPlaylist[];\n};\n\nconst MASTER_PLAYLIST_REGEX =\n /#EXT-X-STREAM-INF:([^\\r\\n]*)(?:[\\r\\n](?:#[^\\r\\n]*)?)*([^\\r\\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\\r\\n]*)[\\r\\n]+/g;\nconst MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;\n\nconst IS_MEDIA_PLAYLIST = /^#EXT(?:INF|-X-TARGETDURATION):/m; // Handle empty Media Playlist (first EXTINF not signaled, but TARGETDURATION present)\n\nconst LEVEL_PLAYLIST_REGEX_FAST = new RegExp(\n [\n /#EXTINF:\\s*(\\d*(?:\\.\\d+)?)(?:,(.*)\\s+)?/.source, // duration (#EXTINF:,), group 1 => duration, group 2 => title\n /(?!#) *(\\S[\\S ]*)/.source, // segment URI, group 3 => the URI (note newline is not eaten)\n /#EXT-X-BYTERANGE:*(.+)/.source, // next segment's byterange, group 4 => range spec (x@y)\n /#EXT-X-PROGRAM-DATE-TIME:(.+)/.source, // next segment's program date/time group 5 => the datetime spec\n /#.*/.source, // All other non-segment oriented tags will match with all groups empty\n ].join('|'),\n 'g'\n);\n\nconst LEVEL_PLAYLIST_REGEX_SLOW = new RegExp(\n [\n /#(EXTM3U)/.source,\n /#EXT-X-(DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/\n .source,\n /#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\\d+)/\n .source,\n /#EXT-X-(DISCONTINUITY|ENDLIST|GAP)/.source,\n /(#)([^:]*):(.*)/.source,\n /(#)(.*)(?:.*)\\r?\\n?/.source,\n ].join('|')\n);\n\nexport default class M3U8Parser {\n static findGroup(\n groups: Array<AudioGroup>,\n mediaGroupId: string\n ): AudioGroup | undefined {\n for (let i = 0; i < groups.length; i++) {\n const group = groups[i];\n if (group.id === mediaGroupId) {\n return group;\n }\n }\n }\n\n static convertAVC1ToAVCOTI(codec) {\n // Convert avc1 codec string from RFC-4281 to RFC-6381 for MediaSource.isTypeSupported\n const avcdata = codec.split('.');\n if (avcdata.length > 2) {\n let result = avcdata.shift() + '.';\n result += parseInt(avcdata.shift()).toString(16);\n result += ('000' + parseInt(avcdata.shift()).toString(16)).slice(-4);\n return result;\n }\n return codec;\n }\n\n static resolve(url, baseUrl) {\n return buildAbsoluteURL(baseUrl, url, { alwaysNormalize: true });\n }\n\n static isMediaPlaylist(str: string): boolean {\n return IS_MEDIA_PLAYLIST.test(str);\n }\n\n static parseMasterPlaylist(\n string: string,\n baseurl: string\n ): ParsedMultivariantPlaylist {\n const hasVariableRefs = __USE_VARIABLE_SUBSTITUTION__\n ? hasVariableReferences(string)\n : false;\n const parsed: ParsedMultivariantPlaylist = {\n contentSteering: null,\n levels: [],\n playlistParsingError: null,\n sessionData: null,\n sessionKeys: null,\n startTimeOffset: null,\n variableList: null,\n hasVariableRefs,\n };\n const levelsWithKnownCodecs: LevelParsed[] = [];\n\n MASTER_PLAYLIST_REGEX.lastIndex = 0;\n\n let result: RegExpExecArray | null;\n while ((result = MASTER_PLAYLIST_REGEX.exec(string)) != null) {\n if (result[1]) {\n // '#EXT-X-STREAM-INF' is found, parse level tag in group 1\n const attrs = new AttrList(result[1]) as LevelAttributes;\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(parsed, attrs, [\n 'CODECS',\n 'SUPPLEMENTAL-CODECS',\n 'ALLOWED-CPC',\n 'PATHWAY-ID',\n 'STABLE-VARIANT-ID',\n 'AUDIO',\n 'VIDEO',\n 'SUBTITLES',\n 'CLOSED-CAPTIONS',\n 'NAME',\n ]);\n }\n const uri = __USE_VARIABLE_SUBSTITUTION__\n ? substituteVariables(parsed, result[2])\n : result[2];\n const level: LevelParsed = {\n attrs,\n bitrate:\n attrs.decimalInteger('AVERAGE-BANDWIDTH') ||\n attrs.decimalInteger('BANDWIDTH'),\n name: attrs.NAME,\n url: M3U8Parser.resolve(uri, baseurl),\n };\n\n const resolution = attrs.decimalResolution('RESOLUTION');\n if (resolution) {\n level.width = resolution.width;\n level.height = resolution.height;\n }\n\n setCodecs(\n ((attrs.CODECS as string) || '').split(/[ ,]+/).filter((c) => c),\n level\n );\n\n if (level.videoCodec && level.videoCodec.indexOf('avc1') !== -1) {\n level.videoCodec = M3U8Parser.convertAVC1ToAVCOTI(level.videoCodec);\n }\n\n if (!level.unknownCodecs?.length) {\n levelsWithKnownCodecs.push(level);\n }\n\n parsed.levels.push(level);\n } else if (result[3]) {\n const tag = result[3];\n const attributes = result[4];\n switch (tag) {\n case 'SESSION-DATA': {\n // #EXT-X-SESSION-DATA\n const sessionAttrs = new AttrList(attributes);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(parsed, sessionAttrs, [\n 'DATA-ID',\n 'LANGUAGE',\n 'VALUE',\n 'URI',\n ]);\n }\n const dataId = sessionAttrs['DATA-ID'];\n if (dataId) {\n if (parsed.sessionData === null) {\n parsed.sessionData = {};\n }\n parsed.sessionData[dataId] = sessionAttrs;\n }\n break;\n }\n case 'SESSION-KEY': {\n // #EXT-X-SESSION-KEY\n const sessionKey = parseKey(attributes, baseurl, parsed);\n if (sessionKey.encrypted && sessionKey.isSupported()) {\n if (parsed.sessionKeys === null) {\n parsed.sessionKeys = [];\n }\n parsed.sessionKeys.push(sessionKey);\n } else {\n logger.warn(\n `[Keys] Ignoring invalid EXT-X-SESSION-KEY tag: \"${attributes}\"`\n );\n }\n break;\n }\n case 'DEFINE': {\n // #EXT-X-DEFINE\n if (__USE_VARIABLE_SUBSTITUTION__) {\n const variableAttributes = new AttrList(attributes);\n substituteVariablesInAttributes(parsed, variableAttributes, [\n 'NAME',\n 'VALUE',\n 'QUERYPARAM',\n ]);\n addVariableDefinition(parsed, variableAttributes, baseurl);\n }\n break;\n }\n case 'CONTENT-STEERING': {\n // #EXT-X-CONTENT-STEERING\n const contentSteeringAttributes = new AttrList(attributes);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(\n parsed,\n contentSteeringAttributes,\n ['SERVER-URI', 'PATHWAY-ID']\n );\n }\n parsed.contentSteering = {\n uri: M3U8Parser.resolve(\n contentSteeringAttributes['SERVER-URI'],\n baseurl\n ),\n pathwayId: contentSteeringAttributes['PATHWAY-ID'] || '.',\n };\n break;\n }\n case 'START': {\n // #EXT-X-START\n parsed.startTimeOffset = parseStartTimeOffset(attributes);\n break;\n }\n default:\n break;\n }\n }\n }\n // Filter out levels with unknown codecs if it does not remove all levels\n const stripUnknownCodecLevels =\n levelsWithKnownCodecs.length > 0 &&\n levelsWithKnownCodecs.length < parsed.levels.length;\n\n parsed.levels = stripUnknownCodecLevels\n ? levelsWithKnownCodecs\n : parsed.levels;\n if (parsed.levels.length === 0) {\n parsed.playlistParsingError = new Error('no levels found in manifest');\n }\n\n return parsed;\n }\n\n static parseMasterPlaylistMedia(\n string: string,\n baseurl: string,\n parsed: ParsedMultivariantPlaylist\n ): ParsedMultivariantMediaOptions {\n let result: RegExpExecArray | null;\n const results: ParsedMultivariantMediaOptions = {};\n const levels = parsed.levels;\n const groupsByType = {\n AUDIO: levels.map((level: LevelParsed) => ({\n id: level.attrs.AUDIO,\n audioCodec: level.audioCodec,\n })),\n SUBTITLES: levels.map((level: LevelParsed) => ({\n id: level.attrs.SUBTITLES,\n textCodec: level.textCodec,\n })),\n 'CLOSED-CAPTIONS': [],\n };\n let id = 0;\n MASTER_PLAYLIST_MEDIA_REGEX.lastIndex = 0;\n while ((result = MASTER_PLAYLIST_MEDIA_REGEX.exec(string)) !== null) {\n const attrs = new AttrList(result[1]) as MediaAttributes;\n const type: MediaPlaylistType | undefined = attrs.TYPE as\n | MediaPlaylistType\n | undefined;\n if (type) {\n const groups = groupsByType[type];\n const medias: MediaPlaylist[] = results[type] || [];\n results[type] = medias;\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(parsed, attrs, [\n 'URI',\n 'GROUP-ID',\n 'LANGUAGE',\n 'ASSOC-LANGUAGE',\n 'STABLE-RENDITION-ID',\n 'NAME',\n 'INSTREAM-ID',\n 'CHARACTERISTICS',\n 'CHANNELS',\n ]);\n }\n const media: MediaPlaylist = {\n attrs,\n bitrate: 0,\n id: id++,\n groupId: attrs['GROUP-ID'] || '',\n instreamId: attrs['INSTREAM-ID'],\n name: attrs.NAME || attrs.LANGUAGE || '',\n type,\n default: attrs.bool('DEFAULT'),\n autoselect: attrs.bool('AUTOSELECT'),\n forced: attrs.bool('FORCED'),\n lang: attrs.LANGUAGE,\n url: attrs.URI ? M3U8Parser.resolve(attrs.URI, baseurl) : '',\n };\n\n if (groups?.length) {\n // If there are audio or text groups signalled in the manifest, let's look for a matching codec string for this track\n // If we don't find the track signalled, lets use the first audio groups codec we have\n // Acting as a best guess\n const groupCodec =\n M3U8Parser.findGroup(groups, media.groupId as string) || groups[0];\n assignCodec(media, groupCodec, 'audioCodec');\n assignCodec(media, groupCodec, 'textCodec');\n }\n\n medias.push(media);\n }\n }\n return results;\n }\n\n static parseLevelPlaylist(\n string: string,\n baseurl: string,\n id: number,\n type: PlaylistLevelType,\n levelUrlId: number,\n multivariantVariableList: VariableMap | null\n ): LevelDetails {\n const level = new LevelDetails(baseurl);\n const fragments: M3U8ParserFragments = level.fragments;\n // The most recent init segment seen (applies to all subsequent segments)\n let currentInitSegment: Fragment | null = null;\n let currentSN = 0;\n let currentPart = 0;\n let totalduration = 0;\n let discontinuityCounter = 0;\n let prevFrag: Fragment | null = null;\n let frag: Fragment = new Fragment(type, baseurl);\n let result: RegExpExecArray | RegExpMatchArray | null;\n let i: number;\n let levelkeys: { [key: string]: LevelKey } | undefined;\n let firstPdtIndex = -1;\n let createNextFrag = false;\n\n LEVEL_PLAYLIST_REGEX_FAST.lastIndex = 0;\n level.m3u8 = string;\n level.hasVariableRefs = __USE_VARIABLE_SUBSTITUTION__\n ? hasVariableReferences(string)\n : false;\n\n while ((result = LEVEL_PLAYLIST_REGEX_FAST.exec(string)) !== null) {\n if (createNextFrag) {\n createNextFrag = false;\n frag = new Fragment(type, baseurl);\n // setup the next fragment for part loading\n frag.start = totalduration;\n frag.sn = currentSN;\n frag.cc = discontinuityCounter;\n frag.level = id;\n if (currentInitSegment) {\n frag.initSegment = currentInitSegment;\n frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime;\n currentInitSegment.rawProgramDateTime = null;\n }\n }\n\n const duration = result[1];\n if (duration) {\n // INF\n frag.duration = parseFloat(duration);\n // avoid sliced strings https://github.com/video-dev/hls.js/issues/939\n const title = (' ' + result[2]).slice(1);\n frag.title = title || null;\n frag.tagList.push(title ? ['INF', duration, title] : ['INF', duration]);\n } else if (result[3]) {\n // url\n if (Number.isFinite(frag.duration)) {\n frag.start = totalduration;\n if (levelkeys) {\n setFragLevelKeys(frag, levelkeys, level);\n }\n frag.sn = currentSN;\n frag.level = id;\n frag.cc = discontinuityCounter;\n frag.urlId = levelUrlId;\n fragments.push(frag);\n // avoid sliced strings https://github.com/video-dev/hls.js/issues/939\n const uri = (' ' + result[3]).slice(1);\n frag.relurl = __USE_VARIABLE_SUBSTITUTION__\n ? substituteVariables(level, uri)\n : uri;\n assignProgramDateTime(frag, prevFrag);\n prevFrag = frag;\n totalduration += frag.duration;\n currentSN++;\n currentPart = 0;\n createNextFrag = true;\n }\n } else if (result[4]) {\n // X-BYTERANGE\n const data = (' ' + result[4]).slice(1);\n if (prevFrag) {\n frag.setByteRange(data, prevFrag);\n } else {\n frag.setByteRange(data);\n }\n } else if (result[5]) {\n // PROGRAM-DATE-TIME\n // avoid sliced strings https://github.com/video-dev/hls.js/issues/939\n frag.rawProgramDateTime = (' ' + result[5]).slice(1);\n frag.tagList.push(['PROGRAM-DATE-TIME', frag.rawProgramDateTime]);\n if (firstPdtIndex === -1) {\n firstPdtIndex = fragments.length;\n }\n } else {\n result = result[0].match(LEVEL_PLAYLIST_REGEX_SLOW);\n if (!result) {\n logger.warn('No matches on slow regex match for level playlist!');\n continue;\n }\n for (i = 1; i < result.length; i++) {\n if (typeof result[i] !== 'undefined') {\n break;\n }\n }\n\n // avoid sliced strings https://github.com/video-dev/hls.js/issues/939\n const tag = (' ' + result[i]).slice(1);\n const value1 = (' ' + result[i + 1]).slice(1);\n const value2 = result[i + 2] ? (' ' + result[i + 2]).slice(1) : '';\n\n switch (tag) {\n case 'PLAYLIST-TYPE':\n level.type = value1.toUpperCase();\n break;\n case 'MEDIA-SEQUENCE':\n currentSN = level.startSN = parseInt(value1);\n break;\n case 'SKIP': {\n const skipAttrs = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, skipAttrs, [\n 'RECENTLY-REMOVED-DATERANGES',\n ]);\n }\n const skippedSegments =\n skipAttrs.decimalInteger('SKIPPED-SEGMENTS');\n if (Number.isFinite(skippedSegments)) {\n level.skippedSegments = skippedSegments;\n // This will result in fragments[] containing undefined values, which we will fill in with `mergeDetails`\n for (let i = skippedSegments; i--; ) {\n fragments.unshift(null);\n }\n currentSN += skippedSegments;\n }\n const recentlyRemovedDateranges = skipAttrs.enumeratedString(\n 'RECENTLY-REMOVED-DATERANGES'\n );\n if (recentlyRemovedDateranges) {\n level.recentlyRemovedDateranges =\n recentlyRemovedDateranges.split('\\t');\n }\n break;\n }\n case 'TARGETDURATION':\n level.targetduration = Math.max(parseInt(value1), 1);\n break;\n case 'VERSION':\n level.version = parseInt(value1);\n break;\n case 'EXTM3U':\n break;\n case 'ENDLIST':\n level.live = false;\n break;\n case '#':\n if (value1 || value2) {\n frag.tagList.push(value2 ? [value1, value2] : [value1]);\n }\n break;\n case 'DISCONTINUITY':\n discontinuityCounter++;\n frag.tagList.push(['DIS']);\n break;\n case 'GAP':\n frag.gap = true;\n frag.tagList.push([tag]);\n break;\n case 'BITRATE':\n frag.tagList.push([tag, value1]);\n break;\n case 'DATERANGE': {\n const dateRangeAttr = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, dateRangeAttr, [\n 'ID',\n 'CLASS',\n 'START-DATE',\n 'END-DATE',\n 'SCTE35-CMD',\n 'SCTE35-OUT',\n 'SCTE35-IN',\n ]);\n substituteVariablesInAttributes(\n level,\n dateRangeAttr,\n dateRangeAttr.clientAttrs\n );\n }\n const dateRange = new DateRange(\n dateRangeAttr,\n level.dateRanges[dateRangeAttr.ID]\n );\n if (dateRange.isValid || level.skippedSegments) {\n level.dateRanges[dateRange.id] = dateRange;\n } else {\n logger.warn(`Ignoring invalid DATERANGE tag: \"${value1}\"`);\n }\n // Add to fragment tag list for backwards compatibility (< v1.2.0)\n frag.tagList.push(['EXT-X-DATERANGE', value1]);\n break;\n }\n case 'DEFINE': {\n if (__USE_VARIABLE_SUBSTITUTION__) {\n const variableAttributes = new AttrList(value1);\n substituteVariablesInAttributes(level, variableAttributes, [\n 'NAME',\n 'VALUE',\n 'IMPORT',\n 'QUERYPARAM',\n ]);\n if ('IMPORT' in variableAttributes) {\n importVariableDefinition(\n level,\n variableAttributes,\n multivariantVariableList\n );\n } else {\n addVariableDefinition(level, variableAttributes, baseurl);\n }\n }\n break;\n }\n\n case 'DISCONTINUITY-SEQUENCE':\n discontinuityCounter = parseInt(value1);\n break;\n case 'KEY': {\n const levelKey = parseKey(value1, baseurl, level);\n if (levelKey.isSupported()) {\n if (levelKey.method === 'NONE') {\n levelkeys = undefined;\n break;\n }\n if (!levelkeys) {\n levelkeys = {};\n }\n if (levelkeys[levelKey.keyFormat]) {\n levelkeys = Object.assign({}, levelkeys);\n }\n levelkeys[levelKey.keyFormat] = levelKey;\n } else {\n logger.warn(`[Keys] Ignoring invalid EXT-X-KEY tag: \"${value1}\"`);\n }\n break;\n }\n case 'START':\n level.startTimeOffset = parseStartTimeOffset(value1);\n break;\n case 'MAP': {\n const mapAttrs = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, mapAttrs, [\n 'BYTERANGE',\n 'URI',\n ]);\n }\n if (frag.duration) {\n // Initial segment tag is after segment duration tag.\n // #EXTINF: 6.0\n // #EXT-X-MAP:URI=\"init.mp4\n const init = new Fragment(type, baseurl);\n setInitSegment(init, mapAttrs, id, levelkeys);\n currentInitSegment = init;\n frag.initSegment = currentInitSegment;\n if (\n currentInitSegment.rawProgramDateTime &&\n !frag.rawProgramDateTime\n ) {\n frag.rawProgramDateTime = currentInitSegment.rawProgramDateTime;\n }\n } else {\n // Initial segment tag is before segment duration tag\n setInitSegment(frag, mapAttrs, id, levelkeys);\n currentInitSegment = frag;\n createNextFrag = true;\n }\n break;\n }\n case 'SERVER-CONTROL': {\n const serverControlAttrs = new AttrList(value1);\n level.canBlockReload = serverControlAttrs.bool('CAN-BLOCK-RELOAD');\n level.canSkipUntil = serverControlAttrs.optionalFloat(\n 'CAN-SKIP-UNTIL',\n 0\n );\n level.canSkipDateRanges =\n level.canSkipUntil > 0 &&\n serverControlAttrs.bool('CAN-SKIP-DATERANGES');\n level.partHoldBack = serverControlAttrs.optionalFloat(\n 'PART-HOLD-BACK',\n 0\n );\n level.holdBack = serverControlAttrs.optionalFloat('HOLD-BACK', 0);\n break;\n }\n case 'PART-INF': {\n const partInfAttrs = new AttrList(value1);\n level.partTarget = partInfAttrs.decimalFloatingPoint('PART-TARGET');\n break;\n }\n case 'PART': {\n let partList = level.partList;\n if (!partList) {\n partList = level.partList = [];\n }\n const previousFragmentPart =\n currentPart > 0 ? partList[partList.length - 1] : undefined;\n const index = currentPart++;\n const partAttrs = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, partAttrs, [\n 'BYTERANGE',\n 'URI',\n ]);\n }\n const part = new Part(\n partAttrs,\n frag,\n baseurl,\n index,\n previousFragmentPart\n );\n partList.push(part);\n frag.duration += part.duration;\n break;\n }\n case 'PRELOAD-HINT': {\n const preloadHintAttrs = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, preloadHintAttrs, ['URI']);\n }\n level.preloadHint = preloadHintAttrs;\n break;\n }\n case 'RENDITION-REPORT': {\n const renditionReportAttrs = new AttrList(value1);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(level, renditionReportAttrs, [\n 'URI',\n ]);\n }\n level.renditionReports = level.renditionReports || [];\n level.renditionReports.push(renditionReportAttrs);\n break;\n }\n default:\n logger.warn(`line parsed but not handled: ${result}`);\n break;\n }\n }\n }\n if (prevFrag && !prevFrag.relurl) {\n fragments.pop();\n totalduration -= prevFrag.duration;\n if (level.partList) {\n level.fragmentHint = prevFrag;\n }\n } else if (level.partList) {\n assignProgramDateTime(frag, prevFrag);\n frag.cc = discontinuityCounter;\n level.fragmentHint = frag;\n if (levelkeys) {\n setFragLevelKeys(frag, levelkeys, level);\n }\n }\n const fragmentLength = fragments.length;\n const firstFragment = fragments[0];\n const lastFragment = fragments[fragmentLength - 1];\n totalduration += level.skippedSegments * level.targetduration;\n if (totalduration > 0 && fragmentLength && lastFragment) {\n level.averagetargetduration = totalduration / fragmentLength;\n const lastSn = lastFragment.sn;\n level.endSN = lastSn !== 'initSegment' ? lastSn : 0;\n if (!level.live) {\n lastFragment.endList = true;\n }\n if (firstFragment) {\n level.startCC = firstFragment.cc;\n }\n } else {\n level.endSN = 0;\n level.startCC = 0;\n }\n if (level.fragmentHint) {\n totalduration += level.fragmentHint.duration;\n }\n level.totalduration = totalduration;\n level.endCC = discontinuityCounter;\n\n /**\n * Backfill any missing PDT values\n * \"If the first EXT-X-PROGRAM-DATE-TIME tag in a Playlist appears after\n * one or more Media Segment URIs, the client SHOULD extrapolate\n * backward from that tag (using EXTINF durations and/or media\n * timestamps) to associate dates with those segments.\"\n * We have already extrapolated forward, but all fragments up to the first instance of PDT do not have their PDTs\n * computed.\n */\n if (firstPdtIndex > 0) {\n backfillProgramDateTimes(fragments, firstPdtIndex);\n }\n\n return level;\n }\n}\n\nfunction parseKey(\n keyTagAttributes: string,\n baseurl: string,\n parsed: ParsedMultivariantPlaylist | LevelDetails\n): LevelKey {\n // https://tools.ietf.org/html/rfc8216#section-4.3.2.4\n const keyAttrs = new AttrList(keyTagAttributes);\n if (__USE_VARIABLE_SUBSTITUTION__) {\n substituteVariablesInAttributes(parsed, keyAttrs, [\n 'KEYFORMAT',\n 'KEYFORMATVERSIONS',\n 'URI',\n 'IV',\n 'URI',\n ]);\n }\n const decryptmethod = keyAttrs.METHOD ?? '';\n const decrypturi = keyAttrs.URI;\n const decryptiv = keyAttrs.hexadecimalInteger('IV');\n const decryptkeyformatversions = keyAttrs.KEYFORMATVERSIONS;\n // From RFC: This attribute is OPTIONAL; its absence indicates an implicit value of \"identity\".\n const decryptkeyformat = keyAttrs.KEYFORMAT ?? 'identity';\n\n if (decrypturi && keyAttrs.IV && !decryptiv) {\n logger.error(`Invalid IV: ${keyAttrs.IV}`);\n }\n // If decrypturi is a URI with a scheme, then baseurl will be ignored\n // No uri is allowed when METHOD is NONE\n const resolvedUri = decrypturi ? M3U8Parser.resolve(decrypturi, baseurl) : '';\n const keyFormatVersions = (\n decryptkeyformatversions ? decryptkeyformatversions : '1'\n )\n .split('/')\n .map(Number)\n .filter(Number.isFinite);\n\n return new LevelKey(\n decryptmethod,\n resolvedUri,\n decryptkeyformat,\n keyFormatVersions,\n decryptiv\n );\n}\n\nfunction parseStartTimeOffset(startAttributes: string): number | null {\n const startAttrs = new AttrList(startAttributes);\n const startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET');\n if (Number.isFinite(startTimeOffset)) {\n return startTimeOffset;\n }\n return null;\n}\n\nfunction setCodecs(codecs: Array<string>, level: LevelParsed) {\n ['video', 'audio', 'text'].forEach((type: CodecType) => {\n const filtered = codecs.filter((codec) => isCodecType(codec, type));\n if (filtered.length) {\n const preferred = filtered.filter((codec) => {\n return (\n codec.lastIndexOf('avc1', 0) === 0 ||\n codec.lastIndexOf('mp4a', 0) === 0\n );\n });\n level[`${type}Codec`] = preferred.length > 0 ? preferred[0] : filtered[0];\n\n // remove from list\n codecs = codecs.filter((codec) => filtered.indexOf(codec) === -1);\n }\n });\n\n level.unknownCodecs = codecs;\n}\n\nfunction assignCodec(media, groupItem, codecProperty) {\n const codecValue = groupItem[codecProperty];\n if (codecValue) {\n media[codecProperty] = codecValue;\n }\n}\n\nfunction backfillProgramDateTimes(\n fragments: M3U8ParserFragments,\n firstPdtIndex: number\n) {\n let fragPrev = fragments[firstPdtIndex] as Fragment;\n for (let i = firstPdtIndex; i--; ) {\n const frag = fragments[i];\n // Exit on delta-playlist skipped segments\n if (!frag) {\n return;\n }\n frag.programDateTime =\n (fragPrev.programDateTime as number) - frag.duration * 1000;\n fragPrev = frag;\n }\n}\n\nfunction assignProgramDateTime(frag, prevFrag) {\n if (frag.rawProgramDateTime) {\n frag.programDateTime = Date.parse(frag.rawProgramDateTime);\n } else if (prevFrag?.programDateTime) {\n frag.programDateTime = prevFrag.endProgramDateTime;\n }\n\n if (!Number.isFinite(frag.programDateTime)) {\n frag.programDateTime = null;\n frag.rawProgramDateTime = null;\n }\n}\n\nfunction setInitSegment(\n frag: Fragment,\n mapAttrs: AttrList,\n id: number,\n levelkeys: { [key: string]: LevelKey } | undefined\n) {\n frag.relurl = mapAttrs.URI;\n if (mapAttrs.BYTERANGE) {\n frag.setByteRange(mapAttrs.BYTERANGE);\n }\n frag.level = id;\n frag.sn = 'initSegment';\n if (levelkeys) {\n frag.levelkeys = levelkeys;\n }\n frag.initSegment = null;\n}\n\nfunction setFragLevelKeys(\n frag: Fragment,\n levelkeys: { [key: string]: LevelKey },\n level: LevelDetails\n) {\n frag.levelkeys = levelkeys;\n const { encryptedFragments } = level;\n if (\n (!encryptedFragments.length ||\n encryptedFragments[encryptedFragments.length - 1].levelkeys !==\n levelkeys) &&\n Object.keys(levelkeys).some(\n (format) => levelkeys![format].isCommonEncryption\n )\n ) {\n encryptedFragments.push(frag);\n }\n}\n","import type { LoaderConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { Part } from '../loader/fragment';\nimport type { KeyLoaderInfo } from '../loader/key-loader';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { HlsUrlParameters } from './level';\n\nexport interface LoaderContext {\n // target URL\n url: string;\n // loader response type (arraybuffer or default response type for playlist)\n responseType: string;\n // headers\n headers?: Record<string, string>;\n // start byte range offset\n rangeStart?: number;\n // end byte range offset\n rangeEnd?: number;\n // true if onProgress should report partial chunk of loaded content\n progressData?: boolean;\n}\n\nexport interface FragmentLoaderContext extends LoaderContext {\n frag: Fragment;\n part: Part | null;\n resetIV?: boolean;\n}\n\nexport interface KeyLoaderContext extends LoaderContext {\n keyInfo: KeyLoaderInfo;\n frag: Fragment;\n}\n\nexport interface LoaderConfiguration {\n // LoaderConfig policy that overrides required settings\n loadPolicy: LoaderConfig;\n /**\n * @deprecated use LoaderConfig timeoutRetry and errorRetry maxNumRetry\n */\n // Max number of load retries\n maxRetry: number;\n /**\n * @deprecated use LoaderConfig maxTimeToFirstByteMs and maxLoadTimeMs\n */\n // Timeout after which `onTimeOut` callback will be triggered\n // when loading has not finished after that delay\n timeout: number;\n /**\n * @deprecated use LoaderConfig timeoutRetry and errorRetry retryDelayMs\n */\n // Delay between an I/O error and following connection retry (ms).\n // This to avoid spamming the server\n retryDelay: number;\n /**\n * @deprecated use LoaderConfig timeoutRetry and errorRetry maxRetryDelayMs\n */\n // max connection retry delay (ms)\n maxRetryDelay: number;\n // When streaming progressively, this is the minimum chunk size required to emit a PROGRESS event\n highWaterMark?: number;\n}\n\nexport interface LoaderResponse {\n url: string;\n data?: string | ArrayBuffer | Object;\n // Errors can include HTTP status code and error message\n // Successful responses should include status code 200\n code?: number;\n text?: string;\n}\n\nexport interface LoaderStats {\n aborted: boolean;\n loaded: number;\n retry: number;\n total: number;\n chunkCount: number;\n bwEstimate: number;\n loading: HlsProgressivePerformanceTiming;\n parsing: HlsPerformanceTiming;\n buffering: HlsProgressivePerformanceTiming;\n}\n\nexport interface HlsPerformanceTiming {\n start: number;\n end: number;\n}\n\nexport interface HlsChunkPerformanceTiming extends HlsPerformanceTiming {\n executeStart: number;\n executeEnd: number;\n}\n\nexport interface HlsProgressivePerformanceTiming extends HlsPerformanceTiming {\n first: number;\n}\n\nexport type LoaderOnSuccess<T extends LoaderContext> = (\n response: LoaderResponse,\n stats: LoaderStats,\n context: T,\n networkDetails: any\n) => void;\n\nexport type LoaderOnProgress<T extends LoaderContext> = (\n stats: LoaderStats,\n context: T,\n data: string | ArrayBuffer,\n networkDetails: any\n) => void;\n\nexport type LoaderOnError<T extends LoaderContext> = (\n error: {\n // error status code\n code: number;\n // error description\n text: string;\n },\n context: T,\n networkDetails: any,\n stats: LoaderStats\n) => void;\n\nexport type LoaderOnTimeout<T extends LoaderContext> = (\n stats: LoaderStats,\n context: T,\n networkDetails: any\n) => void;\n\nexport type LoaderOnAbort<T extends LoaderContext> = (\n stats: LoaderStats,\n context: T,\n networkDetails: any\n) => void;\n\nexport interface LoaderCallbacks<T extends LoaderContext> {\n onSuccess: LoaderOnSuccess<T>;\n onError: LoaderOnError<T>;\n onTimeout: LoaderOnTimeout<T>;\n onAbort?: LoaderOnAbort<T>;\n onProgress?: LoaderOnProgress<T>;\n}\n\nexport interface Loader<T extends LoaderContext> {\n destroy(): void;\n abort(): void;\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<T>\n ): void;\n /**\n * `getCacheAge()` is called by hls.js to get the duration that a given object\n * has been sitting in a cache proxy when playing live. If implemented,\n * this should return a value in seconds.\n *\n * For HTTP based loaders, this should return the contents of the \"age\" header.\n *\n * @returns time object being lodaded\n */\n getCacheAge?: () => number | null;\n getResponseHeader?: (name: string) => string | null;\n context: T;\n stats: LoaderStats;\n}\n\nexport const enum PlaylistContextType {\n MANIFEST = 'manifest',\n LEVEL = 'level',\n AUDIO_TRACK = 'audioTrack',\n SUBTITLE_TRACK = 'subtitleTrack',\n}\n\nexport const enum PlaylistLevelType {\n MAIN = 'main',\n AUDIO = 'audio',\n SUBTITLE = 'subtitle',\n}\n\nexport interface PlaylistLoaderContext extends LoaderContext {\n type: PlaylistContextType;\n // the level index to load\n level: number | null;\n // level or track id from LevelLoadingData / TrackLoadingData\n id: number | null;\n // track group id\n groupId?: string;\n // internal representation of a parsed m3u8 level playlist\n levelDetails?: LevelDetails;\n // Blocking playlist request delivery directives (or null id none were added to playlist url\n deliveryDirectives: HlsUrlParameters | null;\n}\n","/**\n * PlaylistLoader - delegate for media manifest/playlist loading tasks. Takes care of parsing media to internal data-models.\n *\n * Once loaded, dispatches events with parsed data-models of manifest/levels/audio/subtitle tracks.\n *\n * Uses loader(s) set in config to do actual internal loading of resource tasks.\n */\n\nimport { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { logger } from '../utils/logger';\nimport M3U8Parser from './m3u8-parser';\nimport type { LevelParsed, VariableMap } from '../types/level';\nimport type {\n Loader,\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n LoaderResponse,\n LoaderStats,\n PlaylistLoaderContext,\n} from '../types/loader';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { LevelDetails } from './level-details';\nimport { AttrList } from '../utils/attr-list';\nimport type Hls from '../hls';\nimport type {\n ErrorData,\n LevelLoadingData,\n ManifestLoadingData,\n TrackLoadingData,\n} from '../types/events';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { MediaAttributes } from '../types/media-playlist';\nimport type { LoaderConfig, RetryConfig } from '../config';\n\nfunction mapContextToLevelType(\n context: PlaylistLoaderContext\n): PlaylistLevelType {\n const { type } = context;\n\n switch (type) {\n case PlaylistContextType.AUDIO_TRACK:\n return PlaylistLevelType.AUDIO;\n case PlaylistContextType.SUBTITLE_TRACK:\n return PlaylistLevelType.SUBTITLE;\n default:\n return PlaylistLevelType.MAIN;\n }\n}\n\nfunction getResponseUrl(\n response: LoaderResponse,\n context: PlaylistLoaderContext\n): string {\n let url = response.url;\n // responseURL not supported on some browsers (it is used to detect URL redirection)\n // data-uri mode also not supported (but no need to detect redirection)\n if (url === undefined || url.indexOf('data:') === 0) {\n // fallback to initial URL\n url = context.url;\n }\n return url;\n}\n\nclass PlaylistLoader implements NetworkComponentAPI {\n private readonly hls: Hls;\n private readonly loaders: {\n [key: string]: Loader<LoaderContext>;\n } = Object.create(null);\n private variableList: VariableMap | null = null;\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.registerListeners();\n }\n\n public startLoad(startPosition: number): void {}\n\n public stopLoad(): void {\n this.destroyInternalLoaders();\n }\n\n private registerListeners() {\n const { hls } = this;\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.on(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);\n hls.on(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);\n }\n\n private unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.off(Events.AUDIO_TRACK_LOADING, this.onAudioTrackLoading, this);\n hls.off(Events.SUBTITLE_TRACK_LOADING, this.onSubtitleTrackLoading, this);\n }\n\n /**\n * Returns defaults or configured loader-type overloads (pLoader and loader config params)\n */\n private createInternalLoader(\n context: PlaylistLoaderContext\n ): Loader<LoaderContext> {\n const config = this.hls.config;\n const PLoader = config.pLoader;\n const Loader = config.loader;\n const InternalLoader = PLoader || Loader;\n const loader = new InternalLoader(config) as Loader<PlaylistLoaderContext>;\n\n this.loaders[context.type] = loader;\n return loader;\n }\n\n private getInternalLoader(\n context: PlaylistLoaderContext\n ): Loader<LoaderContext> | undefined {\n return this.loaders[context.type];\n }\n\n private resetInternalLoader(contextType): void {\n if (this.loaders[contextType]) {\n delete this.loaders[contextType];\n }\n }\n\n /**\n * Call `destroy` on all internal loader instances mapped (one per context type)\n */\n private destroyInternalLoaders(): void {\n for (const contextType in this.loaders) {\n const loader = this.loaders[contextType];\n if (loader) {\n loader.destroy();\n }\n\n this.resetInternalLoader(contextType);\n }\n }\n\n public destroy(): void {\n this.variableList = null;\n this.unregisterListeners();\n this.destroyInternalLoaders();\n }\n\n private onManifestLoading(\n event: Events.MANIFEST_LOADING,\n data: ManifestLoadingData\n ) {\n const { url } = data;\n this.variableList = null;\n this.load({\n id: null,\n level: 0,\n responseType: 'text',\n type: PlaylistContextType.MANIFEST,\n url,\n deliveryDirectives: null,\n });\n }\n\n private onLevelLoading(event: Events.LEVEL_LOADING, data: LevelLoadingData) {\n const { id, level, url, deliveryDirectives } = data;\n this.load({\n id,\n level,\n responseType: 'text',\n type: PlaylistContextType.LEVEL,\n url,\n deliveryDirectives,\n });\n }\n\n private onAudioTrackLoading(\n event: Events.AUDIO_TRACK_LOADING,\n data: TrackLoadingData\n ) {\n const { id, groupId, url, deliveryDirectives } = data;\n this.load({\n id,\n groupId,\n level: null,\n responseType: 'text',\n type: PlaylistContextType.AUDIO_TRACK,\n url,\n deliveryDirectives,\n });\n }\n\n private onSubtitleTrackLoading(\n event: Events.SUBTITLE_TRACK_LOADING,\n data: TrackLoadingData\n ) {\n const { id, groupId, url, deliveryDirectives } = data;\n this.load({\n id,\n groupId,\n level: null,\n responseType: 'text',\n type: PlaylistContextType.SUBTITLE_TRACK,\n url,\n deliveryDirectives,\n });\n }\n\n private load(context: PlaylistLoaderContext): void {\n const config = this.hls.config;\n\n // logger.debug(`[playlist-loader]: Loading playlist of type ${context.type}, level: ${context.level}, id: ${context.id}`);\n\n // Check if a loader for this context already exists\n let loader = this.getInternalLoader(context);\n if (loader) {\n const loaderContext = loader.context;\n if (loaderContext && loaderContext.url === context.url) {\n // same URL can't overlap\n logger.trace('[playlist-loader]: playlist request ongoing');\n return;\n }\n logger.log(\n `[playlist-loader]: aborting previous loader for type: ${context.type}`\n );\n loader.abort();\n }\n\n // apply different configs for retries depending on\n // context (manifest, level, audio/subs playlist)\n let loadPolicy: LoaderConfig;\n if (context.type === PlaylistContextType.MANIFEST) {\n loadPolicy = config.manifestLoadPolicy.default;\n } else {\n loadPolicy = Object.assign({}, config.playlistLoadPolicy.default, {\n timeoutRetry: null,\n errorRetry: null,\n });\n }\n loader = this.createInternalLoader(context);\n\n // Override level/track timeout for LL-HLS requests\n // (the default of 10000ms is counter productive to blocking playlist reload requests)\n if (context.deliveryDirectives?.part) {\n let levelDetails: LevelDetails | undefined;\n if (\n context.type === PlaylistContextType.LEVEL &&\n context.level !== null\n ) {\n levelDetails = this.hls.levels[context.level].details;\n } else if (\n context.type === PlaylistContextType.AUDIO_TRACK &&\n context.id !== null\n ) {\n levelDetails = this.hls.audioTracks[context.id].details;\n } else if (\n context.type === PlaylistContextType.SUBTITLE_TRACK &&\n context.id !== null\n ) {\n levelDetails = this.hls.subtitleTracks[context.id].details;\n }\n if (levelDetails) {\n const partTarget = levelDetails.partTarget;\n const targetDuration = levelDetails.targetduration;\n if (partTarget && targetDuration) {\n const maxLowLatencyPlaylistRefresh =\n Math.max(partTarget * 3, targetDuration * 0.8) * 1000;\n loadPolicy = Object.assign({}, loadPolicy, {\n maxTimeToFirstByteMs: Math.min(\n maxLowLatencyPlaylistRefresh,\n loadPolicy.maxTimeToFirstByteMs\n ),\n maxLoadTimeMs: Math.min(\n maxLowLatencyPlaylistRefresh,\n loadPolicy.maxTimeToFirstByteMs\n ),\n });\n }\n }\n }\n\n const legacyRetryCompatibility: RetryConfig | Record<string, void> =\n loadPolicy.errorRetry || loadPolicy.timeoutRetry || {};\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: legacyRetryCompatibility.maxNumRetry || 0,\n retryDelay: legacyRetryCompatibility.retryDelayMs || 0,\n maxRetryDelay: legacyRetryCompatibility.maxRetryDelayMs || 0,\n };\n\n const loaderCallbacks: LoaderCallbacks<PlaylistLoaderContext> = {\n onSuccess: (response, stats, context, networkDetails) => {\n const loader = this.getInternalLoader(context) as\n | Loader<PlaylistLoaderContext>\n | undefined;\n this.resetInternalLoader(context.type);\n\n const string = response.data as string;\n\n // Validate if it is an M3U8 at all\n if (string.indexOf('#EXTM3U') !== 0) {\n this.handleManifestParsingError(\n response,\n context,\n new Error('no EXTM3U delimiter'),\n networkDetails || null,\n stats\n );\n return;\n }\n\n stats.parsing.start = performance.now();\n if (M3U8Parser.isMediaPlaylist(string)) {\n this.handleTrackOrLevelPlaylist(\n response,\n stats,\n context,\n networkDetails || null,\n loader\n );\n } else {\n this.handleMasterPlaylist(response, stats, context, networkDetails);\n }\n },\n onError: (response, context, networkDetails, stats) => {\n this.handleNetworkError(\n context,\n networkDetails,\n false,\n response,\n stats\n );\n },\n onTimeout: (stats, context, networkDetails) => {\n this.handleNetworkError(\n context,\n networkDetails,\n true,\n undefined,\n stats\n );\n },\n };\n\n // logger.debug(`[playlist-loader]: Calling internal loader delegate for URL: ${context.url}`);\n\n loader.load(context, loaderConfig, loaderCallbacks);\n }\n\n private handleMasterPlaylist(\n response: LoaderResponse,\n stats: LoaderStats,\n context: PlaylistLoaderContext,\n networkDetails: any\n ): void {\n const hls = this.hls;\n const string = response.data as string;\n\n const url = getResponseUrl(response, context);\n\n const parsedResult = M3U8Parser.parseMasterPlaylist(string, url);\n\n if (parsedResult.playlistParsingError) {\n this.handleManifestParsingError(\n response,\n context,\n parsedResult.playlistParsingError,\n networkDetails,\n stats\n );\n return;\n }\n\n const {\n contentSteering,\n levels,\n sessionData,\n sessionKeys,\n startTimeOffset,\n variableList,\n } = parsedResult;\n\n this.variableList = variableList;\n\n const {\n AUDIO: audioTracks = [],\n SUBTITLES: subtitles,\n 'CLOSED-CAPTIONS': captions,\n } = M3U8Parser.parseMasterPlaylistMedia(string, url, parsedResult);\n\n if (audioTracks.length) {\n // check if we have found an audio track embedded in main playlist (audio track without URI attribute)\n const embeddedAudioFound: boolean = audioTracks.some(\n (audioTrack) => !audioTrack.url\n );\n\n // if no embedded audio track defined, but audio codec signaled in quality level,\n // we need to signal this main audio track this could happen with playlists with\n // alt audio rendition in which quality levels (main)\n // contains both audio+video. but with mixed audio track not signaled\n if (\n !embeddedAudioFound &&\n levels[0].audioCodec &&\n !levels[0].attrs.AUDIO\n ) {\n logger.log(\n '[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one'\n );\n audioTracks.unshift({\n type: 'main',\n name: 'main',\n groupId: 'main',\n default: false,\n autoselect: false,\n forced: false,\n id: -1,\n attrs: new AttrList({}) as MediaAttributes,\n bitrate: 0,\n url: '',\n });\n }\n }\n\n hls.trigger(Events.MANIFEST_LOADED, {\n levels,\n audioTracks,\n subtitles,\n captions,\n contentSteering,\n url,\n stats,\n networkDetails,\n sessionData,\n sessionKeys,\n startTimeOffset,\n variableList,\n });\n }\n\n private handleTrackOrLevelPlaylist(\n response: LoaderResponse,\n stats: LoaderStats,\n context: PlaylistLoaderContext,\n networkDetails: any,\n loader: Loader<PlaylistLoaderContext> | undefined\n ): void {\n const hls = this.hls;\n const { id, level, type } = context;\n\n const url = getResponseUrl(response, context);\n const levelUrlId = Number.isFinite(id as number) ? (id as number) : 0;\n const levelId = Number.isFinite(level as number)\n ? (level as number)\n : levelUrlId;\n const levelType = mapContextToLevelType(context);\n const levelDetails: LevelDetails = M3U8Parser.parseLevelPlaylist(\n response.data as string,\n url,\n levelId,\n levelType,\n levelUrlId,\n this.variableList\n );\n\n // We have done our first request (Manifest-type) and receive\n // not a master playlist but a chunk-list (track/level)\n // We fire the manifest-loaded event anyway with the parsed level-details\n // by creating a single-level structure for it.\n if (type === PlaylistContextType.MANIFEST) {\n const singleLevel: LevelParsed = {\n attrs: new AttrList({}),\n bitrate: 0,\n details: levelDetails,\n name: '',\n url,\n };\n\n hls.trigger(Events.MANIFEST_LOADED, {\n levels: [singleLevel],\n audioTracks: [],\n url,\n stats,\n networkDetails,\n sessionData: null,\n sessionKeys: null,\n contentSteering: null,\n startTimeOffset: null,\n variableList: null,\n });\n }\n\n // save parsing time\n stats.parsing.end = performance.now();\n\n // extend the context with the new levelDetails property\n context.levelDetails = levelDetails;\n\n this.handlePlaylistLoaded(\n levelDetails,\n response,\n stats,\n context,\n networkDetails,\n loader\n );\n }\n\n private handleManifestParsingError(\n response: LoaderResponse,\n context: PlaylistLoaderContext,\n error: Error,\n networkDetails: any,\n stats: LoaderStats\n ): void {\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.MANIFEST_PARSING_ERROR,\n fatal: context.type === PlaylistContextType.MANIFEST,\n url: response.url,\n err: error,\n error,\n reason: error.message,\n response,\n context,\n networkDetails,\n stats,\n });\n }\n\n private handleNetworkError(\n context: PlaylistLoaderContext,\n networkDetails: any,\n timeout = false,\n response: { code: number; text: string } | undefined,\n stats: LoaderStats\n ): void {\n let message = `A network ${\n timeout\n ? 'timeout'\n : 'error' + (response ? ' (status ' + response.code + ')' : '')\n } occurred while loading ${context.type}`;\n if (context.type === PlaylistContextType.LEVEL) {\n message += `: ${context.level} id: ${context.id}`;\n } else if (\n context.type === PlaylistContextType.AUDIO_TRACK ||\n context.type === PlaylistContextType.SUBTITLE_TRACK\n ) {\n message += ` id: ${context.id} group-id: \"${context.groupId}\"`;\n }\n const error = new Error(message);\n logger.warn(`[playlist-loader]: ${message}`);\n let details = ErrorDetails.UNKNOWN;\n let fatal = false;\n\n const loader = this.getInternalLoader(context);\n\n switch (context.type) {\n case PlaylistContextType.MANIFEST:\n details = timeout\n ? ErrorDetails.MANIFEST_LOAD_TIMEOUT\n : ErrorDetails.MANIFEST_LOAD_ERROR;\n fatal = true;\n break;\n case PlaylistContextType.LEVEL:\n details = timeout\n ? ErrorDetails.LEVEL_LOAD_TIMEOUT\n : ErrorDetails.LEVEL_LOAD_ERROR;\n fatal = false;\n break;\n case PlaylistContextType.AUDIO_TRACK:\n details = timeout\n ? ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT\n : ErrorDetails.AUDIO_TRACK_LOAD_ERROR;\n fatal = false;\n break;\n case PlaylistContextType.SUBTITLE_TRACK:\n details = timeout\n ? ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT\n : ErrorDetails.SUBTITLE_LOAD_ERROR;\n fatal = false;\n break;\n }\n\n if (loader) {\n this.resetInternalLoader(context.type);\n }\n\n const errorData: ErrorData = {\n type: ErrorTypes.NETWORK_ERROR,\n details,\n fatal,\n url: context.url,\n loader,\n context,\n error,\n networkDetails,\n stats,\n };\n\n if (response) {\n const url = networkDetails?.url || context.url;\n errorData.response = { url, data: undefined as any, ...response };\n }\n\n this.hls.trigger(Events.ERROR, errorData);\n }\n\n private handlePlaylistLoaded(\n levelDetails: LevelDetails,\n response: LoaderResponse,\n stats: LoaderStats,\n context: PlaylistLoaderContext,\n networkDetails: any,\n loader: Loader<PlaylistLoaderContext> | undefined\n ): void {\n const hls = this.hls;\n const { type, level, id, groupId, deliveryDirectives } = context;\n const url = getResponseUrl(response, context);\n const parent = mapContextToLevelType(context);\n const levelIndex =\n typeof context.level === 'number' && parent === PlaylistLevelType.MAIN\n ? (level as number)\n : undefined;\n if (!levelDetails.fragments.length) {\n const error = new Error('No Segments found in Playlist');\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.LEVEL_EMPTY_ERROR,\n fatal: false,\n url,\n error,\n reason: error.message,\n response,\n context,\n level: levelIndex,\n parent,\n networkDetails,\n stats,\n });\n return;\n }\n if (!levelDetails.targetduration) {\n levelDetails.playlistParsingError = new Error('Missing Target Duration');\n }\n const error = levelDetails.playlistParsingError;\n if (error) {\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.LEVEL_PARSING_ERROR,\n fatal: false,\n url,\n error,\n reason: error.message,\n response,\n context,\n level: levelIndex,\n parent,\n networkDetails,\n stats,\n });\n return;\n }\n\n if (levelDetails.live && loader) {\n if (loader.getCacheAge) {\n levelDetails.ageHeader = loader.getCacheAge() || 0;\n }\n if (!loader.getCacheAge || isNaN(levelDetails.ageHeader)) {\n levelDetails.ageHeader = 0;\n }\n }\n\n switch (type) {\n case PlaylistContextType.MANIFEST:\n case PlaylistContextType.LEVEL:\n hls.trigger(Events.LEVEL_LOADED, {\n details: levelDetails,\n level: levelIndex || 0,\n id: id || 0,\n stats,\n networkDetails,\n deliveryDirectives,\n });\n break;\n case PlaylistContextType.AUDIO_TRACK:\n hls.trigger(Events.AUDIO_TRACK_LOADED, {\n details: levelDetails,\n id: id || 0,\n groupId: groupId || '',\n stats,\n networkDetails,\n deliveryDirectives,\n });\n break;\n case PlaylistContextType.SUBTITLE_TRACK:\n hls.trigger(Events.SUBTITLE_TRACK_LOADED, {\n details: levelDetails,\n id: id || 0,\n groupId: groupId || '',\n stats,\n networkDetails,\n deliveryDirectives,\n });\n break;\n }\n }\n}\n\nexport default PlaylistLoader;\n","import { logger } from './logger';\n\nexport function sendAddTrackEvent(track: TextTrack, videoEl: HTMLMediaElement) {\n let event: Event;\n try {\n event = new Event('addtrack');\n } catch (err) {\n // for IE11\n event = document.createEvent('Event');\n event.initEvent('addtrack', false, false);\n }\n (event as any).track = track;\n videoEl.dispatchEvent(event);\n}\n\nexport function addCueToTrack(track: TextTrack, cue: VTTCue) {\n // Sometimes there are cue overlaps on segmented vtts so the same\n // cue can appear more than once in different vtt files.\n // This avoid showing duplicated cues with same timecode and text.\n const mode = track.mode;\n if (mode === 'disabled') {\n track.mode = 'hidden';\n }\n if (track.cues && !track.cues.getCueById(cue.id)) {\n try {\n track.addCue(cue);\n if (!track.cues.getCueById(cue.id)) {\n throw new Error(`addCue is failed for: ${cue}`);\n }\n } catch (err) {\n logger.debug(`[texttrack-utils]: ${err}`);\n const textTrackCue = new (self.TextTrackCue as any)(\n cue.startTime,\n cue.endTime,\n cue.text\n );\n textTrackCue.id = cue.id;\n track.addCue(textTrackCue);\n }\n }\n if (mode === 'disabled') {\n track.mode = mode;\n }\n}\n\nexport function clearCurrentCues(track: TextTrack) {\n // When track.mode is disabled, track.cues will be null.\n // To guarantee the removal of cues, we need to temporarily\n // change the mode to hidden\n const mode = track.mode;\n if (mode === 'disabled') {\n track.mode = 'hidden';\n }\n if (track.cues) {\n for (let i = track.cues.length; i--; ) {\n track.removeCue(track.cues[i]);\n }\n }\n if (mode === 'disabled') {\n track.mode = mode;\n }\n}\n\nexport function removeCuesInRange(\n track: TextTrack,\n start: number,\n end: number,\n predicate?: (cue: TextTrackCue) => boolean\n) {\n const mode = track.mode;\n if (mode === 'disabled') {\n track.mode = 'hidden';\n }\n\n if (track.cues && track.cues.length > 0) {\n const cues = getCuesInRange(track.cues, start, end);\n for (let i = 0; i < cues.length; i++) {\n if (!predicate || predicate(cues[i])) {\n track.removeCue(cues[i]);\n }\n }\n }\n if (mode === 'disabled') {\n track.mode = mode;\n }\n}\n\n// Find first cue starting after given time.\n// Modified version of binary search O(log(n)).\nfunction getFirstCueIndexAfterTime(\n cues: TextTrackCueList | TextTrackCue[],\n time: number\n): number {\n // If first cue starts after time, start there\n if (time < cues[0].startTime) {\n return 0;\n }\n // If the last cue ends before time there is no overlap\n const len = cues.length - 1;\n if (time > cues[len].endTime) {\n return -1;\n }\n\n let left = 0;\n let right = len;\n\n while (left <= right) {\n const mid = Math.floor((right + left) / 2);\n\n if (time < cues[mid].startTime) {\n right = mid - 1;\n } else if (time > cues[mid].startTime && left < len) {\n left = mid + 1;\n } else {\n // If it's not lower or higher, it must be equal.\n return mid;\n }\n }\n // At this point, left and right have swapped.\n // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.\n return cues[left].startTime - time < time - cues[right].startTime\n ? left\n : right;\n}\n\nexport function getCuesInRange(\n cues: TextTrackCueList | TextTrackCue[],\n start: number,\n end: number\n): TextTrackCue[] {\n const cuesFound: TextTrackCue[] = [];\n const firstCueInRange = getFirstCueIndexAfterTime(cues, start);\n if (firstCueInRange > -1) {\n for (let i = firstCueInRange, len = cues.length; i < len; i++) {\n const cue = cues[i];\n if (cue.startTime >= start && cue.endTime <= end) {\n cuesFound.push(cue);\n } else if (cue.startTime > end) {\n return cuesFound;\n }\n }\n }\n return cuesFound;\n}\n","import type { RationalTimestamp } from '../utils/timescale-conversion';\n\nexport interface Demuxer {\n demux(\n data: Uint8Array,\n timeOffset: number,\n isSampleAes?: boolean,\n flush?: boolean\n ): DemuxerResult;\n demuxSampleAes(\n data: Uint8Array,\n keyData: KeyData,\n timeOffset: number\n ): Promise<DemuxerResult>;\n flush(timeOffset?: number): DemuxerResult | Promise<DemuxerResult>;\n destroy(): void;\n resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number\n );\n resetTimeStamp(defaultInitPTS?: RationalTimestamp | null): void;\n resetContiguity(): void;\n}\n\nexport interface DemuxerResult {\n audioTrack: DemuxedAudioTrack;\n videoTrack: DemuxedVideoTrack;\n id3Track: DemuxedMetadataTrack;\n textTrack: DemuxedUserdataTrack;\n}\n\nexport interface DemuxedTrack {\n type: string;\n id: number;\n pid: number;\n inputTimeScale: number;\n sequenceNumber: number;\n samples:\n | AudioSample[]\n | AvcSample[]\n | MetadataSample[]\n | UserdataSample[]\n | Uint8Array;\n timescale?: number;\n container?: string;\n dropped: number;\n duration?: number;\n pesData?: ElementaryStreamData | null;\n codec?: string;\n}\n\nexport interface PassthroughTrack extends DemuxedTrack {\n sampleDuration: number;\n samples: Uint8Array;\n timescale: number;\n duration: number;\n codec: string;\n}\nexport interface DemuxedAudioTrack extends DemuxedTrack {\n config?: number[];\n samplerate?: number;\n segmentCodec?: string;\n channelCount?: number;\n manifestCodec?: string;\n samples: AudioSample[];\n}\n\nexport interface DemuxedVideoTrack extends DemuxedTrack {\n width?: number;\n height?: number;\n pixelRatio?: [number, number];\n audFound?: boolean;\n pps?: Uint8Array[];\n sps?: Uint8Array[];\n naluState?: number;\n samples: AvcSample[] | Uint8Array;\n}\n\nexport interface DemuxedAvcTrack extends DemuxedVideoTrack {\n samples: AvcSample[];\n}\n\nexport interface DemuxedMetadataTrack extends DemuxedTrack {\n samples: MetadataSample[];\n}\n\nexport interface DemuxedUserdataTrack extends DemuxedTrack {\n samples: UserdataSample[];\n}\n\nexport const enum MetadataSchema {\n audioId3 = 'org.id3',\n dateRange = 'com.apple.quicktime.HLS',\n emsg = 'https://aomedia.org/emsg/ID3',\n}\nexport interface MetadataSample {\n pts: number;\n dts: number;\n duration: number;\n len?: number;\n data: Uint8Array;\n type: MetadataSchema;\n}\n\nexport interface UserdataSample {\n pts: number;\n bytes?: Uint8Array;\n type?: number;\n payloadType?: number;\n uuid?: string;\n userData?: string;\n userDataBytes?: Uint8Array;\n}\n\nexport interface AvcSample {\n dts: number;\n pts: number;\n key: boolean;\n frame: boolean;\n units: AvcSampleUnit[];\n debug: string;\n length: number;\n}\n\nexport interface AvcSampleUnit {\n data: Uint8Array;\n type: number;\n}\n\nexport type AudioSample = {\n unit: Uint8Array;\n pts: number;\n};\n\nexport type AudioFrame = {\n sample: AudioSample;\n length: number;\n missing: number;\n};\n\nexport interface ElementaryStreamData {\n data: Uint8Array[];\n size: number;\n}\n\nexport interface KeyData {\n method: string;\n key: Uint8Array;\n iv: Uint8Array;\n}\n","import { Events } from '../events';\nimport {\n sendAddTrackEvent,\n clearCurrentCues,\n removeCuesInRange,\n} from '../utils/texttrack-utils';\nimport * as ID3 from '../demux/id3';\nimport {\n DateRange,\n isDateRangeCueAttribute,\n isSCTE35Attribute,\n} from '../loader/date-range';\nimport { MetadataSchema } from '../types/demuxer';\nimport type {\n BufferFlushingData,\n FragParsingMetadataData,\n LevelUpdatedData,\n MediaAttachedData,\n} from '../types/events';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\n\ndeclare global {\n interface Window {\n WebKitDataCue: VTTCue | void;\n }\n}\n\ntype Cue = VTTCue | TextTrackCue;\n\nconst MIN_CUE_DURATION = 0.25;\n\nfunction getCueClass() {\n if (typeof self === 'undefined') return undefined;\n\n // Attempt to recreate Safari functionality by creating\n // WebKitDataCue objects when available and store the decoded\n // ID3 data in the value property of the cue\n return (self.WebKitDataCue || self.VTTCue || self.TextTrackCue) as any;\n}\n\n// VTTCue latest draft allows an infinite duration, fallback\n// to MAX_VALUE if necessary\nconst MAX_CUE_ENDTIME = (() => {\n const Cue = getCueClass();\n try {\n new Cue(0, Number.POSITIVE_INFINITY, '');\n } catch (e) {\n return Number.MAX_VALUE;\n }\n return Number.POSITIVE_INFINITY;\n})();\n\nfunction dateRangeDateToTimelineSeconds(date: Date, offset: number): number {\n return date.getTime() / 1000 - offset;\n}\n\nfunction hexToArrayBuffer(str): ArrayBuffer {\n return Uint8Array.from(\n str\n .replace(/^0x/, '')\n .replace(/([\\da-fA-F]{2}) ?/g, '0x$1 ')\n .replace(/ +$/, '')\n .split(' ')\n ).buffer;\n}\nclass ID3TrackController implements ComponentAPI {\n private hls: Hls;\n private id3Track: TextTrack | null = null;\n private media: HTMLMediaElement | null = null;\n private dateRangeCuesAppended: Record<\n string,\n { cues: Record<string, Cue>; dateRange: DateRange; durationKnown: boolean }\n > = {};\n\n constructor(hls) {\n this.hls = hls;\n this._registerListeners();\n }\n\n destroy() {\n this._unregisterListeners();\n this.id3Track = null;\n this.media = null;\n this.dateRangeCuesAppended = {};\n // @ts-ignore\n this.hls = null;\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);\n hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n }\n\n private _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.FRAG_PARSING_METADATA, this.onFragParsingMetadata, this);\n hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n }\n\n // Add ID3 metatadata text track.\n protected onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ): void {\n this.media = data.media;\n }\n\n protected onMediaDetaching(): void {\n if (!this.id3Track) {\n return;\n }\n clearCurrentCues(this.id3Track);\n this.id3Track = null;\n this.media = null;\n this.dateRangeCuesAppended = {};\n }\n\n private onManifestLoading() {\n this.dateRangeCuesAppended = {};\n }\n\n createTrack(media: HTMLMediaElement): TextTrack {\n const track = this.getID3Track(media.textTracks) as TextTrack;\n track.mode = 'hidden';\n return track;\n }\n\n getID3Track(textTracks: TextTrackList): TextTrack | void {\n if (!this.media) {\n return;\n }\n for (let i = 0; i < textTracks.length; i++) {\n const textTrack: TextTrack = textTracks[i];\n if (textTrack.kind === 'metadata' && textTrack.label === 'id3') {\n // send 'addtrack' when reusing the textTrack for metadata,\n // same as what we do for captions\n sendAddTrackEvent(textTrack, this.media);\n\n return textTrack;\n }\n }\n return this.media.addTextTrack('metadata', 'id3');\n }\n\n onFragParsingMetadata(\n event: Events.FRAG_PARSING_METADATA,\n data: FragParsingMetadataData\n ) {\n if (!this.media) {\n return;\n }\n\n const {\n hls: {\n config: { enableEmsgMetadataCues, enableID3MetadataCues },\n },\n } = this;\n if (!enableEmsgMetadataCues && !enableID3MetadataCues) {\n return;\n }\n\n const { samples } = data;\n\n // create track dynamically\n if (!this.id3Track) {\n this.id3Track = this.createTrack(this.media);\n }\n\n const Cue = getCueClass();\n\n for (let i = 0; i < samples.length; i++) {\n const type = samples[i].type;\n if (\n (type === MetadataSchema.emsg && !enableEmsgMetadataCues) ||\n !enableID3MetadataCues\n ) {\n continue;\n }\n\n const frames = ID3.getID3Frames(samples[i].data);\n if (frames) {\n const startTime = samples[i].pts;\n let endTime: number = startTime + samples[i].duration;\n\n if (endTime > MAX_CUE_ENDTIME) {\n endTime = MAX_CUE_ENDTIME;\n }\n\n const timeDiff = endTime - startTime;\n if (timeDiff <= 0) {\n endTime = startTime + MIN_CUE_DURATION;\n }\n\n for (let j = 0; j < frames.length; j++) {\n const frame = frames[j];\n // Safari doesn't put the timestamp frame in the TextTrack\n if (!ID3.isTimeStampFrame(frame)) {\n // add a bounds to any unbounded cues\n this.updateId3CueEnds(startTime, type);\n\n const cue = new Cue(startTime, endTime, '');\n cue.value = frame;\n if (type) {\n cue.type = type;\n }\n this.id3Track.addCue(cue);\n }\n }\n }\n }\n }\n\n updateId3CueEnds(startTime: number, type: MetadataSchema) {\n const cues = this.id3Track?.cues;\n if (cues) {\n for (let i = cues.length; i--; ) {\n const cue = cues[i] as any;\n if (\n cue.type === type &&\n cue.startTime < startTime &&\n cue.endTime === MAX_CUE_ENDTIME\n ) {\n cue.endTime = startTime;\n }\n }\n }\n }\n\n onBufferFlushing(\n event: Events.BUFFER_FLUSHING,\n { startOffset, endOffset, type }: BufferFlushingData\n ) {\n const { id3Track, hls } = this;\n if (!hls) {\n return;\n }\n\n const {\n config: { enableEmsgMetadataCues, enableID3MetadataCues },\n } = hls;\n if (id3Track && (enableEmsgMetadataCues || enableID3MetadataCues)) {\n let predicate;\n\n if (type === 'audio') {\n predicate = (cue) =>\n (cue as any).type === MetadataSchema.audioId3 &&\n enableID3MetadataCues;\n } else if (type === 'video') {\n predicate = (cue) =>\n (cue as any).type === MetadataSchema.emsg && enableEmsgMetadataCues;\n } else {\n predicate = (cue) =>\n ((cue as any).type === MetadataSchema.audioId3 &&\n enableID3MetadataCues) ||\n ((cue as any).type === MetadataSchema.emsg && enableEmsgMetadataCues);\n }\n removeCuesInRange(id3Track, startOffset, endOffset, predicate);\n }\n }\n\n onLevelUpdated(event: Events.LEVEL_UPDATED, { details }: LevelUpdatedData) {\n if (\n !this.media ||\n !details.hasProgramDateTime ||\n !this.hls.config.enableDateRangeMetadataCues\n ) {\n return;\n }\n const { dateRangeCuesAppended, id3Track } = this;\n const { dateRanges } = details;\n const ids = Object.keys(dateRanges);\n // Remove cues from track not found in details.dateRanges\n if (id3Track) {\n const idsToRemove = Object.keys(dateRangeCuesAppended).filter(\n (id) => !ids.includes(id)\n );\n for (let i = idsToRemove.length; i--; ) {\n const id = idsToRemove[i];\n Object.keys(dateRangeCuesAppended[id].cues).forEach((key) => {\n id3Track.removeCue(dateRangeCuesAppended[id].cues[key]);\n });\n delete dateRangeCuesAppended[id];\n }\n }\n // Exit if the playlist does not have Date Ranges or does not have Program Date Time\n const lastFragment = details.fragments[details.fragments.length - 1];\n if (ids.length === 0 || !Number.isFinite(lastFragment?.programDateTime)) {\n return;\n }\n\n if (!this.id3Track) {\n this.id3Track = this.createTrack(this.media);\n }\n\n const dateTimeOffset =\n (lastFragment.programDateTime as number) / 1000 - lastFragment.start;\n const Cue = getCueClass();\n\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i];\n const dateRange = dateRanges[id];\n const appendedDateRangeCues = dateRangeCuesAppended[id];\n const cues = appendedDateRangeCues?.cues || {};\n let durationKnown = appendedDateRangeCues?.durationKnown || false;\n const startTime = dateRangeDateToTimelineSeconds(\n dateRange.startDate,\n dateTimeOffset\n );\n let endTime = MAX_CUE_ENDTIME;\n const endDate = dateRange.endDate;\n if (endDate) {\n endTime = dateRangeDateToTimelineSeconds(endDate, dateTimeOffset);\n durationKnown = true;\n } else if (dateRange.endOnNext && !durationKnown) {\n const nextDateRangeWithSameClass = ids\n .reduce((filterMapArray, id) => {\n const candidate = dateRanges[id];\n if (\n candidate.class === dateRange.class &&\n candidate.id !== id &&\n candidate.startDate > dateRange.startDate\n ) {\n filterMapArray.push(candidate);\n }\n return filterMapArray;\n }, [] as DateRange[])\n .sort((a, b) => a.startDate.getTime() - b.startDate.getTime())[0];\n if (nextDateRangeWithSameClass) {\n endTime = dateRangeDateToTimelineSeconds(\n nextDateRangeWithSameClass.startDate,\n dateTimeOffset\n );\n durationKnown = true;\n }\n }\n\n const attributes = Object.keys(dateRange.attr);\n for (let j = 0; j < attributes.length; j++) {\n const key = attributes[j];\n if (!isDateRangeCueAttribute(key)) {\n continue;\n }\n let cue = cues[key] as any;\n if (cue) {\n if (durationKnown && !appendedDateRangeCues.durationKnown) {\n cue.endTime = endTime;\n }\n } else {\n let data = dateRange.attr[key];\n cue = new Cue(startTime, endTime, '');\n if (isSCTE35Attribute(key)) {\n data = hexToArrayBuffer(data);\n }\n cue.value = { key, data };\n cue.type = MetadataSchema.dateRange;\n cue.id = id;\n this.id3Track.addCue(cue);\n cues[key] = cue;\n }\n }\n dateRangeCuesAppended[id] = {\n cues,\n dateRange,\n durationKnown,\n };\n }\n }\n}\n\nexport default ID3TrackController;\n","import { LevelDetails } from '../loader/level-details';\nimport { ErrorDetails } from '../errors';\nimport { Events } from '../events';\nimport type {\n ErrorData,\n LevelUpdatedData,\n MediaAttachingData,\n} from '../types/events';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\n\nexport default class LatencyController implements ComponentAPI {\n private hls: Hls;\n private readonly config: HlsConfig;\n private media: HTMLMediaElement | null = null;\n private levelDetails: LevelDetails | null = null;\n private currentTime: number = 0;\n private stallCount: number = 0;\n private _latency: number | null = null;\n private timeupdateHandler = () => this.timeupdate();\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.config = hls.config;\n this.registerListeners();\n }\n\n get latency(): number {\n return this._latency || 0;\n }\n\n get maxLatency(): number {\n const { config, levelDetails } = this;\n if (config.liveMaxLatencyDuration !== undefined) {\n return config.liveMaxLatencyDuration;\n }\n return levelDetails\n ? config.liveMaxLatencyDurationCount * levelDetails.targetduration\n : 0;\n }\n\n get targetLatency(): number | null {\n const { levelDetails } = this;\n if (levelDetails === null) {\n return null;\n }\n const { holdBack, partHoldBack, targetduration } = levelDetails;\n const { liveSyncDuration, liveSyncDurationCount, lowLatencyMode } =\n this.config;\n const userConfig = this.hls.userConfig;\n let targetLatency = lowLatencyMode ? partHoldBack || holdBack : holdBack;\n if (\n userConfig.liveSyncDuration ||\n userConfig.liveSyncDurationCount ||\n targetLatency === 0\n ) {\n targetLatency =\n liveSyncDuration !== undefined\n ? liveSyncDuration\n : liveSyncDurationCount * targetduration;\n }\n const maxLiveSyncOnStallIncrease = targetduration;\n const liveSyncOnStallIncrease = 1.0;\n return (\n targetLatency +\n Math.min(\n this.stallCount * liveSyncOnStallIncrease,\n maxLiveSyncOnStallIncrease\n )\n );\n }\n\n get liveSyncPosition(): number | null {\n const liveEdge = this.estimateLiveEdge();\n const targetLatency = this.targetLatency;\n const levelDetails = this.levelDetails;\n if (liveEdge === null || targetLatency === null || levelDetails === null) {\n return null;\n }\n const edge = levelDetails.edge;\n const syncPosition = liveEdge - targetLatency - this.edgeStalled;\n const min = edge - levelDetails.totalduration;\n const max =\n edge -\n ((this.config.lowLatencyMode && levelDetails.partTarget) ||\n levelDetails.targetduration);\n return Math.min(Math.max(min, syncPosition), max);\n }\n\n get drift(): number {\n const { levelDetails } = this;\n if (levelDetails === null) {\n return 1;\n }\n return levelDetails.drift;\n }\n\n get edgeStalled(): number {\n const { levelDetails } = this;\n if (levelDetails === null) {\n return 0;\n }\n const maxLevelUpdateAge =\n ((this.config.lowLatencyMode && levelDetails.partTarget) ||\n levelDetails.targetduration) * 3;\n return Math.max(levelDetails.age - maxLevelUpdateAge, 0);\n }\n\n private get forwardBufferLength(): number {\n const { media, levelDetails } = this;\n if (!media || !levelDetails) {\n return 0;\n }\n const bufferedRanges = media.buffered.length;\n return (\n (bufferedRanges\n ? media.buffered.end(bufferedRanges - 1)\n : levelDetails.edge) - this.currentTime\n );\n }\n\n public destroy(): void {\n this.unregisterListeners();\n this.onMediaDetaching();\n this.levelDetails = null;\n // @ts-ignore\n this.hls = this.timeupdateHandler = null;\n }\n\n private registerListeners() {\n this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n this.hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n this.hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n this.hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n this.hls.on(Events.ERROR, this.onError, this);\n }\n\n private unregisterListeners() {\n this.hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n this.hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n this.hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n this.hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n this.hls.off(Events.ERROR, this.onError, this);\n }\n\n private onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachingData\n ) {\n this.media = data.media;\n this.media.addEventListener('timeupdate', this.timeupdateHandler);\n }\n\n private onMediaDetaching() {\n if (this.media) {\n this.media.removeEventListener('timeupdate', this.timeupdateHandler);\n this.media = null;\n }\n }\n\n private onManifestLoading() {\n this.levelDetails = null;\n this._latency = null;\n this.stallCount = 0;\n }\n\n private onLevelUpdated(\n event: Events.LEVEL_UPDATED,\n { details }: LevelUpdatedData\n ) {\n this.levelDetails = details;\n if (details.advanced) {\n this.timeupdate();\n }\n if (!details.live && this.media) {\n this.media.removeEventListener('timeupdate', this.timeupdateHandler);\n }\n }\n\n private onError(event: Events.ERROR, data: ErrorData) {\n if (data.details !== ErrorDetails.BUFFER_STALLED_ERROR) {\n return;\n }\n this.stallCount++;\n if (this.levelDetails?.live) {\n logger.warn(\n '[playback-rate-controller]: Stall detected, adjusting target latency'\n );\n }\n }\n\n private timeupdate() {\n const { media, levelDetails } = this;\n if (!media || !levelDetails) {\n return;\n }\n this.currentTime = media.currentTime;\n\n const latency = this.computeLatency();\n if (latency === null) {\n return;\n }\n this._latency = latency;\n\n // Adapt playbackRate to meet target latency in low-latency mode\n const { lowLatencyMode, maxLiveSyncPlaybackRate } = this.config;\n if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1) {\n return;\n }\n const targetLatency = this.targetLatency;\n if (targetLatency === null) {\n return;\n }\n const distanceFromTarget = latency - targetLatency;\n // Only adjust playbackRate when within one target duration of targetLatency\n // and more than one second from under-buffering.\n // Playback further than one target duration from target can be considered DVR playback.\n const liveMinLatencyDuration = Math.min(\n this.maxLatency,\n targetLatency + levelDetails.targetduration\n );\n const inLiveRange = distanceFromTarget < liveMinLatencyDuration;\n if (\n levelDetails.live &&\n inLiveRange &&\n distanceFromTarget > 0.05 &&\n this.forwardBufferLength > 1\n ) {\n const max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));\n const rate =\n Math.round(\n (2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled))) *\n 20\n ) / 20;\n media.playbackRate = Math.min(max, Math.max(1, rate));\n } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {\n media.playbackRate = 1;\n }\n }\n\n private estimateLiveEdge(): number | null {\n const { levelDetails } = this;\n if (levelDetails === null) {\n return null;\n }\n return levelDetails.edge + levelDetails.age;\n }\n\n private computeLatency(): number | null {\n const liveEdge = this.estimateLiveEdge();\n if (liveEdge === null) {\n return null;\n }\n return liveEdge - this.currentTime;\n }\n}\n","import { LevelDetails } from '../loader/level-details';\nimport { AttrList } from '../utils/attr-list';\n\nexport interface LevelParsed {\n attrs: LevelAttributes;\n audioCodec?: string;\n bitrate: number;\n details?: LevelDetails;\n height?: number;\n id?: number;\n level?: number;\n name: string;\n textCodec?: string;\n unknownCodecs?: string[];\n url: string;\n videoCodec?: string;\n width?: number;\n}\n\nexport interface LevelAttributes extends AttrList {\n 'ALLOWED-CPC'?: string;\n AUDIO?: string;\n 'AVERAGE-BANDWIDTH'?: string;\n BANDWIDTH?: string;\n 'CLOSED-CAPTIONS'?: string;\n CODECS?: string;\n 'FRAME-RATE'?: string;\n 'HDCP-LEVEL'?: 'TYPE-0' | 'TYPE-1' | 'NONE';\n 'PATHWAY-ID'?: string;\n RESOLUTION?: string;\n SCORE?: string;\n 'STABLE-VARIANT-ID'?: string;\n SUBTITLES?: string;\n 'SUPPLEMENTAL-CODECS'?: string;\n VIDEO?: string;\n 'VIDEO-RANGE'?: 'SDR' | 'HLG' | 'PQ';\n}\n\nexport const HdcpLevels = ['NONE', 'TYPE-0', 'TYPE-1', null] as const;\nexport type HdcpLevel = (typeof HdcpLevels)[number];\n\nexport type VariableMap = Record<string, string>;\n\nexport const enum HlsSkip {\n No = '',\n Yes = 'YES',\n v2 = 'v2',\n}\n\nexport function getSkipValue(details: LevelDetails, msn?: number): HlsSkip {\n const { canSkipUntil, canSkipDateRanges, endSN } = details;\n const snChangeGoal = msn !== undefined ? msn - endSN : 0;\n if (canSkipUntil && snChangeGoal < canSkipUntil) {\n if (canSkipDateRanges) {\n return HlsSkip.v2;\n }\n return HlsSkip.Yes;\n }\n return HlsSkip.No;\n}\n\nexport class HlsUrlParameters {\n msn?: number;\n part?: number;\n skip?: HlsSkip;\n\n constructor(msn?: number, part?: number, skip?: HlsSkip) {\n this.msn = msn;\n this.part = part;\n this.skip = skip;\n }\n\n addDirectives(uri: string): string | never {\n const url: URL = new self.URL(uri);\n if (this.msn !== undefined) {\n url.searchParams.set('_HLS_msn', this.msn.toString());\n }\n if (this.part !== undefined) {\n url.searchParams.set('_HLS_part', this.part.toString());\n }\n if (this.skip) {\n url.searchParams.set('_HLS_skip', this.skip);\n }\n return url.href;\n }\n}\n\nexport class Level {\n public readonly _attrs: LevelAttributes[];\n public readonly audioCodec: string | undefined;\n public readonly bitrate: number;\n public readonly codecSet: string;\n public readonly height: number;\n public readonly id: number;\n public readonly name: string | undefined;\n public readonly videoCodec: string | undefined;\n public readonly width: number;\n public readonly unknownCodecs: string[] | undefined;\n public audioGroupIds?: (string | undefined)[];\n public details?: LevelDetails;\n public fragmentError: number = 0;\n public loadError: number = 0;\n public loaded?: { bytes: number; duration: number };\n public realBitrate: number = 0;\n public textGroupIds?: (string | undefined)[];\n public url: string[];\n private _urlId: number = 0;\n\n constructor(data: LevelParsed) {\n this.url = [data.url];\n this._attrs = [data.attrs];\n this.bitrate = data.bitrate;\n if (data.details) {\n this.details = data.details;\n }\n this.id = data.id || 0;\n this.name = data.name;\n this.width = data.width || 0;\n this.height = data.height || 0;\n this.audioCodec = data.audioCodec;\n this.videoCodec = data.videoCodec;\n this.unknownCodecs = data.unknownCodecs;\n this.codecSet = [data.videoCodec, data.audioCodec]\n .filter((c) => c)\n .join(',')\n .replace(/\\.[^.,]+/g, '');\n }\n\n get maxBitrate(): number {\n return Math.max(this.realBitrate, this.bitrate);\n }\n\n get attrs(): LevelAttributes {\n return this._attrs[this._urlId];\n }\n\n get pathwayId(): string {\n return this.attrs['PATHWAY-ID'] || '.';\n }\n\n get uri(): string {\n return this.url[this._urlId] || '';\n }\n\n get urlId(): number {\n return this._urlId;\n }\n\n set urlId(value: number) {\n const newValue = value % this.url.length;\n if (this._urlId !== newValue) {\n this.fragmentError = 0;\n this.loadError = 0;\n this.details = undefined;\n this._urlId = newValue;\n }\n }\n\n get audioGroupId(): string | undefined {\n return this.audioGroupIds?.[this.urlId];\n }\n\n get textGroupId(): string | undefined {\n return this.textGroupIds?.[this.urlId];\n }\n\n addFallback(data: LevelParsed) {\n this.url.push(data.url);\n this._attrs.push(data.attrs);\n }\n}\n","/**\n * Provides methods dealing with playlist sliding and drift\n */\n\nimport { logger } from '../utils/logger';\nimport { Fragment, Part } from '../loader/fragment';\nimport { LevelDetails } from '../loader/level-details';\nimport type { Level } from '../types/level';\nimport { DateRange } from '../loader/date-range';\n\ntype FragmentIntersection = (oldFrag: Fragment, newFrag: Fragment) => void;\ntype PartIntersection = (oldPart: Part, newPart: Part) => void;\n\nexport function updatePTS(\n fragments: Fragment[],\n fromIdx: number,\n toIdx: number\n): void {\n const fragFrom = fragments[fromIdx];\n const fragTo = fragments[toIdx];\n updateFromToPTS(fragFrom, fragTo);\n}\n\nfunction updateFromToPTS(fragFrom: Fragment, fragTo: Fragment) {\n const fragToPTS = fragTo.startPTS as number;\n // if we know startPTS[toIdx]\n if (Number.isFinite(fragToPTS)) {\n // update fragment duration.\n // it helps to fix drifts between playlist reported duration and fragment real duration\n let duration: number = 0;\n let frag: Fragment;\n if (fragTo.sn > fragFrom.sn) {\n duration = fragToPTS - fragFrom.start;\n frag = fragFrom;\n } else {\n duration = fragFrom.start - fragToPTS;\n frag = fragTo;\n }\n if (frag.duration !== duration) {\n frag.duration = duration;\n }\n // we dont know startPTS[toIdx]\n } else if (fragTo.sn > fragFrom.sn) {\n const contiguous = fragFrom.cc === fragTo.cc;\n // TODO: With part-loading end/durations we need to confirm the whole fragment is loaded before using (or setting) minEndPTS\n if (contiguous && fragFrom.minEndPTS) {\n fragTo.start = fragFrom.start + (fragFrom.minEndPTS - fragFrom.start);\n } else {\n fragTo.start = fragFrom.start + fragFrom.duration;\n }\n } else {\n fragTo.start = Math.max(fragFrom.start - fragTo.duration, 0);\n }\n}\n\nexport function updateFragPTSDTS(\n details: LevelDetails | undefined,\n frag: Fragment,\n startPTS: number,\n endPTS: number,\n startDTS: number,\n endDTS: number\n): number {\n const parsedMediaDuration = endPTS - startPTS;\n if (parsedMediaDuration <= 0) {\n logger.warn('Fragment should have a positive duration', frag);\n endPTS = startPTS + frag.duration;\n endDTS = startDTS + frag.duration;\n }\n let maxStartPTS = startPTS;\n let minEndPTS = endPTS;\n const fragStartPts = frag.startPTS as number;\n const fragEndPts = frag.endPTS as number;\n if (Number.isFinite(fragStartPts)) {\n // delta PTS between audio and video\n const deltaPTS = Math.abs(fragStartPts - startPTS);\n if (!Number.isFinite(frag.deltaPTS as number)) {\n frag.deltaPTS = deltaPTS;\n } else {\n frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS as number);\n }\n\n maxStartPTS = Math.max(startPTS, fragStartPts);\n startPTS = Math.min(startPTS, fragStartPts);\n startDTS = Math.min(startDTS, frag.startDTS);\n\n minEndPTS = Math.min(endPTS, fragEndPts);\n endPTS = Math.max(endPTS, fragEndPts);\n endDTS = Math.max(endDTS, frag.endDTS);\n }\n\n const drift = startPTS - frag.start;\n if (frag.start !== 0) {\n frag.start = startPTS;\n }\n frag.duration = endPTS - frag.start;\n frag.startPTS = startPTS;\n frag.maxStartPTS = maxStartPTS;\n frag.startDTS = startDTS;\n frag.endPTS = endPTS;\n frag.minEndPTS = minEndPTS;\n frag.endDTS = endDTS;\n\n const sn = frag.sn as number; // 'initSegment'\n // exit if sn out of range\n if (!details || sn < details.startSN || sn > details.endSN) {\n return 0;\n }\n let i;\n const fragIdx = sn - details.startSN;\n const fragments = details.fragments;\n // update frag reference in fragments array\n // rationale is that fragments array might not contain this frag object.\n // this will happen if playlist has been refreshed between frag loading and call to updateFragPTSDTS()\n // if we don't update frag, we won't be able to propagate PTS info on the playlist\n // resulting in invalid sliding computation\n fragments[fragIdx] = frag;\n // adjust fragment PTS/duration from seqnum-1 to frag 0\n for (i = fragIdx; i > 0; i--) {\n updateFromToPTS(fragments[i], fragments[i - 1]);\n }\n\n // adjust fragment PTS/duration from seqnum to last frag\n for (i = fragIdx; i < fragments.length - 1; i++) {\n updateFromToPTS(fragments[i], fragments[i + 1]);\n }\n if (details.fragmentHint) {\n updateFromToPTS(fragments[fragments.length - 1], details.fragmentHint);\n }\n\n details.PTSKnown = details.alignedSliding = true;\n return drift;\n}\n\nexport function mergeDetails(\n oldDetails: LevelDetails,\n newDetails: LevelDetails\n): void {\n // Track the last initSegment processed. Initialize it to the last one on the timeline.\n let currentInitSegment: Fragment | null = null;\n const oldFragments = oldDetails.fragments;\n for (let i = oldFragments.length - 1; i >= 0; i--) {\n const oldInit = oldFragments[i].initSegment;\n if (oldInit) {\n currentInitSegment = oldInit;\n break;\n }\n }\n\n if (oldDetails.fragmentHint) {\n // prevent PTS and duration from being adjusted on the next hint\n delete oldDetails.fragmentHint.endPTS;\n }\n // check if old/new playlists have fragments in common\n // loop through overlapping SN and update startPTS , cc, and duration if any found\n let ccOffset = 0;\n let PTSFrag;\n mapFragmentIntersection(\n oldDetails,\n newDetails,\n (oldFrag: Fragment, newFrag: Fragment) => {\n if (oldFrag.relurl) {\n // Do not compare CC if the old fragment has no url. This is a level.fragmentHint used by LL-HLS parts.\n // It maybe be off by 1 if it was created before any parts or discontinuity tags were appended to the end\n // of the playlist.\n ccOffset = oldFrag.cc - newFrag.cc;\n }\n if (\n Number.isFinite(oldFrag.startPTS) &&\n Number.isFinite(oldFrag.endPTS)\n ) {\n newFrag.start = newFrag.startPTS = oldFrag.startPTS as number;\n newFrag.startDTS = oldFrag.startDTS;\n newFrag.maxStartPTS = oldFrag.maxStartPTS;\n\n newFrag.endPTS = oldFrag.endPTS;\n newFrag.endDTS = oldFrag.endDTS;\n newFrag.minEndPTS = oldFrag.minEndPTS;\n newFrag.duration =\n (oldFrag.endPTS as number) - (oldFrag.startPTS as number);\n\n if (newFrag.duration) {\n PTSFrag = newFrag;\n }\n\n // PTS is known when any segment has startPTS and endPTS\n newDetails.PTSKnown = newDetails.alignedSliding = true;\n }\n newFrag.elementaryStreams = oldFrag.elementaryStreams;\n newFrag.loader = oldFrag.loader;\n newFrag.stats = oldFrag.stats;\n newFrag.urlId = oldFrag.urlId;\n if (oldFrag.initSegment) {\n newFrag.initSegment = oldFrag.initSegment;\n currentInitSegment = oldFrag.initSegment;\n }\n }\n );\n\n if (currentInitSegment) {\n const fragmentsToCheck = newDetails.fragmentHint\n ? newDetails.fragments.concat(newDetails.fragmentHint)\n : newDetails.fragments;\n fragmentsToCheck.forEach((frag) => {\n if (\n !frag.initSegment ||\n frag.initSegment.relurl === currentInitSegment?.relurl\n ) {\n frag.initSegment = currentInitSegment;\n }\n });\n }\n\n if (newDetails.skippedSegments) {\n newDetails.deltaUpdateFailed = newDetails.fragments.some((frag) => !frag);\n if (newDetails.deltaUpdateFailed) {\n logger.warn(\n '[level-helper] Previous playlist missing segments skipped in delta playlist'\n );\n for (let i = newDetails.skippedSegments; i--; ) {\n newDetails.fragments.shift();\n }\n newDetails.startSN = newDetails.fragments[0].sn as number;\n newDetails.startCC = newDetails.fragments[0].cc;\n } else if (newDetails.canSkipDateRanges) {\n newDetails.dateRanges = mergeDateRanges(\n oldDetails.dateRanges,\n newDetails.dateRanges,\n newDetails.recentlyRemovedDateranges\n );\n }\n }\n\n const newFragments = newDetails.fragments;\n if (ccOffset) {\n logger.warn('discontinuity sliding from playlist, take drift into account');\n for (let i = 0; i < newFragments.length; i++) {\n newFragments[i].cc += ccOffset;\n }\n }\n if (newDetails.skippedSegments) {\n newDetails.startCC = newDetails.fragments[0].cc;\n }\n\n // Merge parts\n mapPartIntersection(\n oldDetails.partList,\n newDetails.partList,\n (oldPart: Part, newPart: Part) => {\n newPart.elementaryStreams = oldPart.elementaryStreams;\n newPart.stats = oldPart.stats;\n }\n );\n\n // if at least one fragment contains PTS info, recompute PTS information for all fragments\n if (PTSFrag) {\n updateFragPTSDTS(\n newDetails,\n PTSFrag,\n PTSFrag.startPTS,\n PTSFrag.endPTS,\n PTSFrag.startDTS,\n PTSFrag.endDTS\n );\n } else {\n // ensure that delta is within oldFragments range\n // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])\n // in that case we also need to adjust start offset of all fragments\n adjustSliding(oldDetails, newDetails);\n }\n\n if (newFragments.length) {\n newDetails.totalduration = newDetails.edge - newFragments[0].start;\n }\n\n newDetails.driftStartTime = oldDetails.driftStartTime;\n newDetails.driftStart = oldDetails.driftStart;\n const advancedDateTime = newDetails.advancedDateTime;\n if (newDetails.advanced && advancedDateTime) {\n const edge = newDetails.edge;\n if (!newDetails.driftStart) {\n newDetails.driftStartTime = advancedDateTime;\n newDetails.driftStart = edge;\n }\n newDetails.driftEndTime = advancedDateTime;\n newDetails.driftEnd = edge;\n } else {\n newDetails.driftEndTime = oldDetails.driftEndTime;\n newDetails.driftEnd = oldDetails.driftEnd;\n newDetails.advancedDateTime = oldDetails.advancedDateTime;\n }\n}\n\nfunction mergeDateRanges(\n oldDateRanges: Record<string, DateRange>,\n deltaDateRanges: Record<string, DateRange>,\n recentlyRemovedDateranges: string[] | undefined\n): Record<string, DateRange> {\n const dateRanges = Object.assign({}, oldDateRanges);\n if (recentlyRemovedDateranges) {\n recentlyRemovedDateranges.forEach((id) => {\n delete dateRanges[id];\n });\n }\n Object.keys(deltaDateRanges).forEach((id) => {\n const dateRange = new DateRange(deltaDateRanges[id].attr, dateRanges[id]);\n if (dateRange.isValid) {\n dateRanges[id] = dateRange;\n } else {\n logger.warn(\n `Ignoring invalid Playlist Delta Update DATERANGE tag: \"${JSON.stringify(\n deltaDateRanges[id].attr\n )}\"`\n );\n }\n });\n return dateRanges;\n}\n\nexport function mapPartIntersection(\n oldParts: Part[] | null,\n newParts: Part[] | null,\n intersectionFn: PartIntersection\n) {\n if (oldParts && newParts) {\n let delta = 0;\n for (let i = 0, len = oldParts.length; i <= len; i++) {\n const oldPart = oldParts[i];\n const newPart = newParts[i + delta];\n if (\n oldPart &&\n newPart &&\n oldPart.index === newPart.index &&\n oldPart.fragment.sn === newPart.fragment.sn\n ) {\n intersectionFn(oldPart, newPart);\n } else {\n delta--;\n }\n }\n }\n}\n\nexport function mapFragmentIntersection(\n oldDetails: LevelDetails,\n newDetails: LevelDetails,\n intersectionFn: FragmentIntersection\n): void {\n const skippedSegments = newDetails.skippedSegments;\n const start =\n Math.max(oldDetails.startSN, newDetails.startSN) - newDetails.startSN;\n const end =\n (oldDetails.fragmentHint ? 1 : 0) +\n (skippedSegments\n ? newDetails.endSN\n : Math.min(oldDetails.endSN, newDetails.endSN)) -\n newDetails.startSN;\n const delta = newDetails.startSN - oldDetails.startSN;\n const newFrags = newDetails.fragmentHint\n ? newDetails.fragments.concat(newDetails.fragmentHint)\n : newDetails.fragments;\n const oldFrags = oldDetails.fragmentHint\n ? oldDetails.fragments.concat(oldDetails.fragmentHint)\n : oldDetails.fragments;\n\n for (let i = start; i <= end; i++) {\n const oldFrag = oldFrags[delta + i];\n let newFrag = newFrags[i];\n if (skippedSegments && !newFrag && i < skippedSegments) {\n // Fill in skipped segments in delta playlist\n newFrag = newDetails.fragments[i] = oldFrag;\n }\n if (oldFrag && newFrag) {\n intersectionFn(oldFrag, newFrag);\n }\n }\n}\n\nexport function adjustSliding(\n oldDetails: LevelDetails,\n newDetails: LevelDetails\n): void {\n const delta =\n newDetails.startSN + newDetails.skippedSegments - oldDetails.startSN;\n const oldFragments = oldDetails.fragments;\n if (delta < 0 || delta >= oldFragments.length) {\n return;\n }\n addSliding(newDetails, oldFragments[delta].start);\n}\n\nexport function addSliding(details: LevelDetails, start: number) {\n if (start) {\n const fragments = details.fragments;\n for (let i = details.skippedSegments; i < fragments.length; i++) {\n fragments[i].start += start;\n }\n if (details.fragmentHint) {\n details.fragmentHint.start += start;\n }\n }\n}\n\nexport function computeReloadInterval(\n newDetails: LevelDetails,\n distanceToLiveEdgeMs: number = Infinity\n): number {\n let reloadInterval = 1000 * newDetails.targetduration;\n\n if (newDetails.updated) {\n // Use last segment duration when shorter than target duration and near live edge\n const fragments = newDetails.fragments;\n const liveEdgeMaxTargetDurations = 4;\n if (\n fragments.length &&\n reloadInterval * liveEdgeMaxTargetDurations > distanceToLiveEdgeMs\n ) {\n const lastSegmentDuration =\n fragments[fragments.length - 1].duration * 1000;\n if (lastSegmentDuration < reloadInterval) {\n reloadInterval = lastSegmentDuration;\n }\n }\n } else {\n // estimate = 'miss half average';\n // follow HLS Spec, If the client reloads a Playlist file and finds that it has not\n // changed then it MUST wait for a period of one-half the target\n // duration before retrying.\n reloadInterval /= 2;\n }\n\n return Math.round(reloadInterval);\n}\n\nexport function getFragmentWithSN(\n level: Level,\n sn: number,\n fragCurrent: Fragment | null\n): Fragment | null {\n if (!level?.details) {\n return null;\n }\n const levelDetails = level.details;\n let fragment: Fragment | undefined =\n levelDetails.fragments[sn - levelDetails.startSN];\n if (fragment) {\n return fragment;\n }\n fragment = levelDetails.fragmentHint;\n if (fragment && fragment.sn === sn) {\n return fragment;\n }\n if (sn < levelDetails.startSN && fragCurrent && fragCurrent.sn === sn) {\n return fragCurrent;\n }\n return null;\n}\n\nexport function getPartWith(\n level: Level,\n sn: number,\n partIndex: number\n): Part | null {\n if (!level?.details) {\n return null;\n }\n return findPart(level.details?.partList, sn, partIndex);\n}\n\nexport function findPart(\n partList: Part[] | null | undefined,\n sn: number,\n partIndex: number\n): Part | null {\n if (partList) {\n for (let i = partList.length; i--; ) {\n const part = partList[i];\n if (part.index === partIndex && part.fragment.sn === sn) {\n return part;\n }\n }\n }\n return null;\n}\n","import { LoadPolicy, LoaderConfig, RetryConfig } from '../config';\nimport { ErrorDetails } from '../errors';\nimport { ErrorData } from '../types/events';\n\nexport function isTimeoutError(error: ErrorData): boolean {\n switch (error.details) {\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n case ErrorDetails.MANIFEST_LOAD_TIMEOUT:\n return true;\n }\n return false;\n}\n\nexport function getRetryConfig(\n loadPolicy: LoadPolicy,\n error: ErrorData\n): RetryConfig | null {\n const isTimeout = isTimeoutError(error);\n return loadPolicy.default[`${isTimeout ? 'timeout' : 'error'}Retry`];\n}\n\nexport function getRetryDelay(\n retryConfig: RetryConfig,\n retryCount: number\n): number {\n // exponential backoff capped to max retry delay\n const backoffFactor =\n retryConfig.backoff === 'linear' ? 1 : Math.pow(2, retryCount);\n return Math.min(\n backoffFactor * retryConfig.retryDelayMs,\n retryConfig.maxRetryDelayMs\n );\n}\n\nexport function getLoaderConfigWithoutReties(\n loderConfig: LoaderConfig\n): LoaderConfig {\n return {\n ...loderConfig,\n ...{\n errorRetry: null,\n timeoutRetry: null,\n },\n };\n}\n\nexport function shouldRetry(\n retryConfig: RetryConfig | null | undefined,\n retryCount: number,\n isTimeout: boolean,\n httpStatus?: number | undefined\n): retryConfig is RetryConfig & boolean {\n return (\n !!retryConfig &&\n retryCount < retryConfig.maxNumRetry &&\n (retryForHttpStatus(httpStatus) || !!isTimeout)\n );\n}\n\nexport function retryForHttpStatus(httpStatus: number | undefined) {\n // Do not retry on status 4xx, status 0 (CORS error), or undefined (decrypt/gap/parse error)\n return (\n (httpStatus === 0 && navigator.onLine === false) ||\n (!!httpStatus && (httpStatus < 400 || httpStatus > 499))\n );\n}\n","type BinarySearchComparison<T> = (candidate: T) => -1 | 0 | 1;\n\nconst BinarySearch = {\n /**\n * Searches for an item in an array which matches a certain condition.\n * This requires the condition to only match one item in the array,\n * and for the array to be ordered.\n *\n * @param list The array to search.\n * @param comparisonFn\n * Called and provided a candidate item as the first argument.\n * Should return:\n * > -1 if the item should be located at a lower index than the provided item.\n * > 1 if the item should be located at a higher index than the provided item.\n * > 0 if the item is the item you're looking for.\n *\n * @returns the object if found, otherwise returns null\n */\n search: function <T>(\n list: T[],\n comparisonFn: BinarySearchComparison<T>\n ): T | null {\n let minIndex: number = 0;\n let maxIndex: number = list.length - 1;\n let currentIndex: number | null = null;\n let currentElement: T | null = null;\n\n while (minIndex <= maxIndex) {\n currentIndex = ((minIndex + maxIndex) / 2) | 0;\n currentElement = list[currentIndex];\n\n const comparisonResult = comparisonFn(currentElement);\n if (comparisonResult > 0) {\n minIndex = currentIndex + 1;\n } else if (comparisonResult < 0) {\n maxIndex = currentIndex - 1;\n } else {\n return currentElement;\n }\n }\n\n return null;\n },\n};\n\nexport default BinarySearch;\n","import BinarySearch from '../utils/binary-search';\nimport { Fragment } from '../loader/fragment';\n\n/**\n * Returns first fragment whose endPdt value exceeds the given PDT, or null.\n * @param fragments - The array of candidate fragments\n * @param PDTValue - The PDT value which must be exceeded\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous\n */\nexport function findFragmentByPDT(\n fragments: Array<Fragment>,\n PDTValue: number | null,\n maxFragLookUpTolerance: number\n): Fragment | null {\n if (\n PDTValue === null ||\n !Array.isArray(fragments) ||\n !fragments.length ||\n !Number.isFinite(PDTValue)\n ) {\n return null;\n }\n\n // if less than start\n const startPDT = fragments[0].programDateTime;\n if (PDTValue < (startPDT || 0)) {\n return null;\n }\n\n const endPDT = fragments[fragments.length - 1].endProgramDateTime;\n if (PDTValue >= (endPDT || 0)) {\n return null;\n }\n\n maxFragLookUpTolerance = maxFragLookUpTolerance || 0;\n for (let seg = 0; seg < fragments.length; ++seg) {\n const frag = fragments[seg];\n if (pdtWithinToleranceTest(PDTValue, maxFragLookUpTolerance, frag)) {\n return frag;\n }\n }\n\n return null;\n}\n\n/**\n * Finds a fragment based on the SN of the previous fragment; or based on the needs of the current buffer.\n * This method compensates for small buffer gaps by applying a tolerance to the start of any candidate fragment, thus\n * breaking any traps which would cause the same fragment to be continuously selected within a small range.\n * @param fragPrevious - The last frag successfully appended\n * @param fragments - The array of candidate fragments\n * @param bufferEnd - The end of the contiguous buffered range the playhead is currently within\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start/end can be within in order to be considered contiguous\n * @returns a matching fragment or null\n */\nexport function findFragmentByPTS(\n fragPrevious: Fragment | null,\n fragments: Array<Fragment>,\n bufferEnd: number = 0,\n maxFragLookUpTolerance: number = 0\n): Fragment | null {\n let fragNext: Fragment | null = null;\n if (fragPrevious) {\n fragNext =\n fragments[\n (fragPrevious.sn as number) - (fragments[0].sn as number) + 1\n ] || null;\n } else if (bufferEnd === 0 && fragments[0].start === 0) {\n fragNext = fragments[0];\n }\n // Prefer the next fragment if it's within tolerance\n if (\n fragNext &&\n fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext) ===\n 0\n ) {\n return fragNext;\n }\n // We might be seeking past the tolerance so find the best match\n const foundFragment = BinarySearch.search(\n fragments,\n fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance)\n );\n if (foundFragment && (foundFragment !== fragPrevious || !fragNext)) {\n return foundFragment;\n }\n // If no match was found return the next fragment after fragPrevious, or null\n return fragNext;\n}\n\n/**\n * The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.\n * @param candidate - The fragment to test\n * @param bufferEnd - The end of the current buffered range the playhead is currently within\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start can be within in order to be considered contiguous\n * @returns 0 if it matches, 1 if too low, -1 if too high\n */\nexport function fragmentWithinToleranceTest(\n bufferEnd = 0,\n maxFragLookUpTolerance = 0,\n candidate: Fragment\n) {\n // eagerly accept an accurate match (no tolerance)\n if (\n candidate.start <= bufferEnd &&\n candidate.start + candidate.duration > bufferEnd\n ) {\n return 0;\n }\n // offset should be within fragment boundary - config.maxFragLookUpTolerance\n // this is to cope with situations like\n // bufferEnd = 9.991\n // frag[Ø] : [0,10]\n // frag[1] : [10,20]\n // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here\n // frag start frag start+duration\n // |-----------------------------|\n // <---> <--->\n // ...--------><-----------------------------><---------....\n // previous frag matching fragment next frag\n // return -1 return 0 return 1\n // logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);\n // Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments\n const candidateLookupTolerance = Math.min(\n maxFragLookUpTolerance,\n candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)\n );\n if (\n candidate.start + candidate.duration - candidateLookupTolerance <=\n bufferEnd\n ) {\n return 1;\n } else if (\n candidate.start - candidateLookupTolerance > bufferEnd &&\n candidate.start\n ) {\n // if maxFragLookUpTolerance will have negative value then don't return -1 for first element\n return -1;\n }\n\n return 0;\n}\n\n/**\n * The test function used by the findFragmentByPdt's BinarySearch to look for the best match to the current buffer conditions.\n * This function tests the candidate's program date time values, as represented in Unix time\n * @param candidate - The fragment to test\n * @param pdtBufferEnd - The Unix time representing the end of the current buffered range\n * @param maxFragLookUpTolerance - The amount of time that a fragment's start can be within in order to be considered contiguous\n * @returns true if contiguous, false otherwise\n */\nexport function pdtWithinToleranceTest(\n pdtBufferEnd: number,\n maxFragLookUpTolerance: number,\n candidate: Fragment\n): boolean {\n const candidateLookupTolerance =\n Math.min(\n maxFragLookUpTolerance,\n candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0)\n ) * 1000;\n\n // endProgramDateTime can be null, default to zero\n const endProgramDateTime = candidate.endProgramDateTime || 0;\n return endProgramDateTime - candidateLookupTolerance > pdtBufferEnd;\n}\n\nexport function findFragWithCC(\n fragments: Fragment[],\n cc: number\n): Fragment | null {\n return BinarySearch.search(fragments, (candidate) => {\n if (candidate.cc < cc) {\n return 1;\n } else if (candidate.cc > cc) {\n return -1;\n } else {\n return 0;\n }\n });\n}\n","import { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport {\n getRetryConfig,\n isTimeoutError,\n shouldRetry,\n} from '../utils/error-helper';\nimport { findFragmentByPTS } from './fragment-finders';\nimport { HdcpLevel, HdcpLevels, type Level } from '../types/level';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { RetryConfig } from '../config';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { ErrorData } from '../types/events';\nimport type { Fragment } from '../loader/fragment';\nimport type { LevelDetails } from '../hls';\n\nconst RENDITION_PENALTY_DURATION_MS = 300000;\n\nexport const enum NetworkErrorAction {\n DoNothing = 0,\n SendEndCallback = 1, // Reserved for future use\n SendAlternateToPenaltyBox = 2,\n RemoveAlternatePermanently = 3, // Reserved for future use\n InsertDiscontinuity = 4, // Reserved for future use\n RetryRequest = 5,\n}\n\nexport const enum ErrorActionFlags {\n None = 0,\n MoveAllAlternatesMatchingHost = 1,\n MoveAllAlternatesMatchingHDCP = 1 << 1,\n SwitchToSDR = 1 << 2, // Reserved for future use\n}\n\nexport type IErrorAction = {\n action: NetworkErrorAction;\n flags: ErrorActionFlags;\n retryCount?: number;\n retryConfig?: RetryConfig;\n hdcpLevel?: HdcpLevel;\n nextAutoLevel?: number;\n resolved?: boolean;\n};\n\ntype PenalizedRendition = {\n lastErrorPerfMs: number;\n errors: ErrorData[];\n details?: LevelDetails;\n};\n\ntype PenalizedRenditions = { [key: number]: PenalizedRendition };\n\nexport default class ErrorController implements NetworkComponentAPI {\n private readonly hls: Hls;\n private playlistError: number = 0;\n private penalizedRenditions: PenalizedRenditions = {};\n private log: (msg: any) => void;\n private warn: (msg: any) => void;\n private error: (msg: any) => void;\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.log = logger.log.bind(logger, `[info]:`);\n this.warn = logger.warn.bind(logger, `[warning]:`);\n this.error = logger.error.bind(logger, `[error]:`);\n this.registerListeners();\n }\n\n private registerListeners() {\n const hls = this.hls;\n hls.on(Events.ERROR, this.onError, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n }\n\n private unregisterListeners() {\n const hls = this.hls;\n if (!hls) {\n return;\n }\n hls.off(Events.ERROR, this.onError, this);\n hls.off(Events.ERROR, this.onErrorOut, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n }\n\n destroy() {\n this.unregisterListeners();\n // @ts-ignore\n this.hls = null;\n this.penalizedRenditions = {};\n }\n\n startLoad(startPosition: number): void {\n this.playlistError = 0;\n }\n\n stopLoad(): void {}\n\n private getVariantLevelIndex(frag: Fragment | undefined): number {\n return frag?.type === PlaylistLevelType.MAIN\n ? frag.level\n : this.hls.loadLevel;\n }\n\n private onManifestLoading() {\n this.playlistError = 0;\n this.penalizedRenditions = {};\n }\n\n private onLevelUpdated() {\n this.playlistError = 0;\n }\n\n private onError(event: Events.ERROR, data: ErrorData) {\n if (data.fatal) {\n return;\n }\n const hls = this.hls;\n const context = data.context;\n\n switch (data.details) {\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n case ErrorDetails.KEY_LOAD_ERROR:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n data.errorAction = this.getFragRetryOrSwitchAction(data);\n return;\n case ErrorDetails.FRAG_GAP:\n case ErrorDetails.FRAG_PARSING_ERROR:\n case ErrorDetails.FRAG_DECRYPT_ERROR: {\n // Switch level if possible, otherwise allow retry count to reach max error retries\n data.errorAction = this.getFragRetryOrSwitchAction(data);\n data.errorAction.action = NetworkErrorAction.SendAlternateToPenaltyBox;\n return;\n }\n case ErrorDetails.LEVEL_EMPTY_ERROR:\n case ErrorDetails.LEVEL_PARSING_ERROR:\n {\n // Only retry when empty and live\n const levelIndex =\n data.parent === PlaylistLevelType.MAIN\n ? (data.level as number)\n : hls.loadLevel;\n if (\n data.details === ErrorDetails.LEVEL_EMPTY_ERROR &&\n !!data.context?.levelDetails?.live\n ) {\n data.errorAction = this.getPlaylistRetryOrSwitchAction(\n data,\n levelIndex\n );\n } else {\n // Escalate to fatal if not retrying or switching\n data.levelRetry = false;\n data.errorAction = this.getLevelSwitchAction(data, levelIndex);\n }\n }\n return;\n case ErrorDetails.LEVEL_LOAD_ERROR:\n case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n if (typeof context?.level === 'number') {\n data.errorAction = this.getPlaylistRetryOrSwitchAction(\n data,\n context.level\n );\n }\n return;\n case ErrorDetails.AUDIO_TRACK_LOAD_ERROR:\n case ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT:\n case ErrorDetails.SUBTITLE_LOAD_ERROR:\n case ErrorDetails.SUBTITLE_TRACK_LOAD_TIMEOUT:\n if (context) {\n const level = hls.levels[hls.loadLevel];\n if (\n level &&\n ((context.type === PlaylistContextType.AUDIO_TRACK &&\n context.groupId === level.audioGroupId) ||\n (context.type === PlaylistContextType.SUBTITLE_TRACK &&\n context.groupId === level.textGroupId))\n ) {\n // Perform Pathway switch or Redundant failover if possible for fastest recovery\n // otherwise allow playlist retry count to reach max error retries\n data.errorAction = this.getPlaylistRetryOrSwitchAction(\n data,\n hls.loadLevel\n );\n data.errorAction.action =\n NetworkErrorAction.SendAlternateToPenaltyBox;\n data.errorAction.flags =\n ErrorActionFlags.MoveAllAlternatesMatchingHost;\n return;\n }\n }\n return;\n case ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:\n {\n const level = hls.levels[hls.loadLevel];\n const restrictedHdcpLevel = level?.attrs['HDCP-LEVEL'];\n if (restrictedHdcpLevel) {\n data.errorAction = {\n action: NetworkErrorAction.SendAlternateToPenaltyBox,\n flags: ErrorActionFlags.MoveAllAlternatesMatchingHDCP,\n hdcpLevel: restrictedHdcpLevel,\n };\n }\n }\n return;\n case ErrorDetails.BUFFER_ADD_CODEC_ERROR:\n case ErrorDetails.REMUX_ALLOC_ERROR:\n data.errorAction = this.getLevelSwitchAction(\n data,\n data.level ?? hls.loadLevel\n );\n return;\n case ErrorDetails.INTERNAL_EXCEPTION:\n case ErrorDetails.BUFFER_APPENDING_ERROR:\n case ErrorDetails.BUFFER_APPEND_ERROR:\n case ErrorDetails.BUFFER_FULL_ERROR:\n case ErrorDetails.LEVEL_SWITCH_ERROR:\n case ErrorDetails.BUFFER_STALLED_ERROR:\n case ErrorDetails.BUFFER_SEEK_OVER_HOLE:\n case ErrorDetails.BUFFER_NUDGE_ON_STALL:\n data.errorAction = {\n action: NetworkErrorAction.DoNothing,\n flags: ErrorActionFlags.None,\n };\n return;\n }\n\n if (data.type === ErrorTypes.KEY_SYSTEM_ERROR) {\n const levelIndex = this.getVariantLevelIndex(data.frag);\n // Do not retry level. Escalate to fatal if switching levels fails.\n data.levelRetry = false;\n data.errorAction = this.getLevelSwitchAction(data, levelIndex);\n return;\n }\n }\n\n private getPlaylistRetryOrSwitchAction(\n data: ErrorData,\n levelIndex: number | null | undefined\n ): IErrorAction {\n const hls = this.hls;\n const retryConfig = getRetryConfig(hls.config.playlistLoadPolicy, data);\n const retryCount = this.playlistError++;\n const httpStatus = data.response?.code;\n const retry = shouldRetry(\n retryConfig,\n retryCount,\n isTimeoutError(data),\n httpStatus\n );\n if (retry) {\n return {\n action: NetworkErrorAction.RetryRequest,\n flags: ErrorActionFlags.None,\n retryConfig,\n retryCount,\n };\n }\n const errorAction = this.getLevelSwitchAction(data, levelIndex);\n if (retryConfig) {\n errorAction.retryConfig = retryConfig;\n errorAction.retryCount = retryCount;\n }\n return errorAction;\n }\n\n private getFragRetryOrSwitchAction(data: ErrorData): IErrorAction {\n const hls = this.hls;\n // Share fragment error count accross media options (main, audio, subs)\n // This allows for level based rendition switching when media option assets fail\n const variantLevelIndex = this.getVariantLevelIndex(data.frag);\n const level = hls.levels[variantLevelIndex];\n const { fragLoadPolicy, keyLoadPolicy } = hls.config;\n const retryConfig = getRetryConfig(\n data.details.startsWith('key') ? keyLoadPolicy : fragLoadPolicy,\n data\n );\n const fragmentErrors = hls.levels.reduce(\n (acc, level) => acc + level.fragmentError,\n 0\n );\n // Switch levels when out of retried or level index out of bounds\n if (level) {\n if (data.details !== ErrorDetails.FRAG_GAP) {\n level.fragmentError++;\n }\n const httpStatus = data.response?.code;\n const retry = shouldRetry(\n retryConfig,\n fragmentErrors,\n isTimeoutError(data),\n httpStatus\n );\n if (retry) {\n return {\n action: NetworkErrorAction.RetryRequest,\n flags: ErrorActionFlags.None,\n retryConfig,\n retryCount: fragmentErrors,\n };\n }\n }\n // Reach max retry count, or Missing level reference\n // Switch to valid index\n const errorAction = this.getLevelSwitchAction(data, variantLevelIndex);\n // Add retry details to allow skipping of FRAG_PARSING_ERROR\n if (retryConfig) {\n errorAction.retryConfig = retryConfig;\n errorAction.retryCount = fragmentErrors;\n }\n return errorAction;\n }\n\n private getLevelSwitchAction(\n data: ErrorData,\n levelIndex: number | null | undefined\n ): IErrorAction {\n const hls = this.hls;\n if (levelIndex === null || levelIndex === undefined) {\n levelIndex = hls.loadLevel;\n }\n const level = this.hls.levels[levelIndex];\n if (level) {\n level.loadError++;\n if (hls.autoLevelEnabled) {\n // Search for next level to retry\n let nextLevel = -1;\n const levels = hls.levels;\n const fragErrorType = data.frag?.type;\n const { type: playlistErrorType, groupId: playlistErrorGroupId } =\n data.context ?? {};\n for (let i = levels.length; i--; ) {\n const candidate = (i + hls.loadLevel) % levels.length;\n if (\n candidate !== hls.loadLevel &&\n levels[candidate].loadError === 0\n ) {\n const levelCandidate = levels[candidate];\n // Skip level switch if GAP tag is found in next level at same position\n if (data.details === ErrorDetails.FRAG_GAP && data.frag) {\n const levelDetails = levels[candidate].details;\n if (levelDetails) {\n const fragCandidate = findFragmentByPTS(\n data.frag,\n levelDetails.fragments,\n data.frag.start\n );\n if (fragCandidate?.gap) {\n continue;\n }\n }\n } else if (\n (playlistErrorType === PlaylistContextType.AUDIO_TRACK &&\n playlistErrorGroupId === levelCandidate.audioGroupId) ||\n (playlistErrorType === PlaylistContextType.SUBTITLE_TRACK &&\n playlistErrorGroupId === levelCandidate.textGroupId)\n ) {\n // For audio/subs playlist errors find another group ID or fallthrough to redundant fail-over\n continue;\n } else if (\n (fragErrorType === PlaylistLevelType.AUDIO &&\n level.audioGroupId === levelCandidate.audioGroupId) ||\n (fragErrorType === PlaylistLevelType.SUBTITLE &&\n level.textGroupId === levelCandidate.textGroupId)\n ) {\n // For audio/subs frag errors find another group ID or fallthrough to redundant fail-over\n continue;\n }\n nextLevel = candidate;\n break;\n }\n }\n if (nextLevel > -1 && hls.loadLevel !== nextLevel) {\n data.levelRetry = true;\n this.playlistError = 0;\n return {\n action: NetworkErrorAction.SendAlternateToPenaltyBox,\n flags: ErrorActionFlags.None,\n nextAutoLevel: nextLevel,\n };\n }\n }\n }\n // No levels to switch / Manual level selection / Level not found\n // Resolve with Pathway switch, Redundant fail-over, or stay on lowest Level\n return {\n action: NetworkErrorAction.SendAlternateToPenaltyBox,\n flags: ErrorActionFlags.MoveAllAlternatesMatchingHost,\n };\n }\n\n public onErrorOut(event: Events.ERROR, data: ErrorData) {\n switch (data.errorAction?.action) {\n case NetworkErrorAction.DoNothing:\n break;\n case NetworkErrorAction.SendAlternateToPenaltyBox:\n this.sendAlternateToPenaltyBox(data);\n if (\n !data.errorAction.resolved &&\n data.details !== ErrorDetails.FRAG_GAP\n ) {\n data.fatal = true;\n }\n break;\n case NetworkErrorAction.RetryRequest:\n // handled by stream and playlist/level controllers\n break;\n }\n\n if (data.fatal) {\n this.hls.stopLoad();\n return;\n }\n }\n\n private sendAlternateToPenaltyBox(data: ErrorData) {\n const hls = this.hls;\n const errorAction = data.errorAction;\n if (!errorAction) {\n return;\n }\n const { flags, hdcpLevel, nextAutoLevel } = errorAction;\n\n switch (flags) {\n case ErrorActionFlags.None:\n this.switchLevel(data, nextAutoLevel);\n break;\n case ErrorActionFlags.MoveAllAlternatesMatchingHost:\n {\n // Handle Redundant Levels here. Pathway switching is handled by content-steering-controller\n if (!errorAction.resolved) {\n errorAction.resolved = this.redundantFailover(data);\n }\n }\n break;\n case ErrorActionFlags.MoveAllAlternatesMatchingHDCP:\n if (hdcpLevel) {\n hls.maxHdcpLevel = HdcpLevels[HdcpLevels.indexOf(hdcpLevel) - 1];\n errorAction.resolved = true;\n }\n this.warn(\n `Restricting playback to HDCP-LEVEL of \"${hls.maxHdcpLevel}\" or lower`\n );\n break;\n }\n // If not resolved by previous actions try to switch to next level\n if (!errorAction.resolved) {\n this.switchLevel(data, nextAutoLevel);\n }\n }\n\n private switchLevel(data: ErrorData, levelIndex: number | undefined) {\n if (levelIndex !== undefined && data.errorAction) {\n this.warn(`switching to level ${levelIndex} after ${data.details}`);\n this.hls.nextAutoLevel = levelIndex;\n data.errorAction.resolved = true;\n // Stream controller is responsible for this but won't switch on false start\n this.hls.nextLoadLevel = this.hls.nextAutoLevel;\n }\n }\n\n private redundantFailover(data: ErrorData): boolean {\n const { hls, penalizedRenditions } = this;\n const levelIndex: number =\n data.parent === PlaylistLevelType.MAIN\n ? (data.level as number)\n : hls.loadLevel;\n const level = hls.levels[levelIndex];\n const redundantLevels = level.url.length;\n const errorUrlId = data.frag ? data.frag.urlId : level.urlId;\n if (level.urlId === errorUrlId && (!data.frag || level.details)) {\n this.penalizeRendition(level, data);\n }\n for (let i = 1; i < redundantLevels; i++) {\n const newUrlId = (errorUrlId + i) % redundantLevels;\n const penalizedRendition = penalizedRenditions[newUrlId];\n // Check if rendition is penalized and skip if it is a bad fit for failover\n if (\n !penalizedRendition ||\n checkExpired(penalizedRendition, data, penalizedRenditions[errorUrlId])\n ) {\n // delete penalizedRenditions[newUrlId];\n // Update the url id of all levels so that we stay on the same set of variants when level switching\n this.warn(\n `Switching to Redundant Stream ${newUrlId + 1}/${redundantLevels}: \"${\n level.url[newUrlId]\n }\" after ${data.details}`\n );\n this.playlistError = 0;\n hls.levels.forEach((lv) => {\n lv.urlId = newUrlId;\n });\n hls.nextLoadLevel = levelIndex;\n return true;\n }\n }\n return false;\n }\n\n private penalizeRendition(level: Level, data: ErrorData) {\n const { penalizedRenditions } = this;\n const penalizedRendition = penalizedRenditions[level.urlId] || {\n lastErrorPerfMs: 0,\n errors: [],\n details: undefined,\n };\n penalizedRendition.lastErrorPerfMs = performance.now();\n penalizedRendition.errors.push(data);\n penalizedRendition.details = level.details;\n penalizedRenditions[level.urlId] = penalizedRendition;\n }\n}\n\nfunction checkExpired(\n penalizedRendition: PenalizedRendition,\n data: ErrorData,\n currentPenaltyState: PenalizedRendition | undefined\n): boolean {\n // Expire penalty for switching back to rendition after RENDITION_PENALTY_DURATION_MS\n if (\n performance.now() - penalizedRendition.lastErrorPerfMs >\n RENDITION_PENALTY_DURATION_MS\n ) {\n return true;\n }\n // Expire penalty on GAP tag error if rendition has no GAP at position (does not cover media tracks)\n const lastErrorDetails = penalizedRendition.details;\n if (data.details === ErrorDetails.FRAG_GAP && lastErrorDetails && data.frag) {\n const position = data.frag.start;\n const candidateFrag = findFragmentByPTS(\n null,\n lastErrorDetails.fragments,\n position\n );\n if (candidateFrag && !candidateFrag.gap) {\n return true;\n }\n }\n // Expire penalty if there are more errors in currentLevel than in penalizedRendition\n if (\n currentPenaltyState &&\n penalizedRendition.errors.length < currentPenaltyState.errors.length\n ) {\n const lastCandidateError =\n penalizedRendition.errors[penalizedRendition.errors.length - 1];\n if (\n lastErrorDetails &&\n lastCandidateError.frag &&\n data.frag &&\n Math.abs(lastCandidateError.frag.start - data.frag.start) >\n lastErrorDetails.targetduration * 3\n ) {\n return true;\n }\n }\n return false;\n}\n","import type Hls from '../hls';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport { getSkipValue, HlsSkip, HlsUrlParameters, Level } from '../types/level';\nimport { computeReloadInterval, mergeDetails } from './level-helper';\nimport { ErrorData } from '../types/events';\nimport { getRetryDelay, isTimeoutError } from '../utils/error-helper';\nimport { NetworkErrorAction } from './error-controller';\nimport { logger } from '../utils/logger';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport type {\n AudioTrackLoadedData,\n LevelLoadedData,\n TrackLoadedData,\n} from '../types/events';\n\nexport default class BasePlaylistController implements NetworkComponentAPI {\n protected hls: Hls;\n protected timer: number = -1;\n protected requestScheduled: number = -1;\n protected canLoad: boolean = false;\n protected log: (msg: any) => void;\n protected warn: (msg: any) => void;\n\n constructor(hls: Hls, logPrefix: string) {\n this.log = logger.log.bind(logger, `${logPrefix}:`);\n this.warn = logger.warn.bind(logger, `${logPrefix}:`);\n this.hls = hls;\n }\n\n public destroy(): void {\n this.clearTimer();\n // @ts-ignore\n this.hls = this.log = this.warn = null;\n }\n\n protected clearTimer(): void {\n clearTimeout(this.timer);\n this.timer = -1;\n }\n\n public startLoad(): void {\n this.canLoad = true;\n this.requestScheduled = -1;\n this.loadPlaylist();\n }\n\n public stopLoad(): void {\n this.canLoad = false;\n this.clearTimer();\n }\n\n protected switchParams(\n playlistUri: string,\n previous: LevelDetails | undefined\n ): HlsUrlParameters | undefined {\n const renditionReports = previous?.renditionReports;\n if (renditionReports) {\n let foundIndex = -1;\n for (let i = 0; i < renditionReports.length; i++) {\n const attr = renditionReports[i];\n let uri: string;\n try {\n uri = new self.URL(attr.URI, previous.url).href;\n } catch (error) {\n logger.warn(\n `Could not construct new URL for Rendition Report: ${error}`\n );\n uri = attr.URI || '';\n }\n // Use exact match. Otherwise, the last partial match, if any, will be used\n // (Playlist URI includes a query string that the Rendition Report does not)\n if (uri === playlistUri) {\n foundIndex = i;\n break;\n } else if (uri === playlistUri.substring(0, uri.length)) {\n foundIndex = i;\n }\n }\n if (foundIndex !== -1) {\n const attr = renditionReports[foundIndex];\n const msn = parseInt(attr['LAST-MSN']) || previous?.lastPartSn;\n let part = parseInt(attr['LAST-PART']) || previous?.lastPartIndex;\n if (this.hls.config.lowLatencyMode) {\n const currentGoal = Math.min(\n previous.age - previous.partTarget,\n previous.targetduration\n );\n if (part >= 0 && currentGoal > previous.partTarget) {\n part += 1;\n }\n }\n return new HlsUrlParameters(\n msn,\n part >= 0 ? part : undefined,\n HlsSkip.No\n );\n }\n }\n }\n\n protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n if (this.requestScheduled === -1) {\n this.requestScheduled = self.performance.now();\n }\n // Loading is handled by the subclasses\n }\n\n protected shouldLoadPlaylist(\n playlist: Level | MediaPlaylist | null | undefined\n ): boolean {\n return (\n this.canLoad &&\n !!playlist &&\n !!playlist.url &&\n (!playlist.details || playlist.details.live)\n );\n }\n\n protected shouldReloadPlaylist(\n playlist: Level | MediaPlaylist | null | undefined\n ): boolean {\n return (\n this.timer === -1 &&\n this.requestScheduled === -1 &&\n this.shouldLoadPlaylist(playlist)\n );\n }\n\n protected playlistLoaded(\n index: number,\n data: LevelLoadedData | AudioTrackLoadedData | TrackLoadedData,\n previousDetails?: LevelDetails\n ) {\n const { details, stats } = data;\n\n // Set last updated date-time\n const now = self.performance.now();\n const elapsed = stats.loading.first\n ? Math.max(0, now - stats.loading.first)\n : 0;\n details.advancedDateTime = Date.now() - elapsed;\n\n // if current playlist is a live playlist, arm a timer to reload it\n if (details.live || previousDetails?.live) {\n details.reloaded(previousDetails);\n if (previousDetails) {\n this.log(\n `live playlist ${index} ${\n details.advanced\n ? 'REFRESHED ' + details.lastPartSn + '-' + details.lastPartIndex\n : 'MISSED'\n }`\n );\n }\n // Merge live playlists to adjust fragment starts and fill in delta playlist skipped segments\n if (previousDetails && details.fragments.length > 0) {\n mergeDetails(previousDetails, details);\n }\n if (!this.canLoad || !details.live) {\n return;\n }\n let deliveryDirectives: HlsUrlParameters | undefined;\n let msn: number | undefined = undefined;\n let part: number | undefined = undefined;\n if (details.canBlockReload && details.endSN && details.advanced) {\n // Load level with LL-HLS delivery directives\n const lowLatencyMode = this.hls.config.lowLatencyMode;\n const lastPartSn = details.lastPartSn;\n const endSn = details.endSN;\n const lastPartIndex = details.lastPartIndex;\n const hasParts = lastPartIndex !== -1;\n const lastPart = lastPartSn === endSn;\n // When low latency mode is disabled, we'll skip part requests once the last part index is found\n const nextSnStartIndex = lowLatencyMode ? 0 : lastPartIndex;\n if (hasParts) {\n msn = lastPart ? endSn + 1 : lastPartSn;\n part = lastPart ? nextSnStartIndex : lastPartIndex + 1;\n } else {\n msn = endSn + 1;\n }\n // Low-Latency CDN Tune-in: \"age\" header and time since load indicates we're behind by more than one part\n // Update directives to obtain the Playlist that has the estimated additional duration of media\n const lastAdvanced = details.age;\n const cdnAge = lastAdvanced + details.ageHeader;\n let currentGoal = Math.min(\n cdnAge - details.partTarget,\n details.targetduration * 1.5\n );\n if (currentGoal > 0) {\n if (previousDetails && currentGoal > previousDetails.tuneInGoal) {\n // If we attempted to get the next or latest playlist update, but currentGoal increased,\n // then we either can't catchup, or the \"age\" header cannot be trusted.\n this.warn(\n `CDN Tune-in goal increased from: ${previousDetails.tuneInGoal} to: ${currentGoal} with playlist age: ${details.age}`\n );\n currentGoal = 0;\n } else {\n const segments = Math.floor(currentGoal / details.targetduration);\n msn += segments;\n if (part !== undefined) {\n const parts = Math.round(\n (currentGoal % details.targetduration) / details.partTarget\n );\n part += parts;\n }\n this.log(\n `CDN Tune-in age: ${\n details.ageHeader\n }s last advanced ${lastAdvanced.toFixed(\n 2\n )}s goal: ${currentGoal} skip sn ${segments} to part ${part}`\n );\n }\n details.tuneInGoal = currentGoal;\n }\n deliveryDirectives = this.getDeliveryDirectives(\n details,\n data.deliveryDirectives,\n msn,\n part\n );\n if (lowLatencyMode || !lastPart) {\n this.loadPlaylist(deliveryDirectives);\n return;\n }\n } else if (details.canBlockReload) {\n deliveryDirectives = this.getDeliveryDirectives(\n details,\n data.deliveryDirectives,\n msn,\n part\n );\n }\n const bufferInfo = this.hls.mainForwardBufferInfo;\n const position = bufferInfo ? bufferInfo.end - bufferInfo.len : 0;\n const distanceToLiveEdgeMs = (details.edge - position) * 1000;\n const reloadInterval = computeReloadInterval(\n details,\n distanceToLiveEdgeMs\n );\n if (details.updated && now > this.requestScheduled + reloadInterval) {\n this.requestScheduled = stats.loading.start;\n }\n\n if (msn !== undefined && details.canBlockReload) {\n this.requestScheduled =\n stats.loading.first +\n reloadInterval -\n (details.partTarget * 1000 || 1000);\n } else if (\n this.requestScheduled === -1 ||\n this.requestScheduled + reloadInterval < now\n ) {\n this.requestScheduled = now;\n } else if (this.requestScheduled - now <= 0) {\n this.requestScheduled += reloadInterval;\n }\n let estimatedTimeUntilUpdate = this.requestScheduled - now;\n estimatedTimeUntilUpdate = Math.max(0, estimatedTimeUntilUpdate);\n this.log(\n `reload live playlist ${index} in ${Math.round(\n estimatedTimeUntilUpdate\n )} ms`\n );\n // this.log(\n // `live reload ${details.updated ? 'REFRESHED' : 'MISSED'}\n // reload in ${estimatedTimeUntilUpdate / 1000}\n // round trip ${(stats.loading.end - stats.loading.start) / 1000}\n // diff ${\n // (reloadInterval -\n // (estimatedTimeUntilUpdate +\n // stats.loading.end -\n // stats.loading.start)) /\n // 1000\n // }\n // reload interval ${reloadInterval / 1000}\n // target duration ${details.targetduration}\n // distance to edge ${distanceToLiveEdgeMs / 1000}`\n // );\n\n this.timer = self.setTimeout(\n () => this.loadPlaylist(deliveryDirectives),\n estimatedTimeUntilUpdate\n );\n } else {\n this.clearTimer();\n }\n }\n\n private getDeliveryDirectives(\n details: LevelDetails,\n previousDeliveryDirectives: HlsUrlParameters | null,\n msn?: number,\n part?: number\n ): HlsUrlParameters {\n let skip = getSkipValue(details, msn);\n if (previousDeliveryDirectives?.skip && details.deltaUpdateFailed) {\n msn = previousDeliveryDirectives.msn;\n part = previousDeliveryDirectives.part;\n skip = HlsSkip.No;\n }\n return new HlsUrlParameters(msn, part, skip);\n }\n\n protected checkRetry(errorEvent: ErrorData): boolean {\n const errorDetails = errorEvent.details;\n const isTimeout = isTimeoutError(errorEvent);\n const errorAction = errorEvent.errorAction;\n const { action, retryCount = 0, retryConfig } = errorAction || {};\n const retry =\n !!errorAction &&\n !!retryConfig &&\n (action === NetworkErrorAction.RetryRequest ||\n (!errorAction.resolved &&\n action === NetworkErrorAction.SendAlternateToPenaltyBox));\n if (retry) {\n this.requestScheduled = -1;\n if (retryCount >= retryConfig.maxNumRetry) {\n return false;\n }\n if (isTimeout && errorEvent.context?.deliveryDirectives) {\n // The LL-HLS request already timed out so retry immediately\n this.warn(\n `Retrying playlist loading ${retryCount + 1}/${\n retryConfig.maxNumRetry\n } after \"${errorDetails}\" without delivery-directives`\n );\n this.loadPlaylist();\n } else {\n const delay = getRetryDelay(retryConfig, retryCount);\n // Schedule level/track reload\n this.timer = self.setTimeout(() => this.loadPlaylist(), delay);\n this.warn(\n `Retrying playlist loading ${retryCount + 1}/${\n retryConfig.maxNumRetry\n } after \"${errorDetails}\" in ${delay}ms`\n );\n }\n // `levelRetry = true` used to inform other controllers that a retry is happening\n errorEvent.levelRetry = true;\n errorAction.resolved = true;\n }\n return retry;\n }\n}\n","/*\n * Level Controller\n */\n\nimport {\n ManifestLoadedData,\n ManifestParsedData,\n LevelLoadedData,\n TrackSwitchedData,\n FragLoadedData,\n ErrorData,\n LevelSwitchingData,\n LevelsUpdatedData,\n ManifestLoadingData,\n} from '../types/events';\nimport { Level } from '../types/level';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { isCodecSupportedInMp4 } from '../utils/codecs';\nimport BasePlaylistController from './base-playlist-controller';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport type Hls from '../hls';\nimport type { HlsUrlParameters, LevelParsed } from '../types/level';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport ContentSteeringController from './content-steering-controller';\n\nlet chromeOrFirefox: boolean;\n\nexport default class LevelController extends BasePlaylistController {\n private _levels: Level[] = [];\n private _firstLevel: number = -1;\n private _startLevel?: number;\n private currentLevel: Level | null = null;\n private currentLevelIndex: number = -1;\n private manualLevelIndex: number = -1;\n private steering: ContentSteeringController | null;\n\n public onParsedComplete!: Function;\n\n constructor(\n hls: Hls,\n contentSteeringController: ContentSteeringController | null\n ) {\n super(hls, '[level-controller]');\n this.steering = contentSteeringController;\n this._registerListeners();\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.on(Events.ERROR, this.onError, this);\n }\n\n private _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.off(Events.ERROR, this.onError, this);\n }\n\n public destroy() {\n this._unregisterListeners();\n this.steering = null;\n this.resetLevels();\n super.destroy();\n }\n\n public startLoad(): void {\n const levels = this._levels;\n\n // clean up live level details to force reload them, and reset load errors\n levels.forEach((level) => {\n level.loadError = 0;\n level.fragmentError = 0;\n });\n\n super.startLoad();\n }\n\n private resetLevels() {\n this._startLevel = undefined;\n this.manualLevelIndex = -1;\n this.currentLevelIndex = -1;\n this.currentLevel = null;\n this._levels = [];\n }\n\n private onManifestLoading(\n event: Events.MANIFEST_LOADING,\n data: ManifestLoadingData\n ) {\n this.resetLevels();\n }\n\n protected onManifestLoaded(\n event: Events.MANIFEST_LOADED,\n data: ManifestLoadedData\n ) {\n const levels: Level[] = [];\n const levelSet: { [key: string]: Level } = {};\n let levelFromSet: Level;\n\n // regroup redundant levels together\n data.levels.forEach((levelParsed: LevelParsed) => {\n const attributes = levelParsed.attrs;\n\n // erase audio codec info if browser does not support mp4a.40.34.\n // demuxer will autodetect codec and fallback to mpeg/audio\n if (levelParsed.audioCodec?.indexOf('mp4a.40.34') !== -1) {\n chromeOrFirefox ||= /chrome|firefox/i.test(navigator.userAgent);\n if (chromeOrFirefox) {\n levelParsed.audioCodec = undefined;\n }\n }\n\n const {\n AUDIO,\n CODECS,\n 'FRAME-RATE': FRAMERATE,\n 'PATHWAY-ID': PATHWAY,\n RESOLUTION,\n SUBTITLES,\n } = attributes;\n const contentSteeringPrefix = __USE_CONTENT_STEERING__\n ? `${PATHWAY || '.'}-`\n : '';\n const levelKey = `${contentSteeringPrefix}${levelParsed.bitrate}-${RESOLUTION}-${FRAMERATE}-${CODECS}`;\n levelFromSet = levelSet[levelKey];\n\n if (!levelFromSet) {\n levelFromSet = new Level(levelParsed);\n levelSet[levelKey] = levelFromSet;\n levels.push(levelFromSet);\n } else {\n levelFromSet.addFallback(levelParsed);\n }\n\n addGroupId(levelFromSet, 'audio', AUDIO);\n addGroupId(levelFromSet, 'text', SUBTITLES);\n });\n\n this.filterAndSortMediaOptions(levels, data);\n }\n\n private filterAndSortMediaOptions(\n unfilteredLevels: Level[],\n data: ManifestLoadedData\n ) {\n let audioTracks: MediaPlaylist[] = [];\n let subtitleTracks: MediaPlaylist[] = [];\n\n let resolutionFound = false;\n let videoCodecFound = false;\n let audioCodecFound = false;\n\n // only keep levels with supported audio/video codecs\n let levels = unfilteredLevels.filter(\n ({ audioCodec, videoCodec, width, height, unknownCodecs }) => {\n resolutionFound ||= !!(width && height);\n videoCodecFound ||= !!videoCodec;\n audioCodecFound ||= !!audioCodec;\n return (\n !unknownCodecs?.length &&\n (!audioCodec || isCodecSupportedInMp4(audioCodec, 'audio')) &&\n (!videoCodec || isCodecSupportedInMp4(videoCodec, 'video'))\n );\n }\n );\n\n // remove audio-only level if we also have levels with video codecs or RESOLUTION signalled\n if ((resolutionFound || videoCodecFound) && audioCodecFound) {\n levels = levels.filter(\n ({ videoCodec, width, height }) => !!videoCodec || !!(width && height)\n );\n }\n\n if (levels.length === 0) {\n // Dispatch error after MANIFEST_LOADED is done propagating\n Promise.resolve().then(() => {\n if (this.hls) {\n const error = new Error(\n 'no level with compatible codecs found in manifest'\n );\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR,\n fatal: true,\n url: data.url,\n error,\n reason: error.message,\n });\n }\n });\n return;\n }\n\n if (data.audioTracks) {\n audioTracks = data.audioTracks.filter(\n (track) =>\n !track.audioCodec || isCodecSupportedInMp4(track.audioCodec, 'audio')\n );\n // Assign ids after filtering as array indices by group-id\n assignTrackIdsByGroup(audioTracks);\n }\n\n if (data.subtitles) {\n subtitleTracks = data.subtitles;\n assignTrackIdsByGroup(subtitleTracks);\n }\n // start bitrate is the first bitrate of the manifest\n const unsortedLevels = levels.slice(0);\n // sort levels from lowest to highest\n levels.sort((a, b) => {\n if (a.attrs['HDCP-LEVEL'] !== b.attrs['HDCP-LEVEL']) {\n return (a.attrs['HDCP-LEVEL'] || '') > (b.attrs['HDCP-LEVEL'] || '')\n ? 1\n : -1;\n }\n if (a.bitrate !== b.bitrate) {\n return a.bitrate - b.bitrate;\n }\n if (a.attrs['FRAME-RATE'] !== b.attrs['FRAME-RATE']) {\n return (\n a.attrs.decimalFloatingPoint('FRAME-RATE') -\n b.attrs.decimalFloatingPoint('FRAME-RATE')\n );\n }\n if (a.attrs.SCORE !== b.attrs.SCORE) {\n return (\n a.attrs.decimalFloatingPoint('SCORE') -\n b.attrs.decimalFloatingPoint('SCORE')\n );\n }\n if (resolutionFound && a.height !== b.height) {\n return a.height - b.height;\n }\n return 0;\n });\n\n let firstLevelInPlaylist = unsortedLevels[0];\n if (this.steering) {\n levels = this.steering.filterParsedLevels(levels);\n if (levels.length !== unsortedLevels.length) {\n for (let i = 0; i < unsortedLevels.length; i++) {\n if (unsortedLevels[i].pathwayId === levels[0].pathwayId) {\n firstLevelInPlaylist = unsortedLevels[i];\n break;\n }\n }\n }\n }\n\n this._levels = levels;\n\n // find index of first level in sorted levels\n for (let i = 0; i < levels.length; i++) {\n if (levels[i] === firstLevelInPlaylist) {\n this._firstLevel = i;\n this.log(\n `manifest loaded, ${levels.length} level(s) found, first bitrate: ${firstLevelInPlaylist.bitrate}`\n );\n break;\n }\n }\n\n // Audio is only alternate if manifest include a URI along with the audio group tag,\n // and this is not an audio-only stream where levels contain audio-only\n const audioOnly = audioCodecFound && !videoCodecFound;\n const edata: ManifestParsedData = {\n levels,\n audioTracks,\n subtitleTracks,\n sessionData: data.sessionData,\n sessionKeys: data.sessionKeys,\n firstLevel: this._firstLevel,\n stats: data.stats,\n audio: audioCodecFound,\n video: videoCodecFound,\n altAudio: !audioOnly && audioTracks.some((t) => !!t.url),\n };\n this.hls.trigger(Events.MANIFEST_PARSED, edata);\n\n // Initiate loading after all controllers have received MANIFEST_PARSED\n if (this.hls.config.autoStartLoad || this.hls.forceStartLoad) {\n this.hls.startLoad(this.hls.config.startPosition);\n }\n }\n\n get levels(): Level[] | null {\n if (this._levels.length === 0) {\n return null;\n }\n return this._levels;\n }\n\n get level(): number {\n return this.currentLevelIndex;\n }\n\n set level(newLevel: number) {\n const levels = this._levels;\n if (levels.length === 0) {\n return;\n }\n // check if level idx is valid\n if (newLevel < 0 || newLevel >= levels.length) {\n // invalid level id given, trigger error\n const error = new Error('invalid level idx');\n const fatal = newLevel < 0;\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.OTHER_ERROR,\n details: ErrorDetails.LEVEL_SWITCH_ERROR,\n level: newLevel,\n fatal,\n error,\n reason: error.message,\n });\n if (fatal) {\n return;\n }\n newLevel = Math.min(newLevel, levels.length - 1);\n }\n\n const lastLevelIndex = this.currentLevelIndex;\n const lastLevel = this.currentLevel;\n const lastPathwayId = lastLevel ? lastLevel.attrs['PATHWAY-ID'] : undefined;\n const level = levels[newLevel];\n const pathwayId = level.attrs['PATHWAY-ID'];\n this.currentLevelIndex = newLevel;\n this.currentLevel = level;\n\n if (\n lastLevelIndex === newLevel &&\n level.details &&\n lastLevel &&\n lastPathwayId === pathwayId\n ) {\n return;\n }\n\n this.log(\n `Switching to level ${newLevel}${\n pathwayId ? ' with Pathway ' + pathwayId : ''\n } from level ${lastLevelIndex}${\n lastPathwayId ? ' with Pathway ' + lastPathwayId : ''\n }`\n );\n\n const levelSwitchingData: LevelSwitchingData = Object.assign({}, level, {\n level: newLevel,\n maxBitrate: level.maxBitrate,\n attrs: level.attrs,\n uri: level.uri,\n urlId: level.urlId,\n });\n // @ts-ignore\n delete levelSwitchingData._attrs;\n // @ts-ignore\n delete levelSwitchingData._urlId;\n this.hls.trigger(Events.LEVEL_SWITCHING, levelSwitchingData);\n // check if we need to load playlist for this level\n const levelDetails = level.details;\n if (!levelDetails || levelDetails.live) {\n // level not retrieved yet, or live playlist we need to (re)load it\n const hlsUrlParameters = this.switchParams(level.uri, lastLevel?.details);\n this.loadPlaylist(hlsUrlParameters);\n }\n }\n\n get manualLevel(): number {\n return this.manualLevelIndex;\n }\n\n set manualLevel(newLevel) {\n this.manualLevelIndex = newLevel;\n if (this._startLevel === undefined) {\n this._startLevel = newLevel;\n }\n\n if (newLevel !== -1) {\n this.level = newLevel;\n }\n }\n\n get firstLevel(): number {\n return this._firstLevel;\n }\n\n set firstLevel(newLevel) {\n this._firstLevel = newLevel;\n }\n\n get startLevel() {\n // hls.startLevel takes precedence over config.startLevel\n // if none of these values are defined, fallback on this._firstLevel (first quality level appearing in variant manifest)\n if (this._startLevel === undefined) {\n const configStartLevel = this.hls.config.startLevel;\n if (configStartLevel !== undefined) {\n return configStartLevel;\n } else {\n return this._firstLevel;\n }\n } else {\n return this._startLevel;\n }\n }\n\n set startLevel(newLevel) {\n this._startLevel = newLevel;\n }\n\n protected onError(event: Events.ERROR, data: ErrorData) {\n if (data.fatal || !data.context) {\n return;\n }\n\n if (\n data.context.type === PlaylistContextType.LEVEL &&\n data.context.level === this.level\n ) {\n this.checkRetry(data);\n }\n }\n\n // reset errors on the successful load of a fragment\n protected onFragLoaded(event: Events.FRAG_LOADED, { frag }: FragLoadedData) {\n if (frag !== undefined && frag.type === PlaylistLevelType.MAIN) {\n const level = this._levels[frag.level];\n if (level !== undefined) {\n level.loadError = 0;\n }\n }\n }\n\n protected onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n const { level, details } = data;\n const curLevel = this._levels[level];\n\n if (!curLevel) {\n this.warn(`Invalid level index ${level}`);\n if (data.deliveryDirectives?.skip) {\n details.deltaUpdateFailed = true;\n }\n return;\n }\n\n // only process level loaded events matching with expected level\n if (level === this.currentLevelIndex) {\n // reset level load error counter on successful level loaded only if there is no issues with fragments\n if (curLevel.fragmentError === 0) {\n curLevel.loadError = 0;\n }\n this.playlistLoaded(level, data, curLevel.details);\n } else if (data.deliveryDirectives?.skip) {\n // received a delta playlist update that cannot be merged\n details.deltaUpdateFailed = true;\n }\n }\n\n protected onAudioTrackSwitched(\n event: Events.AUDIO_TRACK_SWITCHED,\n data: TrackSwitchedData\n ) {\n const currentLevel = this.currentLevel;\n if (!currentLevel) {\n return;\n }\n\n const audioGroupId = this.hls.audioTracks[data.id].groupId;\n if (\n currentLevel.audioGroupIds &&\n currentLevel.audioGroupId !== audioGroupId\n ) {\n let urlId = -1;\n for (let i = 0; i < currentLevel.audioGroupIds.length; i++) {\n if (currentLevel.audioGroupIds[i] === audioGroupId) {\n urlId = i;\n break;\n }\n }\n\n if (urlId !== -1 && urlId !== currentLevel.urlId) {\n currentLevel.urlId = urlId;\n if (this.canLoad) {\n this.startLoad();\n }\n }\n }\n }\n\n protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters) {\n super.loadPlaylist();\n const currentLevelIndex = this.currentLevelIndex;\n const currentLevel = this.currentLevel;\n\n if (currentLevel && this.shouldLoadPlaylist(currentLevel)) {\n const id = currentLevel.urlId;\n let url = currentLevel.uri;\n if (hlsUrlParameters) {\n try {\n url = hlsUrlParameters.addDirectives(url);\n } catch (error) {\n this.warn(\n `Could not construct new URL with HLS Delivery Directives: ${error}`\n );\n }\n }\n\n const pathwayId = currentLevel.attrs['PATHWAY-ID'];\n this.log(\n `Loading level index ${currentLevelIndex}${\n hlsUrlParameters?.msn !== undefined\n ? ' at sn ' +\n hlsUrlParameters.msn +\n ' part ' +\n hlsUrlParameters.part\n : ''\n } with${pathwayId ? ' Pathway ' + pathwayId : ''} URI ${id + 1}/${\n currentLevel.url.length\n } ${url}`\n );\n\n // console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);\n // console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);\n this.clearTimer();\n this.hls.trigger(Events.LEVEL_LOADING, {\n url,\n level: currentLevelIndex,\n id,\n deliveryDirectives: hlsUrlParameters || null,\n });\n }\n }\n\n get nextLoadLevel() {\n if (this.manualLevelIndex !== -1) {\n return this.manualLevelIndex;\n } else {\n return this.hls.nextAutoLevel;\n }\n }\n\n set nextLoadLevel(nextLevel) {\n this.level = nextLevel;\n if (this.manualLevelIndex === -1) {\n this.hls.nextAutoLevel = nextLevel;\n }\n }\n\n removeLevel(levelIndex, urlId) {\n const filterLevelAndGroupByIdIndex = (url, id) => id !== urlId;\n const levels = this._levels.filter((level, index) => {\n if (index !== levelIndex) {\n return true;\n }\n\n if (level.url.length > 1 && urlId !== undefined) {\n level.url = level.url.filter(filterLevelAndGroupByIdIndex);\n if (level.audioGroupIds) {\n level.audioGroupIds = level.audioGroupIds.filter(\n filterLevelAndGroupByIdIndex\n );\n }\n if (level.textGroupIds) {\n level.textGroupIds = level.textGroupIds.filter(\n filterLevelAndGroupByIdIndex\n );\n }\n level.urlId = 0;\n return true;\n }\n if (this.steering) {\n this.steering.removeLevel(level);\n }\n return false;\n });\n\n this.hls.trigger(Events.LEVELS_UPDATED, { levels });\n }\n\n private onLevelsUpdated(\n event: Events.LEVELS_UPDATED,\n { levels }: LevelsUpdatedData\n ) {\n levels.forEach((level, index) => {\n const { details } = level;\n if (details?.fragments) {\n details.fragments.forEach((fragment) => {\n fragment.level = index;\n });\n }\n });\n this._levels = levels;\n }\n}\n\nexport function addGroupId(\n level: Level,\n type: string,\n id: string | undefined\n): void {\n if (!id) {\n return;\n }\n if (type === 'audio') {\n if (!level.audioGroupIds) {\n level.audioGroupIds = [];\n }\n level.audioGroupIds[level.url.length - 1] = id;\n } else if (type === 'text') {\n if (!level.textGroupIds) {\n level.textGroupIds = [];\n }\n level.textGroupIds[level.url.length - 1] = id;\n }\n}\n\nfunction assignTrackIdsByGroup(tracks: MediaPlaylist[]): void {\n const groups = {};\n tracks.forEach((track) => {\n const groupId = track.groupId || '';\n track.id = groups[groupId] = groups[groupId] || 0;\n groups[groupId]++;\n });\n}\n","import { Events } from '../events';\nimport { Fragment, Part } from '../loader/fragment';\nimport { PlaylistLevelType } from '../types/loader';\nimport type { SourceBufferName } from '../types/buffer';\nimport type {\n FragmentBufferedRange,\n FragmentEntity,\n FragmentTimeRange,\n} from '../types/fragment-tracker';\nimport type { ComponentAPI } from '../types/component-api';\nimport type {\n BufferAppendedData,\n FragBufferedData,\n FragLoadedData,\n} from '../types/events';\nimport type Hls from '../hls';\n\nexport const enum FragmentState {\n NOT_LOADED = 'NOT_LOADED',\n APPENDING = 'APPENDING',\n PARTIAL = 'PARTIAL',\n OK = 'OK',\n}\n\nexport class FragmentTracker implements ComponentAPI {\n private activePartLists: { [key in PlaylistLevelType]?: Part[] } =\n Object.create(null);\n private endListFragments: { [key in PlaylistLevelType]?: FragmentEntity } =\n Object.create(null);\n private fragments: Partial<Record<string, FragmentEntity>> =\n Object.create(null);\n private timeRanges:\n | {\n [key in SourceBufferName]?: TimeRanges;\n }\n | null = Object.create(null);\n\n private bufferPadding: number = 0.2;\n private hls: Hls;\n private hasGaps: boolean = false;\n\n constructor(hls: Hls) {\n this.hls = hls;\n\n this._registerListeners();\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.BUFFER_APPENDED, this.onBufferAppended, this);\n hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n }\n\n private _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.BUFFER_APPENDED, this.onBufferAppended, this);\n hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n }\n\n public destroy() {\n this._unregisterListeners();\n // @ts-ignore\n this.fragments =\n // @ts-ignore\n this.activePartLists =\n // @ts-ignore\n this.endListFragments =\n this.timeRanges =\n null;\n }\n\n /**\n * Return a Fragment or Part with an appended range that matches the position and levelType\n * Otherwise, return null\n */\n public getAppendedFrag(\n position: number,\n levelType: PlaylistLevelType\n ): Fragment | Part | null {\n const activeParts = this.activePartLists[levelType];\n if (activeParts) {\n for (let i = activeParts.length; i--; ) {\n const activePart = activeParts[i];\n if (!activePart) {\n break;\n }\n const appendedPTS = activePart.end;\n if (\n activePart.start <= position &&\n appendedPTS !== null &&\n position <= appendedPTS\n ) {\n return activePart;\n }\n }\n }\n return this.getBufferedFrag(position, levelType);\n }\n\n /**\n * Return a buffered Fragment that matches the position and levelType.\n * A buffered Fragment is one whose loading, parsing and appending is done (completed or \"partial\" meaning aborted).\n * If not found any Fragment, return null\n */\n public getBufferedFrag(\n position: number,\n levelType: PlaylistLevelType\n ): Fragment | null {\n const { fragments } = this;\n const keys = Object.keys(fragments);\n for (let i = keys.length; i--; ) {\n const fragmentEntity = fragments[keys[i]];\n if (fragmentEntity?.body.type === levelType && fragmentEntity.buffered) {\n const frag = fragmentEntity.body;\n if (frag.start <= position && position <= frag.end) {\n return frag;\n }\n }\n }\n return null;\n }\n\n /**\n * Partial fragments effected by coded frame eviction will be removed\n * The browser will unload parts of the buffer to free up memory for new buffer data\n * Fragments will need to be reloaded when the buffer is freed up, removing partial fragments will allow them to reload(since there might be parts that are still playable)\n */\n public detectEvictedFragments(\n elementaryStream: SourceBufferName,\n timeRange: TimeRanges,\n playlistType: PlaylistLevelType,\n appendedPart?: Part | null\n ) {\n if (this.timeRanges) {\n this.timeRanges[elementaryStream] = timeRange;\n }\n // Check if any flagged fragments have been unloaded\n // excluding anything newer than appendedPartSn\n const appendedPartSn = (appendedPart?.fragment.sn || -1) as number;\n Object.keys(this.fragments).forEach((key) => {\n const fragmentEntity = this.fragments[key];\n if (!fragmentEntity) {\n return;\n }\n if (appendedPartSn >= (fragmentEntity.body.sn as number)) {\n return;\n }\n if (!fragmentEntity.buffered && !fragmentEntity.loaded) {\n if (fragmentEntity.body.type === playlistType) {\n this.removeFragment(fragmentEntity.body);\n }\n return;\n }\n const esData = fragmentEntity.range[elementaryStream];\n if (!esData) {\n return;\n }\n esData.time.some((time: FragmentTimeRange) => {\n const isNotBuffered = !this.isTimeBuffered(\n time.startPTS,\n time.endPTS,\n timeRange\n );\n if (isNotBuffered) {\n // Unregister partial fragment as it needs to load again to be reused\n this.removeFragment(fragmentEntity.body);\n }\n return isNotBuffered;\n });\n });\n }\n\n /**\n * Checks if the fragment passed in is loaded in the buffer properly\n * Partially loaded fragments will be registered as a partial fragment\n */\n public detectPartialFragments(data: FragBufferedData) {\n const timeRanges = this.timeRanges;\n const { frag, part } = data;\n if (!timeRanges || frag.sn === 'initSegment') {\n return;\n }\n\n const fragKey = getFragmentKey(frag);\n const fragmentEntity = this.fragments[fragKey];\n if (!fragmentEntity) {\n return;\n }\n const isFragHint = !frag.relurl;\n Object.keys(timeRanges).forEach((elementaryStream: SourceBufferName) => {\n const streamInfo = frag.elementaryStreams[elementaryStream];\n if (!streamInfo) {\n return;\n }\n const timeRange = timeRanges[elementaryStream] as TimeRanges;\n const partial = isFragHint || streamInfo.partial === true;\n fragmentEntity.range[elementaryStream] = this.getBufferedTimes(\n frag,\n part,\n partial,\n timeRange\n );\n });\n fragmentEntity.loaded = null;\n if (Object.keys(fragmentEntity.range).length) {\n fragmentEntity.buffered = true;\n if (fragmentEntity.body.endList) {\n this.endListFragments[fragmentEntity.body.type] = fragmentEntity;\n }\n if (!isPartial(fragmentEntity)) {\n // Remove older fragment parts from lookup after frag is tracked as buffered\n this.removeParts((frag.sn as number) - 1, frag.type);\n }\n } else {\n // remove fragment if nothing was appended\n this.removeFragment(fragmentEntity.body);\n }\n }\n\n private removeParts(snToKeep: number, levelType: PlaylistLevelType) {\n const activeParts = this.activePartLists[levelType];\n if (!activeParts) {\n return;\n }\n this.activePartLists[levelType] = activeParts.filter(\n (part) => (part.fragment.sn as number) >= snToKeep\n );\n }\n\n public fragBuffered(frag: Fragment, force?: true) {\n const fragKey = getFragmentKey(frag);\n let fragmentEntity = this.fragments[fragKey];\n if (!fragmentEntity && force) {\n fragmentEntity = this.fragments[fragKey] = {\n body: frag,\n appendedPTS: null,\n loaded: null,\n buffered: false,\n range: Object.create(null),\n };\n if (frag.gap) {\n this.hasGaps = true;\n }\n }\n if (fragmentEntity) {\n fragmentEntity.loaded = null;\n fragmentEntity.buffered = true;\n }\n }\n\n private getBufferedTimes(\n fragment: Fragment,\n part: Part | null,\n partial: boolean,\n timeRange: TimeRanges\n ): FragmentBufferedRange {\n const buffered: FragmentBufferedRange = {\n time: [],\n partial,\n };\n const startPTS = fragment.start;\n const endPTS = fragment.end;\n const minEndPTS = fragment.minEndPTS || endPTS;\n const maxStartPTS = fragment.maxStartPTS || startPTS;\n for (let i = 0; i < timeRange.length; i++) {\n const startTime = timeRange.start(i) - this.bufferPadding;\n const endTime = timeRange.end(i) + this.bufferPadding;\n if (maxStartPTS >= startTime && minEndPTS <= endTime) {\n // Fragment is entirely contained in buffer\n // No need to check the other timeRange times since it's completely playable\n buffered.time.push({\n startPTS: Math.max(startPTS, timeRange.start(i)),\n endPTS: Math.min(endPTS, timeRange.end(i)),\n });\n break;\n } else if (startPTS < endTime && endPTS > startTime) {\n buffered.partial = true;\n // Check for intersection with buffer\n // Get playable sections of the fragment\n buffered.time.push({\n startPTS: Math.max(startPTS, timeRange.start(i)),\n endPTS: Math.min(endPTS, timeRange.end(i)),\n });\n } else if (endPTS <= startTime) {\n // No need to check the rest of the timeRange as it is in order\n break;\n }\n }\n return buffered;\n }\n\n /**\n * Gets the partial fragment for a certain time\n */\n public getPartialFragment(time: number): Fragment | null {\n let bestFragment: Fragment | null = null;\n let timePadding: number;\n let startTime: number;\n let endTime: number;\n let bestOverlap: number = 0;\n const { bufferPadding, fragments } = this;\n Object.keys(fragments).forEach((key) => {\n const fragmentEntity = fragments[key];\n if (!fragmentEntity) {\n return;\n }\n if (isPartial(fragmentEntity)) {\n startTime = fragmentEntity.body.start - bufferPadding;\n endTime = fragmentEntity.body.end + bufferPadding;\n if (time >= startTime && time <= endTime) {\n // Use the fragment that has the most padding from start and end time\n timePadding = Math.min(time - startTime, endTime - time);\n if (bestOverlap <= timePadding) {\n bestFragment = fragmentEntity.body;\n bestOverlap = timePadding;\n }\n }\n }\n });\n return bestFragment;\n }\n\n public isEndListAppended(type: PlaylistLevelType): boolean {\n const lastFragmentEntity = this.endListFragments[type];\n return (\n lastFragmentEntity !== undefined &&\n (lastFragmentEntity.buffered || isPartial(lastFragmentEntity))\n );\n }\n\n public getState(fragment: Fragment): FragmentState {\n const fragKey = getFragmentKey(fragment);\n const fragmentEntity = this.fragments[fragKey];\n\n if (fragmentEntity) {\n if (!fragmentEntity.buffered) {\n return FragmentState.APPENDING;\n } else if (isPartial(fragmentEntity)) {\n return FragmentState.PARTIAL;\n } else {\n return FragmentState.OK;\n }\n }\n\n return FragmentState.NOT_LOADED;\n }\n\n private isTimeBuffered(\n startPTS: number,\n endPTS: number,\n timeRange: TimeRanges\n ): boolean {\n let startTime;\n let endTime;\n for (let i = 0; i < timeRange.length; i++) {\n startTime = timeRange.start(i) - this.bufferPadding;\n endTime = timeRange.end(i) + this.bufferPadding;\n if (startPTS >= startTime && endPTS <= endTime) {\n return true;\n }\n\n if (endPTS <= startTime) {\n // No need to check the rest of the timeRange as it is in order\n return false;\n }\n }\n\n return false;\n }\n\n private onFragLoaded(event: Events.FRAG_LOADED, data: FragLoadedData) {\n const { frag, part } = data;\n // don't track initsegment (for which sn is not a number)\n // don't track frags used for bitrateTest, they're irrelevant.\n if (frag.sn === 'initSegment' || frag.bitrateTest) {\n return;\n }\n\n // Fragment entity `loaded` FragLoadedData is null when loading parts\n const loaded = part ? null : data;\n\n const fragKey = getFragmentKey(frag);\n this.fragments[fragKey] = {\n body: frag,\n appendedPTS: null,\n loaded,\n buffered: false,\n range: Object.create(null),\n };\n }\n\n private onBufferAppended(\n event: Events.BUFFER_APPENDED,\n data: BufferAppendedData\n ) {\n const { frag, part, timeRanges } = data;\n if (frag.sn === 'initSegment') {\n return;\n }\n const playlistType = frag.type;\n if (part) {\n let activeParts = this.activePartLists[playlistType];\n if (!activeParts) {\n this.activePartLists[playlistType] = activeParts = [];\n }\n activeParts.push(part);\n }\n // Store the latest timeRanges loaded in the buffer\n this.timeRanges = timeRanges;\n Object.keys(timeRanges).forEach((elementaryStream: SourceBufferName) => {\n const timeRange = timeRanges[elementaryStream] as TimeRanges;\n this.detectEvictedFragments(\n elementaryStream,\n timeRange,\n playlistType,\n part\n );\n });\n }\n\n private onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n this.detectPartialFragments(data);\n }\n\n private hasFragment(fragment: Fragment): boolean {\n const fragKey = getFragmentKey(fragment);\n return !!this.fragments[fragKey];\n }\n\n public hasParts(type: PlaylistLevelType): boolean {\n return !!this.activePartLists[type]?.length;\n }\n\n public removeFragmentsInRange(\n start: number,\n end: number,\n playlistType: PlaylistLevelType,\n withGapOnly?: boolean,\n unbufferedOnly?: boolean\n ) {\n if (withGapOnly && !this.hasGaps) {\n return;\n }\n Object.keys(this.fragments).forEach((key) => {\n const fragmentEntity = this.fragments[key];\n if (!fragmentEntity) {\n return;\n }\n const frag = fragmentEntity.body;\n if (frag.type !== playlistType || (withGapOnly && !frag.gap)) {\n return;\n }\n if (\n frag.start < end &&\n frag.end > start &&\n (fragmentEntity.buffered || unbufferedOnly)\n ) {\n this.removeFragment(frag);\n }\n });\n }\n\n public removeFragment(fragment: Fragment) {\n const fragKey = getFragmentKey(fragment);\n fragment.stats.loaded = 0;\n fragment.clearElementaryStreamInfo();\n const activeParts = this.activePartLists[fragment.type];\n if (activeParts) {\n const snToRemove = fragment.sn;\n this.activePartLists[fragment.type] = activeParts.filter(\n (part) => part.fragment.sn !== snToRemove\n );\n }\n delete this.fragments[fragKey];\n if (fragment.endList) {\n delete this.endListFragments[fragment.type];\n }\n }\n\n public removeAllFragments() {\n this.fragments = Object.create(null);\n this.endListFragments = Object.create(null);\n this.activePartLists = Object.create(null);\n this.hasGaps = false;\n }\n}\n\nfunction isPartial(fragmentEntity: FragmentEntity): boolean {\n return (\n fragmentEntity.buffered &&\n (fragmentEntity.body.gap ||\n fragmentEntity.range.video?.partial ||\n fragmentEntity.range.audio?.partial ||\n fragmentEntity.range.audiovideo?.partial)\n );\n}\n\nfunction getFragmentKey(fragment: Fragment): string {\n return `${fragment.type}_${fragment.level}_${fragment.urlId}_${fragment.sn}`;\n}\n","import { ErrorTypes, ErrorDetails } from '../errors';\nimport { Fragment } from './fragment';\nimport {\n Loader,\n LoaderConfiguration,\n FragmentLoaderContext,\n} from '../types/loader';\nimport { getLoaderConfigWithoutReties } from '../utils/error-helper';\nimport type { HlsConfig } from '../config';\nimport type { BaseSegment, Part } from './fragment';\nimport type {\n ErrorData,\n FragLoadedData,\n PartsLoadedData,\n} from '../types/events';\n\nconst MIN_CHUNK_SIZE = Math.pow(2, 17); // 128kb\n\nexport default class FragmentLoader {\n private readonly config: HlsConfig;\n private loader: Loader<FragmentLoaderContext> | null = null;\n private partLoadTimeout: number = -1;\n\n constructor(config: HlsConfig) {\n this.config = config;\n }\n\n destroy() {\n if (this.loader) {\n this.loader.destroy();\n this.loader = null;\n }\n }\n\n abort() {\n if (this.loader) {\n // Abort the loader for current fragment. Only one may load at any given time\n this.loader.abort();\n }\n }\n\n load(\n frag: Fragment,\n onProgress?: FragmentLoadProgressCallback\n ): Promise<FragLoadedData> {\n const url = frag.url;\n if (!url) {\n return Promise.reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.FRAG_LOAD_ERROR,\n fatal: false,\n frag,\n error: new Error(\n `Fragment does not have a ${url ? 'part list' : 'url'}`\n ),\n networkDetails: null,\n })\n );\n }\n this.abort();\n\n const config = this.config;\n const FragmentILoader = config.fLoader;\n const DefaultILoader = config.loader;\n\n return new Promise((resolve, reject) => {\n if (this.loader) {\n this.loader.destroy();\n }\n if (frag.gap) {\n reject(createGapLoadError(frag));\n return;\n }\n const loader =\n (this.loader =\n frag.loader =\n FragmentILoader\n ? new FragmentILoader(config)\n : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));\n const loaderContext = createLoaderContext(frag);\n const loadPolicy = getLoaderConfigWithoutReties(\n config.fragLoadPolicy.default\n );\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: 0,\n retryDelay: 0,\n maxRetryDelay: 0,\n highWaterMark: frag.sn === 'initSegment' ? Infinity : MIN_CHUNK_SIZE,\n };\n // Assign frag stats to the loader's stats reference\n frag.stats = loader.stats;\n loader.load(loaderContext, loaderConfig, {\n onSuccess: (response, stats, context, networkDetails) => {\n this.resetLoader(frag, loader);\n let payload = response.data as ArrayBuffer;\n if (context.resetIV && frag.decryptdata) {\n frag.decryptdata.iv = new Uint8Array(payload.slice(0, 16));\n payload = payload.slice(16);\n }\n resolve({\n frag,\n part: null,\n payload,\n networkDetails,\n });\n },\n onError: (response, context, networkDetails, stats) => {\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.FRAG_LOAD_ERROR,\n fatal: false,\n frag,\n response: { url, data: undefined, ...response },\n error: new Error(`HTTP Error ${response.code} ${response.text}`),\n networkDetails,\n stats,\n })\n );\n },\n onAbort: (stats, context, networkDetails) => {\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.INTERNAL_ABORTED,\n fatal: false,\n frag,\n error: new Error('Aborted'),\n networkDetails,\n stats,\n })\n );\n },\n onTimeout: (stats, context, networkDetails) => {\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.FRAG_LOAD_TIMEOUT,\n fatal: false,\n frag,\n error: new Error(`Timeout after ${loaderConfig.timeout}ms`),\n networkDetails,\n stats,\n })\n );\n },\n onProgress: (stats, context, data, networkDetails) => {\n if (onProgress) {\n onProgress({\n frag,\n part: null,\n payload: data as ArrayBuffer,\n networkDetails,\n });\n }\n },\n });\n });\n }\n\n public loadPart(\n frag: Fragment,\n part: Part,\n onProgress: FragmentLoadProgressCallback\n ): Promise<FragLoadedData> {\n this.abort();\n\n const config = this.config;\n const FragmentILoader = config.fLoader;\n const DefaultILoader = config.loader;\n\n return new Promise((resolve, reject) => {\n if (this.loader) {\n this.loader.destroy();\n }\n if (frag.gap || part.gap) {\n reject(createGapLoadError(frag, part));\n return;\n }\n const loader =\n (this.loader =\n frag.loader =\n FragmentILoader\n ? new FragmentILoader(config)\n : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));\n const loaderContext = createLoaderContext(frag, part);\n // Should we define another load policy for parts?\n const loadPolicy = getLoaderConfigWithoutReties(\n config.fragLoadPolicy.default\n );\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: 0,\n retryDelay: 0,\n maxRetryDelay: 0,\n highWaterMark: MIN_CHUNK_SIZE,\n };\n // Assign part stats to the loader's stats reference\n part.stats = loader.stats;\n loader.load(loaderContext, loaderConfig, {\n onSuccess: (response, stats, context, networkDetails) => {\n this.resetLoader(frag, loader);\n this.updateStatsFromPart(frag, part);\n const partLoadedData: FragLoadedData = {\n frag,\n part,\n payload: response.data as ArrayBuffer,\n networkDetails,\n };\n onProgress(partLoadedData);\n resolve(partLoadedData);\n },\n onError: (response, context, networkDetails, stats) => {\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.FRAG_LOAD_ERROR,\n fatal: false,\n frag,\n part,\n response: {\n url: loaderContext.url,\n data: undefined,\n ...response,\n },\n error: new Error(`HTTP Error ${response.code} ${response.text}`),\n networkDetails,\n stats,\n })\n );\n },\n onAbort: (stats, context, networkDetails) => {\n frag.stats.aborted = part.stats.aborted;\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.INTERNAL_ABORTED,\n fatal: false,\n frag,\n part,\n error: new Error('Aborted'),\n networkDetails,\n stats,\n })\n );\n },\n onTimeout: (stats, context, networkDetails) => {\n this.resetLoader(frag, loader);\n reject(\n new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details: ErrorDetails.FRAG_LOAD_TIMEOUT,\n fatal: false,\n frag,\n part,\n error: new Error(`Timeout after ${loaderConfig.timeout}ms`),\n networkDetails,\n stats,\n })\n );\n },\n });\n });\n }\n\n private updateStatsFromPart(frag: Fragment, part: Part) {\n const fragStats = frag.stats;\n const partStats = part.stats;\n const partTotal = partStats.total;\n fragStats.loaded += partStats.loaded;\n if (partTotal) {\n const estTotalParts = Math.round(frag.duration / part.duration);\n const estLoadedParts = Math.min(\n Math.round(fragStats.loaded / partTotal),\n estTotalParts\n );\n const estRemainingParts = estTotalParts - estLoadedParts;\n const estRemainingBytes =\n estRemainingParts * Math.round(fragStats.loaded / estLoadedParts);\n fragStats.total = fragStats.loaded + estRemainingBytes;\n } else {\n fragStats.total = Math.max(fragStats.loaded, fragStats.total);\n }\n const fragLoading = fragStats.loading;\n const partLoading = partStats.loading;\n if (fragLoading.start) {\n // add to fragment loader latency\n fragLoading.first += partLoading.first - partLoading.start;\n } else {\n fragLoading.start = partLoading.start;\n fragLoading.first = partLoading.first;\n }\n fragLoading.end = partLoading.end;\n }\n\n private resetLoader(frag: Fragment, loader: Loader<FragmentLoaderContext>) {\n frag.loader = null;\n if (this.loader === loader) {\n self.clearTimeout(this.partLoadTimeout);\n this.loader = null;\n }\n loader.destroy();\n }\n}\n\nfunction createLoaderContext(\n frag: Fragment,\n part: Part | null = null\n): FragmentLoaderContext {\n const segment: BaseSegment = part || frag;\n const loaderContext: FragmentLoaderContext = {\n frag,\n part,\n responseType: 'arraybuffer',\n url: segment.url,\n headers: {},\n rangeStart: 0,\n rangeEnd: 0,\n };\n const start = segment.byteRangeStartOffset;\n const end = segment.byteRangeEndOffset;\n if (Number.isFinite(start) && Number.isFinite(end)) {\n let byteRangeStart = start;\n let byteRangeEnd = end;\n if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {\n // MAP segment encrypted with method 'AES-128', when served with HTTP Range,\n // has the unencrypted size specified in the range.\n // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6\n const fragmentLen = end - start;\n if (fragmentLen % 16) {\n byteRangeEnd = end + (16 - (fragmentLen % 16));\n }\n if (start !== 0) {\n loaderContext.resetIV = true;\n byteRangeStart = start - 16;\n }\n }\n loaderContext.rangeStart = byteRangeStart;\n loaderContext.rangeEnd = byteRangeEnd;\n }\n return loaderContext;\n}\n\nfunction createGapLoadError(frag: Fragment, part?: Part): LoadError {\n const error = new Error(`GAP ${frag.gap ? 'tag' : 'attribute'} found`);\n const errorData: FragLoadFailResult = {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_GAP,\n fatal: false,\n frag,\n error,\n networkDetails: null,\n };\n if (part) {\n errorData.part = part;\n }\n (part ? part : frag).stats.aborted = true;\n return new LoadError(errorData);\n}\n\nexport class LoadError extends Error {\n public readonly data: FragLoadFailResult;\n constructor(data: FragLoadFailResult) {\n super(data.error.message);\n this.data = data;\n }\n}\n\nexport interface FragLoadFailResult extends ErrorData {\n frag: Fragment;\n part?: Part;\n response?: {\n data: any;\n // error status code\n code: number;\n // error description\n text: string;\n url: string;\n };\n networkDetails: any;\n}\n\nexport type FragmentLoadProgressCallback = (\n result: FragLoadedData | PartsLoadedData\n) => void;\n","import { ErrorTypes, ErrorDetails } from '../errors';\nimport {\n LoaderStats,\n LoaderResponse,\n LoaderConfiguration,\n LoaderCallbacks,\n Loader,\n KeyLoaderContext,\n PlaylistLevelType,\n} from '../types/loader';\nimport { LoadError } from './fragment-loader';\nimport type { HlsConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { KeyLoadedData } from '../types/events';\nimport type { LevelKey } from './level-key';\nimport type EMEController from '../controller/eme-controller';\nimport type { MediaKeySessionContext } from '../controller/eme-controller';\nimport type { KeySystemFormats } from '../utils/mediakeys-helper';\n\nexport interface KeyLoaderInfo {\n decryptdata: LevelKey;\n keyLoadPromise: Promise<KeyLoadedData> | null;\n loader: Loader<KeyLoaderContext> | null;\n mediaKeySessionContext: MediaKeySessionContext | null;\n}\nexport default class KeyLoader implements ComponentAPI {\n private readonly config: HlsConfig;\n public keyUriToKeyInfo: { [keyuri: string]: KeyLoaderInfo } = {};\n public emeController: EMEController | null = null;\n\n constructor(config: HlsConfig) {\n this.config = config;\n }\n\n abort(type?: PlaylistLevelType) {\n for (const uri in this.keyUriToKeyInfo) {\n const loader = this.keyUriToKeyInfo[uri].loader;\n if (loader) {\n if (type && type !== loader.context.frag.type) {\n return;\n }\n loader.abort();\n }\n }\n }\n\n detach() {\n for (const uri in this.keyUriToKeyInfo) {\n const keyInfo = this.keyUriToKeyInfo[uri];\n // Remove cached EME keys on detach\n if (\n keyInfo.mediaKeySessionContext ||\n keyInfo.decryptdata.isCommonEncryption\n ) {\n delete this.keyUriToKeyInfo[uri];\n }\n }\n }\n\n destroy() {\n this.detach();\n for (const uri in this.keyUriToKeyInfo) {\n const loader = this.keyUriToKeyInfo[uri].loader;\n if (loader) {\n loader.destroy();\n }\n }\n this.keyUriToKeyInfo = {};\n }\n\n createKeyLoadError(\n frag: Fragment,\n details: ErrorDetails = ErrorDetails.KEY_LOAD_ERROR,\n error: Error,\n networkDetails?: any,\n response?: { url: string; data: undefined; code: number; text: string }\n ): LoadError {\n return new LoadError({\n type: ErrorTypes.NETWORK_ERROR,\n details,\n fatal: false,\n frag,\n response,\n error,\n networkDetails,\n });\n }\n\n loadClear(\n loadingFrag: Fragment,\n encryptedFragments: Fragment[]\n ): void | Promise<void> {\n if (this.emeController && this.config.emeEnabled) {\n // access key-system with nearest key on start (loaidng frag is unencrypted)\n const { sn, cc } = loadingFrag;\n for (let i = 0; i < encryptedFragments.length; i++) {\n const frag = encryptedFragments[i];\n if (\n cc <= frag.cc &&\n (sn === 'initSegment' || frag.sn === 'initSegment' || sn < frag.sn)\n ) {\n this.emeController\n .selectKeySystemFormat(frag)\n .then((keySystemFormat) => {\n frag.setKeyFormat(keySystemFormat);\n });\n break;\n }\n }\n }\n }\n\n load(frag: Fragment): Promise<KeyLoadedData> {\n if (!frag.decryptdata && frag.encrypted && this.emeController) {\n // Multiple keys, but none selected, resolve in eme-controller\n return this.emeController\n .selectKeySystemFormat(frag)\n .then((keySystemFormat) => {\n return this.loadInternal(frag, keySystemFormat);\n });\n }\n\n return this.loadInternal(frag);\n }\n\n loadInternal(\n frag: Fragment,\n keySystemFormat?: KeySystemFormats\n ): Promise<KeyLoadedData> {\n if (keySystemFormat) {\n frag.setKeyFormat(keySystemFormat);\n }\n const decryptdata = frag.decryptdata;\n if (!decryptdata) {\n const error = new Error(\n keySystemFormat\n ? `Expected frag.decryptdata to be defined after setting format ${keySystemFormat}`\n : 'Missing decryption data on fragment in onKeyLoading'\n );\n return Promise.reject(\n this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, error)\n );\n }\n const uri = decryptdata.uri;\n if (!uri) {\n return Promise.reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.KEY_LOAD_ERROR,\n new Error(`Invalid key URI: \"${uri}\"`)\n )\n );\n }\n let keyInfo = this.keyUriToKeyInfo[uri];\n\n if (keyInfo?.decryptdata.key) {\n decryptdata.key = keyInfo.decryptdata.key;\n return Promise.resolve({ frag, keyInfo });\n }\n // Return key load promise as long as it does not have a mediakey session with an unusable key status\n if (keyInfo?.keyLoadPromise) {\n switch (keyInfo.mediaKeySessionContext?.keyStatus) {\n case undefined:\n case 'status-pending':\n case 'usable':\n case 'usable-in-future':\n return keyInfo.keyLoadPromise.then((keyLoadedData) => {\n // Return the correct fragment with updated decryptdata key and loaded keyInfo\n decryptdata.key = keyLoadedData.keyInfo.decryptdata.key;\n return { frag, keyInfo };\n });\n }\n // If we have a key session and status and it is not pending or usable, continue\n // This will go back to the eme-controller for expired keys to get a new keyLoadPromise\n }\n\n // Load the key or return the loading promise\n keyInfo = this.keyUriToKeyInfo[uri] = {\n decryptdata,\n keyLoadPromise: null,\n loader: null,\n mediaKeySessionContext: null,\n };\n\n switch (decryptdata.method) {\n case 'ISO-23001-7':\n case 'SAMPLE-AES':\n case 'SAMPLE-AES-CENC':\n case 'SAMPLE-AES-CTR':\n if (decryptdata.keyFormat === 'identity') {\n // loadKeyHTTP handles http(s) and data URLs\n return this.loadKeyHTTP(keyInfo, frag);\n }\n return this.loadKeyEME(keyInfo, frag);\n case 'AES-128':\n return this.loadKeyHTTP(keyInfo, frag);\n default:\n return Promise.reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.KEY_LOAD_ERROR,\n new Error(\n `Key supplied with unsupported METHOD: \"${decryptdata.method}\"`\n )\n )\n );\n }\n }\n\n loadKeyEME(keyInfo: KeyLoaderInfo, frag: Fragment): Promise<KeyLoadedData> {\n const keyLoadedData: KeyLoadedData = { frag, keyInfo };\n if (this.emeController && this.config.emeEnabled) {\n const keySessionContextPromise =\n this.emeController.loadKey(keyLoadedData);\n if (keySessionContextPromise) {\n return (keyInfo.keyLoadPromise = keySessionContextPromise.then(\n (keySessionContext) => {\n keyInfo.mediaKeySessionContext = keySessionContext;\n return keyLoadedData;\n }\n )).catch((error) => {\n // Remove promise for license renewal or retry\n keyInfo.keyLoadPromise = null;\n throw error;\n });\n }\n }\n return Promise.resolve(keyLoadedData);\n }\n\n loadKeyHTTP(keyInfo: KeyLoaderInfo, frag: Fragment): Promise<KeyLoadedData> {\n const config = this.config;\n const Loader = config.loader;\n const keyLoader = new Loader(config) as Loader<KeyLoaderContext>;\n frag.keyLoader = keyInfo.loader = keyLoader;\n\n return (keyInfo.keyLoadPromise = new Promise((resolve, reject) => {\n const loaderContext: KeyLoaderContext = {\n keyInfo,\n frag,\n responseType: 'arraybuffer',\n url: keyInfo.decryptdata.uri,\n };\n\n // maxRetry is 0 so that instead of retrying the same key on the same variant multiple times,\n // key-loader will trigger an error and rely on stream-controller to handle retry logic.\n // this will also align retry logic with fragment-loader\n const loadPolicy = config.keyLoadPolicy.default;\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: 0,\n retryDelay: 0,\n maxRetryDelay: 0,\n };\n\n const loaderCallbacks: LoaderCallbacks<KeyLoaderContext> = {\n onSuccess: (\n response: LoaderResponse,\n stats: LoaderStats,\n context: KeyLoaderContext,\n networkDetails: any\n ) => {\n const { frag, keyInfo, url: uri } = context;\n if (!frag.decryptdata || keyInfo !== this.keyUriToKeyInfo[uri]) {\n return reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.KEY_LOAD_ERROR,\n new Error('after key load, decryptdata unset or changed'),\n networkDetails\n )\n );\n }\n\n keyInfo.decryptdata.key = frag.decryptdata.key = new Uint8Array(\n response.data as ArrayBuffer\n );\n\n // detach fragment key loader on load success\n frag.keyLoader = null;\n keyInfo.loader = null;\n resolve({ frag, keyInfo });\n },\n\n onError: (\n response: { code: number; text: string },\n context: KeyLoaderContext,\n networkDetails: any,\n stats: LoaderStats\n ) => {\n this.resetLoader(context);\n reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.KEY_LOAD_ERROR,\n new Error(\n `HTTP Error ${response.code} loading key ${response.text}`\n ),\n networkDetails,\n { url: loaderContext.url, data: undefined, ...response }\n )\n );\n },\n\n onTimeout: (\n stats: LoaderStats,\n context: KeyLoaderContext,\n networkDetails: any\n ) => {\n this.resetLoader(context);\n reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.KEY_LOAD_TIMEOUT,\n new Error('key loading timed out'),\n networkDetails\n )\n );\n },\n\n onAbort: (\n stats: LoaderStats,\n context: KeyLoaderContext,\n networkDetails: any\n ) => {\n this.resetLoader(context);\n reject(\n this.createKeyLoadError(\n frag,\n ErrorDetails.INTERNAL_ABORTED,\n new Error('key loading aborted'),\n networkDetails\n )\n );\n },\n };\n\n keyLoader.load(loaderContext, loaderConfig, loaderCallbacks);\n }));\n }\n\n private resetLoader(context: KeyLoaderContext) {\n const { frag, keyInfo, url: uri } = context;\n const loader = keyInfo.loader;\n if (frag.keyLoader === loader) {\n frag.keyLoader = null;\n keyInfo.loader = null;\n }\n delete this.keyUriToKeyInfo[uri];\n if (loader) {\n loader.destroy();\n }\n }\n}\n","/**\n * @ignore\n * Sub-class specialization of EventHandler base class.\n *\n * TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop,\n * scheduled asynchroneously, avoiding recursive calls in the same tick.\n *\n * The task itself is implemented in `doTick`. It can be requested and called for single execution\n * using the `tick` method.\n *\n * It will be assured that the task execution method (`tick`) only gets called once per main loop \"tick\",\n * no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly.\n *\n * If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`,\n * and cancelled with `clearNextTick`.\n *\n * The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`).\n *\n * Sub-classes need to implement the `doTick` method which will effectively have the task execution routine.\n *\n * Further explanations:\n *\n * The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously\n * only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks.\n *\n * When the task execution (`tick` method) is called in re-entrant way this is detected and\n * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further\n * task processing on the next main loop iteration (also known as \"next tick\" in the Node/JS runtime lingo).\n */\nexport default class TaskLoop {\n private readonly _boundTick: () => void;\n private _tickTimer: number | null = null;\n private _tickInterval: number | null = null;\n private _tickCallCount = 0;\n\n constructor() {\n this._boundTick = this.tick.bind(this);\n }\n\n public destroy() {\n this.onHandlerDestroying();\n this.onHandlerDestroyed();\n }\n\n protected onHandlerDestroying() {\n // clear all timers before unregistering from event bus\n this.clearNextTick();\n this.clearInterval();\n }\n\n protected onHandlerDestroyed() {}\n\n public hasInterval(): boolean {\n return !!this._tickInterval;\n }\n\n public hasNextTick(): boolean {\n return !!this._tickTimer;\n }\n\n /**\n * @param millis - Interval time (ms)\n * @eturns True when interval has been scheduled, false when already scheduled (no effect)\n */\n public setInterval(millis: number): boolean {\n if (!this._tickInterval) {\n this._tickCallCount = 0;\n this._tickInterval = self.setInterval(this._boundTick, millis);\n return true;\n }\n return false;\n }\n\n /**\n * @returns True when interval was cleared, false when none was set (no effect)\n */\n public clearInterval(): boolean {\n if (this._tickInterval) {\n self.clearInterval(this._tickInterval);\n this._tickInterval = null;\n return true;\n }\n return false;\n }\n\n /**\n * @returns True when timeout was cleared, false when none was set (no effect)\n */\n public clearNextTick(): boolean {\n if (this._tickTimer) {\n self.clearTimeout(this._tickTimer);\n this._tickTimer = null;\n return true;\n }\n return false;\n }\n\n /**\n * Will call the subclass doTick implementation in this main loop tick\n * or in the next one (via setTimeout(,0)) in case it has already been called\n * in this tick (in case this is a re-entrant call).\n */\n public tick(): void {\n this._tickCallCount++;\n if (this._tickCallCount === 1) {\n this.doTick();\n // re-entrant call to tick from previous doTick call stack\n // -> schedule a call on the next main loop iteration to process this task processing request\n if (this._tickCallCount > 1) {\n // make sure only one timer exists at any time at max\n this.tickImmediate();\n }\n this._tickCallCount = 0;\n }\n }\n\n public tickImmediate(): void {\n this.clearNextTick();\n this._tickTimer = self.setTimeout(this._boundTick, 0);\n }\n\n /**\n * For subclass to implement task logic\n * @abstract\n */\n protected doTick(): void {}\n}\n","/**\n * Provides methods dealing with buffer length retrieval for example.\n *\n * In general, a helper around HTML5 MediaElement TimeRanges gathered from `buffered` property.\n *\n * Also @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered\n */\n\nimport { logger } from './logger';\n\ntype BufferTimeRange = {\n start: number;\n end: number;\n};\n\nexport type Bufferable = {\n buffered: TimeRanges;\n};\n\nexport type BufferInfo = {\n len: number;\n start: number;\n end: number;\n nextStart?: number;\n};\n\nconst noopBuffered: TimeRanges = {\n length: 0,\n start: () => 0,\n end: () => 0,\n};\n\nexport class BufferHelper {\n /**\n * Return true if `media`'s buffered include `position`\n */\n static isBuffered(media: Bufferable, position: number): boolean {\n try {\n if (media) {\n const buffered = BufferHelper.getBuffered(media);\n for (let i = 0; i < buffered.length; i++) {\n if (position >= buffered.start(i) && position <= buffered.end(i)) {\n return true;\n }\n }\n }\n } catch (error) {\n // this is to catch\n // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':\n // This SourceBuffer has been removed from the parent media source\n }\n return false;\n }\n\n static bufferInfo(\n media: Bufferable | null,\n pos: number,\n maxHoleDuration: number\n ): BufferInfo {\n try {\n if (media) {\n const vbuffered = BufferHelper.getBuffered(media);\n const buffered: BufferTimeRange[] = [];\n let i: number;\n for (i = 0; i < vbuffered.length; i++) {\n buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) });\n }\n\n return this.bufferedInfo(buffered, pos, maxHoleDuration);\n }\n } catch (error) {\n // this is to catch\n // InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':\n // This SourceBuffer has been removed from the parent media source\n }\n return { len: 0, start: pos, end: pos, nextStart: undefined };\n }\n\n static bufferedInfo(\n buffered: BufferTimeRange[],\n pos: number,\n maxHoleDuration: number\n ): {\n len: number;\n start: number;\n end: number;\n nextStart?: number;\n } {\n pos = Math.max(0, pos);\n // sort on buffer.start/smaller end (IE does not always return sorted buffered range)\n buffered.sort(function (a, b) {\n const diff = a.start - b.start;\n if (diff) {\n return diff;\n } else {\n return b.end - a.end;\n }\n });\n\n let buffered2: BufferTimeRange[] = [];\n if (maxHoleDuration) {\n // there might be some small holes between buffer time range\n // consider that holes smaller than maxHoleDuration are irrelevant and build another\n // buffer time range representations that discards those holes\n for (let i = 0; i < buffered.length; i++) {\n const buf2len = buffered2.length;\n if (buf2len) {\n const buf2end = buffered2[buf2len - 1].end;\n // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)\n if (buffered[i].start - buf2end < maxHoleDuration) {\n // merge overlapping time ranges\n // update lastRange.end only if smaller than item.end\n // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)\n // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])\n if (buffered[i].end > buf2end) {\n buffered2[buf2len - 1].end = buffered[i].end;\n }\n } else {\n // big hole\n buffered2.push(buffered[i]);\n }\n } else {\n // first value\n buffered2.push(buffered[i]);\n }\n }\n } else {\n buffered2 = buffered;\n }\n\n let bufferLen = 0;\n\n // bufferStartNext can possibly be undefined based on the conditional logic below\n let bufferStartNext: number | undefined;\n\n // bufferStart and bufferEnd are buffer boundaries around current video position\n let bufferStart: number = pos;\n let bufferEnd: number = pos;\n for (let i = 0; i < buffered2.length; i++) {\n const start = buffered2[i].start;\n const end = buffered2[i].end;\n // logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));\n if (pos + maxHoleDuration >= start && pos < end) {\n // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length\n bufferStart = start;\n bufferEnd = end;\n bufferLen = bufferEnd - pos;\n } else if (pos + maxHoleDuration < start) {\n bufferStartNext = start;\n break;\n }\n }\n return {\n len: bufferLen,\n start: bufferStart || 0,\n end: bufferEnd || 0,\n nextStart: bufferStartNext,\n };\n }\n\n /**\n * Safe method to get buffered property.\n * SourceBuffer.buffered may throw if SourceBuffer is removed from it's MediaSource\n */\n static getBuffered(media: Bufferable): TimeRanges {\n try {\n return media.buffered;\n } catch (e) {\n logger.log('failed to get media.buffered', e);\n return noopBuffered;\n }\n }\n}\n","import type { RemuxerResult } from './remuxer';\nimport type { HlsChunkPerformanceTiming } from './loader';\nimport type { SourceBufferName } from './buffer';\n\nexport interface TransmuxerResult {\n remuxResult: RemuxerResult;\n chunkMeta: ChunkMetadata;\n}\n\nexport class ChunkMetadata {\n public readonly level: number;\n public readonly sn: number;\n public readonly part: number;\n public readonly id: number;\n public readonly size: number;\n public readonly partial: boolean;\n public readonly transmuxing: HlsChunkPerformanceTiming =\n getNewPerformanceTiming();\n public readonly buffering: {\n [key in SourceBufferName]: HlsChunkPerformanceTiming;\n } = {\n audio: getNewPerformanceTiming(),\n video: getNewPerformanceTiming(),\n audiovideo: getNewPerformanceTiming(),\n };\n\n constructor(\n level: number,\n sn: number,\n id: number,\n size = 0,\n part = -1,\n partial = false\n ) {\n this.level = level;\n this.sn = sn;\n this.id = id;\n this.size = size;\n this.part = part;\n this.partial = partial;\n }\n}\n\nfunction getNewPerformanceTiming(): HlsChunkPerformanceTiming {\n return { start: 0, executeStart: 0, executeEnd: 0, end: 0 };\n}\n","import { logger } from './logger';\nimport { adjustSliding } from '../controller/level-helper';\n\nimport type { Fragment } from '../loader/fragment';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { Level } from '../types/level';\nimport type { RequiredProperties } from '../types/general';\n\nexport function findFirstFragWithCC(fragments: Fragment[], cc: number) {\n let firstFrag: Fragment | null = null;\n\n for (let i = 0, len = fragments.length; i < len; i++) {\n const currentFrag = fragments[i];\n if (currentFrag && currentFrag.cc === cc) {\n firstFrag = currentFrag;\n break;\n }\n }\n\n return firstFrag;\n}\n\nexport function shouldAlignOnDiscontinuities(\n lastFrag: Fragment | null,\n lastLevel: Level,\n details: LevelDetails\n): lastLevel is RequiredProperties<Level, 'details'> {\n if (lastLevel.details) {\n if (\n details.endCC > details.startCC ||\n (lastFrag && lastFrag.cc < details.startCC)\n ) {\n return true;\n }\n }\n return false;\n}\n\n// Find the first frag in the previous level which matches the CC of the first frag of the new level\nexport function findDiscontinuousReferenceFrag(\n prevDetails: LevelDetails,\n curDetails: LevelDetails,\n referenceIndex: number = 0\n) {\n const prevFrags = prevDetails.fragments;\n const curFrags = curDetails.fragments;\n\n if (!curFrags.length || !prevFrags.length) {\n logger.log('No fragments to align');\n return;\n }\n\n const prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc);\n\n if (!prevStartFrag || (prevStartFrag && !prevStartFrag.startPTS)) {\n logger.log('No frag in previous level to align on');\n return;\n }\n\n return prevStartFrag;\n}\n\nfunction adjustFragmentStart(frag: Fragment, sliding: number) {\n if (frag) {\n const start = frag.start + sliding;\n frag.start = frag.startPTS = start;\n frag.endPTS = start + frag.duration;\n }\n}\n\nexport function adjustSlidingStart(sliding: number, details: LevelDetails) {\n // Update segments\n const fragments = details.fragments;\n for (let i = 0, len = fragments.length; i < len; i++) {\n adjustFragmentStart(fragments[i], sliding);\n }\n // Update LL-HLS parts at the end of the playlist\n if (details.fragmentHint) {\n adjustFragmentStart(details.fragmentHint, sliding);\n }\n details.alignedSliding = true;\n}\n\n/**\n * Using the parameters of the last level, this function computes PTS' of the new fragments so that they form a\n * contiguous stream with the last fragments.\n * The PTS of a fragment lets Hls.js know where it fits into a stream - by knowing every PTS, we know which fragment to\n * download at any given time. PTS is normally computed when the fragment is demuxed, so taking this step saves us time\n * and an extra download.\n * @param lastFrag\n * @param lastLevel\n * @param details\n */\nexport function alignStream(\n lastFrag: Fragment | null,\n lastLevel: Level | null,\n details: LevelDetails\n) {\n if (!lastLevel) {\n return;\n }\n alignDiscontinuities(lastFrag, details, lastLevel);\n if (!details.alignedSliding && lastLevel.details) {\n // If the PTS wasn't figured out via discontinuity sequence that means there was no CC increase within the level.\n // Aligning via Program Date Time should therefore be reliable, since PDT should be the same within the same\n // discontinuity sequence.\n alignPDT(details, lastLevel.details);\n }\n if (\n !details.alignedSliding &&\n lastLevel.details &&\n !details.skippedSegments\n ) {\n // Try to align on sn so that we pick a better start fragment.\n // Do not perform this on playlists with delta updates as this is only to align levels on switch\n // and adjustSliding only adjusts fragments after skippedSegments.\n adjustSliding(lastLevel.details, details);\n }\n}\n\n/**\n * Computes the PTS if a new level's fragments using the PTS of a fragment in the last level which shares the same\n * discontinuity sequence.\n * @param lastFrag - The last Fragment which shares the same discontinuity sequence\n * @param lastLevel - The details of the last loaded level\n * @param details - The details of the new level\n */\nfunction alignDiscontinuities(\n lastFrag: Fragment | null,\n details: LevelDetails,\n lastLevel: Level\n) {\n if (shouldAlignOnDiscontinuities(lastFrag, lastLevel, details)) {\n const referenceFrag = findDiscontinuousReferenceFrag(\n lastLevel.details,\n details\n );\n if (referenceFrag && Number.isFinite(referenceFrag.start)) {\n logger.log(\n `Adjusting PTS using last level due to CC increase within current level ${details.url}`\n );\n adjustSlidingStart(referenceFrag.start, details);\n }\n }\n}\n\n/**\n * Computes the PTS of a new level's fragments using the difference in Program Date Time from the last level.\n * @param details - The details of the new level\n * @param lastDetails - The details of the last loaded level\n */\nexport function alignPDT(details: LevelDetails, lastDetails: LevelDetails) {\n // This check protects the unsafe \"!\" usage below for null program date time access.\n if (\n !lastDetails.fragments.length ||\n !details.hasProgramDateTime ||\n !lastDetails.hasProgramDateTime\n ) {\n return;\n }\n // if last level sliding is 1000 and its first frag PROGRAM-DATE-TIME is 2017-08-20 1:10:00 AM\n // and if new details first frag PROGRAM DATE-TIME is 2017-08-20 1:10:08 AM\n // then we can deduce that playlist B sliding is 1000+8 = 1008s\n const lastPDT = lastDetails.fragments[0].programDateTime!; // hasProgramDateTime check above makes this safe.\n const newPDT = details.fragments[0].programDateTime!;\n // date diff is in ms. frag.start is in seconds\n const sliding = (newPDT - lastPDT) / 1000 + lastDetails.fragments[0].start;\n if (sliding && Number.isFinite(sliding)) {\n logger.log(\n `Adjusting PTS using programDateTime delta ${\n newPDT - lastPDT\n }ms, sliding:${sliding.toFixed(3)} ${details.url} `\n );\n adjustSlidingStart(sliding, details);\n }\n}\n\n/**\n * Ensures appropriate time-alignment between renditions based on PDT. Unlike `alignPDT`, which adjusts\n * the timeline based on the delta between PDTs of the 0th fragment of two playlists/`LevelDetails`,\n * this function assumes the timelines represented in `refDetails` are accurate, including the PDTs,\n * and uses the \"wallclock\"/PDT timeline as a cross-reference to `details`, adjusting the presentation\n * times/timelines of `details` accordingly.\n * Given the asynchronous nature of fetches and initial loads of live `main` and audio/subtitle tracks,\n * the primary purpose of this function is to ensure the \"local timelines\" of audio/subtitle tracks\n * are aligned to the main/video timeline, using PDT as the cross-reference/\"anchor\" that should\n * be consistent across playlists, per the HLS spec.\n * @param details - The details of the rendition you'd like to time-align (e.g. an audio rendition).\n * @param refDetails - The details of the reference rendition with start and PDT times for alignment.\n */\nexport function alignMediaPlaylistByPDT(\n details: LevelDetails,\n refDetails: LevelDetails\n) {\n if (!details.hasProgramDateTime || !refDetails.hasProgramDateTime) {\n return;\n }\n\n const fragments = details.fragments;\n const refFragments = refDetails.fragments;\n if (!fragments.length || !refFragments.length) {\n return;\n }\n\n // Calculate a delta to apply to all fragments according to the delta in PDT times and start times\n // of a fragment in the reference details, and a fragment in the target details of the same discontinuity.\n // If a fragment of the same discontinuity was not found use the middle fragment of both.\n const middleFrag = Math.round(refFragments.length / 2) - 1;\n const refFrag = refFragments[middleFrag];\n const frag =\n findFirstFragWithCC(fragments, refFrag.cc) ||\n fragments[Math.round(fragments.length / 2) - 1];\n\n const refPDT = refFrag.programDateTime;\n const targetPDT = frag.programDateTime;\n if (refPDT === null || targetPDT === null) {\n return;\n }\n\n const delta = (targetPDT - refPDT) / 1000 - (frag.start - refFrag.start);\n adjustSlidingStart(delta, details);\n}\n","export default class AESCrypto {\n private subtle: SubtleCrypto;\n private aesIV: Uint8Array;\n\n constructor(subtle: SubtleCrypto, iv: Uint8Array) {\n this.subtle = subtle;\n this.aesIV = iv;\n }\n\n decrypt(data: ArrayBuffer, key: CryptoKey) {\n return this.subtle.decrypt({ name: 'AES-CBC', iv: this.aesIV }, key, data);\n }\n}\n","export default class FastAESKey {\n private subtle: any;\n private key: ArrayBuffer;\n\n constructor(subtle, key) {\n this.subtle = subtle;\n this.key = key;\n }\n\n expandKey() {\n return this.subtle.importKey('raw', this.key, { name: 'AES-CBC' }, false, [\n 'encrypt',\n 'decrypt',\n ]);\n }\n}\n","import { sliceUint8 } from '../utils/typed-array';\n\n// PKCS7\nexport function removePadding(array: Uint8Array): Uint8Array {\n const outputBytes = array.byteLength;\n const paddingBytes =\n outputBytes && new DataView(array.buffer).getUint8(outputBytes - 1);\n if (paddingBytes) {\n return sliceUint8(array, 0, outputBytes - paddingBytes);\n }\n return array;\n}\n\nexport default class AESDecryptor {\n private rcon: Array<number> = [\n 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,\n ];\n private subMix: Array<Uint32Array> = [\n new Uint32Array(256),\n new Uint32Array(256),\n new Uint32Array(256),\n new Uint32Array(256),\n ];\n private invSubMix: Array<Uint32Array> = [\n new Uint32Array(256),\n new Uint32Array(256),\n new Uint32Array(256),\n new Uint32Array(256),\n ];\n private sBox: Uint32Array = new Uint32Array(256);\n private invSBox: Uint32Array = new Uint32Array(256);\n private key: Uint32Array = new Uint32Array(0);\n\n private ksRows: number = 0;\n private keySize: number = 0;\n private keySchedule!: Uint32Array;\n private invKeySchedule!: Uint32Array;\n\n constructor() {\n this.initTable();\n }\n\n // Using view.getUint32() also swaps the byte order.\n uint8ArrayToUint32Array_(arrayBuffer) {\n const view = new DataView(arrayBuffer);\n const newArray = new Uint32Array(4);\n for (let i = 0; i < 4; i++) {\n newArray[i] = view.getUint32(i * 4);\n }\n\n return newArray;\n }\n\n initTable() {\n const sBox = this.sBox;\n const invSBox = this.invSBox;\n const subMix = this.subMix;\n const subMix0 = subMix[0];\n const subMix1 = subMix[1];\n const subMix2 = subMix[2];\n const subMix3 = subMix[3];\n const invSubMix = this.invSubMix;\n const invSubMix0 = invSubMix[0];\n const invSubMix1 = invSubMix[1];\n const invSubMix2 = invSubMix[2];\n const invSubMix3 = invSubMix[3];\n\n const d = new Uint32Array(256);\n let x = 0;\n let xi = 0;\n let i = 0;\n for (i = 0; i < 256; i++) {\n if (i < 128) {\n d[i] = i << 1;\n } else {\n d[i] = (i << 1) ^ 0x11b;\n }\n }\n\n for (i = 0; i < 256; i++) {\n let sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);\n sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;\n sBox[x] = sx;\n invSBox[sx] = x;\n\n // Compute multiplication\n const x2 = d[x];\n const x4 = d[x2];\n const x8 = d[x4];\n\n // Compute sub/invSub bytes, mix columns tables\n let t = (d[sx] * 0x101) ^ (sx * 0x1010100);\n subMix0[x] = (t << 24) | (t >>> 8);\n subMix1[x] = (t << 16) | (t >>> 16);\n subMix2[x] = (t << 8) | (t >>> 24);\n subMix3[x] = t;\n\n // Compute inv sub bytes, inv mix columns tables\n t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);\n invSubMix0[sx] = (t << 24) | (t >>> 8);\n invSubMix1[sx] = (t << 16) | (t >>> 16);\n invSubMix2[sx] = (t << 8) | (t >>> 24);\n invSubMix3[sx] = t;\n\n // Compute next counter\n if (!x) {\n x = xi = 1;\n } else {\n x = x2 ^ d[d[d[x8 ^ x2]]];\n xi ^= d[d[xi]];\n }\n }\n }\n\n expandKey(keyBuffer: ArrayBuffer) {\n // convert keyBuffer to Uint32Array\n const key = this.uint8ArrayToUint32Array_(keyBuffer);\n let sameKey = true;\n let offset = 0;\n\n while (offset < key.length && sameKey) {\n sameKey = key[offset] === this.key[offset];\n offset++;\n }\n\n if (sameKey) {\n return;\n }\n\n this.key = key;\n const keySize = (this.keySize = key.length);\n\n if (keySize !== 4 && keySize !== 6 && keySize !== 8) {\n throw new Error('Invalid aes key size=' + keySize);\n }\n\n const ksRows = (this.ksRows = (keySize + 6 + 1) * 4);\n let ksRow;\n let invKsRow;\n\n const keySchedule = (this.keySchedule = new Uint32Array(ksRows));\n const invKeySchedule = (this.invKeySchedule = new Uint32Array(ksRows));\n const sbox = this.sBox;\n const rcon = this.rcon;\n\n const invSubMix = this.invSubMix;\n const invSubMix0 = invSubMix[0];\n const invSubMix1 = invSubMix[1];\n const invSubMix2 = invSubMix[2];\n const invSubMix3 = invSubMix[3];\n\n let prev;\n let t;\n\n for (ksRow = 0; ksRow < ksRows; ksRow++) {\n if (ksRow < keySize) {\n prev = keySchedule[ksRow] = key[ksRow];\n continue;\n }\n t = prev;\n\n if (ksRow % keySize === 0) {\n // Rot word\n t = (t << 8) | (t >>> 24);\n\n // Sub word\n t =\n (sbox[t >>> 24] << 24) |\n (sbox[(t >>> 16) & 0xff] << 16) |\n (sbox[(t >>> 8) & 0xff] << 8) |\n sbox[t & 0xff];\n\n // Mix Rcon\n t ^= rcon[(ksRow / keySize) | 0] << 24;\n } else if (keySize > 6 && ksRow % keySize === 4) {\n // Sub word\n t =\n (sbox[t >>> 24] << 24) |\n (sbox[(t >>> 16) & 0xff] << 16) |\n (sbox[(t >>> 8) & 0xff] << 8) |\n sbox[t & 0xff];\n }\n\n keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;\n }\n\n for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {\n ksRow = ksRows - invKsRow;\n if (invKsRow & 3) {\n t = keySchedule[ksRow];\n } else {\n t = keySchedule[ksRow - 4];\n }\n\n if (invKsRow < 4 || ksRow <= 4) {\n invKeySchedule[invKsRow] = t;\n } else {\n invKeySchedule[invKsRow] =\n invSubMix0[sbox[t >>> 24]] ^\n invSubMix1[sbox[(t >>> 16) & 0xff]] ^\n invSubMix2[sbox[(t >>> 8) & 0xff]] ^\n invSubMix3[sbox[t & 0xff]];\n }\n\n invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;\n }\n }\n\n // Adding this as a method greatly improves performance.\n networkToHostOrderSwap(word) {\n return (\n (word << 24) |\n ((word & 0xff00) << 8) |\n ((word & 0xff0000) >> 8) |\n (word >>> 24)\n );\n }\n\n decrypt(inputArrayBuffer: ArrayBuffer, offset: number, aesIV: ArrayBuffer) {\n const nRounds = this.keySize + 6;\n const invKeySchedule = this.invKeySchedule;\n const invSBOX = this.invSBox;\n\n const invSubMix = this.invSubMix;\n const invSubMix0 = invSubMix[0];\n const invSubMix1 = invSubMix[1];\n const invSubMix2 = invSubMix[2];\n const invSubMix3 = invSubMix[3];\n\n const initVector = this.uint8ArrayToUint32Array_(aesIV);\n let initVector0 = initVector[0];\n let initVector1 = initVector[1];\n let initVector2 = initVector[2];\n let initVector3 = initVector[3];\n\n const inputInt32 = new Int32Array(inputArrayBuffer);\n const outputInt32 = new Int32Array(inputInt32.length);\n\n let t0, t1, t2, t3;\n let s0, s1, s2, s3;\n let inputWords0, inputWords1, inputWords2, inputWords3;\n\n let ksRow, i;\n const swapWord = this.networkToHostOrderSwap;\n\n while (offset < inputInt32.length) {\n inputWords0 = swapWord(inputInt32[offset]);\n inputWords1 = swapWord(inputInt32[offset + 1]);\n inputWords2 = swapWord(inputInt32[offset + 2]);\n inputWords3 = swapWord(inputInt32[offset + 3]);\n\n s0 = inputWords0 ^ invKeySchedule[0];\n s1 = inputWords3 ^ invKeySchedule[1];\n s2 = inputWords2 ^ invKeySchedule[2];\n s3 = inputWords1 ^ invKeySchedule[3];\n\n ksRow = 4;\n\n // Iterate through the rounds of decryption\n for (i = 1; i < nRounds; i++) {\n t0 =\n invSubMix0[s0 >>> 24] ^\n invSubMix1[(s1 >> 16) & 0xff] ^\n invSubMix2[(s2 >> 8) & 0xff] ^\n invSubMix3[s3 & 0xff] ^\n invKeySchedule[ksRow];\n t1 =\n invSubMix0[s1 >>> 24] ^\n invSubMix1[(s2 >> 16) & 0xff] ^\n invSubMix2[(s3 >> 8) & 0xff] ^\n invSubMix3[s0 & 0xff] ^\n invKeySchedule[ksRow + 1];\n t2 =\n invSubMix0[s2 >>> 24] ^\n invSubMix1[(s3 >> 16) & 0xff] ^\n invSubMix2[(s0 >> 8) & 0xff] ^\n invSubMix3[s1 & 0xff] ^\n invKeySchedule[ksRow + 2];\n t3 =\n invSubMix0[s3 >>> 24] ^\n invSubMix1[(s0 >> 16) & 0xff] ^\n invSubMix2[(s1 >> 8) & 0xff] ^\n invSubMix3[s2 & 0xff] ^\n invKeySchedule[ksRow + 3];\n // Update state\n s0 = t0;\n s1 = t1;\n s2 = t2;\n s3 = t3;\n\n ksRow = ksRow + 4;\n }\n\n // Shift rows, sub bytes, add round key\n t0 =\n (invSBOX[s0 >>> 24] << 24) ^\n (invSBOX[(s1 >> 16) & 0xff] << 16) ^\n (invSBOX[(s2 >> 8) & 0xff] << 8) ^\n invSBOX[s3 & 0xff] ^\n invKeySchedule[ksRow];\n t1 =\n (invSBOX[s1 >>> 24] << 24) ^\n (invSBOX[(s2 >> 16) & 0xff] << 16) ^\n (invSBOX[(s3 >> 8) & 0xff] << 8) ^\n invSBOX[s0 & 0xff] ^\n invKeySchedule[ksRow + 1];\n t2 =\n (invSBOX[s2 >>> 24] << 24) ^\n (invSBOX[(s3 >> 16) & 0xff] << 16) ^\n (invSBOX[(s0 >> 8) & 0xff] << 8) ^\n invSBOX[s1 & 0xff] ^\n invKeySchedule[ksRow + 2];\n t3 =\n (invSBOX[s3 >>> 24] << 24) ^\n (invSBOX[(s0 >> 16) & 0xff] << 16) ^\n (invSBOX[(s1 >> 8) & 0xff] << 8) ^\n invSBOX[s2 & 0xff] ^\n invKeySchedule[ksRow + 3];\n\n // Write\n outputInt32[offset] = swapWord(t0 ^ initVector0);\n outputInt32[offset + 1] = swapWord(t3 ^ initVector1);\n outputInt32[offset + 2] = swapWord(t2 ^ initVector2);\n outputInt32[offset + 3] = swapWord(t1 ^ initVector3);\n\n // reset initVector to last 4 unsigned int\n initVector0 = inputWords0;\n initVector1 = inputWords1;\n initVector2 = inputWords2;\n initVector3 = inputWords3;\n\n offset = offset + 4;\n }\n\n return outputInt32.buffer;\n }\n}\n","import AESCrypto from './aes-crypto';\nimport FastAESKey from './fast-aes-key';\nimport AESDecryptor, { removePadding } from './aes-decryptor';\nimport { logger } from '../utils/logger';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { sliceUint8 } from '../utils/typed-array';\nimport type { HlsConfig } from '../config';\n\nconst CHUNK_SIZE = 16; // 16 bytes, 128 bits\n\nexport default class Decrypter {\n private logEnabled: boolean = true;\n private removePKCS7Padding: boolean;\n private subtle: SubtleCrypto | null = null;\n private softwareDecrypter: AESDecryptor | null = null;\n private key: ArrayBuffer | null = null;\n private fastAesKey: FastAESKey | null = null;\n private remainderData: Uint8Array | null = null;\n private currentIV: ArrayBuffer | null = null;\n private currentResult: ArrayBuffer | null = null;\n private useSoftware: boolean;\n\n constructor(config: HlsConfig, { removePKCS7Padding = true } = {}) {\n this.useSoftware = config.enableSoftwareAES;\n this.removePKCS7Padding = removePKCS7Padding;\n // built in decryptor expects PKCS7 padding\n if (removePKCS7Padding) {\n try {\n const browserCrypto = self.crypto;\n if (browserCrypto) {\n this.subtle =\n browserCrypto.subtle ||\n ((browserCrypto as any).webkitSubtle as SubtleCrypto);\n }\n } catch (e) {\n /* no-op */\n }\n }\n if (this.subtle === null) {\n this.useSoftware = true;\n }\n }\n\n destroy() {\n this.subtle = null;\n this.softwareDecrypter = null;\n this.key = null;\n this.fastAesKey = null;\n this.remainderData = null;\n this.currentIV = null;\n this.currentResult = null;\n }\n\n public isSync() {\n return this.useSoftware;\n }\n\n public flush(): Uint8Array | null {\n const { currentResult, remainderData } = this;\n if (!currentResult || remainderData) {\n this.reset();\n return null;\n }\n const data = new Uint8Array(currentResult);\n this.reset();\n if (this.removePKCS7Padding) {\n return removePadding(data);\n }\n return data;\n }\n\n public reset() {\n this.currentResult = null;\n this.currentIV = null;\n this.remainderData = null;\n if (this.softwareDecrypter) {\n this.softwareDecrypter = null;\n }\n }\n\n public decrypt(\n data: Uint8Array | ArrayBuffer,\n key: ArrayBuffer,\n iv: ArrayBuffer\n ): Promise<ArrayBuffer> {\n if (this.useSoftware) {\n return new Promise((resolve, reject) => {\n this.softwareDecrypt(new Uint8Array(data), key, iv);\n const decryptResult = this.flush();\n if (decryptResult) {\n resolve(decryptResult.buffer);\n } else {\n reject(new Error('[softwareDecrypt] Failed to decrypt data'));\n }\n });\n }\n return this.webCryptoDecrypt(new Uint8Array(data), key, iv);\n }\n\n // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached\n // data is handled in the flush() call\n public softwareDecrypt(\n data: Uint8Array,\n key: ArrayBuffer,\n iv: ArrayBuffer\n ): ArrayBuffer | null {\n const { currentIV, currentResult, remainderData } = this;\n this.logOnce('JS AES decrypt');\n // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call\n // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached\n // the end on flush(), but by that time we have already received all bytes for the segment.\n // Progressive decryption does not work with WebCrypto\n\n if (remainderData) {\n data = appendUint8Array(remainderData, data);\n this.remainderData = null;\n }\n\n // Byte length must be a multiple of 16 (AES-128 = 128 bit blocks = 16 bytes)\n const currentChunk = this.getValidChunk(data);\n if (!currentChunk.length) {\n return null;\n }\n\n if (currentIV) {\n iv = currentIV;\n }\n\n let softwareDecrypter = this.softwareDecrypter;\n if (!softwareDecrypter) {\n softwareDecrypter = this.softwareDecrypter = new AESDecryptor();\n }\n softwareDecrypter.expandKey(key);\n\n const result = currentResult;\n\n this.currentResult = softwareDecrypter.decrypt(currentChunk.buffer, 0, iv);\n this.currentIV = sliceUint8(currentChunk, -16).buffer;\n\n if (!result) {\n return null;\n }\n return result;\n }\n\n public webCryptoDecrypt(\n data: Uint8Array,\n key: ArrayBuffer,\n iv: ArrayBuffer\n ): Promise<ArrayBuffer> {\n const subtle = this.subtle;\n if (this.key !== key || !this.fastAesKey) {\n this.key = key;\n this.fastAesKey = new FastAESKey(subtle, key);\n }\n return this.fastAesKey\n .expandKey()\n .then((aesKey) => {\n // decrypt using web crypto\n if (!subtle) {\n return Promise.reject(new Error('web crypto not initialized'));\n }\n this.logOnce('WebCrypto AES decrypt');\n const crypto = new AESCrypto(subtle, new Uint8Array(iv));\n return crypto.decrypt(data.buffer, aesKey);\n })\n .catch((err) => {\n logger.warn(\n `[decrypter]: WebCrypto Error, disable WebCrypto API, ${err.name}: ${err.message}`\n );\n\n return this.onWebCryptoError(data, key, iv);\n });\n }\n\n private onWebCryptoError(data, key, iv): ArrayBuffer | never {\n this.useSoftware = true;\n this.logEnabled = true;\n this.softwareDecrypt(data, key, iv);\n const decryptResult = this.flush();\n if (decryptResult) {\n return decryptResult.buffer;\n }\n throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');\n }\n\n private getValidChunk(data: Uint8Array): Uint8Array {\n let currentChunk = data;\n const splitPoint = data.length - (data.length % CHUNK_SIZE);\n if (splitPoint !== data.length) {\n currentChunk = sliceUint8(data, 0, splitPoint);\n this.remainderData = sliceUint8(data, splitPoint);\n }\n return currentChunk;\n }\n\n private logOnce(msg: string) {\n if (!this.logEnabled) {\n return;\n }\n logger.log(`[decrypter]: ${msg}`);\n this.logEnabled = false;\n }\n}\n","import TaskLoop from '../task-loop';\nimport { FragmentState } from './fragment-tracker';\nimport { Bufferable, BufferHelper, BufferInfo } from '../utils/buffer-helper';\nimport { logger } from '../utils/logger';\nimport { Events } from '../events';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { alignStream } from '../utils/discontinuities';\nimport {\n findFragmentByPDT,\n findFragmentByPTS,\n findFragWithCC,\n} from './fragment-finders';\nimport {\n findPart,\n getFragmentWithSN,\n getPartWith,\n updateFragPTSDTS,\n} from './level-helper';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { Fragment, Part } from '../loader/fragment';\nimport FragmentLoader, {\n FragmentLoadProgressCallback,\n LoadError,\n} from '../loader/fragment-loader';\nimport KeyLoader from '../loader/key-loader';\nimport { LevelDetails } from '../loader/level-details';\nimport Decrypter from '../crypt/decrypter';\nimport TimeRanges from '../utils/time-ranges';\nimport { PlaylistLevelType } from '../types/loader';\nimport { getRetryDelay } from '../utils/error-helper';\nimport { NetworkErrorAction } from './error-controller';\nimport type {\n BufferAppendingData,\n ErrorData,\n FragLoadedData,\n PartsLoadedData,\n KeyLoadedData,\n MediaAttachedData,\n BufferFlushingData,\n ManifestLoadedData,\n} from '../types/events';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type { Level } from '../types/level';\nimport type { RemuxedTrack } from '../types/remuxer';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type { SourceBufferName } from '../types/buffer';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\ntype ResolveFragLoaded = (FragLoadedEndData) => void;\ntype RejectFragLoaded = (LoadError) => void;\n\nexport const State = {\n STOPPED: 'STOPPED',\n IDLE: 'IDLE',\n KEY_LOADING: 'KEY_LOADING',\n FRAG_LOADING: 'FRAG_LOADING',\n FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY',\n WAITING_TRACK: 'WAITING_TRACK',\n PARSING: 'PARSING',\n PARSED: 'PARSED',\n ENDED: 'ENDED',\n ERROR: 'ERROR',\n WAITING_INIT_PTS: 'WAITING_INIT_PTS',\n WAITING_LEVEL: 'WAITING_LEVEL',\n};\n\nexport default class BaseStreamController\n extends TaskLoop\n implements NetworkComponentAPI\n{\n protected hls: Hls;\n\n protected fragPrevious: Fragment | null = null;\n protected fragCurrent: Fragment | null = null;\n protected fragmentTracker: FragmentTracker;\n protected transmuxer: TransmuxerInterface | null = null;\n protected _state: string = State.STOPPED;\n protected playlistType: PlaylistLevelType;\n protected media: HTMLMediaElement | null = null;\n protected mediaBuffer: Bufferable | null = null;\n protected config: HlsConfig;\n protected bitrateTest: boolean = false;\n protected lastCurrentTime: number = 0;\n protected nextLoadPosition: number = 0;\n protected startPosition: number = 0;\n protected startTimeOffset: number | null = null;\n protected loadedmetadata: boolean = false;\n protected retryDate: number = 0;\n protected levels: Array<Level> | null = null;\n protected fragmentLoader: FragmentLoader;\n protected keyLoader: KeyLoader;\n protected levelLastLoaded: number | null = null;\n protected startFragRequested: boolean = false;\n protected decrypter: Decrypter;\n protected initPTS: RationalTimestamp[] = [];\n protected onvseeking: EventListener | null = null;\n protected onvended: EventListener | null = null;\n\n private readonly logPrefix: string = '';\n protected log: (msg: any) => void;\n protected warn: (msg: any) => void;\n\n constructor(\n hls: Hls,\n fragmentTracker: FragmentTracker,\n keyLoader: KeyLoader,\n logPrefix: string,\n playlistType: PlaylistLevelType\n ) {\n super();\n this.playlistType = playlistType;\n this.logPrefix = logPrefix;\n this.log = logger.log.bind(logger, `${logPrefix}:`);\n this.warn = logger.warn.bind(logger, `${logPrefix}:`);\n this.hls = hls;\n this.fragmentLoader = new FragmentLoader(hls.config);\n this.keyLoader = keyLoader;\n this.fragmentTracker = fragmentTracker;\n this.config = hls.config;\n this.decrypter = new Decrypter(hls.config);\n hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n }\n\n protected doTick() {\n this.onTickEnd();\n }\n\n protected onTickEnd() {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public startLoad(startPosition: number): void {}\n\n public stopLoad() {\n this.fragmentLoader.abort();\n this.keyLoader.abort(this.playlistType);\n const frag = this.fragCurrent;\n if (frag?.loader) {\n frag.abortRequests();\n this.fragmentTracker.removeFragment(frag);\n }\n this.resetTransmuxer();\n this.fragCurrent = null;\n this.fragPrevious = null;\n this.clearInterval();\n this.clearNextTick();\n this.state = State.STOPPED;\n }\n\n protected _streamEnded(\n bufferInfo: BufferInfo,\n levelDetails: LevelDetails\n ): boolean {\n // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,\n // of nothing loading/loaded return false\n if (\n levelDetails.live ||\n bufferInfo.nextStart ||\n !bufferInfo.end ||\n !this.media\n ) {\n return false;\n }\n const partList = levelDetails.partList;\n // Since the last part isn't guaranteed to correspond to the last playlist segment for Low-Latency HLS,\n // check instead if the last part is buffered.\n if (partList?.length) {\n const lastPart = partList[partList.length - 1];\n\n // Checking the midpoint of the part for potential margin of error and related issues.\n // NOTE: Technically I believe parts could yield content that is < the computed duration (including potential a duration of 0)\n // and still be spec-compliant, so there may still be edge cases here. Likewise, there could be issues in end of stream\n // part mismatches for independent audio and video playlists/segments.\n const lastPartBuffered = BufferHelper.isBuffered(\n this.media,\n lastPart.start + lastPart.duration / 2\n );\n return lastPartBuffered;\n }\n\n const playlistType =\n levelDetails.fragments[levelDetails.fragments.length - 1].type;\n return this.fragmentTracker.isEndListAppended(playlistType);\n }\n\n protected getLevelDetails(): LevelDetails | undefined {\n if (this.levels && this.levelLastLoaded !== null) {\n return this.levels[this.levelLastLoaded]?.details;\n }\n }\n\n protected onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ) {\n const media = (this.media = this.mediaBuffer = data.media);\n this.onvseeking = this.onMediaSeeking.bind(this) as EventListener;\n this.onvended = this.onMediaEnded.bind(this) as EventListener;\n media.addEventListener('seeking', this.onvseeking);\n media.addEventListener('ended', this.onvended);\n const config = this.config;\n if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {\n this.startLoad(config.startPosition);\n }\n }\n\n protected onMediaDetaching() {\n const media = this.media;\n if (media?.ended) {\n this.log('MSE detaching and video ended, reset startPosition');\n this.startPosition = this.lastCurrentTime = 0;\n }\n\n // remove video listeners\n if (media && this.onvseeking && this.onvended) {\n media.removeEventListener('seeking', this.onvseeking);\n media.removeEventListener('ended', this.onvended);\n this.onvseeking = this.onvended = null;\n }\n if (this.keyLoader) {\n this.keyLoader.detach();\n }\n this.media = this.mediaBuffer = null;\n this.loadedmetadata = false;\n this.fragmentTracker.removeAllFragments();\n this.stopLoad();\n }\n\n protected onMediaSeeking() {\n const { config, fragCurrent, media, mediaBuffer, state } = this;\n const currentTime: number = media ? media.currentTime : 0;\n const bufferInfo = BufferHelper.bufferInfo(\n mediaBuffer ? mediaBuffer : media,\n currentTime,\n config.maxBufferHole\n );\n\n this.log(\n `media seeking to ${\n Number.isFinite(currentTime) ? currentTime.toFixed(3) : currentTime\n }, state: ${state}`\n );\n\n if (this.state === State.ENDED) {\n this.resetLoadingState();\n } else if (fragCurrent) {\n // Seeking while frag load is in progress\n const tolerance = config.maxFragLookUpTolerance;\n const fragStartOffset = fragCurrent.start - tolerance;\n const fragEndOffset =\n fragCurrent.start + fragCurrent.duration + tolerance;\n // if seeking out of buffered range or into new one\n if (\n !bufferInfo.len ||\n fragEndOffset < bufferInfo.start ||\n fragStartOffset > bufferInfo.end\n ) {\n const pastFragment = currentTime > fragEndOffset;\n // if the seek position is outside the current fragment range\n if (currentTime < fragStartOffset || pastFragment) {\n if (pastFragment && fragCurrent.loader) {\n this.log(\n 'seeking outside of buffer while fragment load in progress, cancel fragment load'\n );\n fragCurrent.abortRequests();\n this.resetLoadingState();\n }\n this.fragPrevious = null;\n }\n }\n }\n\n if (media) {\n // Remove gap fragments\n this.fragmentTracker.removeFragmentsInRange(\n currentTime,\n Infinity,\n this.playlistType,\n true\n );\n\n this.lastCurrentTime = currentTime;\n }\n\n // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target\n if (!this.loadedmetadata && !bufferInfo.len) {\n this.nextLoadPosition = this.startPosition = currentTime;\n }\n\n // Async tick to speed up processing\n this.tickImmediate();\n }\n\n protected onMediaEnded() {\n // reset startPosition and lastCurrentTime to restart playback @ stream beginning\n this.startPosition = this.lastCurrentTime = 0;\n }\n\n protected onManifestLoaded(\n event: Events.MANIFEST_LOADED,\n data: ManifestLoadedData\n ): void {\n this.startTimeOffset = data.startTimeOffset;\n this.initPTS = [];\n }\n\n protected onHandlerDestroying() {\n this.stopLoad();\n super.onHandlerDestroying();\n }\n\n protected onHandlerDestroyed() {\n this.state = State.STOPPED;\n if (this.fragmentLoader) {\n this.fragmentLoader.destroy();\n }\n if (this.keyLoader) {\n this.keyLoader.destroy();\n }\n if (this.decrypter) {\n this.decrypter.destroy();\n }\n\n this.hls =\n this.log =\n this.warn =\n this.decrypter =\n this.keyLoader =\n this.fragmentLoader =\n this.fragmentTracker =\n null as any;\n super.onHandlerDestroyed();\n }\n\n protected loadFragment(\n frag: Fragment,\n level: Level,\n targetBufferTime: number\n ) {\n this._loadFragForPlayback(frag, level, targetBufferTime);\n }\n\n private _loadFragForPlayback(\n frag: Fragment,\n level: Level,\n targetBufferTime: number\n ) {\n const progressCallback: FragmentLoadProgressCallback = (\n data: FragLoadedData\n ) => {\n if (this.fragContextChanged(frag)) {\n this.warn(\n `Fragment ${frag.sn}${\n data.part ? ' p: ' + data.part.index : ''\n } of level ${frag.level} was dropped during download.`\n );\n this.fragmentTracker.removeFragment(frag);\n return;\n }\n frag.stats.chunkCount++;\n this._handleFragmentLoadProgress(data);\n };\n\n this._doFragLoad(frag, level, targetBufferTime, progressCallback)\n .then((data) => {\n if (!data) {\n // if we're here we probably needed to backtrack or are waiting for more parts\n return;\n }\n const state = this.state;\n if (this.fragContextChanged(frag)) {\n if (\n state === State.FRAG_LOADING ||\n (!this.fragCurrent && state === State.PARSING)\n ) {\n this.fragmentTracker.removeFragment(frag);\n this.state = State.IDLE;\n }\n return;\n }\n\n if ('payload' in data) {\n this.log(`Loaded fragment ${frag.sn} of level ${frag.level}`);\n this.hls.trigger(Events.FRAG_LOADED, data);\n }\n\n // Pass through the whole payload; controllers not implementing progressive loading receive data from this callback\n this._handleFragmentLoadComplete(data);\n })\n .catch((reason) => {\n if (this.state === State.STOPPED || this.state === State.ERROR) {\n return;\n }\n this.warn(reason);\n this.resetFragmentLoading(frag);\n });\n }\n\n protected clearTrackerIfNeeded(frag: Fragment) {\n const { fragmentTracker } = this;\n const fragState = fragmentTracker.getState(frag);\n if (fragState === FragmentState.APPENDING) {\n // Lower the buffer size and try again\n const playlistType = frag.type as PlaylistLevelType;\n const bufferedInfo = this.getFwdBufferInfo(\n this.mediaBuffer,\n playlistType\n );\n const minForwardBufferLength = Math.max(\n frag.duration,\n bufferedInfo ? bufferedInfo.len : this.config.maxBufferLength\n );\n if (this.reduceMaxBufferLength(minForwardBufferLength)) {\n fragmentTracker.removeFragment(frag);\n }\n } else if (this.mediaBuffer?.buffered.length === 0) {\n // Stop gap for bad tracker / buffer flush behavior\n fragmentTracker.removeAllFragments();\n } else if (fragmentTracker.hasParts(frag.type)) {\n // In low latency mode, remove fragments for which only some parts were buffered\n fragmentTracker.detectPartialFragments({\n frag,\n part: null,\n stats: frag.stats,\n id: frag.type,\n });\n if (fragmentTracker.getState(frag) === FragmentState.PARTIAL) {\n fragmentTracker.removeFragment(frag);\n }\n }\n }\n\n protected flushMainBuffer(\n startOffset: number,\n endOffset: number,\n type: SourceBufferName | null = null\n ) {\n if (!(startOffset - endOffset)) {\n return;\n }\n // When alternate audio is playing, the audio-stream-controller is responsible for the audio buffer. Otherwise,\n // passing a null type flushes both buffers\n const flushScope: BufferFlushingData = { startOffset, endOffset, type };\n this.hls.trigger(Events.BUFFER_FLUSHING, flushScope);\n }\n\n protected _loadInitSegment(frag: Fragment, level: Level) {\n this._doFragLoad(frag, level)\n .then((data) => {\n if (!data || this.fragContextChanged(frag) || !this.levels) {\n throw new Error('init load aborted');\n }\n\n return data;\n })\n .then((data: FragLoadedData) => {\n const { hls } = this;\n const { payload } = data;\n const decryptData = frag.decryptdata;\n\n // check to see if the payload needs to be decrypted\n if (\n payload &&\n payload.byteLength > 0 &&\n decryptData &&\n decryptData.key &&\n decryptData.iv &&\n decryptData.method === 'AES-128'\n ) {\n const startTime = self.performance.now();\n // decrypt init segment data\n return this.decrypter\n .decrypt(\n new Uint8Array(payload),\n decryptData.key.buffer,\n decryptData.iv.buffer\n )\n .catch((err) => {\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_DECRYPT_ERROR,\n fatal: false,\n error: err,\n reason: err.message,\n frag,\n });\n throw err;\n })\n .then((decryptedData) => {\n const endTime = self.performance.now();\n hls.trigger(Events.FRAG_DECRYPTED, {\n frag,\n payload: decryptedData,\n stats: {\n tstart: startTime,\n tdecrypt: endTime,\n },\n });\n data.payload = decryptedData;\n\n return data;\n });\n }\n\n return data;\n })\n .then((data: FragLoadedData) => {\n const { fragCurrent, hls, levels } = this;\n if (!levels) {\n throw new Error('init load aborted, missing levels');\n }\n\n const stats = frag.stats;\n this.state = State.IDLE;\n level.fragmentError = 0;\n frag.data = new Uint8Array(data.payload);\n stats.parsing.start = stats.buffering.start = self.performance.now();\n stats.parsing.end = stats.buffering.end = self.performance.now();\n\n // Silence FRAG_BUFFERED event if fragCurrent is null\n if (data.frag === fragCurrent) {\n hls.trigger(Events.FRAG_BUFFERED, {\n stats,\n frag: fragCurrent,\n part: null,\n id: frag.type,\n });\n }\n this.tick();\n })\n .catch((reason) => {\n if (this.state === State.STOPPED || this.state === State.ERROR) {\n return;\n }\n this.warn(reason);\n this.resetFragmentLoading(frag);\n });\n }\n\n protected fragContextChanged(frag: Fragment | null) {\n const { fragCurrent } = this;\n return (\n !frag ||\n !fragCurrent ||\n frag.level !== fragCurrent.level ||\n frag.sn !== fragCurrent.sn ||\n frag.urlId !== fragCurrent.urlId\n );\n }\n\n protected fragBufferedComplete(frag: Fragment, part: Part | null) {\n const media = this.mediaBuffer ? this.mediaBuffer : this.media;\n this.log(\n `Buffered ${frag.type} sn: ${frag.sn}${\n part ? ' part: ' + part.index : ''\n } of ${\n this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'\n } ${frag.level} (frag:[${(frag.startPTS ?? NaN).toFixed(3)}-${(\n frag.endPTS ?? NaN\n ).toFixed(3)}] > buffer:${\n media\n ? TimeRanges.toString(BufferHelper.getBuffered(media))\n : '(detached)'\n })`\n );\n this.state = State.IDLE;\n if (!media) {\n return;\n }\n if (\n !this.loadedmetadata &&\n frag.type == PlaylistLevelType.MAIN &&\n media.buffered.length &&\n this.fragCurrent?.sn === this.fragPrevious?.sn\n ) {\n this.loadedmetadata = true;\n this.seekToStartPos();\n }\n this.tick();\n }\n\n protected seekToStartPos() {}\n\n protected _handleFragmentLoadComplete(fragLoadedEndData: PartsLoadedData) {\n const { transmuxer } = this;\n if (!transmuxer) {\n return;\n }\n const { frag, part, partsLoaded } = fragLoadedEndData;\n // If we did not load parts, or loaded all parts, we have complete (not partial) fragment data\n const complete =\n !partsLoaded ||\n partsLoaded.length === 0 ||\n partsLoaded.some((fragLoaded) => !fragLoaded);\n const chunkMeta = new ChunkMetadata(\n frag.level,\n frag.sn as number,\n frag.stats.chunkCount + 1,\n 0,\n part ? part.index : -1,\n !complete\n );\n transmuxer.flush(chunkMeta);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleFragmentLoadProgress(\n frag: PartsLoadedData | FragLoadedData\n ) {}\n\n protected _doFragLoad(\n frag: Fragment,\n level: Level,\n targetBufferTime: number | null = null,\n progressCallback?: FragmentLoadProgressCallback\n ): Promise<PartsLoadedData | FragLoadedData | null> {\n const details = level?.details;\n if (!this.levels || !details) {\n throw new Error(\n `frag load aborted, missing level${details ? '' : ' detail'}s`\n );\n }\n\n let keyLoadingPromise: Promise<KeyLoadedData | void> | null = null;\n if (frag.encrypted && !frag.decryptdata?.key) {\n this.log(\n `Loading key for ${frag.sn} of [${details.startSN}-${details.endSN}], ${\n this.logPrefix === '[stream-controller]' ? 'level' : 'track'\n } ${frag.level}`\n );\n this.state = State.KEY_LOADING;\n this.fragCurrent = frag;\n keyLoadingPromise = this.keyLoader.load(frag).then((keyLoadedData) => {\n if (!this.fragContextChanged(keyLoadedData.frag)) {\n this.hls.trigger(Events.KEY_LOADED, keyLoadedData);\n if (this.state === State.KEY_LOADING) {\n this.state = State.IDLE;\n }\n return keyLoadedData;\n }\n });\n this.hls.trigger(Events.KEY_LOADING, { frag });\n if (this.fragCurrent === null) {\n keyLoadingPromise = Promise.reject(\n new Error(`frag load aborted, context changed in KEY_LOADING`)\n );\n }\n } else if (!frag.encrypted && details.encryptedFragments.length) {\n this.keyLoader.loadClear(frag, details.encryptedFragments);\n }\n\n targetBufferTime = Math.max(frag.start, targetBufferTime || 0);\n if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {\n const partList = details.partList;\n if (partList && progressCallback) {\n if (targetBufferTime > frag.end && details.fragmentHint) {\n frag = details.fragmentHint;\n }\n const partIndex = this.getNextPart(partList, frag, targetBufferTime);\n if (partIndex > -1) {\n const part = partList[partIndex];\n this.log(\n `Loading part sn: ${frag.sn} p: ${part.index} cc: ${\n frag.cc\n } of playlist [${details.startSN}-${\n details.endSN\n }] parts [0-${partIndex}-${partList.length - 1}] ${\n this.logPrefix === '[stream-controller]' ? 'level' : 'track'\n }: ${frag.level}, target: ${parseFloat(\n targetBufferTime.toFixed(3)\n )}`\n );\n this.nextLoadPosition = part.start + part.duration;\n this.state = State.FRAG_LOADING;\n let result: Promise<PartsLoadedData | FragLoadedData | null>;\n if (keyLoadingPromise) {\n result = keyLoadingPromise\n .then((keyLoadedData) => {\n if (\n !keyLoadedData ||\n this.fragContextChanged(keyLoadedData.frag)\n ) {\n return null;\n }\n return this.doFragPartsLoad(\n frag,\n part,\n level,\n progressCallback\n );\n })\n .catch((error) => this.handleFragLoadError(error));\n } else {\n result = this.doFragPartsLoad(\n frag,\n part,\n level,\n progressCallback\n ).catch((error: LoadError) => this.handleFragLoadError(error));\n }\n this.hls.trigger(Events.FRAG_LOADING, {\n frag,\n part,\n targetBufferTime,\n });\n if (this.fragCurrent === null) {\n return Promise.reject(\n new Error(\n `frag load aborted, context changed in FRAG_LOADING parts`\n )\n );\n }\n return result;\n } else if (\n !frag.url ||\n this.loadedEndOfParts(partList, targetBufferTime)\n ) {\n // Fragment hint has no parts\n return Promise.resolve(null);\n }\n }\n }\n\n this.log(\n `Loading fragment ${frag.sn} cc: ${frag.cc} ${\n details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''\n }${this.logPrefix === '[stream-controller]' ? 'level' : 'track'}: ${\n frag.level\n }, target: ${parseFloat(targetBufferTime.toFixed(3))}`\n );\n // Don't update nextLoadPosition for fragments which are not buffered\n if (Number.isFinite(frag.sn as number) && !this.bitrateTest) {\n this.nextLoadPosition = frag.start + frag.duration;\n }\n this.state = State.FRAG_LOADING;\n\n // Load key before streaming fragment data\n const dataOnProgress = this.config.progressive;\n let result: Promise<PartsLoadedData | FragLoadedData | null>;\n if (dataOnProgress && keyLoadingPromise) {\n result = keyLoadingPromise\n .then((keyLoadedData) => {\n if (!keyLoadedData || this.fragContextChanged(keyLoadedData?.frag)) {\n return null;\n }\n return this.fragmentLoader.load(frag, progressCallback);\n })\n .catch((error) => this.handleFragLoadError(error));\n } else {\n // load unencrypted fragment data with progress event,\n // or handle fragment result after key and fragment are finished loading\n result = Promise.all([\n this.fragmentLoader.load(\n frag,\n dataOnProgress ? progressCallback : undefined\n ),\n keyLoadingPromise,\n ])\n .then(([fragLoadedData]) => {\n if (!dataOnProgress && fragLoadedData && progressCallback) {\n progressCallback(fragLoadedData);\n }\n return fragLoadedData;\n })\n .catch((error) => this.handleFragLoadError(error));\n }\n this.hls.trigger(Events.FRAG_LOADING, { frag, targetBufferTime });\n if (this.fragCurrent === null) {\n return Promise.reject(\n new Error(`frag load aborted, context changed in FRAG_LOADING`)\n );\n }\n return result;\n }\n\n private doFragPartsLoad(\n frag: Fragment,\n fromPart: Part,\n level: Level,\n progressCallback: FragmentLoadProgressCallback\n ): Promise<PartsLoadedData | null> {\n return new Promise(\n (resolve: ResolveFragLoaded, reject: RejectFragLoaded) => {\n const partsLoaded: FragLoadedData[] = [];\n const initialPartList = level.details?.partList;\n const loadPart = (part: Part) => {\n this.fragmentLoader\n .loadPart(frag, part, progressCallback)\n .then((partLoadedData: FragLoadedData) => {\n partsLoaded[part.index] = partLoadedData;\n const loadedPart = partLoadedData.part as Part;\n this.hls.trigger(Events.FRAG_LOADED, partLoadedData);\n const nextPart =\n getPartWith(level, frag.sn as number, part.index + 1) ||\n findPart(initialPartList, frag.sn as number, part.index + 1);\n if (nextPart) {\n loadPart(nextPart);\n } else {\n return resolve({\n frag,\n part: loadedPart,\n partsLoaded,\n });\n }\n })\n .catch(reject);\n };\n loadPart(fromPart);\n }\n );\n }\n\n private handleFragLoadError(error: LoadError | Error) {\n if ('data' in error) {\n const data = error.data;\n if (error.data && data.details === ErrorDetails.INTERNAL_ABORTED) {\n this.handleFragLoadAborted(data.frag, data.part);\n } else {\n this.hls.trigger(Events.ERROR, data as ErrorData);\n }\n } else {\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.OTHER_ERROR,\n details: ErrorDetails.INTERNAL_EXCEPTION,\n err: error,\n error,\n fatal: true,\n });\n }\n return null;\n }\n\n protected _handleTransmuxerFlush(chunkMeta: ChunkMetadata) {\n const context = this.getCurrentContext(chunkMeta);\n if (!context || this.state !== State.PARSING) {\n if (\n !this.fragCurrent &&\n this.state !== State.STOPPED &&\n this.state !== State.ERROR\n ) {\n this.state = State.IDLE;\n }\n return;\n }\n const { frag, part, level } = context;\n const now = self.performance.now();\n frag.stats.parsing.end = now;\n if (part) {\n part.stats.parsing.end = now;\n }\n this.updateLevelTiming(frag, part, level, chunkMeta.partial);\n }\n\n protected getCurrentContext(\n chunkMeta: ChunkMetadata\n ): { frag: Fragment; part: Part | null; level: Level } | null {\n const { levels, fragCurrent } = this;\n const { level: levelIndex, sn, part: partIndex } = chunkMeta;\n if (!levels?.[levelIndex]) {\n this.warn(\n `Levels object was unset while buffering fragment ${sn} of level ${levelIndex}. The current chunk will not be buffered.`\n );\n return null;\n }\n const level = levels[levelIndex];\n const part = partIndex > -1 ? getPartWith(level, sn, partIndex) : null;\n const frag = part\n ? part.fragment\n : getFragmentWithSN(level, sn, fragCurrent);\n if (!frag) {\n return null;\n }\n if (fragCurrent && fragCurrent !== frag) {\n frag.stats = fragCurrent.stats;\n }\n return { frag, part, level };\n }\n\n protected bufferFragmentData(\n data: RemuxedTrack,\n frag: Fragment,\n part: Part | null,\n chunkMeta: ChunkMetadata\n ) {\n if (!data || this.state !== State.PARSING) {\n return;\n }\n\n const { data1, data2 } = data;\n let buffer = data1;\n if (data1 && data2) {\n // Combine the moof + mdat so that we buffer with a single append\n buffer = appendUint8Array(data1, data2);\n }\n\n if (!buffer?.length) {\n return;\n }\n\n const segment: BufferAppendingData = {\n type: data.type,\n frag,\n part,\n chunkMeta,\n parent: frag.type,\n data: buffer,\n };\n this.hls.trigger(Events.BUFFER_APPENDING, segment);\n\n if (data.dropped && data.independent && !part) {\n // Clear buffer so that we reload previous segments sequentially if required\n this.flushBufferGap(frag);\n }\n }\n\n protected flushBufferGap(frag: Fragment) {\n const media = this.media;\n if (!media) {\n return;\n }\n // If currentTime is not buffered, clear the back buffer so that we can backtrack as much as needed\n if (!BufferHelper.isBuffered(media, media.currentTime)) {\n this.flushMainBuffer(0, frag.start);\n return;\n }\n // Remove back-buffer without interrupting playback to allow back tracking\n const currentTime = media.currentTime;\n const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n const fragDuration = frag.duration;\n const segmentFraction = Math.min(\n this.config.maxFragLookUpTolerance * 2,\n fragDuration * 0.25\n );\n const start = Math.max(\n Math.min(frag.start - segmentFraction, bufferInfo.end - segmentFraction),\n currentTime + segmentFraction\n );\n if (frag.start - start > segmentFraction) {\n this.flushMainBuffer(start, frag.start);\n }\n }\n\n protected getFwdBufferInfo(\n bufferable: Bufferable | null,\n type: PlaylistLevelType\n ): BufferInfo | null {\n const pos = this.getLoadPosition();\n if (!Number.isFinite(pos)) {\n return null;\n }\n return this.getFwdBufferInfoAtPos(bufferable, pos, type);\n }\n\n protected getFwdBufferInfoAtPos(\n bufferable: Bufferable | null,\n pos: number,\n type: PlaylistLevelType\n ): BufferInfo | null {\n const {\n config: { maxBufferHole },\n } = this;\n const bufferInfo = BufferHelper.bufferInfo(bufferable, pos, maxBufferHole);\n // Workaround flaw in getting forward buffer when maxBufferHole is smaller than gap at current pos\n if (bufferInfo.len === 0 && bufferInfo.nextStart !== undefined) {\n const bufferedFragAtPos = this.fragmentTracker.getBufferedFrag(pos, type);\n if (bufferedFragAtPos && bufferInfo.nextStart < bufferedFragAtPos.end) {\n return BufferHelper.bufferInfo(\n bufferable,\n pos,\n Math.max(bufferInfo.nextStart, maxBufferHole)\n );\n }\n }\n return bufferInfo;\n }\n\n protected getMaxBufferLength(levelBitrate?: number): number {\n const { config } = this;\n let maxBufLen;\n if (levelBitrate) {\n maxBufLen = Math.max(\n (8 * config.maxBufferSize) / levelBitrate,\n config.maxBufferLength\n );\n } else {\n maxBufLen = config.maxBufferLength;\n }\n return Math.min(maxBufLen, config.maxMaxBufferLength);\n }\n\n protected reduceMaxBufferLength(threshold: number) {\n const config = this.config;\n const minLength = threshold || config.maxBufferLength;\n if (config.maxMaxBufferLength >= minLength) {\n // reduce max buffer length as it might be too high. we do this to avoid loop flushing ...\n config.maxMaxBufferLength /= 2;\n this.warn(`Reduce max buffer length to ${config.maxMaxBufferLength}s`);\n return true;\n }\n return false;\n }\n\n protected getAppendedFrag(\n position: number,\n playlistType: PlaylistLevelType = PlaylistLevelType.MAIN\n ): Fragment | null {\n const fragOrPart = this.fragmentTracker.getAppendedFrag(\n position,\n PlaylistLevelType.MAIN\n );\n if (fragOrPart && 'fragment' in fragOrPart) {\n return fragOrPart.fragment;\n }\n return fragOrPart;\n }\n\n protected getNextFragment(\n pos: number,\n levelDetails: LevelDetails\n ): Fragment | null {\n const fragments = levelDetails.fragments;\n const fragLen = fragments.length;\n\n if (!fragLen) {\n return null;\n }\n\n // find fragment index, contiguous with end of buffer position\n const { config } = this;\n const start = fragments[0].start;\n let frag;\n\n if (levelDetails.live) {\n const initialLiveManifestSize = config.initialLiveManifestSize;\n if (fragLen < initialLiveManifestSize) {\n this.warn(\n `Not enough fragments to start playback (have: ${fragLen}, need: ${initialLiveManifestSize})`\n );\n return null;\n }\n // The real fragment start times for a live stream are only known after the PTS range for that level is known.\n // In order to discover the range, we load the best matching fragment for that level and demux it.\n // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that\n // we get the fragment matching that start time\n if (\n !levelDetails.PTSKnown &&\n !this.startFragRequested &&\n this.startPosition === -1\n ) {\n frag = this.getInitialLiveFragment(levelDetails, fragments);\n this.startPosition = frag\n ? this.hls.liveSyncPosition || frag.start\n : pos;\n }\n } else if (pos <= start) {\n // VoD playlist: if loadPosition before start of playlist, load first fragment\n frag = fragments[0];\n }\n\n // If we haven't run into any special cases already, just load the fragment most closely matching the requested position\n if (!frag) {\n const end = config.lowLatencyMode\n ? levelDetails.partEnd\n : levelDetails.fragmentEnd;\n frag = this.getFragmentAtPosition(pos, end, levelDetails);\n }\n\n return this.mapToInitFragWhenRequired(frag);\n }\n\n protected isLoopLoading(frag: Fragment, targetBufferTime: number): boolean {\n const trackerState = this.fragmentTracker.getState(frag);\n return (\n (trackerState === FragmentState.OK ||\n (trackerState === FragmentState.PARTIAL && !!frag.gap)) &&\n this.nextLoadPosition > targetBufferTime\n );\n }\n\n protected getNextFragmentLoopLoading(\n frag: Fragment,\n levelDetails: LevelDetails,\n bufferInfo: BufferInfo,\n playlistType: PlaylistLevelType,\n maxBufLen: number\n ): Fragment | null {\n const gapStart = frag.gap;\n const nextFragment = this.getNextFragment(\n this.nextLoadPosition,\n levelDetails\n );\n if (nextFragment === null) {\n return nextFragment;\n }\n frag = nextFragment;\n if (gapStart && frag && !frag.gap && bufferInfo.nextStart) {\n // Media buffered after GAP tags should not make the next buffer timerange exceed forward buffer length\n const nextbufferInfo = this.getFwdBufferInfoAtPos(\n this.mediaBuffer ? this.mediaBuffer : this.media,\n bufferInfo.nextStart,\n playlistType\n );\n if (\n nextbufferInfo !== null &&\n bufferInfo.len + nextbufferInfo.len >= maxBufLen\n ) {\n // Returning here might result in not finding an audio and video candiate to skip to\n this.log(\n `buffer full after gaps in \"${playlistType}\" playlist starting at sn: ${frag.sn}`\n );\n return null;\n }\n }\n return frag;\n }\n\n mapToInitFragWhenRequired(frag: Fragment | null): typeof frag {\n // If an initSegment is present, it must be buffered first\n if (frag?.initSegment && !frag?.initSegment.data && !this.bitrateTest) {\n return frag.initSegment;\n }\n\n return frag;\n }\n\n getNextPart(\n partList: Part[],\n frag: Fragment,\n targetBufferTime: number\n ): number {\n let nextPart = -1;\n let contiguous = false;\n let independentAttrOmitted = true;\n for (let i = 0, len = partList.length; i < len; i++) {\n const part = partList[i];\n independentAttrOmitted = independentAttrOmitted && !part.independent;\n if (nextPart > -1 && targetBufferTime < part.start) {\n break;\n }\n const loaded = part.loaded;\n if (loaded) {\n nextPart = -1;\n } else if (\n (contiguous || part.independent || independentAttrOmitted) &&\n part.fragment === frag\n ) {\n nextPart = i;\n }\n contiguous = loaded;\n }\n return nextPart;\n }\n\n private loadedEndOfParts(\n partList: Part[],\n targetBufferTime: number\n ): boolean {\n const lastPart = partList[partList.length - 1];\n return lastPart && targetBufferTime > lastPart.start && lastPart.loaded;\n }\n\n /*\n This method is used find the best matching first fragment for a live playlist. This fragment is used to calculate the\n \"sliding\" of the playlist, which is its offset from the start of playback. After sliding we can compute the real\n start and end times for each fragment in the playlist (after which this method will not need to be called).\n */\n protected getInitialLiveFragment(\n levelDetails: LevelDetails,\n fragments: Array<Fragment>\n ): Fragment | null {\n const fragPrevious = this.fragPrevious;\n let frag: Fragment | null = null;\n if (fragPrevious) {\n if (levelDetails.hasProgramDateTime) {\n // Prefer using PDT, because it can be accurate enough to choose the correct fragment without knowing the level sliding\n this.log(\n `Live playlist, switching playlist, load frag with same PDT: ${fragPrevious.programDateTime}`\n );\n frag = findFragmentByPDT(\n fragments,\n fragPrevious.endProgramDateTime,\n this.config.maxFragLookUpTolerance\n );\n }\n if (!frag) {\n // SN does not need to be accurate between renditions, but depending on the packaging it may be so.\n const targetSN = (fragPrevious.sn as number) + 1;\n if (\n targetSN >= levelDetails.startSN &&\n targetSN <= levelDetails.endSN\n ) {\n const fragNext = fragments[targetSN - levelDetails.startSN];\n // Ensure that we're staying within the continuity range, since PTS resets upon a new range\n if (fragPrevious.cc === fragNext.cc) {\n frag = fragNext;\n this.log(\n `Live playlist, switching playlist, load frag with next SN: ${\n frag!.sn\n }`\n );\n }\n }\n // It's important to stay within the continuity range if available; otherwise the fragments in the playlist\n // will have the wrong start times\n if (!frag) {\n frag = findFragWithCC(fragments, fragPrevious.cc);\n if (frag) {\n this.log(\n `Live playlist, switching playlist, load frag with same CC: ${frag.sn}`\n );\n }\n }\n }\n } else {\n // Find a new start fragment when fragPrevious is null\n const liveStart = this.hls.liveSyncPosition;\n if (liveStart !== null) {\n frag = this.getFragmentAtPosition(\n liveStart,\n this.bitrateTest ? levelDetails.fragmentEnd : levelDetails.edge,\n levelDetails\n );\n }\n }\n\n return frag;\n }\n\n /*\n This method finds the best matching fragment given the provided position.\n */\n protected getFragmentAtPosition(\n bufferEnd: number,\n end: number,\n levelDetails: LevelDetails\n ): Fragment | null {\n const { config } = this;\n let { fragPrevious } = this;\n let { fragments, endSN } = levelDetails;\n const { fragmentHint } = levelDetails;\n const tolerance = config.maxFragLookUpTolerance;\n const partList = levelDetails.partList;\n\n const loadingParts = !!(\n config.lowLatencyMode &&\n partList?.length &&\n fragmentHint\n );\n if (loadingParts && fragmentHint && !this.bitrateTest) {\n // Include incomplete fragment with parts at end\n fragments = fragments.concat(fragmentHint);\n endSN = fragmentHint.sn as number;\n }\n\n let frag;\n if (bufferEnd < end) {\n const lookupTolerance = bufferEnd > end - tolerance ? 0 : tolerance;\n // Remove the tolerance if it would put the bufferEnd past the actual end of stream\n // Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)\n frag = findFragmentByPTS(\n fragPrevious,\n fragments,\n bufferEnd,\n lookupTolerance\n );\n } else {\n // reach end of playlist\n frag = fragments[fragments.length - 1];\n }\n\n if (frag) {\n const curSNIdx = frag.sn - levelDetails.startSN;\n // Move fragPrevious forward to support forcing the next fragment to load\n // when the buffer catches up to a previously buffered range.\n const fragState = this.fragmentTracker.getState(frag);\n if (\n fragState === FragmentState.OK ||\n (fragState === FragmentState.PARTIAL && frag.gap)\n ) {\n fragPrevious = frag;\n }\n if (\n fragPrevious &&\n frag.sn === fragPrevious.sn &&\n (!loadingParts || partList[0].fragment.sn > frag.sn)\n ) {\n // Force the next fragment to load if the previous one was already selected. This can occasionally happen with\n // non-uniform fragment durations\n const sameLevel = fragPrevious && frag.level === fragPrevious.level;\n if (sameLevel) {\n const nextFrag = fragments[curSNIdx + 1];\n if (\n frag.sn < endSN &&\n this.fragmentTracker.getState(nextFrag) !== FragmentState.OK\n ) {\n frag = nextFrag;\n } else {\n frag = null;\n }\n }\n }\n }\n return frag;\n }\n\n protected synchronizeToLiveEdge(levelDetails: LevelDetails) {\n const { config, media } = this;\n if (!media) {\n return;\n }\n const liveSyncPosition = this.hls.liveSyncPosition;\n const currentTime = media.currentTime;\n const start = levelDetails.fragments[0].start;\n const end = levelDetails.edge;\n const withinSlidingWindow =\n currentTime >= start - config.maxFragLookUpTolerance &&\n currentTime <= end;\n // Continue if we can seek forward to sync position or if current time is outside of sliding window\n if (\n liveSyncPosition !== null &&\n media.duration > liveSyncPosition &&\n (currentTime < liveSyncPosition || !withinSlidingWindow)\n ) {\n // Continue if buffer is starving or if current time is behind max latency\n const maxLatency =\n config.liveMaxLatencyDuration !== undefined\n ? config.liveMaxLatencyDuration\n : config.liveMaxLatencyDurationCount * levelDetails.targetduration;\n if (\n (!withinSlidingWindow && media.readyState < 4) ||\n currentTime < end - maxLatency\n ) {\n if (!this.loadedmetadata) {\n this.nextLoadPosition = liveSyncPosition;\n }\n // Only seek if ready and there is not a significant forward buffer available for playback\n if (media.readyState) {\n this.warn(\n `Playback: ${currentTime.toFixed(\n 3\n )} is located too far from the end of live sliding playlist: ${end}, reset currentTime to : ${liveSyncPosition.toFixed(\n 3\n )}`\n );\n media.currentTime = liveSyncPosition;\n }\n }\n }\n }\n\n protected alignPlaylists(\n details: LevelDetails,\n previousDetails?: LevelDetails\n ): number {\n const { levels, levelLastLoaded, fragPrevious } = this;\n const lastLevel: Level | null =\n levelLastLoaded !== null ? levels![levelLastLoaded] : null;\n\n // FIXME: If not for `shouldAlignOnDiscontinuities` requiring fragPrevious.cc,\n // this could all go in level-helper mergeDetails()\n const length = details.fragments.length;\n if (!length) {\n this.warn(`No fragments in live playlist`);\n return 0;\n }\n const slidingStart = details.fragments[0].start;\n const firstLevelLoad = !previousDetails;\n const aligned = details.alignedSliding && Number.isFinite(slidingStart);\n if (firstLevelLoad || (!aligned && !slidingStart)) {\n alignStream(fragPrevious, lastLevel, details);\n const alignedSlidingStart = details.fragments[0].start;\n this.log(\n `Live playlist sliding: ${alignedSlidingStart.toFixed(2)} start-sn: ${\n previousDetails ? previousDetails.startSN : 'na'\n }->${details.startSN} prev-sn: ${\n fragPrevious ? fragPrevious.sn : 'na'\n } fragments: ${length}`\n );\n return alignedSlidingStart;\n }\n return slidingStart;\n }\n\n protected waitForCdnTuneIn(details: LevelDetails) {\n // Wait for Low-Latency CDN Tune-in to get an updated playlist\n const advancePartLimit = 3;\n return (\n details.live &&\n details.canBlockReload &&\n details.partTarget &&\n details.tuneInGoal >\n Math.max(details.partHoldBack, details.partTarget * advancePartLimit)\n );\n }\n\n protected setStartPosition(details: LevelDetails, sliding: number) {\n // compute start position if set to -1. use it straight away if value is defined\n let startPosition = this.startPosition;\n if (startPosition < sliding) {\n startPosition = -1;\n }\n if (startPosition === -1 || this.lastCurrentTime === -1) {\n // Use Playlist EXT-X-START:TIME-OFFSET when set\n // Prioritize Multivariant Playlist offset so that main, audio, and subtitle stream-controller start times match\n const offsetInMultivariantPlaylist = this.startTimeOffset !== null;\n const startTimeOffset = offsetInMultivariantPlaylist\n ? this.startTimeOffset\n : details.startTimeOffset;\n if (startTimeOffset !== null && Number.isFinite(startTimeOffset)) {\n startPosition = sliding + startTimeOffset;\n if (startTimeOffset < 0) {\n startPosition += details.totalduration;\n }\n startPosition = Math.min(\n Math.max(sliding, startPosition),\n sliding + details.totalduration\n );\n this.log(\n `Start time offset ${startTimeOffset} found in ${\n offsetInMultivariantPlaylist ? 'multivariant' : 'media'\n } playlist, adjust startPosition to ${startPosition}`\n );\n this.startPosition = startPosition;\n } else if (details.live) {\n // Leave this.startPosition at -1, so that we can use `getInitialLiveFragment` logic when startPosition has\n // not been specified via the config or an as an argument to startLoad (#3736).\n startPosition = this.hls.liveSyncPosition || sliding;\n } else {\n this.startPosition = startPosition = 0;\n }\n this.lastCurrentTime = startPosition;\n }\n this.nextLoadPosition = startPosition;\n }\n\n protected getLoadPosition(): number {\n const { media } = this;\n // if we have not yet loaded any fragment, start loading from start position\n let pos = 0;\n if (this.loadedmetadata && media) {\n pos = media.currentTime;\n } else if (this.nextLoadPosition) {\n pos = this.nextLoadPosition;\n }\n\n return pos;\n }\n\n private handleFragLoadAborted(frag: Fragment, part: Part | undefined) {\n if (this.transmuxer && frag.sn !== 'initSegment' && frag.stats.aborted) {\n this.warn(\n `Fragment ${frag.sn}${part ? ' part ' + part.index : ''} of level ${\n frag.level\n } was aborted`\n );\n this.resetFragmentLoading(frag);\n }\n }\n\n protected resetFragmentLoading(frag: Fragment) {\n if (\n !this.fragCurrent ||\n (!this.fragContextChanged(frag) &&\n this.state !== State.FRAG_LOADING_WAITING_RETRY)\n ) {\n this.state = State.IDLE;\n }\n }\n\n protected onFragmentOrKeyLoadError(\n filterType: PlaylistLevelType,\n data: ErrorData\n ) {\n if (data.chunkMeta && !data.frag) {\n const context = this.getCurrentContext(data.chunkMeta);\n if (context) {\n data.frag = context.frag;\n }\n }\n const frag = data.frag;\n // Handle frag error related to caller's filterType\n if (!frag || frag.type !== filterType || !this.levels) {\n return;\n }\n if (this.fragContextChanged(frag)) {\n this.warn(\n `Frag load error must match current frag to retry ${frag.url} > ${this.fragCurrent?.url}`\n );\n return;\n }\n const gapTagEncountered = data.details === ErrorDetails.FRAG_GAP;\n if (gapTagEncountered) {\n this.fragmentTracker.fragBuffered(frag, true);\n }\n // keep retrying until the limit will be reached\n const errorAction = data.errorAction;\n const { action, retryCount = 0, retryConfig } = errorAction || {};\n if (\n errorAction &&\n action === NetworkErrorAction.RetryRequest &&\n retryConfig\n ) {\n if (!this.loadedmetadata) {\n this.startFragRequested = false;\n this.nextLoadPosition = this.startPosition;\n }\n const delay = getRetryDelay(retryConfig, retryCount);\n this.warn(\n `Fragment ${frag.sn} of ${filterType} ${frag.level} errored with ${\n data.details\n }, retrying loading ${retryCount + 1}/${\n retryConfig.maxNumRetry\n } in ${delay}ms`\n );\n errorAction.resolved = true;\n this.retryDate = self.performance.now() + delay;\n this.state = State.FRAG_LOADING_WAITING_RETRY;\n } else if (retryConfig && errorAction) {\n this.resetFragmentErrors(filterType);\n if (retryCount < retryConfig.maxNumRetry) {\n // Network retry is skipped when level switch is preferred\n if (!gapTagEncountered) {\n errorAction.resolved = true;\n }\n } else {\n logger.warn(\n `${data.details} reached or exceeded max retry (${retryCount})`\n );\n }\n } else {\n this.state = State.ERROR;\n }\n // Perform next async tick sooner to speed up error action resolution\n this.tickImmediate();\n }\n\n protected reduceLengthAndFlushBuffer(data: ErrorData): boolean {\n // if in appending state\n if (this.state === State.PARSING || this.state === State.PARSED) {\n const playlistType = data.parent as PlaylistLevelType;\n const bufferedInfo = this.getFwdBufferInfo(\n this.mediaBuffer,\n playlistType\n );\n // 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end\n // reduce max buf len if current position is buffered\n const buffered = bufferedInfo && bufferedInfo.len > 0.5;\n if (buffered) {\n this.reduceMaxBufferLength(bufferedInfo.len);\n }\n const flushBuffer = !buffered;\n if (flushBuffer) {\n // current position is not buffered, but browser is still complaining about buffer full error\n // this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708\n // in that case flush the whole audio buffer to recover\n this.warn(\n `Buffer full error while media.currentTime is not buffered, flush ${playlistType} buffer`\n );\n }\n if (data.frag) {\n this.fragmentTracker.removeFragment(data.frag);\n this.nextLoadPosition = data.frag.start;\n }\n this.resetLoadingState();\n return flushBuffer;\n }\n return false;\n }\n\n protected resetFragmentErrors(filterType: PlaylistLevelType) {\n if (filterType === PlaylistLevelType.AUDIO) {\n // Reset current fragment since audio track audio is essential and may not have a fail-over track\n this.fragCurrent = null;\n }\n // Fragment errors that result in a level switch or redundant fail-over\n // should reset the stream controller state to idle\n if (!this.loadedmetadata) {\n this.startFragRequested = false;\n }\n if (this.state !== State.STOPPED) {\n this.state = State.IDLE;\n }\n }\n\n protected afterBufferFlushed(\n media: Bufferable,\n bufferType: SourceBufferName,\n playlistType: PlaylistLevelType\n ) {\n if (!media) {\n return;\n }\n // After successful buffer flushing, filter flushed fragments from bufferedFrags use mediaBuffered instead of media\n // (so that we will check against video.buffered ranges in case of alt audio track)\n const bufferedTimeRanges = BufferHelper.getBuffered(media);\n this.fragmentTracker.detectEvictedFragments(\n bufferType,\n bufferedTimeRanges,\n playlistType\n );\n if (this.state === State.ENDED) {\n this.resetLoadingState();\n }\n }\n\n protected resetLoadingState() {\n this.log('Reset loading state');\n this.fragCurrent = null;\n this.fragPrevious = null;\n this.state = State.IDLE;\n }\n\n protected resetStartWhenNotLoaded(level: number): void {\n // if loadedmetadata is not set, it means that first frag request failed\n // in that case, reset startFragRequested flag\n if (!this.loadedmetadata) {\n this.startFragRequested = false;\n const details = this.levels ? this.levels[level].details : null;\n if (details?.live) {\n // Update the start position and return to IDLE to recover live start\n this.startPosition = -1;\n this.setStartPosition(details, 0);\n this.resetLoadingState();\n } else {\n this.nextLoadPosition = this.startPosition;\n }\n }\n }\n\n protected resetWhenMissingContext(chunkMeta: ChunkMetadata) {\n this.warn(\n `The loading context changed while buffering fragment ${chunkMeta.sn} of level ${chunkMeta.level}. This chunk will not be buffered.`\n );\n this.removeUnbufferedFrags();\n this.resetStartWhenNotLoaded(chunkMeta.level);\n this.resetLoadingState();\n }\n\n protected removeUnbufferedFrags(start: number = 0) {\n this.fragmentTracker.removeFragmentsInRange(\n start,\n Infinity,\n this.playlistType,\n false,\n true\n );\n }\n\n private updateLevelTiming(\n frag: Fragment,\n part: Part | null,\n level: Level,\n partial: boolean\n ) {\n const details = level.details as LevelDetails;\n if (!details) {\n this.warn('level.details undefined');\n return;\n }\n const parsed = Object.keys(frag.elementaryStreams).reduce(\n (result, type) => {\n const info = frag.elementaryStreams[type];\n if (info) {\n const parsedDuration = info.endPTS - info.startPTS;\n if (parsedDuration <= 0) {\n // Destroy the transmuxer after it's next time offset failed to advance because duration was <= 0.\n // The new transmuxer will be configured with a time offset matching the next fragment start,\n // preventing the timeline from shifting.\n this.warn(\n `Could not parse fragment ${frag.sn} ${type} duration reliably (${parsedDuration})`\n );\n return result || false;\n }\n const drift = partial\n ? 0\n : updateFragPTSDTS(\n details,\n frag,\n info.startPTS,\n info.endPTS,\n info.startDTS,\n info.endDTS\n );\n this.hls.trigger(Events.LEVEL_PTS_UPDATED, {\n details,\n level,\n drift,\n type,\n frag,\n start: info.startPTS,\n end: info.endPTS,\n });\n return true;\n }\n return result;\n },\n false\n );\n if (parsed) {\n level.fragmentError = 0;\n } else if (this.transmuxer?.error === null) {\n const error = new Error(\n `Found no media in fragment ${frag.sn} of level ${level.id} resetting transmuxer to fallback to playlist timing`\n );\n this.warn(error.message);\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n fatal: false,\n error,\n frag,\n reason: `Found no media in msn ${frag.sn} of level \"${level.url}\"`,\n });\n if (!this.hls) {\n return;\n }\n this.resetTransmuxer();\n // For this error fallthrough. Marking parsed will allow advancing to next fragment.\n }\n this.state = State.PARSED;\n this.hls.trigger(Events.FRAG_PARSED, { frag, part });\n }\n\n protected resetTransmuxer() {\n if (this.transmuxer) {\n this.transmuxer.destroy();\n this.transmuxer = null;\n }\n }\n\n protected recoverWorkerError(data: ErrorData) {\n if (data.event === 'demuxerWorker') {\n this.resetTransmuxer();\n this.resetLoadingState();\n }\n }\n\n set state(nextState) {\n const previousState = this._state;\n if (previousState !== nextState) {\n this._state = nextState;\n this.log(`${previousState}->${nextState}`);\n }\n }\n\n get state() {\n return this._state;\n }\n}\n","/**\n * TimeRanges to string helper\n */\n\nconst TimeRanges = {\n toString: function (r: TimeRanges) {\n let log = '';\n const len = r.length;\n for (let i = 0; i < len; i++) {\n log += `[${r.start(i).toFixed(3)}-${r.end(i).toFixed(3)}]`;\n }\n\n return log;\n },\n};\n\nexport default TimeRanges;\n","import { getMediaSource } from './utils/mediasource-helper';\nimport type { ExtendedSourceBuffer } from './types/buffer';\n\nfunction getSourceBuffer(): typeof self.SourceBuffer {\n return self.SourceBuffer || (self as any).WebKitSourceBuffer;\n}\n\n/**\n * @ignore\n */\nexport function isSupported(): boolean {\n const mediaSource = getMediaSource();\n if (!mediaSource) {\n return false;\n }\n const sourceBuffer = getSourceBuffer();\n const isTypeSupported =\n mediaSource &&\n typeof mediaSource.isTypeSupported === 'function' &&\n mediaSource.isTypeSupported('video/mp4; codecs=\"avc1.42E01E,mp4a.40.2\"');\n\n // if SourceBuffer is exposed ensure its API is valid\n // Older browsers do not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible\n const sourceBufferValidAPI =\n !sourceBuffer ||\n (sourceBuffer.prototype &&\n typeof sourceBuffer.prototype.appendBuffer === 'function' &&\n typeof sourceBuffer.prototype.remove === 'function');\n return !!isTypeSupported && !!sourceBufferValidAPI;\n}\n\n/**\n * @ignore\n */\nexport function changeTypeSupported(): boolean {\n const sourceBuffer = getSourceBuffer();\n return (\n typeof (sourceBuffer?.prototype as ExtendedSourceBuffer)?.changeType ===\n 'function'\n );\n}\n","import type { DemuxedTrack } from '../types/demuxer';\n\nexport function dummyTrack(type = '', inputTimeScale = 90000): DemuxedTrack {\n return {\n type,\n id: -1,\n pid: -1,\n inputTimeScale,\n sequenceNumber: -1,\n samples: [],\n dropped: 0,\n };\n}\n","import * as ID3 from '../demux/id3';\nimport {\n DemuxerResult,\n Demuxer,\n DemuxedAudioTrack,\n AudioFrame,\n DemuxedMetadataTrack,\n DemuxedVideoTrack,\n DemuxedUserdataTrack,\n KeyData,\n MetadataSchema,\n} from '../types/demuxer';\nimport { dummyTrack } from './dummy-demuxed-track';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { sliceUint8 } from '../utils/typed-array';\nimport { RationalTimestamp } from '../utils/timescale-conversion';\n\nclass BaseAudioDemuxer implements Demuxer {\n protected _audioTrack!: DemuxedAudioTrack;\n protected _id3Track!: DemuxedMetadataTrack;\n protected frameIndex: number = 0;\n protected cachedData: Uint8Array | null = null;\n protected basePTS: number | null = null;\n protected initPTS: RationalTimestamp | null = null;\n protected lastPTS: number | null = null;\n\n resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number\n ) {\n this._id3Track = {\n type: 'id3',\n id: 3,\n pid: -1,\n inputTimeScale: 90000,\n sequenceNumber: 0,\n samples: [],\n dropped: 0,\n };\n }\n\n resetTimeStamp(deaultTimestamp: RationalTimestamp | null) {\n this.initPTS = deaultTimestamp;\n this.resetContiguity();\n }\n\n resetContiguity(): void {\n this.basePTS = null;\n this.lastPTS = null;\n this.frameIndex = 0;\n }\n\n canParse(data: Uint8Array, offset: number): boolean {\n return false;\n }\n\n appendFrame(\n track: DemuxedAudioTrack,\n data: Uint8Array,\n offset: number\n ): AudioFrame | void {}\n\n // feed incoming data to the front of the parsing pipeline\n demux(data: Uint8Array, timeOffset: number): DemuxerResult {\n if (this.cachedData) {\n data = appendUint8Array(this.cachedData, data);\n this.cachedData = null;\n }\n\n let id3Data: Uint8Array | undefined = ID3.getID3Data(data, 0);\n let offset = id3Data ? id3Data.length : 0;\n let lastDataIndex;\n const track = this._audioTrack;\n const id3Track = this._id3Track;\n const timestamp = id3Data ? ID3.getTimeStamp(id3Data) : undefined;\n const length = data.length;\n\n if (\n this.basePTS === null ||\n (this.frameIndex === 0 && Number.isFinite(timestamp))\n ) {\n this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);\n this.lastPTS = this.basePTS;\n }\n\n if (this.lastPTS === null) {\n this.lastPTS = this.basePTS;\n }\n\n // more expressive than alternative: id3Data?.length\n if (id3Data && id3Data.length > 0) {\n id3Track.samples.push({\n pts: this.lastPTS,\n dts: this.lastPTS,\n data: id3Data,\n type: MetadataSchema.audioId3,\n duration: Number.POSITIVE_INFINITY,\n });\n }\n\n while (offset < length) {\n if (this.canParse(data, offset)) {\n const frame = this.appendFrame(track, data, offset);\n if (frame) {\n this.frameIndex++;\n this.lastPTS = frame.sample.pts;\n offset += frame.length;\n lastDataIndex = offset;\n } else {\n offset = length;\n }\n } else if (ID3.canParse(data, offset)) {\n // after a ID3.canParse, a call to ID3.getID3Data *should* always returns some data\n id3Data = ID3.getID3Data(data, offset)!;\n id3Track.samples.push({\n pts: this.lastPTS,\n dts: this.lastPTS,\n data: id3Data,\n type: MetadataSchema.audioId3,\n duration: Number.POSITIVE_INFINITY,\n });\n offset += id3Data.length;\n lastDataIndex = offset;\n } else {\n offset++;\n }\n if (offset === length && lastDataIndex !== length) {\n const partialData = sliceUint8(data, lastDataIndex);\n if (this.cachedData) {\n this.cachedData = appendUint8Array(this.cachedData, partialData);\n } else {\n this.cachedData = partialData;\n }\n }\n }\n\n return {\n audioTrack: track,\n videoTrack: dummyTrack() as DemuxedVideoTrack,\n id3Track,\n textTrack: dummyTrack() as DemuxedUserdataTrack,\n };\n }\n\n demuxSampleAes(\n data: Uint8Array,\n keyData: KeyData,\n timeOffset: number\n ): Promise<DemuxerResult> {\n return Promise.reject(\n new Error(`[${this}] This demuxer does not support Sample-AES decryption`)\n );\n }\n\n flush(timeOffset: number): DemuxerResult {\n // Parse cache in case of remaining frames.\n const cachedData = this.cachedData;\n if (cachedData) {\n this.cachedData = null;\n this.demux(cachedData, 0);\n }\n\n return {\n audioTrack: this._audioTrack,\n videoTrack: dummyTrack() as DemuxedVideoTrack,\n id3Track: this._id3Track,\n textTrack: dummyTrack() as DemuxedUserdataTrack,\n };\n }\n\n destroy() {}\n}\n\n/**\n * Initialize PTS\n * <p>\n * use timestamp unless it is undefined, NaN or Infinity\n * </p>\n */\nexport const initPTSFn = (\n timestamp: number | undefined,\n timeOffset: number,\n initPTS: RationalTimestamp | null\n): number => {\n if (Number.isFinite(timestamp as number)) {\n return timestamp! * 90;\n }\n const init90kHz = initPTS\n ? (initPTS.baseTime * 90000) / initPTS.timescale\n : 0;\n return timeOffset * 90000 + init90kHz;\n};\nexport default BaseAudioDemuxer;\n","/**\n * ADTS parser helper\n * @link https://wiki.multimedia.cx/index.php?title=ADTS\n */\nimport { logger } from '../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport type { HlsEventEmitter } from '../events';\nimport { Events } from '../events';\nimport type {\n DemuxedAudioTrack,\n AudioFrame,\n AudioSample,\n} from '../types/demuxer';\n\ntype AudioConfig = {\n config: number[];\n samplerate: number;\n channelCount: number;\n codec: string;\n manifestCodec: string;\n};\n\ntype FrameHeader = {\n headerLength: number;\n frameLength: number;\n};\n\nexport function getAudioConfig(\n observer,\n data: Uint8Array,\n offset: number,\n audioCodec: string\n): AudioConfig | void {\n let adtsObjectType: number;\n let adtsExtensionSamplingIndex: number;\n let adtsChannelConfig: number;\n let config: number[];\n const userAgent = navigator.userAgent.toLowerCase();\n const manifestCodec = audioCodec;\n const adtsSamplingRates = [\n 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025,\n 8000, 7350,\n ];\n // byte 2\n adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;\n const adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;\n if (adtsSamplingIndex > adtsSamplingRates.length - 1) {\n observer.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n fatal: true,\n reason: `invalid ADTS sampling index:${adtsSamplingIndex}`,\n });\n return;\n }\n adtsChannelConfig = (data[offset + 2] & 0x01) << 2;\n // byte 3\n adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;\n logger.log(\n `manifest codec:${audioCodec}, ADTS type:${adtsObjectType}, samplingIndex:${adtsSamplingIndex}`\n );\n // firefox: freq less than 24kHz = AAC SBR (HE-AAC)\n if (/firefox/i.test(userAgent)) {\n if (adtsSamplingIndex >= 6) {\n adtsObjectType = 5;\n config = new Array(4);\n // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n // there is a factor 2 between frame sample rate and output sample rate\n // multiply frequency by 2 (see table below, equivalent to substract 3)\n adtsExtensionSamplingIndex = adtsSamplingIndex - 3;\n } else {\n adtsObjectType = 2;\n config = new Array(2);\n adtsExtensionSamplingIndex = adtsSamplingIndex;\n }\n // Android : always use AAC\n } else if (userAgent.indexOf('android') !== -1) {\n adtsObjectType = 2;\n config = new Array(2);\n adtsExtensionSamplingIndex = adtsSamplingIndex;\n } else {\n /* for other browsers (Chrome/Vivaldi/Opera ...)\n always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)\n */\n adtsObjectType = 5;\n config = new Array(4);\n // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)\n if (\n (audioCodec &&\n (audioCodec.indexOf('mp4a.40.29') !== -1 ||\n audioCodec.indexOf('mp4a.40.5') !== -1)) ||\n (!audioCodec && adtsSamplingIndex >= 6)\n ) {\n // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n // there is a factor 2 between frame sample rate and output sample rate\n // multiply frequency by 2 (see table below, equivalent to substract 3)\n adtsExtensionSamplingIndex = adtsSamplingIndex - 3;\n } else {\n // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)\n // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo.\n if (\n (audioCodec &&\n audioCodec.indexOf('mp4a.40.2') !== -1 &&\n ((adtsSamplingIndex >= 6 && adtsChannelConfig === 1) ||\n /vivaldi/i.test(userAgent))) ||\n (!audioCodec && adtsChannelConfig === 1)\n ) {\n adtsObjectType = 2;\n config = new Array(2);\n }\n adtsExtensionSamplingIndex = adtsSamplingIndex;\n }\n }\n /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config\n ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()\n Audio Profile / Audio Object Type\n 0: Null\n 1: AAC Main\n 2: AAC LC (Low Complexity)\n 3: AAC SSR (Scalable Sample Rate)\n 4: AAC LTP (Long Term Prediction)\n 5: SBR (Spectral Band Replication)\n 6: AAC Scalable\n sampling freq\n 0: 96000 Hz\n 1: 88200 Hz\n 2: 64000 Hz\n 3: 48000 Hz\n 4: 44100 Hz\n 5: 32000 Hz\n 6: 24000 Hz\n 7: 22050 Hz\n 8: 16000 Hz\n 9: 12000 Hz\n 10: 11025 Hz\n 11: 8000 Hz\n 12: 7350 Hz\n 13: Reserved\n 14: Reserved\n 15: frequency is written explictly\n Channel Configurations\n These are the channel configurations:\n 0: Defined in AOT Specifc Config\n 1: 1 channel: front-center\n 2: 2 channels: front-left, front-right\n */\n // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1\n config[0] = adtsObjectType << 3;\n // samplingFrequencyIndex\n config[0] |= (adtsSamplingIndex & 0x0e) >> 1;\n config[1] |= (adtsSamplingIndex & 0x01) << 7;\n // channelConfiguration\n config[1] |= adtsChannelConfig << 3;\n if (adtsObjectType === 5) {\n // adtsExtensionSamplingIndex\n config[1] |= (adtsExtensionSamplingIndex & 0x0e) >> 1;\n config[2] = (adtsExtensionSamplingIndex & 0x01) << 7;\n // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???\n // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc\n config[2] |= 2 << 2;\n config[3] = 0;\n }\n return {\n config,\n samplerate: adtsSamplingRates[adtsSamplingIndex],\n channelCount: adtsChannelConfig,\n codec: 'mp4a.40.' + adtsObjectType,\n manifestCodec,\n };\n}\n\nexport function isHeaderPattern(data: Uint8Array, offset: number): boolean {\n return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;\n}\n\nexport function getHeaderLength(data: Uint8Array, offset: number): number {\n return data[offset + 1] & 0x01 ? 7 : 9;\n}\n\nexport function getFullFrameLength(data: Uint8Array, offset: number): number {\n return (\n ((data[offset + 3] & 0x03) << 11) |\n (data[offset + 4] << 3) |\n ((data[offset + 5] & 0xe0) >>> 5)\n );\n}\n\nexport function canGetFrameLength(data: Uint8Array, offset: number): boolean {\n return offset + 5 < data.length;\n}\n\nexport function isHeader(data: Uint8Array, offset: number): boolean {\n // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1\n // Layer bits (position 14 and 15) in header should be always 0 for ADTS\n // More info https://wiki.multimedia.cx/index.php?title=ADTS\n return offset + 1 < data.length && isHeaderPattern(data, offset);\n}\n\nexport function canParse(data: Uint8Array, offset: number): boolean {\n return (\n canGetFrameLength(data, offset) &&\n isHeaderPattern(data, offset) &&\n getFullFrameLength(data, offset) <= data.length - offset\n );\n}\n\nexport function probe(data: Uint8Array, offset: number): boolean {\n // same as isHeader but we also check that ADTS frame follows last ADTS frame\n // or end of data is reached\n if (isHeader(data, offset)) {\n // ADTS header Length\n const headerLength = getHeaderLength(data, offset);\n if (offset + headerLength >= data.length) {\n return false;\n }\n // ADTS frame Length\n const frameLength = getFullFrameLength(data, offset);\n if (frameLength <= headerLength) {\n return false;\n }\n\n const newOffset = offset + frameLength;\n return newOffset === data.length || isHeader(data, newOffset);\n }\n return false;\n}\n\nexport function initTrackConfig(\n track: DemuxedAudioTrack,\n observer: HlsEventEmitter,\n data: Uint8Array,\n offset: number,\n audioCodec: string\n) {\n if (!track.samplerate) {\n const config = getAudioConfig(observer, data, offset, audioCodec);\n if (!config) {\n return;\n }\n track.config = config.config;\n track.samplerate = config.samplerate;\n track.channelCount = config.channelCount;\n track.codec = config.codec;\n track.manifestCodec = config.manifestCodec;\n logger.log(\n `parsed codec:${track.codec}, rate:${config.samplerate}, channels:${config.channelCount}`\n );\n }\n}\n\nexport function getFrameDuration(samplerate: number): number {\n return (1024 * 90000) / samplerate;\n}\n\nexport function parseFrameHeader(\n data: Uint8Array,\n offset: number\n): FrameHeader | void {\n // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header\n const headerLength = getHeaderLength(data, offset);\n if (offset + headerLength <= data.length) {\n // retrieve frame size\n const frameLength = getFullFrameLength(data, offset) - headerLength;\n if (frameLength > 0) {\n // logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}`);\n return { headerLength, frameLength };\n }\n }\n}\n\nexport function appendFrame(\n track: DemuxedAudioTrack,\n data: Uint8Array,\n offset: number,\n pts: number,\n frameIndex: number\n): AudioFrame {\n const frameDuration = getFrameDuration(track.samplerate as number);\n const stamp = pts + frameIndex * frameDuration;\n const header = parseFrameHeader(data, offset);\n let unit: Uint8Array;\n if (header) {\n const { frameLength, headerLength } = header;\n const length = headerLength + frameLength;\n const missing = Math.max(0, offset + length - data.length);\n // logger.log(`AAC frame ${frameIndex}, pts:${stamp} length@offset/total: ${frameLength}@${offset+headerLength}/${data.byteLength} missing: ${missing}`);\n if (missing) {\n unit = new Uint8Array(length - headerLength);\n unit.set(data.subarray(offset + headerLength, data.length), 0);\n } else {\n unit = data.subarray(offset + headerLength, offset + length);\n }\n\n const sample: AudioSample = {\n unit,\n pts: stamp,\n };\n if (!missing) {\n track.samples.push(sample as AudioSample);\n }\n\n return { sample, length, missing };\n }\n // overflow incomplete header\n const length = data.length - offset;\n unit = new Uint8Array(length);\n unit.set(data.subarray(offset, data.length), 0);\n const sample: AudioSample = {\n unit,\n pts: stamp,\n };\n return { sample, length, missing: -1 };\n}\n","/**\n * MP4 demuxer\n */\nimport {\n Demuxer,\n DemuxerResult,\n PassthroughTrack,\n DemuxedAudioTrack,\n DemuxedUserdataTrack,\n DemuxedMetadataTrack,\n KeyData,\n MetadataSchema,\n} from '../types/demuxer';\nimport {\n findBox,\n segmentValidRange,\n appendUint8Array,\n parseEmsg,\n parseSamples,\n parseInitSegment,\n RemuxerTrackIdConfig,\n} from '../utils/mp4-tools';\nimport { dummyTrack } from './dummy-demuxed-track';\nimport type { HlsEventEmitter } from '../events';\nimport type { HlsConfig } from '../config';\n\nconst emsgSchemePattern = /\\/emsg[-/]ID3/i;\n\nclass MP4Demuxer implements Demuxer {\n private remainderData: Uint8Array | null = null;\n private timeOffset: number = 0;\n private config: HlsConfig;\n private videoTrack?: PassthroughTrack;\n private audioTrack?: DemuxedAudioTrack;\n private id3Track?: DemuxedMetadataTrack;\n private txtTrack?: DemuxedUserdataTrack;\n\n constructor(observer: HlsEventEmitter, config: HlsConfig) {\n this.config = config;\n }\n\n public resetTimeStamp() {}\n\n public resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number\n ) {\n const videoTrack = (this.videoTrack = dummyTrack(\n 'video',\n 1\n ) as PassthroughTrack);\n const audioTrack = (this.audioTrack = dummyTrack(\n 'audio',\n 1\n ) as DemuxedAudioTrack);\n const captionTrack = (this.txtTrack = dummyTrack(\n 'text',\n 1\n ) as DemuxedUserdataTrack);\n\n this.id3Track = dummyTrack('id3', 1) as DemuxedMetadataTrack;\n this.timeOffset = 0;\n\n if (!initSegment?.byteLength) {\n return;\n }\n const initData = parseInitSegment(initSegment);\n\n if (initData.video) {\n const { id, timescale, codec } = initData.video;\n videoTrack.id = id;\n videoTrack.timescale = captionTrack.timescale = timescale;\n videoTrack.codec = codec;\n }\n\n if (initData.audio) {\n const { id, timescale, codec } = initData.audio;\n audioTrack.id = id;\n audioTrack.timescale = timescale;\n audioTrack.codec = codec;\n }\n\n captionTrack.id = RemuxerTrackIdConfig.text;\n videoTrack.sampleDuration = 0;\n videoTrack.duration = audioTrack.duration = trackDuration;\n }\n\n public resetContiguity(): void {\n this.remainderData = null;\n }\n\n static probe(data: Uint8Array) {\n // ensure we find a moof box in the first 16 kB\n data = data.length > 16384 ? data.subarray(0, 16384) : data;\n return findBox(data, ['moof']).length > 0;\n }\n\n public demux(data: Uint8Array, timeOffset: number): DemuxerResult {\n this.timeOffset = timeOffset;\n // Load all data into the avc track. The CMAF remuxer will look for the data in the samples object; the rest of the fields do not matter\n let videoSamples = data;\n const videoTrack = this.videoTrack as PassthroughTrack;\n const textTrack = this.txtTrack as DemuxedUserdataTrack;\n if (this.config.progressive) {\n // Split the bytestream into two ranges: one encompassing all data up until the start of the last moof, and everything else.\n // This is done to guarantee that we're sending valid data to MSE - when demuxing progressively, we have no guarantee\n // that the fetch loader gives us flush moof+mdat pairs. If we push jagged data to MSE, it will throw an exception.\n if (this.remainderData) {\n videoSamples = appendUint8Array(this.remainderData, data);\n }\n const segmentedData = segmentValidRange(videoSamples);\n this.remainderData = segmentedData.remainder;\n videoTrack.samples = segmentedData.valid || new Uint8Array();\n } else {\n videoTrack.samples = videoSamples;\n }\n\n const id3Track = this.extractID3Track(videoTrack, timeOffset);\n textTrack.samples = parseSamples(timeOffset, videoTrack);\n\n return {\n videoTrack,\n audioTrack: this.audioTrack as DemuxedAudioTrack,\n id3Track,\n textTrack: this.txtTrack as DemuxedUserdataTrack,\n };\n }\n\n public flush() {\n const timeOffset = this.timeOffset;\n const videoTrack = this.videoTrack as PassthroughTrack;\n const textTrack = this.txtTrack as DemuxedUserdataTrack;\n videoTrack.samples = this.remainderData || new Uint8Array();\n this.remainderData = null;\n\n const id3Track = this.extractID3Track(videoTrack, this.timeOffset);\n textTrack.samples = parseSamples(timeOffset, videoTrack);\n\n return {\n videoTrack,\n audioTrack: dummyTrack() as DemuxedAudioTrack,\n id3Track,\n textTrack: dummyTrack() as DemuxedUserdataTrack,\n };\n }\n\n private extractID3Track(\n videoTrack: PassthroughTrack,\n timeOffset: number\n ): DemuxedMetadataTrack {\n const id3Track = this.id3Track as DemuxedMetadataTrack;\n if (videoTrack.samples.length) {\n const emsgs = findBox(videoTrack.samples, ['emsg']);\n if (emsgs) {\n emsgs.forEach((data: Uint8Array) => {\n const emsgInfo = parseEmsg(data);\n if (emsgSchemePattern.test(emsgInfo.schemeIdUri)) {\n const pts = Number.isFinite(emsgInfo.presentationTime)\n ? emsgInfo.presentationTime! / emsgInfo.timeScale\n : timeOffset +\n emsgInfo.presentationTimeDelta! / emsgInfo.timeScale;\n let duration =\n emsgInfo.eventDuration === 0xffffffff\n ? Number.POSITIVE_INFINITY\n : emsgInfo.eventDuration / emsgInfo.timeScale;\n // Safari takes anything <= 0.001 seconds and maps it to Infinity\n if (duration <= 0.001) {\n duration = Number.POSITIVE_INFINITY;\n }\n const payload = emsgInfo.payload;\n id3Track.samples.push({\n data: payload,\n len: payload.byteLength,\n dts: pts,\n pts: pts,\n type: MetadataSchema.emsg,\n duration: duration,\n });\n }\n });\n }\n }\n return id3Track;\n }\n\n demuxSampleAes(\n data: Uint8Array,\n keyData: KeyData,\n timeOffset: number\n ): Promise<DemuxerResult> {\n return Promise.reject(\n new Error('The MP4 demuxer does not support SAMPLE-AES decryption')\n );\n }\n\n destroy() {}\n}\n\nexport default MP4Demuxer;\n","/**\n * MPEG parser helper\n */\nimport { DemuxedAudioTrack } from '../types/demuxer';\n\nlet chromeVersion: number | null = null;\n\nconst BitratesMap = [\n 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56,\n 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80,\n 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144,\n 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144,\n 160,\n];\n\nconst SamplingRateMap = [\n 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000,\n];\n\nconst SamplesCoefficients = [\n // MPEG 2.5\n [\n 0, // Reserved\n 72, // Layer3\n 144, // Layer2\n 12, // Layer1\n ],\n // Reserved\n [\n 0, // Reserved\n 0, // Layer3\n 0, // Layer2\n 0, // Layer1\n ],\n // MPEG 2\n [\n 0, // Reserved\n 72, // Layer3\n 144, // Layer2\n 12, // Layer1\n ],\n // MPEG 1\n [\n 0, // Reserved\n 144, // Layer3\n 144, // Layer2\n 12, // Layer1\n ],\n];\n\nconst BytesInSlot = [\n 0, // Reserved\n 1, // Layer3\n 1, // Layer2\n 4, // Layer1\n];\n\nexport function appendFrame(\n track: DemuxedAudioTrack,\n data: Uint8Array,\n offset: number,\n pts: number,\n frameIndex: number\n) {\n // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference\n if (offset + 24 > data.length) {\n return;\n }\n\n const header = parseHeader(data, offset);\n if (header && offset + header.frameLength <= data.length) {\n const frameDuration = (header.samplesPerFrame * 90000) / header.sampleRate;\n const stamp = pts + frameIndex * frameDuration;\n const sample = {\n unit: data.subarray(offset, offset + header.frameLength),\n pts: stamp,\n dts: stamp,\n };\n\n track.config = [];\n track.channelCount = header.channelCount;\n track.samplerate = header.sampleRate;\n track.samples.push(sample);\n\n return { sample, length: header.frameLength, missing: 0 };\n }\n}\n\nexport function parseHeader(data: Uint8Array, offset: number) {\n const mpegVersion = (data[offset + 1] >> 3) & 3;\n const mpegLayer = (data[offset + 1] >> 1) & 3;\n const bitRateIndex = (data[offset + 2] >> 4) & 15;\n const sampleRateIndex = (data[offset + 2] >> 2) & 3;\n if (\n mpegVersion !== 1 &&\n bitRateIndex !== 0 &&\n bitRateIndex !== 15 &&\n sampleRateIndex !== 3\n ) {\n const paddingBit = (data[offset + 2] >> 1) & 1;\n const channelMode = data[offset + 3] >> 6;\n const columnInBitrates =\n mpegVersion === 3 ? 3 - mpegLayer : mpegLayer === 3 ? 3 : 4;\n const bitRate =\n BitratesMap[columnInBitrates * 14 + bitRateIndex - 1] * 1000;\n const columnInSampleRates =\n mpegVersion === 3 ? 0 : mpegVersion === 2 ? 1 : 2;\n const sampleRate =\n SamplingRateMap[columnInSampleRates * 3 + sampleRateIndex];\n const channelCount = channelMode === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)\n const sampleCoefficient = SamplesCoefficients[mpegVersion][mpegLayer];\n const bytesInSlot = BytesInSlot[mpegLayer];\n const samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;\n const frameLength =\n Math.floor((sampleCoefficient * bitRate) / sampleRate + paddingBit) *\n bytesInSlot;\n\n if (chromeVersion === null) {\n const userAgent = navigator.userAgent || '';\n const result = userAgent.match(/Chrome\\/(\\d+)/i);\n chromeVersion = result ? parseInt(result[1]) : 0;\n }\n const needChromeFix = !!chromeVersion && chromeVersion <= 87;\n\n if (\n needChromeFix &&\n mpegLayer === 2 &&\n bitRate >= 224000 &&\n channelMode === 0\n ) {\n // Work around bug in Chromium by setting channelMode to dual-channel (01) instead of stereo (00)\n data[offset + 3] = data[offset + 3] | 0x80;\n }\n\n return { sampleRate, channelCount, frameLength, samplesPerFrame };\n }\n}\n\nexport function isHeaderPattern(data: Uint8Array, offset: number): boolean {\n return (\n data[offset] === 0xff &&\n (data[offset + 1] & 0xe0) === 0xe0 &&\n (data[offset + 1] & 0x06) !== 0x00\n );\n}\n\nexport function isHeader(data: Uint8Array, offset: number): boolean {\n // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1\n // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)\n // More info http://www.mp3-tech.org/programmer/frame_header.html\n return offset + 1 < data.length && isHeaderPattern(data, offset);\n}\n\nexport function canParse(data: Uint8Array, offset: number): boolean {\n const headerSize = 4;\n\n return isHeaderPattern(data, offset) && headerSize <= data.length - offset;\n}\n\nexport function probe(data: Uint8Array, offset: number): boolean {\n // same as isHeader but we also check that MPEG frame follows last MPEG frame\n // or end of data is reached\n if (offset + 1 < data.length && isHeaderPattern(data, offset)) {\n // MPEG header Length\n const headerLength = 4;\n // MPEG frame Length\n const header = parseHeader(data, offset);\n let frameLength = headerLength;\n if (header?.frameLength) {\n frameLength = header.frameLength;\n }\n\n const newOffset = offset + frameLength;\n return newOffset === data.length || isHeader(data, newOffset);\n }\n return false;\n}\n","/**\n * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.\n */\n\nimport { logger } from '../utils/logger';\n\nclass ExpGolomb {\n private data: Uint8Array;\n public bytesAvailable: number;\n private word: number;\n private bitsAvailable: number;\n\n constructor(data: Uint8Array) {\n this.data = data;\n // the number of bytes left to examine in this.data\n this.bytesAvailable = data.byteLength;\n // the current word being examined\n this.word = 0; // :uint\n // the number of bits left to examine in the current word\n this.bitsAvailable = 0; // :uint\n }\n\n // ():void\n loadWord(): void {\n const data = this.data;\n const bytesAvailable = this.bytesAvailable;\n const position = data.byteLength - bytesAvailable;\n const workingBytes = new Uint8Array(4);\n const availableBytes = Math.min(4, bytesAvailable);\n if (availableBytes === 0) {\n throw new Error('no bytes available');\n }\n\n workingBytes.set(data.subarray(position, position + availableBytes));\n this.word = new DataView(workingBytes.buffer).getUint32(0);\n // track the amount of this.data that has been processed\n this.bitsAvailable = availableBytes * 8;\n this.bytesAvailable -= availableBytes;\n }\n\n // (count:int):void\n skipBits(count: number): void {\n let skipBytes; // :int\n count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable);\n if (this.bitsAvailable > count) {\n this.word <<= count;\n this.bitsAvailable -= count;\n } else {\n count -= this.bitsAvailable;\n skipBytes = count >> 3;\n count -= skipBytes << 3;\n this.bytesAvailable -= skipBytes;\n this.loadWord();\n this.word <<= count;\n this.bitsAvailable -= count;\n }\n }\n\n // (size:int):uint\n readBits(size: number): number {\n let bits = Math.min(this.bitsAvailable, size); // :uint\n const valu = this.word >>> (32 - bits); // :uint\n if (size > 32) {\n logger.error('Cannot read more than 32 bits at a time');\n }\n\n this.bitsAvailable -= bits;\n if (this.bitsAvailable > 0) {\n this.word <<= bits;\n } else if (this.bytesAvailable > 0) {\n this.loadWord();\n } else {\n throw new Error('no bits available');\n }\n\n bits = size - bits;\n if (bits > 0 && this.bitsAvailable) {\n return (valu << bits) | this.readBits(bits);\n } else {\n return valu;\n }\n }\n\n // ():uint\n skipLZ(): number {\n let leadingZeroCount; // :uint\n for (\n leadingZeroCount = 0;\n leadingZeroCount < this.bitsAvailable;\n ++leadingZeroCount\n ) {\n if ((this.word & (0x80000000 >>> leadingZeroCount)) !== 0) {\n // the first bit of working word is 1\n this.word <<= leadingZeroCount;\n this.bitsAvailable -= leadingZeroCount;\n return leadingZeroCount;\n }\n }\n // we exhausted word and still have not found a 1\n this.loadWord();\n return leadingZeroCount + this.skipLZ();\n }\n\n // ():void\n skipUEG(): void {\n this.skipBits(1 + this.skipLZ());\n }\n\n // ():void\n skipEG(): void {\n this.skipBits(1 + this.skipLZ());\n }\n\n // ():uint\n readUEG(): number {\n const clz = this.skipLZ(); // :uint\n return this.readBits(clz + 1) - 1;\n }\n\n // ():int\n readEG(): number {\n const valu = this.readUEG(); // :int\n if (0x01 & valu) {\n // the number is odd if the low order bit is set\n return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2\n } else {\n return -1 * (valu >>> 1); // divide by two then make it negative\n }\n }\n\n // Some convenience functions\n // :Boolean\n readBoolean(): boolean {\n return this.readBits(1) === 1;\n }\n\n // ():int\n readUByte(): number {\n return this.readBits(8);\n }\n\n // ():int\n readUShort(): number {\n return this.readBits(16);\n }\n\n // ():int\n readUInt(): number {\n return this.readBits(32);\n }\n\n /**\n * Advance the ExpGolomb decoder past a scaling list. The scaling\n * list is optionally transmitted as part of a sequence parameter\n * set and is not relevant to transmuxing.\n * @param count the number of entries in this scaling list\n * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1\n */\n skipScalingList(count: number): void {\n let lastScale = 8;\n let nextScale = 8;\n let deltaScale;\n for (let j = 0; j < count; j++) {\n if (nextScale !== 0) {\n deltaScale = this.readEG();\n nextScale = (lastScale + deltaScale + 256) % 256;\n }\n lastScale = nextScale === 0 ? lastScale : nextScale;\n }\n }\n\n /**\n * Read a sequence parameter set and return some interesting video\n * properties. A sequence parameter set is the H264 metadata that\n * describes the properties of upcoming video frames.\n * @returns an object with configuration parsed from the\n * sequence parameter set, including the dimensions of the\n * associated video frames.\n */\n readSPS(): {\n width: number;\n height: number;\n pixelRatio: [number, number];\n } {\n let frameCropLeftOffset = 0;\n let frameCropRightOffset = 0;\n let frameCropTopOffset = 0;\n let frameCropBottomOffset = 0;\n let numRefFramesInPicOrderCntCycle;\n let scalingListCount;\n let i;\n const readUByte = this.readUByte.bind(this);\n const readBits = this.readBits.bind(this);\n const readUEG = this.readUEG.bind(this);\n const readBoolean = this.readBoolean.bind(this);\n const skipBits = this.skipBits.bind(this);\n const skipEG = this.skipEG.bind(this);\n const skipUEG = this.skipUEG.bind(this);\n const skipScalingList = this.skipScalingList.bind(this);\n\n readUByte();\n const profileIdc = readUByte(); // profile_idc\n readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)\n skipBits(3); // reserved_zero_3bits u(3),\n readUByte(); // level_idc u(8)\n skipUEG(); // seq_parameter_set_id\n // some profiles have more optional data we don't need\n if (\n profileIdc === 100 ||\n profileIdc === 110 ||\n profileIdc === 122 ||\n profileIdc === 244 ||\n profileIdc === 44 ||\n profileIdc === 83 ||\n profileIdc === 86 ||\n profileIdc === 118 ||\n profileIdc === 128\n ) {\n const chromaFormatIdc = readUEG();\n if (chromaFormatIdc === 3) {\n skipBits(1);\n } // separate_colour_plane_flag\n\n skipUEG(); // bit_depth_luma_minus8\n skipUEG(); // bit_depth_chroma_minus8\n skipBits(1); // qpprime_y_zero_transform_bypass_flag\n if (readBoolean()) {\n // seq_scaling_matrix_present_flag\n scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;\n for (i = 0; i < scalingListCount; i++) {\n if (readBoolean()) {\n // seq_scaling_list_present_flag[ i ]\n if (i < 6) {\n skipScalingList(16);\n } else {\n skipScalingList(64);\n }\n }\n }\n }\n }\n skipUEG(); // log2_max_frame_num_minus4\n const picOrderCntType = readUEG();\n if (picOrderCntType === 0) {\n readUEG(); // log2_max_pic_order_cnt_lsb_minus4\n } else if (picOrderCntType === 1) {\n skipBits(1); // delta_pic_order_always_zero_flag\n skipEG(); // offset_for_non_ref_pic\n skipEG(); // offset_for_top_to_bottom_field\n numRefFramesInPicOrderCntCycle = readUEG();\n for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {\n skipEG();\n } // offset_for_ref_frame[ i ]\n }\n skipUEG(); // max_num_ref_frames\n skipBits(1); // gaps_in_frame_num_value_allowed_flag\n const picWidthInMbsMinus1 = readUEG();\n const picHeightInMapUnitsMinus1 = readUEG();\n const frameMbsOnlyFlag = readBits(1);\n if (frameMbsOnlyFlag === 0) {\n skipBits(1);\n } // mb_adaptive_frame_field_flag\n\n skipBits(1); // direct_8x8_inference_flag\n if (readBoolean()) {\n // frame_cropping_flag\n frameCropLeftOffset = readUEG();\n frameCropRightOffset = readUEG();\n frameCropTopOffset = readUEG();\n frameCropBottomOffset = readUEG();\n }\n let pixelRatio: [number, number] = [1, 1];\n if (readBoolean()) {\n // vui_parameters_present_flag\n if (readBoolean()) {\n // aspect_ratio_info_present_flag\n const aspectRatioIdc = readUByte();\n switch (aspectRatioIdc) {\n case 1:\n pixelRatio = [1, 1];\n break;\n case 2:\n pixelRatio = [12, 11];\n break;\n case 3:\n pixelRatio = [10, 11];\n break;\n case 4:\n pixelRatio = [16, 11];\n break;\n case 5:\n pixelRatio = [40, 33];\n break;\n case 6:\n pixelRatio = [24, 11];\n break;\n case 7:\n pixelRatio = [20, 11];\n break;\n case 8:\n pixelRatio = [32, 11];\n break;\n case 9:\n pixelRatio = [80, 33];\n break;\n case 10:\n pixelRatio = [18, 11];\n break;\n case 11:\n pixelRatio = [15, 11];\n break;\n case 12:\n pixelRatio = [64, 33];\n break;\n case 13:\n pixelRatio = [160, 99];\n break;\n case 14:\n pixelRatio = [4, 3];\n break;\n case 15:\n pixelRatio = [3, 2];\n break;\n case 16:\n pixelRatio = [2, 1];\n break;\n case 255: {\n pixelRatio = [\n (readUByte() << 8) | readUByte(),\n (readUByte() << 8) | readUByte(),\n ];\n break;\n }\n }\n }\n }\n return {\n width: Math.ceil(\n (picWidthInMbsMinus1 + 1) * 16 -\n frameCropLeftOffset * 2 -\n frameCropRightOffset * 2\n ),\n height:\n (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -\n (frameMbsOnlyFlag ? 2 : 4) *\n (frameCropTopOffset + frameCropBottomOffset),\n pixelRatio: pixelRatio,\n };\n }\n\n readSliceType() {\n // skip NALu type\n this.readUByte();\n // discard first_mb_in_slice\n this.readUEG();\n // return slice_type\n return this.readUEG();\n }\n}\n\nexport default ExpGolomb;\n","/**\n * SAMPLE-AES decrypter\n */\n\nimport { HlsConfig } from '../config';\nimport Decrypter from '../crypt/decrypter';\nimport { HlsEventEmitter } from '../events';\nimport type {\n AudioSample,\n AvcSample,\n AvcSampleUnit,\n DemuxedVideoTrack,\n KeyData,\n} from '../types/demuxer';\nimport { discardEPB } from '../utils/mp4-tools';\n\nclass SampleAesDecrypter {\n private keyData: KeyData;\n private decrypter: Decrypter;\n\n constructor(observer: HlsEventEmitter, config: HlsConfig, keyData: KeyData) {\n this.keyData = keyData;\n this.decrypter = new Decrypter(config, {\n removePKCS7Padding: false,\n });\n }\n\n decryptBuffer(encryptedData: Uint8Array | ArrayBuffer): Promise<ArrayBuffer> {\n return this.decrypter.decrypt(\n encryptedData,\n this.keyData.key.buffer,\n this.keyData.iv.buffer\n );\n }\n\n // AAC - encrypt all full 16 bytes blocks starting from offset 16\n private decryptAacSample(\n samples: AudioSample[],\n sampleIndex: number,\n callback: () => void\n ) {\n const curUnit = samples[sampleIndex].unit;\n if (curUnit.length <= 16) {\n // No encrypted portion in this sample (first 16 bytes is not\n // encrypted, see https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption/Encryption/Encryption.html),\n return;\n }\n const encryptedData = curUnit.subarray(\n 16,\n curUnit.length - (curUnit.length % 16)\n );\n const encryptedBuffer = encryptedData.buffer.slice(\n encryptedData.byteOffset,\n encryptedData.byteOffset + encryptedData.length\n );\n\n this.decryptBuffer(encryptedBuffer).then((decryptedBuffer: ArrayBuffer) => {\n const decryptedData = new Uint8Array(decryptedBuffer);\n curUnit.set(decryptedData, 16);\n\n if (!this.decrypter.isSync()) {\n this.decryptAacSamples(samples, sampleIndex + 1, callback);\n }\n });\n }\n\n decryptAacSamples(\n samples: AudioSample[],\n sampleIndex: number,\n callback: () => void\n ) {\n for (; ; sampleIndex++) {\n if (sampleIndex >= samples.length) {\n callback();\n return;\n }\n\n if (samples[sampleIndex].unit.length < 32) {\n continue;\n }\n\n this.decryptAacSample(samples, sampleIndex, callback);\n\n if (!this.decrypter.isSync()) {\n return;\n }\n }\n }\n\n // AVC - encrypt one 16 bytes block out of ten, starting from offset 32\n getAvcEncryptedData(decodedData: Uint8Array) {\n const encryptedDataLen =\n Math.floor((decodedData.length - 48) / 160) * 16 + 16;\n const encryptedData = new Int8Array(encryptedDataLen);\n let outputPos = 0;\n for (\n let inputPos = 32;\n inputPos < decodedData.length - 16;\n inputPos += 160, outputPos += 16\n ) {\n encryptedData.set(\n decodedData.subarray(inputPos, inputPos + 16),\n outputPos\n );\n }\n\n return encryptedData;\n }\n\n getAvcDecryptedUnit(\n decodedData: Uint8Array,\n decryptedData: ArrayLike<number> | ArrayBuffer | SharedArrayBuffer\n ) {\n const uint8DecryptedData = new Uint8Array(decryptedData);\n let inputPos = 0;\n for (\n let outputPos = 32;\n outputPos < decodedData.length - 16;\n outputPos += 160, inputPos += 16\n ) {\n decodedData.set(\n uint8DecryptedData.subarray(inputPos, inputPos + 16),\n outputPos\n );\n }\n\n return decodedData;\n }\n\n decryptAvcSample(\n samples: AvcSample[],\n sampleIndex: number,\n unitIndex: number,\n callback: () => void,\n curUnit: AvcSampleUnit\n ) {\n const decodedData = discardEPB(curUnit.data);\n const encryptedData = this.getAvcEncryptedData(decodedData);\n\n this.decryptBuffer(encryptedData.buffer).then(\n (decryptedBuffer: ArrayBuffer) => {\n curUnit.data = this.getAvcDecryptedUnit(decodedData, decryptedBuffer);\n\n if (!this.decrypter.isSync()) {\n this.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);\n }\n }\n );\n }\n\n decryptAvcSamples(\n samples: DemuxedVideoTrack['samples'],\n sampleIndex: number,\n unitIndex: number,\n callback: () => void\n ) {\n if (samples instanceof Uint8Array) {\n throw new Error('Cannot decrypt samples of type Uint8Array');\n }\n\n for (; ; sampleIndex++, unitIndex = 0) {\n if (sampleIndex >= samples.length) {\n callback();\n return;\n }\n\n const curUnits = samples[sampleIndex].units;\n for (; ; unitIndex++) {\n if (unitIndex >= curUnits.length) {\n break;\n }\n\n const curUnit = curUnits[unitIndex];\n if (\n curUnit.data.length <= 48 ||\n (curUnit.type !== 1 && curUnit.type !== 5)\n ) {\n continue;\n }\n\n this.decryptAvcSample(\n samples,\n sampleIndex,\n unitIndex,\n callback,\n curUnit\n );\n\n if (!this.decrypter.isSync()) {\n return;\n }\n }\n }\n }\n}\n\nexport default SampleAesDecrypter;\n","/**\n * highly optimized TS demuxer:\n * parse PAT, PMT\n * extract PES packet from audio and video PIDs\n * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet\n * trigger the remuxer upon parsing completion\n * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.\n * it also controls the remuxing process :\n * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.\n */\n\nimport * as ADTS from './adts';\nimport * as MpegAudio from './mpegaudio';\nimport ExpGolomb from './exp-golomb';\nimport SampleAesDecrypter from './sample-aes';\nimport { Events } from '../events';\nimport {\n appendUint8Array,\n parseSEIMessageFromNALu,\n RemuxerTrackIdConfig,\n} from '../utils/mp4-tools';\nimport { logger } from '../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport type { HlsConfig } from '../config';\nimport type { HlsEventEmitter } from '../events';\nimport {\n DemuxedAvcTrack,\n DemuxedAudioTrack,\n DemuxedTrack,\n Demuxer,\n DemuxerResult,\n AvcSample,\n DemuxedMetadataTrack,\n DemuxedUserdataTrack,\n ElementaryStreamData,\n KeyData,\n MetadataSchema,\n} from '../types/demuxer';\nimport { AudioFrame } from '../types/demuxer';\n\ntype ParsedTimestamp = {\n pts?: number;\n dts?: number;\n};\n\ntype PES = ParsedTimestamp & {\n data: Uint8Array;\n len: number;\n};\n\ntype ParsedAvcSample = ParsedTimestamp & Omit<AvcSample, 'pts' | 'dts'>;\n\nexport interface TypeSupported {\n mpeg: boolean;\n mp3: boolean;\n mp4: boolean;\n}\n\nconst PACKET_LENGTH = 188;\n\nclass TSDemuxer implements Demuxer {\n private readonly observer: HlsEventEmitter;\n private readonly config: HlsConfig;\n private typeSupported: TypeSupported;\n\n private sampleAes: SampleAesDecrypter | null = null;\n private pmtParsed: boolean = false;\n private audioCodec?: string;\n private videoCodec?: string;\n private _duration: number = 0;\n private _pmtId: number = -1;\n\n private _avcTrack?: DemuxedAvcTrack;\n private _audioTrack?: DemuxedAudioTrack;\n private _id3Track?: DemuxedMetadataTrack;\n private _txtTrack?: DemuxedUserdataTrack;\n private aacOverFlow: AudioFrame | null = null;\n private avcSample: ParsedAvcSample | null = null;\n private remainderData: Uint8Array | null = null;\n\n constructor(\n observer: HlsEventEmitter,\n config: HlsConfig,\n typeSupported: TypeSupported\n ) {\n this.observer = observer;\n this.config = config;\n this.typeSupported = typeSupported;\n }\n\n static probe(data: Uint8Array) {\n const syncOffset = TSDemuxer.syncOffset(data);\n if (syncOffset > 0) {\n logger.warn(\n `MPEG2-TS detected but first sync word found @ offset ${syncOffset}`\n );\n }\n return syncOffset !== -1;\n }\n\n static syncOffset(data: Uint8Array): number {\n const length = data.length;\n let scanwindow =\n Math.min(PACKET_LENGTH * 5, data.length - PACKET_LENGTH) + 1;\n let i = 0;\n while (i < scanwindow) {\n // a TS init segment should contain at least 2 TS packets: PAT and PMT, each starting with 0x47\n let foundPat = false;\n let packetStart = -1;\n let tsPackets = 0;\n for (let j = i; j < length; j += PACKET_LENGTH) {\n if (data[j] === 0x47) {\n tsPackets++;\n if (packetStart === -1) {\n packetStart = j;\n // First sync word found at offset, increase scan length (#5251)\n if (packetStart !== 0) {\n scanwindow =\n Math.min(\n packetStart + PACKET_LENGTH * 99,\n data.length - PACKET_LENGTH\n ) + 1;\n }\n }\n if (!foundPat) {\n foundPat = parsePID(data, j) === 0;\n }\n // Sync word found at 0 with 3 packets, or found at offset least 2 packets up to scanwindow (#5501)\n if (\n foundPat &&\n tsPackets > 1 &&\n ((packetStart === 0 && tsPackets > 2) ||\n j + PACKET_LENGTH > scanwindow)\n ) {\n return packetStart;\n }\n } else if (tsPackets) {\n // Exit if sync word found, but does not contain contiguous packets (#5501)\n return -1;\n } else {\n break;\n }\n }\n i++;\n }\n return -1;\n }\n\n /**\n * Creates a track model internal to demuxer used to drive remuxing input\n */\n static createTrack(\n type: 'audio' | 'video' | 'id3' | 'text',\n duration?: number\n ): DemuxedTrack {\n return {\n container:\n type === 'video' || type === 'audio' ? 'video/mp2t' : undefined,\n type,\n id: RemuxerTrackIdConfig[type],\n pid: -1,\n inputTimeScale: 90000,\n sequenceNumber: 0,\n samples: [],\n dropped: 0,\n duration: type === 'audio' ? duration : undefined,\n };\n }\n\n /**\n * Initializes a new init segment on the demuxer/remuxer interface. Needed for discontinuities/track-switches (or at stream start)\n * Resets all internal track instances of the demuxer.\n */\n public resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string,\n videoCodec: string,\n trackDuration: number\n ) {\n this.pmtParsed = false;\n this._pmtId = -1;\n\n this._avcTrack = TSDemuxer.createTrack('video') as DemuxedAvcTrack;\n this._audioTrack = TSDemuxer.createTrack(\n 'audio',\n trackDuration\n ) as DemuxedAudioTrack;\n this._id3Track = TSDemuxer.createTrack('id3') as DemuxedMetadataTrack;\n this._txtTrack = TSDemuxer.createTrack('text') as DemuxedUserdataTrack;\n this._audioTrack.segmentCodec = 'aac';\n\n // flush any partial content\n this.aacOverFlow = null;\n this.avcSample = null;\n this.remainderData = null;\n this.audioCodec = audioCodec;\n this.videoCodec = videoCodec;\n this._duration = trackDuration;\n }\n\n public resetTimeStamp() {}\n\n public resetContiguity(): void {\n const { _audioTrack, _avcTrack, _id3Track } = this;\n if (_audioTrack) {\n _audioTrack.pesData = null;\n }\n if (_avcTrack) {\n _avcTrack.pesData = null;\n }\n if (_id3Track) {\n _id3Track.pesData = null;\n }\n this.aacOverFlow = null;\n this.avcSample = null;\n this.remainderData = null;\n }\n\n public demux(\n data: Uint8Array,\n timeOffset: number,\n isSampleAes = false,\n flush = false\n ): DemuxerResult {\n if (!isSampleAes) {\n this.sampleAes = null;\n }\n\n let pes: PES | null;\n\n const videoTrack = this._avcTrack as DemuxedAvcTrack;\n const audioTrack = this._audioTrack as DemuxedAudioTrack;\n const id3Track = this._id3Track as DemuxedMetadataTrack;\n const textTrack = this._txtTrack as DemuxedUserdataTrack;\n\n let avcId = videoTrack.pid;\n let avcData = videoTrack.pesData;\n let audioId = audioTrack.pid;\n let id3Id = id3Track.pid;\n let audioData = audioTrack.pesData;\n let id3Data = id3Track.pesData;\n let unknownPID: number | null = null;\n let pmtParsed = this.pmtParsed;\n let pmtId = this._pmtId;\n\n let len = data.length;\n if (this.remainderData) {\n data = appendUint8Array(this.remainderData, data);\n len = data.length;\n this.remainderData = null;\n }\n\n if (len < PACKET_LENGTH && !flush) {\n this.remainderData = data;\n return {\n audioTrack,\n videoTrack,\n id3Track,\n textTrack,\n };\n }\n\n const syncOffset = Math.max(0, TSDemuxer.syncOffset(data));\n len -= (len - syncOffset) % PACKET_LENGTH;\n if (len < data.byteLength && !flush) {\n this.remainderData = new Uint8Array(\n data.buffer,\n len,\n data.buffer.byteLength - len\n );\n }\n\n // loop through TS packets\n let tsPacketErrors = 0;\n for (let start = syncOffset; start < len; start += PACKET_LENGTH) {\n if (data[start] === 0x47) {\n const stt = !!(data[start + 1] & 0x40);\n const pid = parsePID(data, start);\n const atf = (data[start + 3] & 0x30) >> 4;\n\n // if an adaption field is present, its length is specified by the fifth byte of the TS packet header.\n let offset: number;\n if (atf > 1) {\n offset = start + 5 + data[start + 4];\n // continue if there is only adaptation field\n if (offset === start + PACKET_LENGTH) {\n continue;\n }\n } else {\n offset = start + 4;\n }\n switch (pid) {\n case avcId:\n if (stt) {\n if (avcData && (pes = parsePES(avcData))) {\n this.parseAVCPES(videoTrack, textTrack, pes, false);\n }\n\n avcData = { data: [], size: 0 };\n }\n if (avcData) {\n avcData.data.push(data.subarray(offset, start + PACKET_LENGTH));\n avcData.size += start + PACKET_LENGTH - offset;\n }\n break;\n case audioId:\n if (stt) {\n if (audioData && (pes = parsePES(audioData))) {\n switch (audioTrack.segmentCodec) {\n case 'aac':\n this.parseAACPES(audioTrack, pes);\n break;\n case 'mp3':\n this.parseMPEGPES(audioTrack, pes);\n break;\n }\n }\n audioData = { data: [], size: 0 };\n }\n if (audioData) {\n audioData.data.push(data.subarray(offset, start + PACKET_LENGTH));\n audioData.size += start + PACKET_LENGTH - offset;\n }\n break;\n case id3Id:\n if (stt) {\n if (id3Data && (pes = parsePES(id3Data))) {\n this.parseID3PES(id3Track, pes);\n }\n\n id3Data = { data: [], size: 0 };\n }\n if (id3Data) {\n id3Data.data.push(data.subarray(offset, start + PACKET_LENGTH));\n id3Data.size += start + PACKET_LENGTH - offset;\n }\n break;\n case 0:\n if (stt) {\n offset += data[offset] + 1;\n }\n\n pmtId = this._pmtId = parsePAT(data, offset);\n // logger.log('PMT PID:' + this._pmtId);\n break;\n case pmtId: {\n if (stt) {\n offset += data[offset] + 1;\n }\n\n const parsedPIDs = parsePMT(\n data,\n offset,\n this.typeSupported,\n isSampleAes\n );\n\n // only update track id if track PID found while parsing PMT\n // this is to avoid resetting the PID to -1 in case\n // track PID transiently disappears from the stream\n // this could happen in case of transient missing audio samples for example\n // NOTE this is only the PID of the track as found in TS,\n // but we are not using this for MP4 track IDs.\n avcId = parsedPIDs.avc;\n if (avcId > 0) {\n videoTrack.pid = avcId;\n }\n\n audioId = parsedPIDs.audio;\n if (audioId > 0) {\n audioTrack.pid = audioId;\n audioTrack.segmentCodec = parsedPIDs.segmentCodec;\n }\n id3Id = parsedPIDs.id3;\n if (id3Id > 0) {\n id3Track.pid = id3Id;\n }\n\n if (unknownPID !== null && !pmtParsed) {\n logger.warn(\n `MPEG-TS PMT found at ${start} after unknown PID '${unknownPID}'. Backtracking to sync byte @${syncOffset} to parse all TS packets.`\n );\n unknownPID = null;\n // we set it to -188, the += 188 in the for loop will reset start to 0\n start = syncOffset - 188;\n }\n pmtParsed = this.pmtParsed = true;\n break;\n }\n case 0x11:\n case 0x1fff:\n break;\n default:\n unknownPID = pid;\n break;\n }\n } else {\n tsPacketErrors++;\n }\n }\n\n if (tsPacketErrors > 0) {\n const error = new Error(\n `Found ${tsPacketErrors} TS packet/s that do not start with 0x47`\n );\n this.observer.emit(Events.ERROR, Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n fatal: false,\n error,\n reason: error.message,\n });\n }\n\n videoTrack.pesData = avcData;\n audioTrack.pesData = audioData;\n id3Track.pesData = id3Data;\n\n const demuxResult: DemuxerResult = {\n audioTrack,\n videoTrack,\n id3Track,\n textTrack,\n };\n\n if (flush) {\n this.extractRemainingSamples(demuxResult);\n }\n\n return demuxResult;\n }\n\n public flush(): DemuxerResult | Promise<DemuxerResult> {\n const { remainderData } = this;\n this.remainderData = null;\n let result: DemuxerResult;\n if (remainderData) {\n result = this.demux(remainderData, -1, false, true);\n } else {\n result = {\n videoTrack: this._avcTrack as DemuxedAvcTrack,\n audioTrack: this._audioTrack as DemuxedAudioTrack,\n id3Track: this._id3Track as DemuxedMetadataTrack,\n textTrack: this._txtTrack as DemuxedUserdataTrack,\n };\n }\n this.extractRemainingSamples(result);\n if (this.sampleAes) {\n return this.decrypt(result, this.sampleAes);\n }\n return result;\n }\n\n private extractRemainingSamples(demuxResult: DemuxerResult) {\n const { audioTrack, videoTrack, id3Track, textTrack } = demuxResult;\n const avcData = videoTrack.pesData;\n const audioData = audioTrack.pesData;\n const id3Data = id3Track.pesData;\n // try to parse last PES packets\n let pes: PES | null;\n if (avcData && (pes = parsePES(avcData))) {\n this.parseAVCPES(\n videoTrack as DemuxedAvcTrack,\n textTrack as DemuxedUserdataTrack,\n pes,\n true\n );\n videoTrack.pesData = null;\n } else {\n // either avcData null or PES truncated, keep it for next frag parsing\n videoTrack.pesData = avcData;\n }\n\n if (audioData && (pes = parsePES(audioData))) {\n switch (audioTrack.segmentCodec) {\n case 'aac':\n this.parseAACPES(audioTrack, pes);\n break;\n case 'mp3':\n this.parseMPEGPES(audioTrack, pes);\n break;\n }\n audioTrack.pesData = null;\n } else {\n if (audioData?.size) {\n logger.log(\n 'last AAC PES packet truncated,might overlap between fragments'\n );\n }\n\n // either audioData null or PES truncated, keep it for next frag parsing\n audioTrack.pesData = audioData;\n }\n\n if (id3Data && (pes = parsePES(id3Data))) {\n this.parseID3PES(id3Track, pes);\n id3Track.pesData = null;\n } else {\n // either id3Data null or PES truncated, keep it for next frag parsing\n id3Track.pesData = id3Data;\n }\n }\n\n public demuxSampleAes(\n data: Uint8Array,\n keyData: KeyData,\n timeOffset: number\n ): Promise<DemuxerResult> {\n const demuxResult = this.demux(\n data,\n timeOffset,\n true,\n !this.config.progressive\n );\n const sampleAes = (this.sampleAes = new SampleAesDecrypter(\n this.observer,\n this.config,\n keyData\n ));\n return this.decrypt(demuxResult, sampleAes);\n }\n\n private decrypt(\n demuxResult: DemuxerResult,\n sampleAes: SampleAesDecrypter\n ): Promise<DemuxerResult> {\n return new Promise((resolve) => {\n const { audioTrack, videoTrack } = demuxResult;\n if (audioTrack.samples && audioTrack.segmentCodec === 'aac') {\n sampleAes.decryptAacSamples(audioTrack.samples, 0, () => {\n if (videoTrack.samples) {\n sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, () => {\n resolve(demuxResult);\n });\n } else {\n resolve(demuxResult);\n }\n });\n } else if (videoTrack.samples) {\n sampleAes.decryptAvcSamples(videoTrack.samples, 0, 0, () => {\n resolve(demuxResult);\n });\n }\n });\n }\n\n public destroy() {\n this._duration = 0;\n }\n\n private parseAVCPES(\n track: DemuxedAvcTrack,\n textTrack: DemuxedUserdataTrack,\n pes: PES,\n last: boolean\n ) {\n const units = this.parseAVCNALu(track, pes.data);\n const debug = false;\n let avcSample = this.avcSample;\n let push: boolean;\n let spsfound = false;\n // free pes.data to save up some memory\n (pes as any).data = null;\n\n // if new NAL units found and last sample still there, let's push ...\n // this helps parsing streams with missing AUD (only do this if AUD never found)\n if (avcSample && units.length && !track.audFound) {\n pushAccessUnit(avcSample, track);\n avcSample = this.avcSample = createAVCSample(false, pes.pts, pes.dts, '');\n }\n\n units.forEach((unit) => {\n switch (unit.type) {\n // NDR\n case 1: {\n push = true;\n if (!avcSample) {\n avcSample = this.avcSample = createAVCSample(\n true,\n pes.pts,\n pes.dts,\n ''\n );\n }\n\n if (debug) {\n avcSample.debug += 'NDR ';\n }\n\n avcSample.frame = true;\n const data = unit.data;\n // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)\n if (spsfound && data.length > 4) {\n // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR\n const sliceType = new ExpGolomb(data).readSliceType();\n // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice\n // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.\n // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.\n // I slice: A slice that is not an SI slice that is decoded using intra prediction only.\n // if (sliceType === 2 || sliceType === 7) {\n if (\n sliceType === 2 ||\n sliceType === 4 ||\n sliceType === 7 ||\n sliceType === 9\n ) {\n avcSample.key = true;\n }\n }\n break;\n // IDR\n }\n case 5:\n push = true;\n // handle PES not starting with AUD\n if (!avcSample) {\n avcSample = this.avcSample = createAVCSample(\n true,\n pes.pts,\n pes.dts,\n ''\n );\n }\n\n if (debug) {\n avcSample.debug += 'IDR ';\n }\n\n avcSample.key = true;\n avcSample.frame = true;\n break;\n // SEI\n case 6: {\n push = true;\n if (debug && avcSample) {\n avcSample.debug += 'SEI ';\n }\n parseSEIMessageFromNALu(\n unit.data,\n 1,\n pes.pts as number,\n textTrack.samples\n );\n break;\n // SPS\n }\n case 7:\n push = true;\n spsfound = true;\n if (debug && avcSample) {\n avcSample.debug += 'SPS ';\n }\n\n if (!track.sps) {\n const sps = unit.data;\n const expGolombDecoder = new ExpGolomb(sps);\n const config = expGolombDecoder.readSPS();\n track.width = config.width;\n track.height = config.height;\n track.pixelRatio = config.pixelRatio;\n track.sps = [sps];\n track.duration = this._duration;\n const codecarray = sps.subarray(1, 4);\n let codecstring = 'avc1.';\n for (let i = 0; i < 3; i++) {\n let h = codecarray[i].toString(16);\n if (h.length < 2) {\n h = '0' + h;\n }\n\n codecstring += h;\n }\n track.codec = codecstring;\n }\n break;\n // PPS\n case 8:\n push = true;\n if (debug && avcSample) {\n avcSample.debug += 'PPS ';\n }\n\n if (!track.pps) {\n track.pps = [unit.data];\n }\n\n break;\n // AUD\n case 9:\n push = false;\n track.audFound = true;\n if (avcSample) {\n pushAccessUnit(avcSample, track);\n }\n\n avcSample = this.avcSample = createAVCSample(\n false,\n pes.pts,\n pes.dts,\n debug ? 'AUD ' : ''\n );\n break;\n // Filler Data\n case 12:\n push = true;\n break;\n default:\n push = false;\n if (avcSample) {\n avcSample.debug += 'unknown NAL ' + unit.type + ' ';\n }\n\n break;\n }\n if (avcSample && push) {\n const units = avcSample.units;\n units.push(unit);\n }\n });\n // if last PES packet, push samples\n if (last && avcSample) {\n pushAccessUnit(avcSample, track);\n this.avcSample = null;\n }\n }\n\n private getLastNalUnit(samples: AvcSample[]) {\n let avcSample = this.avcSample;\n let lastUnit;\n // try to fallback to previous sample if current one is empty\n if (!avcSample || avcSample.units.length === 0) {\n avcSample = samples[samples.length - 1];\n }\n if (avcSample?.units) {\n const units = avcSample.units;\n lastUnit = units[units.length - 1];\n }\n return lastUnit;\n }\n\n private parseAVCNALu(\n track: DemuxedAvcTrack,\n array: Uint8Array\n ): Array<{\n data: Uint8Array;\n type: number;\n state?: number;\n }> {\n const len = array.byteLength;\n let state = track.naluState || 0;\n const lastState = state;\n const units = [] as Array<{\n data: Uint8Array;\n type: number;\n state?: number;\n }>;\n let i = 0;\n let value;\n let overflow;\n let unitType;\n let lastUnitStart = -1;\n let lastUnitType: number = 0;\n // logger.log('PES:' + Hex.hexDump(array));\n\n if (state === -1) {\n // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet\n lastUnitStart = 0;\n // NALu type is value read from offset 0\n lastUnitType = array[0] & 0x1f;\n state = 0;\n i = 1;\n }\n\n while (i < len) {\n value = array[i++];\n // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case\n if (!state) {\n state = value ? 0 : 1;\n continue;\n }\n if (state === 1) {\n state = value ? 0 : 2;\n continue;\n }\n // here we have state either equal to 2 or 3\n if (!value) {\n state = 3;\n } else if (value === 1) {\n if (lastUnitStart >= 0) {\n const unit = {\n data: array.subarray(lastUnitStart, i - state - 1),\n type: lastUnitType,\n };\n // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);\n units.push(unit);\n } else {\n // lastUnitStart is undefined => this is the first start code found in this PES packet\n // first check if start code delimiter is overlapping between 2 PES packets,\n // ie it started in last packet (lastState not zero)\n // and ended at the beginning of this PES packet (i <= 4 - lastState)\n const lastUnit = this.getLastNalUnit(track.samples);\n if (lastUnit) {\n if (lastState && i <= 4 - lastState) {\n // start delimiter overlapping between PES packets\n // strip start delimiter bytes from the end of last NAL unit\n // check if lastUnit had a state different from zero\n if (lastUnit.state) {\n // strip last bytes\n lastUnit.data = lastUnit.data.subarray(\n 0,\n lastUnit.data.byteLength - lastState\n );\n }\n }\n // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.\n overflow = i - state - 1;\n if (overflow > 0) {\n // logger.log('first NALU found with overflow:' + overflow);\n const tmp = new Uint8Array(lastUnit.data.byteLength + overflow);\n tmp.set(lastUnit.data, 0);\n tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength);\n lastUnit.data = tmp;\n lastUnit.state = 0;\n }\n }\n }\n // check if we can read unit type\n if (i < len) {\n unitType = array[i] & 0x1f;\n // logger.log('find NALU @ offset:' + i + ',type:' + unitType);\n lastUnitStart = i;\n lastUnitType = unitType;\n state = 0;\n } else {\n // not enough byte to read unit type. let's read it on next PES parsing\n state = -1;\n }\n } else {\n state = 0;\n }\n }\n if (lastUnitStart >= 0 && state >= 0) {\n const unit = {\n data: array.subarray(lastUnitStart, len),\n type: lastUnitType,\n state: state,\n };\n units.push(unit);\n // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);\n }\n // no NALu found\n if (units.length === 0) {\n // append pes.data to previous NAL unit\n const lastUnit = this.getLastNalUnit(track.samples);\n if (lastUnit) {\n const tmp = new Uint8Array(lastUnit.data.byteLength + array.byteLength);\n tmp.set(lastUnit.data, 0);\n tmp.set(array, lastUnit.data.byteLength);\n lastUnit.data = tmp;\n }\n }\n track.naluState = state;\n return units;\n }\n\n private parseAACPES(track: DemuxedAudioTrack, pes: PES) {\n let startOffset = 0;\n const aacOverFlow = this.aacOverFlow;\n let data = pes.data;\n if (aacOverFlow) {\n this.aacOverFlow = null;\n const frameMissingBytes = aacOverFlow.missing;\n const sampleLength = aacOverFlow.sample.unit.byteLength;\n // logger.log(`AAC: append overflowing ${sampleLength} bytes to beginning of new PES`);\n if (frameMissingBytes === -1) {\n const tmp = new Uint8Array(sampleLength + data.byteLength);\n tmp.set(aacOverFlow.sample.unit, 0);\n tmp.set(data, sampleLength);\n data = tmp;\n } else {\n const frameOverflowBytes = sampleLength - frameMissingBytes;\n aacOverFlow.sample.unit.set(\n data.subarray(0, frameMissingBytes),\n frameOverflowBytes\n );\n track.samples.push(aacOverFlow.sample);\n startOffset = aacOverFlow.missing;\n }\n }\n // look for ADTS header (0xFFFx)\n let offset: number;\n let len: number;\n for (offset = startOffset, len = data.length; offset < len - 1; offset++) {\n if (ADTS.isHeader(data, offset)) {\n break;\n }\n }\n // if ADTS header does not start straight from the beginning of the PES payload, raise an error\n if (offset !== startOffset) {\n let reason: string;\n const recoverable = offset < len - 1;\n if (recoverable) {\n reason = `AAC PES did not start with ADTS header,offset:${offset}`;\n } else {\n reason = 'No ADTS header found in AAC PES';\n }\n const error = new Error(reason);\n logger.warn(`parsing error: ${reason}`);\n this.observer.emit(Events.ERROR, Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n fatal: false,\n levelRetry: recoverable,\n error,\n reason,\n });\n if (!recoverable) {\n return;\n }\n }\n\n ADTS.initTrackConfig(\n track,\n this.observer,\n data,\n offset,\n this.audioCodec as string\n );\n\n let pts: number;\n if (pes.pts !== undefined) {\n pts = pes.pts;\n } else if (aacOverFlow) {\n // if last AAC frame is overflowing, we should ensure timestamps are contiguous:\n // first sample PTS should be equal to last sample PTS + frameDuration\n const frameDuration = ADTS.getFrameDuration(track.samplerate as number);\n pts = aacOverFlow.sample.pts + frameDuration;\n } else {\n logger.warn('[tsdemuxer]: AAC PES unknown PTS');\n return;\n }\n\n // scan for aac samples\n let frameIndex = 0;\n let frame;\n while (offset < len) {\n frame = ADTS.appendFrame(track, data, offset, pts, frameIndex);\n offset += frame.length;\n if (!frame.missing) {\n frameIndex++;\n for (; offset < len - 1; offset++) {\n if (ADTS.isHeader(data, offset)) {\n break;\n }\n }\n } else {\n this.aacOverFlow = frame;\n break;\n }\n }\n }\n\n private parseMPEGPES(track: DemuxedAudioTrack, pes: PES) {\n const data = pes.data;\n const length = data.length;\n let frameIndex = 0;\n let offset = 0;\n const pts = pes.pts;\n if (pts === undefined) {\n logger.warn('[tsdemuxer]: MPEG PES unknown PTS');\n return;\n }\n\n while (offset < length) {\n if (MpegAudio.isHeader(data, offset)) {\n const frame = MpegAudio.appendFrame(\n track,\n data,\n offset,\n pts,\n frameIndex\n );\n if (frame) {\n offset += frame.length;\n frameIndex++;\n } else {\n // logger.log('Unable to parse Mpeg audio frame');\n break;\n }\n } else {\n // nothing found, keep looking\n offset++;\n }\n }\n }\n\n private parseID3PES(id3Track: DemuxedMetadataTrack, pes: PES) {\n if (pes.pts === undefined) {\n logger.warn('[tsdemuxer]: ID3 PES unknown PTS');\n return;\n }\n const id3Sample = Object.assign({}, pes as Required<PES>, {\n type: this._avcTrack ? MetadataSchema.emsg : MetadataSchema.audioId3,\n duration: Number.POSITIVE_INFINITY,\n });\n id3Track.samples.push(id3Sample);\n }\n}\n\nfunction createAVCSample(\n key: boolean,\n pts: number | undefined,\n dts: number | undefined,\n debug: string\n): ParsedAvcSample {\n return {\n key,\n frame: false,\n pts,\n dts,\n units: [],\n debug,\n length: 0,\n };\n}\n\nfunction parsePID(data: Uint8Array, offset: number): number {\n // pid is a 13-bit field starting at the last bit of TS[1]\n return ((data[offset + 1] & 0x1f) << 8) + data[offset + 2];\n}\n\nfunction parsePAT(data: Uint8Array, offset: number): number {\n // skip the PSI header and parse the first PMT entry\n return ((data[offset + 10] & 0x1f) << 8) | data[offset + 11];\n}\n\nfunction parsePMT(\n data: Uint8Array,\n offset: number,\n typeSupported: TypeSupported,\n isSampleAes: boolean\n) {\n const result = { audio: -1, avc: -1, id3: -1, segmentCodec: 'aac' };\n const sectionLength = ((data[offset + 1] & 0x0f) << 8) | data[offset + 2];\n const tableEnd = offset + 3 + sectionLength - 4;\n // to determine where the table is, we have to figure out how\n // long the program info descriptors are\n const programInfoLength =\n ((data[offset + 10] & 0x0f) << 8) | data[offset + 11];\n // advance the offset to the first entry in the mapping table\n offset += 12 + programInfoLength;\n while (offset < tableEnd) {\n const pid = parsePID(data, offset);\n switch (data[offset]) {\n case 0xcf: // SAMPLE-AES AAC\n if (!isSampleAes) {\n logger.log(\n 'ADTS AAC with AES-128-CBC frame encryption found in unencrypted stream'\n );\n break;\n }\n /* falls through */\n case 0x0f: // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)\n // logger.log('AAC PID:' + pid);\n if (result.audio === -1) {\n result.audio = pid;\n }\n\n break;\n\n // Packetized metadata (ID3)\n case 0x15:\n // logger.log('ID3 PID:' + pid);\n if (result.id3 === -1) {\n result.id3 = pid;\n }\n\n break;\n\n case 0xdb: // SAMPLE-AES AVC\n if (!isSampleAes) {\n logger.log(\n 'H.264 with AES-128-CBC slice encryption found in unencrypted stream'\n );\n break;\n }\n /* falls through */\n case 0x1b: // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)\n // logger.log('AVC PID:' + pid);\n if (result.avc === -1) {\n result.avc = pid;\n }\n\n break;\n\n // ISO/IEC 11172-3 (MPEG-1 audio)\n // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)\n case 0x03:\n case 0x04:\n // logger.log('MPEG PID:' + pid);\n if (typeSupported.mpeg !== true && typeSupported.mp3 !== true) {\n logger.log('MPEG audio found, not supported in this browser');\n } else if (result.audio === -1) {\n result.audio = pid;\n result.segmentCodec = 'mp3';\n }\n break;\n\n case 0x24:\n logger.warn('Unsupported HEVC stream type found');\n break;\n\n default:\n // logger.log('unknown stream type:' + data[offset]);\n break;\n }\n // move to the next table entry\n // skip past the elementary stream descriptors, if present\n offset += (((data[offset + 3] & 0x0f) << 8) | data[offset + 4]) + 5;\n }\n return result;\n}\n\nfunction parsePES(stream: ElementaryStreamData): PES | null {\n let i = 0;\n let frag: Uint8Array;\n let pesLen: number;\n let pesHdrLen: number;\n let pesPts: number | undefined;\n let pesDts: number | undefined;\n const data = stream.data;\n // safety check\n if (!stream || stream.size === 0) {\n return null;\n }\n\n // we might need up to 19 bytes to read PES header\n // if first chunk of data is less than 19 bytes, let's merge it with following ones until we get 19 bytes\n // usually only one merge is needed (and this is rare ...)\n while (data[0].length < 19 && data.length > 1) {\n const newData = new Uint8Array(data[0].length + data[1].length);\n newData.set(data[0]);\n newData.set(data[1], data[0].length);\n data[0] = newData;\n data.splice(1, 1);\n }\n // retrieve PTS/DTS from first fragment\n frag = data[0];\n const pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2];\n if (pesPrefix === 1) {\n pesLen = (frag[4] << 8) + frag[5];\n // if PES parsed length is not zero and greater than total received length, stop parsing. PES might be truncated\n // minus 6 : PES header size\n if (pesLen && pesLen > stream.size - 6) {\n return null;\n }\n\n const pesFlags = frag[7];\n if (pesFlags & 0xc0) {\n /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html\n as PTS / DTS is 33 bit we cannot use bitwise operator in JS,\n as Bitwise operators treat their operands as a sequence of 32 bits */\n pesPts =\n (frag[9] & 0x0e) * 536870912 + // 1 << 29\n (frag[10] & 0xff) * 4194304 + // 1 << 22\n (frag[11] & 0xfe) * 16384 + // 1 << 14\n (frag[12] & 0xff) * 128 + // 1 << 7\n (frag[13] & 0xfe) / 2;\n\n if (pesFlags & 0x40) {\n pesDts =\n (frag[14] & 0x0e) * 536870912 + // 1 << 29\n (frag[15] & 0xff) * 4194304 + // 1 << 22\n (frag[16] & 0xfe) * 16384 + // 1 << 14\n (frag[17] & 0xff) * 128 + // 1 << 7\n (frag[18] & 0xfe) / 2;\n\n if (pesPts - pesDts > 60 * 90000) {\n logger.warn(\n `${Math.round(\n (pesPts - pesDts) / 90000\n )}s delta between PTS and DTS, align them`\n );\n pesPts = pesDts;\n }\n } else {\n pesDts = pesPts;\n }\n }\n pesHdrLen = frag[8];\n // 9 bytes : 6 bytes for PES header + 3 bytes for PES extension\n let payloadStartOffset = pesHdrLen + 9;\n if (stream.size <= payloadStartOffset) {\n return null;\n }\n stream.size -= payloadStartOffset;\n // reassemble PES packet\n const pesData = new Uint8Array(stream.size);\n for (let j = 0, dataLen = data.length; j < dataLen; j++) {\n frag = data[j];\n let len = frag.byteLength;\n if (payloadStartOffset) {\n if (payloadStartOffset > len) {\n // trim full frag if PES header bigger than frag\n payloadStartOffset -= len;\n continue;\n } else {\n // trim partial frag if PES header smaller than frag\n frag = frag.subarray(payloadStartOffset);\n len -= payloadStartOffset;\n payloadStartOffset = 0;\n }\n }\n pesData.set(frag, i);\n i += len;\n }\n if (pesLen) {\n // payload size : remove PES header + PES extension\n pesLen -= pesHdrLen + 3;\n }\n return { data: pesData, pts: pesPts, dts: pesDts, len: pesLen };\n }\n return null;\n}\n\nfunction pushAccessUnit(avcSample: ParsedAvcSample, avcTrack: DemuxedAvcTrack) {\n if (avcSample.units.length && avcSample.frame) {\n // if sample does not have PTS/DTS, patch with last sample PTS/DTS\n if (avcSample.pts === undefined) {\n const samples = avcTrack.samples;\n const nbSamples = samples.length;\n if (nbSamples) {\n const lastSample = samples[nbSamples - 1];\n avcSample.pts = lastSample.pts;\n avcSample.dts = lastSample.dts;\n } else {\n // dropping samples, no timestamp found\n avcTrack.dropped++;\n return;\n }\n }\n avcTrack.samples.push(avcSample as AvcSample);\n }\n if (avcSample.debug.length) {\n logger.log(avcSample.pts + '/' + avcSample.dts + ':' + avcSample.debug);\n }\n}\n\nexport default TSDemuxer;\n","/**\n * AAC helper\n */\n\nclass AAC {\n static getSilentFrame(\n codec?: string,\n channelCount?: number\n ): Uint8Array | undefined {\n switch (codec) {\n case 'mp4a.40.2':\n if (channelCount === 1) {\n return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);\n } else if (channelCount === 2) {\n return new Uint8Array([\n 0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80,\n ]);\n } else if (channelCount === 3) {\n return new Uint8Array([\n 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n 0x00, 0x8e,\n ]);\n } else if (channelCount === 4) {\n return new Uint8Array([\n 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38,\n ]);\n } else if (channelCount === 5) {\n return new Uint8Array([\n 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38,\n ]);\n } else if (channelCount === 6) {\n return new Uint8Array([\n 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,\n 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2,\n 0x00, 0x20, 0x08, 0xe0,\n ]);\n }\n\n break;\n // handle HE-AAC below (mp4a.40.5 / mp4a.40.29)\n default:\n if (channelCount === 1) {\n // ffmpeg -y -f lavfi -i \"aevalsrc=0:d=0.05\" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n return new Uint8Array([\n 0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5e,\n ]);\n } else if (channelCount === 2) {\n // ffmpeg -y -f lavfi -i \"aevalsrc=0|0:d=0.05\" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n return new Uint8Array([\n 0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5e,\n ]);\n } else if (channelCount === 3) {\n // ffmpeg -y -f lavfi -i \"aevalsrc=0|0|0:d=0.05\" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 \"0x%x,\" \"\\n\"' -v output.aac\n return new Uint8Array([\n 0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,\n 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,\n 0x5a, 0x5e,\n ]);\n }\n break;\n }\n return undefined;\n }\n}\n\nexport default AAC;\n","/**\n * Generate MP4 Box\n */\n\ntype HdlrTypes = {\n video: Uint8Array;\n audio: Uint8Array;\n};\n\nconst UINT32_MAX = Math.pow(2, 32) - 1;\n\nclass MP4 {\n public static types: Record<string, number[]>;\n private static HDLR_TYPES: HdlrTypes;\n private static STTS: Uint8Array;\n private static STSC: Uint8Array;\n private static STCO: Uint8Array;\n private static STSZ: Uint8Array;\n private static VMHD: Uint8Array;\n private static SMHD: Uint8Array;\n private static STSD: Uint8Array;\n private static FTYP: Uint8Array;\n private static DINF: Uint8Array;\n\n static init() {\n MP4.types = {\n avc1: [], // codingname\n avcC: [],\n btrt: [],\n dinf: [],\n dref: [],\n esds: [],\n ftyp: [],\n hdlr: [],\n mdat: [],\n mdhd: [],\n mdia: [],\n mfhd: [],\n minf: [],\n moof: [],\n moov: [],\n mp4a: [],\n '.mp3': [],\n mvex: [],\n mvhd: [],\n pasp: [],\n sdtp: [],\n stbl: [],\n stco: [],\n stsc: [],\n stsd: [],\n stsz: [],\n stts: [],\n tfdt: [],\n tfhd: [],\n traf: [],\n trak: [],\n trun: [],\n trex: [],\n tkhd: [],\n vmhd: [],\n smhd: [],\n };\n\n let i: string;\n for (i in MP4.types) {\n if (MP4.types.hasOwnProperty(i)) {\n MP4.types[i] = [\n i.charCodeAt(0),\n i.charCodeAt(1),\n i.charCodeAt(2),\n i.charCodeAt(3),\n ];\n }\n }\n\n const videoHdlr = new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00, // pre_defined\n 0x76,\n 0x69,\n 0x64,\n 0x65, // handler_type: 'vide'\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x56,\n 0x69,\n 0x64,\n 0x65,\n 0x6f,\n 0x48,\n 0x61,\n 0x6e,\n 0x64,\n 0x6c,\n 0x65,\n 0x72,\n 0x00, // name: 'VideoHandler'\n ]);\n\n const audioHdlr = new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00, // pre_defined\n 0x73,\n 0x6f,\n 0x75,\n 0x6e, // handler_type: 'soun'\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x53,\n 0x6f,\n 0x75,\n 0x6e,\n 0x64,\n 0x48,\n 0x61,\n 0x6e,\n 0x64,\n 0x6c,\n 0x65,\n 0x72,\n 0x00, // name: 'SoundHandler'\n ]);\n\n MP4.HDLR_TYPES = {\n video: videoHdlr,\n audio: audioHdlr,\n };\n\n const dref = new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x01, // entry_count\n 0x00,\n 0x00,\n 0x00,\n 0x0c, // entry_size\n 0x75,\n 0x72,\n 0x6c,\n 0x20, // 'url' type\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x01, // entry_flags\n ]);\n\n const stco = new Uint8Array([\n 0x00, // version\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00, // entry_count\n ]);\n\n MP4.STTS = MP4.STSC = MP4.STCO = stco;\n\n MP4.STSZ = new Uint8Array([\n 0x00, // version\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00, // sample_size\n 0x00,\n 0x00,\n 0x00,\n 0x00, // sample_count\n ]);\n MP4.VMHD = new Uint8Array([\n 0x00, // version\n 0x00,\n 0x00,\n 0x01, // flags\n 0x00,\n 0x00, // graphicsmode\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // opcolor\n ]);\n MP4.SMHD = new Uint8Array([\n 0x00, // version\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00, // balance\n 0x00,\n 0x00, // reserved\n ]);\n\n MP4.STSD = new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x01,\n ]); // entry_count\n\n const majorBrand = new Uint8Array([105, 115, 111, 109]); // isom\n const avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1\n const minorVersion = new Uint8Array([0, 0, 0, 1]);\n\n MP4.FTYP = MP4.box(\n MP4.types.ftyp,\n majorBrand,\n minorVersion,\n majorBrand,\n avc1Brand\n );\n MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));\n }\n\n static box(type, ...payload: Uint8Array[]) {\n let size = 8;\n let i = payload.length;\n const len = i;\n // calculate the total size we need to allocate\n while (i--) {\n size += payload[i].byteLength;\n }\n\n const result = new Uint8Array(size);\n result[0] = (size >> 24) & 0xff;\n result[1] = (size >> 16) & 0xff;\n result[2] = (size >> 8) & 0xff;\n result[3] = size & 0xff;\n result.set(type, 4);\n // copy the payload into the result\n for (i = 0, size = 8; i < len; i++) {\n // copy payload[i] array @ offset size\n result.set(payload[i], size);\n size += payload[i].byteLength;\n }\n return result;\n }\n\n static hdlr(type) {\n return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);\n }\n\n static mdat(data) {\n return MP4.box(MP4.types.mdat, data);\n }\n\n static mdhd(timescale, duration) {\n duration *= timescale;\n const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n return MP4.box(\n MP4.types.mdhd,\n new Uint8Array([\n 0x01, // version 1\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x02, // creation_time\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x03, // modification_time\n (timescale >> 24) & 0xff,\n (timescale >> 16) & 0xff,\n (timescale >> 8) & 0xff,\n timescale & 0xff, // timescale\n upperWordDuration >> 24,\n (upperWordDuration >> 16) & 0xff,\n (upperWordDuration >> 8) & 0xff,\n upperWordDuration & 0xff,\n lowerWordDuration >> 24,\n (lowerWordDuration >> 16) & 0xff,\n (lowerWordDuration >> 8) & 0xff,\n lowerWordDuration & 0xff,\n 0x55,\n 0xc4, // 'und' language (undetermined)\n 0x00,\n 0x00,\n ])\n );\n }\n\n static mdia(track) {\n return MP4.box(\n MP4.types.mdia,\n MP4.mdhd(track.timescale, track.duration),\n MP4.hdlr(track.type),\n MP4.minf(track)\n );\n }\n\n static mfhd(sequenceNumber) {\n return MP4.box(\n MP4.types.mfhd,\n new Uint8Array([\n 0x00,\n 0x00,\n 0x00,\n 0x00, // flags\n sequenceNumber >> 24,\n (sequenceNumber >> 16) & 0xff,\n (sequenceNumber >> 8) & 0xff,\n sequenceNumber & 0xff, // sequence_number\n ])\n );\n }\n\n static minf(track) {\n if (track.type === 'audio') {\n return MP4.box(\n MP4.types.minf,\n MP4.box(MP4.types.smhd, MP4.SMHD),\n MP4.DINF,\n MP4.stbl(track)\n );\n } else {\n return MP4.box(\n MP4.types.minf,\n MP4.box(MP4.types.vmhd, MP4.VMHD),\n MP4.DINF,\n MP4.stbl(track)\n );\n }\n }\n\n static moof(sn, baseMediaDecodeTime, track) {\n return MP4.box(\n MP4.types.moof,\n MP4.mfhd(sn),\n MP4.traf(track, baseMediaDecodeTime)\n );\n }\n\n static moov(tracks) {\n let i = tracks.length;\n const boxes: Uint8Array[] = [];\n\n while (i--) {\n boxes[i] = MP4.trak(tracks[i]);\n }\n\n return MP4.box.apply(\n null,\n [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)]\n .concat(boxes)\n .concat(MP4.mvex(tracks))\n );\n }\n\n static mvex(tracks) {\n let i = tracks.length;\n const boxes: Uint8Array[] = [];\n\n while (i--) {\n boxes[i] = MP4.trex(tracks[i]);\n }\n\n return MP4.box.apply(null, [MP4.types.mvex, ...boxes]);\n }\n\n static mvhd(timescale, duration) {\n duration *= timescale;\n const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n const bytes = new Uint8Array([\n 0x01, // version 1\n 0x00,\n 0x00,\n 0x00, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x02, // creation_time\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x03, // modification_time\n (timescale >> 24) & 0xff,\n (timescale >> 16) & 0xff,\n (timescale >> 8) & 0xff,\n timescale & 0xff, // timescale\n upperWordDuration >> 24,\n (upperWordDuration >> 16) & 0xff,\n (upperWordDuration >> 8) & 0xff,\n upperWordDuration & 0xff,\n lowerWordDuration >> 24,\n (lowerWordDuration >> 16) & 0xff,\n (lowerWordDuration >> 8) & 0xff,\n lowerWordDuration & 0xff,\n 0x00,\n 0x01,\n 0x00,\n 0x00, // 1.0 rate\n 0x01,\n 0x00, // 1.0 volume\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x40,\n 0x00,\n 0x00,\n 0x00, // transformation: unity matrix\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // pre_defined\n 0xff,\n 0xff,\n 0xff,\n 0xff, // next_track_ID\n ]);\n return MP4.box(MP4.types.mvhd, bytes);\n }\n\n static sdtp(track) {\n const samples = track.samples || [];\n const bytes = new Uint8Array(4 + samples.length);\n let i;\n let flags;\n // leave the full box header (4 bytes) all zero\n // write the sample table\n for (i = 0; i < samples.length; i++) {\n flags = samples[i].flags;\n bytes[i + 4] =\n (flags.dependsOn << 4) |\n (flags.isDependedOn << 2) |\n flags.hasRedundancy;\n }\n\n return MP4.box(MP4.types.sdtp, bytes);\n }\n\n static stbl(track) {\n return MP4.box(\n MP4.types.stbl,\n MP4.stsd(track),\n MP4.box(MP4.types.stts, MP4.STTS),\n MP4.box(MP4.types.stsc, MP4.STSC),\n MP4.box(MP4.types.stsz, MP4.STSZ),\n MP4.box(MP4.types.stco, MP4.STCO)\n );\n }\n\n static avc1(track) {\n let sps: number[] = [];\n let pps: number[] = [];\n let i;\n let data;\n let len;\n // assemble the SPSs\n\n for (i = 0; i < track.sps.length; i++) {\n data = track.sps[i];\n len = data.byteLength;\n sps.push((len >>> 8) & 0xff);\n sps.push(len & 0xff);\n\n // SPS\n sps = sps.concat(Array.prototype.slice.call(data));\n }\n\n // assemble the PPSs\n for (i = 0; i < track.pps.length; i++) {\n data = track.pps[i];\n len = data.byteLength;\n pps.push((len >>> 8) & 0xff);\n pps.push(len & 0xff);\n\n pps = pps.concat(Array.prototype.slice.call(data));\n }\n\n const avcc = MP4.box(\n MP4.types.avcC,\n new Uint8Array(\n [\n 0x01, // version\n sps[3], // profile\n sps[4], // profile compat\n sps[5], // level\n 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes\n 0xe0 | track.sps.length, // 3bit reserved (111) + numOfSequenceParameterSets\n ]\n .concat(sps)\n .concat([\n track.pps.length, // numOfPictureParameterSets\n ])\n .concat(pps)\n )\n ); // \"PPS\"\n const width = track.width;\n const height = track.height;\n const hSpacing = track.pixelRatio[0];\n const vSpacing = track.pixelRatio[1];\n\n return MP4.box(\n MP4.types.avc1,\n new Uint8Array([\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01, // data_reference_index\n 0x00,\n 0x00, // pre_defined\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // pre_defined\n (width >> 8) & 0xff,\n width & 0xff, // width\n (height >> 8) & 0xff,\n height & 0xff, // height\n 0x00,\n 0x48,\n 0x00,\n 0x00, // horizresolution\n 0x00,\n 0x48,\n 0x00,\n 0x00, // vertresolution\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01, // frame_count\n 0x12,\n 0x64,\n 0x61,\n 0x69,\n 0x6c, // dailymotion/hls.js\n 0x79,\n 0x6d,\n 0x6f,\n 0x74,\n 0x69,\n 0x6f,\n 0x6e,\n 0x2f,\n 0x68,\n 0x6c,\n 0x73,\n 0x2e,\n 0x6a,\n 0x73,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // compressorname\n 0x00,\n 0x18, // depth = 24\n 0x11,\n 0x11,\n ]), // pre_defined = -1\n avcc,\n MP4.box(\n MP4.types.btrt,\n new Uint8Array([\n 0x00,\n 0x1c,\n 0x9c,\n 0x80, // bufferSizeDB\n 0x00,\n 0x2d,\n 0xc6,\n 0xc0, // maxBitrate\n 0x00,\n 0x2d,\n 0xc6,\n 0xc0,\n ])\n ), // avgBitrate\n MP4.box(\n MP4.types.pasp,\n new Uint8Array([\n hSpacing >> 24, // hSpacing\n (hSpacing >> 16) & 0xff,\n (hSpacing >> 8) & 0xff,\n hSpacing & 0xff,\n vSpacing >> 24, // vSpacing\n (vSpacing >> 16) & 0xff,\n (vSpacing >> 8) & 0xff,\n vSpacing & 0xff,\n ])\n )\n );\n }\n\n static esds(track) {\n const configlen = track.config.length;\n return new Uint8Array(\n [\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n\n 0x03, // descriptor_type\n 0x17 + configlen, // length\n 0x00,\n 0x01, // es_id\n 0x00, // stream_priority\n\n 0x04, // descriptor_type\n 0x0f + configlen, // length\n 0x40, // codec : mpeg4_audio\n 0x15, // stream_type\n 0x00,\n 0x00,\n 0x00, // buffer_size\n 0x00,\n 0x00,\n 0x00,\n 0x00, // maxBitrate\n 0x00,\n 0x00,\n 0x00,\n 0x00, // avgBitrate\n\n 0x05, // descriptor_type\n ]\n .concat([configlen])\n .concat(track.config)\n .concat([0x06, 0x01, 0x02])\n ); // GASpecificConfig)); // length + audio config descriptor\n }\n\n static mp4a(track) {\n const samplerate = track.samplerate;\n return MP4.box(\n MP4.types.mp4a,\n new Uint8Array([\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01, // data_reference_index\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n track.channelCount, // channelcount\n 0x00,\n 0x10, // sampleSize:16bits\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved2\n (samplerate >> 8) & 0xff,\n samplerate & 0xff, //\n 0x00,\n 0x00,\n ]),\n MP4.box(MP4.types.esds, MP4.esds(track))\n );\n }\n\n static mp3(track) {\n const samplerate = track.samplerate;\n return MP4.box(\n MP4.types['.mp3'],\n new Uint8Array([\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01, // data_reference_index\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n track.channelCount, // channelcount\n 0x00,\n 0x10, // sampleSize:16bits\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved2\n (samplerate >> 8) & 0xff,\n samplerate & 0xff, //\n 0x00,\n 0x00,\n ])\n );\n }\n\n static stsd(track) {\n if (track.type === 'audio') {\n if (track.segmentCodec === 'mp3' && track.codec === 'mp3') {\n return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track));\n }\n\n return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));\n } else {\n return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));\n }\n }\n\n static tkhd(track) {\n const id = track.id;\n const duration = track.duration * track.timescale;\n const width = track.width;\n const height = track.height;\n const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));\n const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));\n return MP4.box(\n MP4.types.tkhd,\n new Uint8Array([\n 0x01, // version 1\n 0x00,\n 0x00,\n 0x07, // flags\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x02, // creation_time\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x03, // modification_time\n (id >> 24) & 0xff,\n (id >> 16) & 0xff,\n (id >> 8) & 0xff,\n id & 0xff, // track_ID\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n upperWordDuration >> 24,\n (upperWordDuration >> 16) & 0xff,\n (upperWordDuration >> 8) & 0xff,\n upperWordDuration & 0xff,\n lowerWordDuration >> 24,\n (lowerWordDuration >> 16) & 0xff,\n (lowerWordDuration >> 8) & 0xff,\n lowerWordDuration & 0xff,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x00, // layer\n 0x00,\n 0x00, // alternate_group\n 0x00,\n 0x00, // non-audio track volume\n 0x00,\n 0x00, // reserved\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x40,\n 0x00,\n 0x00,\n 0x00, // transformation: unity matrix\n (width >> 8) & 0xff,\n width & 0xff,\n 0x00,\n 0x00, // width\n (height >> 8) & 0xff,\n height & 0xff,\n 0x00,\n 0x00, // height\n ])\n );\n }\n\n static traf(track, baseMediaDecodeTime) {\n const sampleDependencyTable = MP4.sdtp(track);\n const id = track.id;\n const upperWordBaseMediaDecodeTime = Math.floor(\n baseMediaDecodeTime / (UINT32_MAX + 1)\n );\n const lowerWordBaseMediaDecodeTime = Math.floor(\n baseMediaDecodeTime % (UINT32_MAX + 1)\n );\n return MP4.box(\n MP4.types.traf,\n MP4.box(\n MP4.types.tfhd,\n new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n id >> 24,\n (id >> 16) & 0xff,\n (id >> 8) & 0xff,\n id & 0xff, // track_ID\n ])\n ),\n MP4.box(\n MP4.types.tfdt,\n new Uint8Array([\n 0x01, // version 1\n 0x00,\n 0x00,\n 0x00, // flags\n upperWordBaseMediaDecodeTime >> 24,\n (upperWordBaseMediaDecodeTime >> 16) & 0xff,\n (upperWordBaseMediaDecodeTime >> 8) & 0xff,\n upperWordBaseMediaDecodeTime & 0xff,\n lowerWordBaseMediaDecodeTime >> 24,\n (lowerWordBaseMediaDecodeTime >> 16) & 0xff,\n (lowerWordBaseMediaDecodeTime >> 8) & 0xff,\n lowerWordBaseMediaDecodeTime & 0xff,\n ])\n ),\n MP4.trun(\n track,\n sampleDependencyTable.length +\n 16 + // tfhd\n 20 + // tfdt\n 8 + // traf header\n 16 + // mfhd\n 8 + // moof header\n 8\n ), // mdat header\n sampleDependencyTable\n );\n }\n\n /**\n * Generate a track box.\n * @param track a track definition\n */\n static trak(track) {\n track.duration = track.duration || 0xffffffff;\n return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));\n }\n\n static trex(track) {\n const id = track.id;\n return MP4.box(\n MP4.types.trex,\n new Uint8Array([\n 0x00, // version 0\n 0x00,\n 0x00,\n 0x00, // flags\n id >> 24,\n (id >> 16) & 0xff,\n (id >> 8) & 0xff,\n id & 0xff, // track_ID\n 0x00,\n 0x00,\n 0x00,\n 0x01, // default_sample_description_index\n 0x00,\n 0x00,\n 0x00,\n 0x00, // default_sample_duration\n 0x00,\n 0x00,\n 0x00,\n 0x00, // default_sample_size\n 0x00,\n 0x01,\n 0x00,\n 0x01, // default_sample_flags\n ])\n );\n }\n\n static trun(track, offset) {\n const samples = track.samples || [];\n const len = samples.length;\n const arraylen = 12 + 16 * len;\n const array = new Uint8Array(arraylen);\n let i;\n let sample;\n let duration;\n let size;\n let flags;\n let cts;\n offset += 8 + arraylen;\n array.set(\n [\n track.type === 'video' ? 0x01 : 0x00, // version 1 for video with signed-int sample_composition_time_offset\n 0x00,\n 0x0f,\n 0x01, // flags\n (len >>> 24) & 0xff,\n (len >>> 16) & 0xff,\n (len >>> 8) & 0xff,\n len & 0xff, // sample_count\n (offset >>> 24) & 0xff,\n (offset >>> 16) & 0xff,\n (offset >>> 8) & 0xff,\n offset & 0xff, // data_offset\n ],\n 0\n );\n for (i = 0; i < len; i++) {\n sample = samples[i];\n duration = sample.duration;\n size = sample.size;\n flags = sample.flags;\n cts = sample.cts;\n array.set(\n [\n (duration >>> 24) & 0xff,\n (duration >>> 16) & 0xff,\n (duration >>> 8) & 0xff,\n duration & 0xff, // sample_duration\n (size >>> 24) & 0xff,\n (size >>> 16) & 0xff,\n (size >>> 8) & 0xff,\n size & 0xff, // sample_size\n (flags.isLeading << 2) | flags.dependsOn,\n (flags.isDependedOn << 6) |\n (flags.hasRedundancy << 4) |\n (flags.paddingValue << 1) |\n flags.isNonSync,\n flags.degradPrio & (0xf0 << 8),\n flags.degradPrio & 0x0f, // sample_flags\n (cts >>> 24) & 0xff,\n (cts >>> 16) & 0xff,\n (cts >>> 8) & 0xff,\n cts & 0xff, // sample_composition_time_offset\n ],\n 12 + 16 * i\n );\n }\n return MP4.box(MP4.types.trun, array);\n }\n\n static initSegment(tracks) {\n if (!MP4.types) {\n MP4.init();\n }\n\n const movie = MP4.moov(tracks);\n const result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);\n result.set(MP4.FTYP);\n result.set(movie, MP4.FTYP.byteLength);\n return result;\n }\n}\n\nexport default MP4;\n","const MPEG_TS_CLOCK_FREQ_HZ = 90000;\n\nexport type RationalTimestamp = {\n baseTime: number; // ticks\n timescale: number; // ticks per second\n};\n\nexport function toTimescaleFromBase(\n baseTime: number,\n destScale: number,\n srcBase: number = 1,\n round: boolean = false\n): number {\n const result = baseTime * destScale * srcBase; // equivalent to `(value * scale) / (1 / base)`\n return round ? Math.round(result) : result;\n}\n\nexport function toTimescaleFromScale(\n baseTime: number,\n destScale: number,\n srcScale: number = 1,\n round: boolean = false\n): number {\n return toTimescaleFromBase(baseTime, destScale, 1 / srcScale, round);\n}\n\nexport function toMsFromMpegTsClock(\n baseTime: number,\n round: boolean = false\n): number {\n return toTimescaleFromBase(baseTime, 1000, 1 / MPEG_TS_CLOCK_FREQ_HZ, round);\n}\n\nexport function toMpegTsClockFromTimescale(\n baseTime: number,\n srcScale: number = 1\n): number {\n return toTimescaleFromBase(baseTime, MPEG_TS_CLOCK_FREQ_HZ, 1 / srcScale);\n}\n","import AAC from './aac-helper';\nimport MP4 from './mp4-generator';\nimport type { HlsEventEmitter } from '../events';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { logger } from '../utils/logger';\nimport {\n InitSegmentData,\n Remuxer,\n RemuxerResult,\n RemuxedMetadata,\n RemuxedTrack,\n RemuxedUserdata,\n} from '../types/remuxer';\nimport { PlaylistLevelType } from '../types/loader';\nimport {\n RationalTimestamp,\n toMsFromMpegTsClock,\n} from '../utils/timescale-conversion';\nimport type {\n AudioSample,\n AvcSample,\n DemuxedAudioTrack,\n DemuxedAvcTrack,\n DemuxedMetadataTrack,\n DemuxedUserdataTrack,\n} from '../types/demuxer';\nimport type { TrackSet } from '../types/track';\nimport type { SourceBufferName } from '../types/buffer';\nimport type { Fragment } from '../loader/fragment';\nimport type { HlsConfig } from '../config';\n\nconst MAX_SILENT_FRAME_DURATION = 10 * 1000; // 10 seconds\nconst AAC_SAMPLES_PER_FRAME = 1024;\nconst MPEG_AUDIO_SAMPLE_PER_FRAME = 1152;\n\nlet chromeVersion: number | null = null;\nlet safariWebkitVersion: number | null = null;\n\nexport default class MP4Remuxer implements Remuxer {\n private observer: HlsEventEmitter;\n private config: HlsConfig;\n private typeSupported: any;\n private ISGenerated: boolean = false;\n private _initPTS: RationalTimestamp | null = null;\n private _initDTS: RationalTimestamp | null = null;\n private nextAvcDts: number | null = null;\n private nextAudioPts: number | null = null;\n private videoSampleDuration: number | null = null;\n private isAudioContiguous: boolean = false;\n private isVideoContiguous: boolean = false;\n\n constructor(\n observer: HlsEventEmitter,\n config: HlsConfig,\n typeSupported,\n vendor = ''\n ) {\n this.observer = observer;\n this.config = config;\n this.typeSupported = typeSupported;\n this.ISGenerated = false;\n\n if (chromeVersion === null) {\n const userAgent = navigator.userAgent || '';\n const result = userAgent.match(/Chrome\\/(\\d+)/i);\n chromeVersion = result ? parseInt(result[1]) : 0;\n }\n if (safariWebkitVersion === null) {\n const result = navigator.userAgent.match(/Safari\\/(\\d+)/i);\n safariWebkitVersion = result ? parseInt(result[1]) : 0;\n }\n }\n\n destroy() {}\n\n resetTimeStamp(defaultTimeStamp: RationalTimestamp | null) {\n logger.log('[mp4-remuxer]: initPTS & initDTS reset');\n this._initPTS = this._initDTS = defaultTimeStamp;\n }\n\n resetNextTimestamp() {\n logger.log('[mp4-remuxer]: reset next timestamp');\n this.isVideoContiguous = false;\n this.isAudioContiguous = false;\n }\n\n resetInitSegment() {\n logger.log('[mp4-remuxer]: ISGenerated flag reset');\n this.ISGenerated = false;\n }\n\n getVideoStartPts(videoSamples) {\n let rolloverDetected = false;\n const startPTS = videoSamples.reduce((minPTS, sample) => {\n const delta = sample.pts - minPTS;\n if (delta < -4294967296) {\n // 2^32, see PTSNormalize for reasoning, but we're hitting a rollover here, and we don't want that to impact the timeOffset calculation\n rolloverDetected = true;\n return normalizePts(minPTS, sample.pts);\n } else if (delta > 0) {\n return minPTS;\n } else {\n return sample.pts;\n }\n }, videoSamples[0].pts);\n if (rolloverDetected) {\n logger.debug('PTS rollover detected');\n }\n return startPTS;\n }\n\n remux(\n audioTrack: DemuxedAudioTrack,\n videoTrack: DemuxedAvcTrack,\n id3Track: DemuxedMetadataTrack,\n textTrack: DemuxedUserdataTrack,\n timeOffset: number,\n accurateTimeOffset: boolean,\n flush: boolean,\n playlistType: PlaylistLevelType\n ): RemuxerResult {\n let video: RemuxedTrack | undefined;\n let audio: RemuxedTrack | undefined;\n let initSegment: InitSegmentData | undefined;\n let text: RemuxedUserdata | undefined;\n let id3: RemuxedMetadata | undefined;\n let independent: boolean | undefined;\n let audioTimeOffset = timeOffset;\n let videoTimeOffset = timeOffset;\n\n // If we're remuxing audio and video progressively, wait until we've received enough samples for each track before proceeding.\n // This is done to synchronize the audio and video streams. We know if the current segment will have samples if the \"pid\"\n // parameter is greater than -1. The pid is set when the PMT is parsed, which contains the tracks list.\n // However, if the initSegment has already been generated, or we've reached the end of a segment (flush),\n // then we can remux one track without waiting for the other.\n const hasAudio = audioTrack.pid > -1;\n const hasVideo = videoTrack.pid > -1;\n const length = videoTrack.samples.length;\n const enoughAudioSamples = audioTrack.samples.length > 0;\n const enoughVideoSamples = (flush && length > 0) || length > 1;\n const canRemuxAvc =\n ((!hasAudio || enoughAudioSamples) &&\n (!hasVideo || enoughVideoSamples)) ||\n this.ISGenerated ||\n flush;\n\n if (canRemuxAvc) {\n if (!this.ISGenerated) {\n initSegment = this.generateIS(\n audioTrack,\n videoTrack,\n timeOffset,\n accurateTimeOffset\n );\n }\n\n const isVideoContiguous = this.isVideoContiguous;\n let firstKeyFrameIndex = -1;\n let firstKeyFramePTS;\n\n if (enoughVideoSamples) {\n firstKeyFrameIndex = findKeyframeIndex(videoTrack.samples);\n if (!isVideoContiguous && this.config.forceKeyFrameOnDiscontinuity) {\n independent = true;\n if (firstKeyFrameIndex > 0) {\n logger.warn(\n `[mp4-remuxer]: Dropped ${firstKeyFrameIndex} out of ${length} video samples due to a missing keyframe`\n );\n const startPTS = this.getVideoStartPts(videoTrack.samples);\n videoTrack.samples = videoTrack.samples.slice(firstKeyFrameIndex);\n videoTrack.dropped += firstKeyFrameIndex;\n videoTimeOffset +=\n (videoTrack.samples[0].pts - startPTS) /\n videoTrack.inputTimeScale;\n firstKeyFramePTS = videoTimeOffset;\n } else if (firstKeyFrameIndex === -1) {\n logger.warn(\n `[mp4-remuxer]: No keyframe found out of ${length} video samples`\n );\n independent = false;\n }\n }\n }\n\n if (this.ISGenerated) {\n if (enoughAudioSamples && enoughVideoSamples) {\n // timeOffset is expected to be the offset of the first timestamp of this fragment (first DTS)\n // if first audio DTS is not aligned with first video DTS then we need to take that into account\n // when providing timeOffset to remuxAudio / remuxVideo. if we don't do that, there might be a permanent / small\n // drift between audio and video streams\n const startPTS = this.getVideoStartPts(videoTrack.samples);\n const tsDelta =\n normalizePts(audioTrack.samples[0].pts, startPTS) - startPTS;\n const audiovideoTimestampDelta = tsDelta / videoTrack.inputTimeScale;\n audioTimeOffset += Math.max(0, audiovideoTimestampDelta);\n videoTimeOffset += Math.max(0, -audiovideoTimestampDelta);\n }\n\n // Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is calculated in remuxAudio.\n if (enoughAudioSamples) {\n // if initSegment was generated without audio samples, regenerate it again\n if (!audioTrack.samplerate) {\n logger.warn(\n '[mp4-remuxer]: regenerate InitSegment as audio detected'\n );\n initSegment = this.generateIS(\n audioTrack,\n videoTrack,\n timeOffset,\n accurateTimeOffset\n );\n }\n audio = this.remuxAudio(\n audioTrack,\n audioTimeOffset,\n this.isAudioContiguous,\n accurateTimeOffset,\n hasVideo ||\n enoughVideoSamples ||\n playlistType === PlaylistLevelType.AUDIO\n ? videoTimeOffset\n : undefined\n );\n if (enoughVideoSamples) {\n const audioTrackLength = audio ? audio.endPTS - audio.startPTS : 0;\n // if initSegment was generated without video samples, regenerate it again\n if (!videoTrack.inputTimeScale) {\n logger.warn(\n '[mp4-remuxer]: regenerate InitSegment as video detected'\n );\n initSegment = this.generateIS(\n audioTrack,\n videoTrack,\n timeOffset,\n accurateTimeOffset\n );\n }\n video = this.remuxVideo(\n videoTrack,\n videoTimeOffset,\n isVideoContiguous,\n audioTrackLength\n );\n }\n } else if (enoughVideoSamples) {\n video = this.remuxVideo(\n videoTrack,\n videoTimeOffset,\n isVideoContiguous,\n 0\n );\n }\n if (video) {\n video.firstKeyFrame = firstKeyFrameIndex;\n video.independent = firstKeyFrameIndex !== -1;\n video.firstKeyFramePTS = firstKeyFramePTS;\n }\n }\n }\n\n // Allow ID3 and text to remux, even if more audio/video samples are required\n if (this.ISGenerated && this._initPTS && this._initDTS) {\n if (id3Track.samples.length) {\n id3 = flushTextTrackMetadataCueSamples(\n id3Track,\n timeOffset,\n this._initPTS,\n this._initDTS\n );\n }\n\n if (textTrack.samples.length) {\n text = flushTextTrackUserdataCueSamples(\n textTrack,\n timeOffset,\n this._initPTS\n );\n }\n }\n\n return {\n audio,\n video,\n initSegment,\n independent,\n text,\n id3,\n };\n }\n\n generateIS(\n audioTrack: DemuxedAudioTrack,\n videoTrack: DemuxedAvcTrack,\n timeOffset: number,\n accurateTimeOffset: boolean\n ): InitSegmentData | undefined {\n const audioSamples = audioTrack.samples;\n const videoSamples = videoTrack.samples;\n const typeSupported = this.typeSupported;\n const tracks: TrackSet = {};\n const _initPTS = this._initPTS;\n let computePTSDTS = !_initPTS || accurateTimeOffset;\n let container = 'audio/mp4';\n let initPTS: number | undefined;\n let initDTS: number | undefined;\n let timescale: number | undefined;\n\n if (computePTSDTS) {\n initPTS = initDTS = Infinity;\n }\n\n if (audioTrack.config && audioSamples.length) {\n // let's use audio sampling rate as MP4 time scale.\n // rationale is that there is a integer nb of audio frames per audio sample (1024 for AAC)\n // using audio sampling rate here helps having an integer MP4 frame duration\n // this avoids potential rounding issue and AV sync issue\n audioTrack.timescale = audioTrack.samplerate;\n switch (audioTrack.segmentCodec) {\n case 'mp3':\n if (typeSupported.mpeg) {\n // Chrome and Safari\n container = 'audio/mpeg';\n audioTrack.codec = '';\n } else if (typeSupported.mp3) {\n // Firefox\n audioTrack.codec = 'mp3';\n }\n break;\n }\n tracks.audio = {\n id: 'audio',\n container: container,\n codec: audioTrack.codec,\n initSegment:\n audioTrack.segmentCodec === 'mp3' && typeSupported.mpeg\n ? new Uint8Array(0)\n : MP4.initSegment([audioTrack]),\n metadata: {\n channelCount: audioTrack.channelCount,\n },\n };\n if (computePTSDTS) {\n timescale = audioTrack.inputTimeScale;\n if (!_initPTS || timescale !== _initPTS.timescale) {\n // remember first PTS of this demuxing context. for audio, PTS = DTS\n initPTS = initDTS =\n audioSamples[0].pts - Math.round(timescale * timeOffset);\n } else {\n computePTSDTS = false;\n }\n }\n }\n\n if (videoTrack.sps && videoTrack.pps && videoSamples.length) {\n // let's use input time scale as MP4 video timescale\n // we use input time scale straight away to avoid rounding issues on frame duration / cts computation\n videoTrack.timescale = videoTrack.inputTimeScale;\n tracks.video = {\n id: 'main',\n container: 'video/mp4',\n codec: videoTrack.codec,\n initSegment: MP4.initSegment([videoTrack]),\n metadata: {\n width: videoTrack.width,\n height: videoTrack.height,\n },\n };\n if (computePTSDTS) {\n timescale = videoTrack.inputTimeScale;\n if (!_initPTS || timescale !== _initPTS.timescale) {\n const startPTS = this.getVideoStartPts(videoSamples);\n const startOffset = Math.round(timescale * timeOffset);\n initDTS = Math.min(\n initDTS as number,\n normalizePts(videoSamples[0].dts, startPTS) - startOffset\n );\n initPTS = Math.min(initPTS as number, startPTS - startOffset);\n } else {\n computePTSDTS = false;\n }\n }\n }\n\n if (Object.keys(tracks).length) {\n this.ISGenerated = true;\n if (computePTSDTS) {\n this._initPTS = {\n baseTime: initPTS as number,\n timescale: timescale as number,\n };\n this._initDTS = {\n baseTime: initDTS as number,\n timescale: timescale as number,\n };\n } else {\n initPTS = timescale = undefined;\n }\n\n return {\n tracks,\n initPTS,\n timescale,\n };\n }\n }\n\n remuxVideo(\n track: DemuxedAvcTrack,\n timeOffset: number,\n contiguous: boolean,\n audioTrackLength: number\n ): RemuxedTrack | undefined {\n const timeScale: number = track.inputTimeScale;\n const inputSamples: Array<AvcSample> = track.samples;\n const outputSamples: Array<Mp4Sample> = [];\n const nbSamples = inputSamples.length;\n const initPTS = this._initPTS as RationalTimestamp;\n let nextAvcDts = this.nextAvcDts;\n let offset = 8;\n let mp4SampleDuration = this.videoSampleDuration;\n let firstDTS;\n let lastDTS;\n let minPTS: number = Number.POSITIVE_INFINITY;\n let maxPTS: number = Number.NEGATIVE_INFINITY;\n let sortSamples = false;\n\n // if parsed fragment is contiguous with last one, let's use last DTS value as reference\n if (!contiguous || nextAvcDts === null) {\n const pts = timeOffset * timeScale;\n const cts =\n inputSamples[0].pts -\n normalizePts(inputSamples[0].dts, inputSamples[0].pts);\n // if not contiguous, let's use target timeOffset\n nextAvcDts = pts - cts;\n }\n\n // PTS is coded on 33bits, and can loop from -2^32 to 2^32\n // PTSNormalize will make PTS/DTS value monotonic, we use last known DTS value as reference value\n const initTime = (initPTS.baseTime * timeScale) / initPTS.timescale;\n for (let i = 0; i < nbSamples; i++) {\n const sample = inputSamples[i];\n sample.pts = normalizePts(sample.pts - initTime, nextAvcDts);\n sample.dts = normalizePts(sample.dts - initTime, nextAvcDts);\n if (sample.dts < inputSamples[i > 0 ? i - 1 : i].dts) {\n sortSamples = true;\n }\n }\n\n // sort video samples by DTS then PTS then demux id order\n if (sortSamples) {\n inputSamples.sort(function (a, b) {\n const deltadts = a.dts - b.dts;\n const deltapts = a.pts - b.pts;\n return deltadts || deltapts;\n });\n }\n\n // Get first/last DTS\n firstDTS = inputSamples[0].dts;\n lastDTS = inputSamples[inputSamples.length - 1].dts;\n\n // Sample duration (as expected by trun MP4 boxes), should be the delta between sample DTS\n // set this constant duration as being the avg delta between consecutive DTS.\n const inputDuration = lastDTS - firstDTS;\n const averageSampleDuration = inputDuration\n ? Math.round(inputDuration / (nbSamples - 1))\n : mp4SampleDuration || track.inputTimeScale / 30;\n\n // if fragment are contiguous, detect hole/overlapping between fragments\n if (contiguous) {\n // check timestamp continuity across consecutive fragments (this is to remove inter-fragment gap/hole)\n const delta = firstDTS - nextAvcDts;\n const foundHole = delta > averageSampleDuration;\n const foundOverlap = delta < -1;\n if (foundHole || foundOverlap) {\n if (foundHole) {\n logger.warn(\n `AVC: ${toMsFromMpegTsClock(\n delta,\n true\n )} ms (${delta}dts) hole between fragments detected, filling it`\n );\n } else {\n logger.warn(\n `AVC: ${toMsFromMpegTsClock(\n -delta,\n true\n )} ms (${delta}dts) overlapping between fragments detected`\n );\n }\n if (!foundOverlap || nextAvcDts >= inputSamples[0].pts) {\n firstDTS = nextAvcDts;\n const firstPTS = inputSamples[0].pts - delta;\n inputSamples[0].dts = firstDTS;\n inputSamples[0].pts = firstPTS;\n logger.log(\n `Video: First PTS/DTS adjusted: ${toMsFromMpegTsClock(\n firstPTS,\n true\n )}/${toMsFromMpegTsClock(\n firstDTS,\n true\n )}, delta: ${toMsFromMpegTsClock(delta, true)} ms`\n );\n }\n }\n }\n\n firstDTS = Math.max(0, firstDTS);\n\n let nbNalu = 0;\n let naluLen = 0;\n for (let i = 0; i < nbSamples; i++) {\n // compute total/avc sample length and nb of NAL units\n const sample = inputSamples[i];\n const units = sample.units;\n const nbUnits = units.length;\n let sampleLen = 0;\n for (let j = 0; j < nbUnits; j++) {\n sampleLen += units[j].data.length;\n }\n\n naluLen += sampleLen;\n nbNalu += nbUnits;\n sample.length = sampleLen;\n\n // ensure sample monotonic DTS\n sample.dts = Math.max(sample.dts, firstDTS);\n\n minPTS = Math.min(sample.pts, minPTS);\n maxPTS = Math.max(sample.pts, maxPTS);\n }\n lastDTS = inputSamples[nbSamples - 1].dts;\n\n /* concatenate the video data and construct the mdat in place\n (need 8 more bytes to fill length and mpdat type) */\n const mdatSize = naluLen + 4 * nbNalu + 8;\n let mdat;\n try {\n mdat = new Uint8Array(mdatSize);\n } catch (err) {\n this.observer.emit(Events.ERROR, Events.ERROR, {\n type: ErrorTypes.MUX_ERROR,\n details: ErrorDetails.REMUX_ALLOC_ERROR,\n fatal: false,\n error: err,\n bytes: mdatSize,\n reason: `fail allocating video mdat ${mdatSize}`,\n });\n return;\n }\n const view = new DataView(mdat.buffer);\n view.setUint32(0, mdatSize);\n mdat.set(MP4.types.mdat, 4);\n\n let stretchedLastFrame = false;\n let minDtsDelta = Number.POSITIVE_INFINITY;\n let minPtsDelta = Number.POSITIVE_INFINITY;\n let maxDtsDelta = Number.NEGATIVE_INFINITY;\n let maxPtsDelta = Number.NEGATIVE_INFINITY;\n for (let i = 0; i < nbSamples; i++) {\n const avcSample = inputSamples[i];\n const avcSampleUnits = avcSample.units;\n let mp4SampleLength = 0;\n // convert NALU bitstream to MP4 format (prepend NALU with size field)\n for (let j = 0, nbUnits = avcSampleUnits.length; j < nbUnits; j++) {\n const unit = avcSampleUnits[j];\n const unitData = unit.data;\n const unitDataLen = unit.data.byteLength;\n view.setUint32(offset, unitDataLen);\n offset += 4;\n mdat.set(unitData, offset);\n offset += unitDataLen;\n mp4SampleLength += 4 + unitDataLen;\n }\n\n // expected sample duration is the Decoding Timestamp diff of consecutive samples\n let ptsDelta;\n if (i < nbSamples - 1) {\n mp4SampleDuration = inputSamples[i + 1].dts - avcSample.dts;\n ptsDelta = inputSamples[i + 1].pts - avcSample.pts;\n } else {\n const config = this.config;\n const lastFrameDuration =\n i > 0\n ? avcSample.dts - inputSamples[i - 1].dts\n : averageSampleDuration;\n ptsDelta =\n i > 0\n ? avcSample.pts - inputSamples[i - 1].pts\n : averageSampleDuration;\n if (config.stretchShortVideoTrack && this.nextAudioPts !== null) {\n // In some cases, a segment's audio track duration may exceed the video track duration.\n // Since we've already remuxed audio, and we know how long the audio track is, we look to\n // see if the delta to the next segment is longer than maxBufferHole.\n // If so, playback would potentially get stuck, so we artificially inflate\n // the duration of the last frame to minimize any potential gap between segments.\n const gapTolerance = Math.floor(config.maxBufferHole * timeScale);\n const deltaToFrameEnd =\n (audioTrackLength\n ? minPTS + audioTrackLength * timeScale\n : this.nextAudioPts) - avcSample.pts;\n if (deltaToFrameEnd > gapTolerance) {\n // We subtract lastFrameDuration from deltaToFrameEnd to try to prevent any video\n // frame overlap. maxBufferHole should be >> lastFrameDuration anyway.\n mp4SampleDuration = deltaToFrameEnd - lastFrameDuration;\n if (mp4SampleDuration < 0) {\n mp4SampleDuration = lastFrameDuration;\n } else {\n stretchedLastFrame = true;\n }\n logger.log(\n `[mp4-remuxer]: It is approximately ${\n deltaToFrameEnd / 90\n } ms to the next segment; using duration ${\n mp4SampleDuration / 90\n } ms for the last video frame.`\n );\n } else {\n mp4SampleDuration = lastFrameDuration;\n }\n } else {\n mp4SampleDuration = lastFrameDuration;\n }\n }\n const compositionTimeOffset = Math.round(avcSample.pts - avcSample.dts);\n minDtsDelta = Math.min(minDtsDelta, mp4SampleDuration);\n maxDtsDelta = Math.max(maxDtsDelta, mp4SampleDuration);\n minPtsDelta = Math.min(minPtsDelta, ptsDelta);\n maxPtsDelta = Math.max(maxPtsDelta, ptsDelta);\n\n outputSamples.push(\n new Mp4Sample(\n avcSample.key,\n mp4SampleDuration,\n mp4SampleLength,\n compositionTimeOffset\n )\n );\n }\n\n if (outputSamples.length) {\n if (chromeVersion) {\n if (chromeVersion < 70) {\n // Chrome workaround, mark first sample as being a Random Access Point (keyframe) to avoid sourcebuffer append issue\n // https://code.google.com/p/chromium/issues/detail?id=229412\n const flags = outputSamples[0].flags;\n flags.dependsOn = 2;\n flags.isNonSync = 0;\n }\n } else if (safariWebkitVersion) {\n // Fix for \"CNN special report, with CC\" in test-streams (Safari browser only)\n // Ignore DTS when frame durations are irregular. Safari MSE does not handle this leading to gaps.\n if (\n maxPtsDelta - minPtsDelta < maxDtsDelta - minDtsDelta &&\n averageSampleDuration / maxDtsDelta < 0.025 &&\n outputSamples[0].cts === 0\n ) {\n logger.warn(\n 'Found irregular gaps in sample duration. Using PTS instead of DTS to determine MP4 sample duration.'\n );\n let dts = firstDTS;\n for (let i = 0, len = outputSamples.length; i < len; i++) {\n const nextDts = dts + outputSamples[i].duration;\n const pts = dts + outputSamples[i].cts;\n if (i < len - 1) {\n const nextPts = nextDts + outputSamples[i + 1].cts;\n outputSamples[i].duration = nextPts - pts;\n } else {\n outputSamples[i].duration = i\n ? outputSamples[i - 1].duration\n : averageSampleDuration;\n }\n outputSamples[i].cts = 0;\n dts = nextDts;\n }\n }\n }\n }\n // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)\n mp4SampleDuration =\n stretchedLastFrame || !mp4SampleDuration\n ? averageSampleDuration\n : mp4SampleDuration;\n this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;\n this.videoSampleDuration = mp4SampleDuration;\n this.isVideoContiguous = true;\n const moof = MP4.moof(\n track.sequenceNumber++,\n firstDTS,\n Object.assign({}, track, {\n samples: outputSamples,\n })\n );\n const type: SourceBufferName = 'video';\n const data = {\n data1: moof,\n data2: mdat,\n startPTS: minPTS / timeScale,\n endPTS: (maxPTS + mp4SampleDuration) / timeScale,\n startDTS: firstDTS / timeScale,\n endDTS: (nextAvcDts as number) / timeScale,\n type,\n hasAudio: false,\n hasVideo: true,\n nb: outputSamples.length,\n dropped: track.dropped,\n };\n track.samples = [];\n track.dropped = 0;\n return data;\n }\n\n remuxAudio(\n track: DemuxedAudioTrack,\n timeOffset: number,\n contiguous: boolean,\n accurateTimeOffset: boolean,\n videoTimeOffset?: number\n ): RemuxedTrack | undefined {\n const inputTimeScale: number = track.inputTimeScale;\n const mp4timeScale: number = track.samplerate\n ? track.samplerate\n : inputTimeScale;\n const scaleFactor: number = inputTimeScale / mp4timeScale;\n const mp4SampleDuration: number =\n track.segmentCodec === 'aac'\n ? AAC_SAMPLES_PER_FRAME\n : MPEG_AUDIO_SAMPLE_PER_FRAME;\n const inputSampleDuration: number = mp4SampleDuration * scaleFactor;\n const initPTS = this._initPTS as RationalTimestamp;\n const rawMPEG: boolean =\n track.segmentCodec === 'mp3' && this.typeSupported.mpeg;\n const outputSamples: Array<Mp4Sample> = [];\n const alignedWithVideo = videoTimeOffset !== undefined;\n\n let inputSamples: Array<AudioSample> = track.samples;\n let offset: number = rawMPEG ? 0 : 8;\n let nextAudioPts: number = this.nextAudioPts || -1;\n\n // window.audioSamples ? window.audioSamples.push(inputSamples.map(s => s.pts)) : (window.audioSamples = [inputSamples.map(s => s.pts)]);\n\n // for audio samples, also consider consecutive fragments as being contiguous (even if a level switch occurs),\n // for sake of clarity:\n // consecutive fragments are frags with\n // - less than 100ms gaps between new time offset (if accurate) and next expected PTS OR\n // - less than 20 audio frames distance\n // contiguous fragments are consecutive fragments from same quality level (same level, new SN = old SN + 1)\n // this helps ensuring audio continuity\n // and this also avoids audio glitches/cut when switching quality, or reporting wrong duration on first audio frame\n const timeOffsetMpegTS = timeOffset * inputTimeScale;\n const initTime = (initPTS.baseTime * inputTimeScale) / initPTS.timescale;\n this.isAudioContiguous = contiguous =\n contiguous ||\n ((inputSamples.length &&\n nextAudioPts > 0 &&\n ((accurateTimeOffset &&\n Math.abs(timeOffsetMpegTS - nextAudioPts) < 9000) ||\n Math.abs(\n normalizePts(inputSamples[0].pts - initTime, timeOffsetMpegTS) -\n nextAudioPts\n ) <\n 20 * inputSampleDuration)) as boolean);\n\n // compute normalized PTS\n inputSamples.forEach(function (sample) {\n sample.pts = normalizePts(sample.pts - initTime, timeOffsetMpegTS);\n });\n\n if (!contiguous || nextAudioPts < 0) {\n // filter out sample with negative PTS that are not playable anyway\n // if we don't remove these negative samples, they will shift all audio samples forward.\n // leading to audio overlap between current / next fragment\n inputSamples = inputSamples.filter((sample) => sample.pts >= 0);\n\n // in case all samples have negative PTS, and have been filtered out, return now\n if (!inputSamples.length) {\n return;\n }\n\n if (videoTimeOffset === 0) {\n // Set the start to 0 to match video so that start gaps larger than inputSampleDuration are filled with silence\n nextAudioPts = 0;\n } else if (accurateTimeOffset && !alignedWithVideo) {\n // When not seeking, not live, and LevelDetails.PTSKnown, use fragment start as predicted next audio PTS\n nextAudioPts = Math.max(0, timeOffsetMpegTS);\n } else {\n // if frags are not contiguous and if we cant trust time offset, let's use first sample PTS as next audio PTS\n nextAudioPts = inputSamples[0].pts;\n }\n }\n\n // If the audio track is missing samples, the frames seem to get \"left-shifted\" within the\n // resulting mp4 segment, causing sync issues and leaving gaps at the end of the audio segment.\n // In an effort to prevent this from happening, we inject frames here where there are gaps.\n // When possible, we inject a silent frame; when that's not possible, we duplicate the last\n // frame.\n\n if (track.segmentCodec === 'aac') {\n const maxAudioFramesDrift = this.config.maxAudioFramesDrift;\n for (let i = 0, nextPts = nextAudioPts; i < inputSamples.length; i++) {\n // First, let's see how far off this frame is from where we expect it to be\n const sample = inputSamples[i];\n const pts = sample.pts;\n const delta = pts - nextPts;\n const duration = Math.abs((1000 * delta) / inputTimeScale);\n\n // When remuxing with video, if we're overlapping by more than a duration, drop this sample to stay in sync\n if (\n delta <= -maxAudioFramesDrift * inputSampleDuration &&\n alignedWithVideo\n ) {\n if (i === 0) {\n logger.warn(\n `Audio frame @ ${(pts / inputTimeScale).toFixed(\n 3\n )}s overlaps nextAudioPts by ${Math.round(\n (1000 * delta) / inputTimeScale\n )} ms.`\n );\n this.nextAudioPts = nextAudioPts = nextPts = pts;\n }\n } // eslint-disable-line brace-style\n\n // Insert missing frames if:\n // 1: We're more than maxAudioFramesDrift frame away\n // 2: Not more than MAX_SILENT_FRAME_DURATION away\n // 3: currentTime (aka nextPtsNorm) is not 0\n // 4: remuxing with video (videoTimeOffset !== undefined)\n else if (\n delta >= maxAudioFramesDrift * inputSampleDuration &&\n duration < MAX_SILENT_FRAME_DURATION &&\n alignedWithVideo\n ) {\n let missing = Math.round(delta / inputSampleDuration);\n // Adjust nextPts so that silent samples are aligned with media pts. This will prevent media samples from\n // later being shifted if nextPts is based on timeOffset and delta is not a multiple of inputSampleDuration.\n nextPts = pts - missing * inputSampleDuration;\n if (nextPts < 0) {\n missing--;\n nextPts += inputSampleDuration;\n }\n if (i === 0) {\n this.nextAudioPts = nextAudioPts = nextPts;\n }\n logger.warn(\n `[mp4-remuxer]: Injecting ${missing} audio frame @ ${(\n nextPts / inputTimeScale\n ).toFixed(3)}s due to ${Math.round(\n (1000 * delta) / inputTimeScale\n )} ms gap.`\n );\n for (let j = 0; j < missing; j++) {\n const newStamp = Math.max(nextPts as number, 0);\n let fillFrame = AAC.getSilentFrame(\n track.manifestCodec || track.codec,\n track.channelCount\n );\n if (!fillFrame) {\n logger.log(\n '[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.'\n );\n fillFrame = sample.unit.subarray();\n }\n inputSamples.splice(i, 0, {\n unit: fillFrame,\n pts: newStamp,\n });\n nextPts += inputSampleDuration;\n i++;\n }\n }\n sample.pts = nextPts;\n nextPts += inputSampleDuration;\n }\n }\n let firstPTS: number | null = null;\n let lastPTS: number | null = null;\n let mdat: any;\n let mdatSize: number = 0;\n let sampleLength: number = inputSamples.length;\n while (sampleLength--) {\n mdatSize += inputSamples[sampleLength].unit.byteLength;\n }\n for (let j = 0, nbSamples = inputSamples.length; j < nbSamples; j++) {\n const audioSample = inputSamples[j];\n const unit = audioSample.unit;\n let pts = audioSample.pts;\n if (lastPTS !== null) {\n // If we have more than one sample, set the duration of the sample to the \"real\" duration; the PTS diff with\n // the previous sample\n const prevSample = outputSamples[j - 1];\n prevSample.duration = Math.round((pts - lastPTS) / scaleFactor);\n } else {\n if (contiguous && track.segmentCodec === 'aac') {\n // set PTS/DTS to expected PTS/DTS\n pts = nextAudioPts;\n }\n // remember first PTS of our audioSamples\n firstPTS = pts;\n if (mdatSize > 0) {\n /* concatenate the audio data and construct the mdat in place\n (need 8 more bytes to fill length and mdat type) */\n mdatSize += offset;\n try {\n mdat = new Uint8Array(mdatSize);\n } catch (err) {\n this.observer.emit(Events.ERROR, Events.ERROR, {\n type: ErrorTypes.MUX_ERROR,\n details: ErrorDetails.REMUX_ALLOC_ERROR,\n fatal: false,\n error: err,\n bytes: mdatSize,\n reason: `fail allocating audio mdat ${mdatSize}`,\n });\n return;\n }\n if (!rawMPEG) {\n const view = new DataView(mdat.buffer);\n view.setUint32(0, mdatSize);\n mdat.set(MP4.types.mdat, 4);\n }\n } else {\n // no audio samples\n return;\n }\n }\n mdat.set(unit, offset);\n const unitLen = unit.byteLength;\n offset += unitLen;\n // Default the sample's duration to the computed mp4SampleDuration, which will either be 1024 for AAC or 1152 for MPEG\n // In the case that we have 1 sample, this will be the duration. If we have more than one sample, the duration\n // becomes the PTS diff with the previous sample\n outputSamples.push(new Mp4Sample(true, mp4SampleDuration, unitLen, 0));\n lastPTS = pts;\n }\n\n // We could end up with no audio samples if all input samples were overlapping with the previously remuxed ones\n const nbSamples = outputSamples.length;\n if (!nbSamples) {\n return;\n }\n\n // The next audio sample PTS should be equal to last sample PTS + duration\n const lastSample = outputSamples[outputSamples.length - 1];\n this.nextAudioPts = nextAudioPts =\n lastPTS! + scaleFactor * lastSample.duration;\n\n // Set the track samples from inputSamples to outputSamples before remuxing\n const moof = rawMPEG\n ? new Uint8Array(0)\n : MP4.moof(\n track.sequenceNumber++,\n firstPTS! / scaleFactor,\n Object.assign({}, track, { samples: outputSamples })\n );\n\n // Clear the track samples. This also clears the samples array in the demuxer, since the reference is shared\n track.samples = [];\n const start = firstPTS! / inputTimeScale;\n const end = nextAudioPts / inputTimeScale;\n const type: SourceBufferName = 'audio';\n const audioData = {\n data1: moof,\n data2: mdat,\n startPTS: start,\n endPTS: end,\n startDTS: start,\n endDTS: end,\n type,\n hasAudio: true,\n hasVideo: false,\n nb: nbSamples,\n };\n\n this.isAudioContiguous = true;\n return audioData;\n }\n\n remuxEmptyAudio(\n track: DemuxedAudioTrack,\n timeOffset: number,\n contiguous: boolean,\n videoData: Fragment\n ): RemuxedTrack | undefined {\n const inputTimeScale: number = track.inputTimeScale;\n const mp4timeScale: number = track.samplerate\n ? track.samplerate\n : inputTimeScale;\n const scaleFactor: number = inputTimeScale / mp4timeScale;\n const nextAudioPts: number | null = this.nextAudioPts;\n // sync with video's timestamp\n const initDTS = this._initDTS as RationalTimestamp;\n const init90kHz = (initDTS.baseTime * 90000) / initDTS.timescale;\n const startDTS: number =\n (nextAudioPts !== null\n ? nextAudioPts\n : videoData.startDTS * inputTimeScale) + init90kHz;\n const endDTS: number = videoData.endDTS * inputTimeScale + init90kHz;\n // one sample's duration value\n const frameDuration: number = scaleFactor * AAC_SAMPLES_PER_FRAME;\n // samples count of this segment's duration\n const nbSamples: number = Math.ceil((endDTS - startDTS) / frameDuration);\n // silent frame\n const silentFrame: Uint8Array | undefined = AAC.getSilentFrame(\n track.manifestCodec || track.codec,\n track.channelCount\n );\n\n logger.warn('[mp4-remuxer]: remux empty Audio');\n // Can't remux if we can't generate a silent frame...\n if (!silentFrame) {\n logger.trace(\n '[mp4-remuxer]: Unable to remuxEmptyAudio since we were unable to get a silent frame for given audio codec'\n );\n return;\n }\n\n const samples: Array<any> = [];\n for (let i = 0; i < nbSamples; i++) {\n const stamp = startDTS + i * frameDuration;\n samples.push({ unit: silentFrame, pts: stamp, dts: stamp });\n }\n track.samples = samples;\n\n return this.remuxAudio(track, timeOffset, contiguous, false);\n }\n}\n\nexport function normalizePts(value: number, reference: number | null): number {\n let offset;\n if (reference === null) {\n return value;\n }\n\n if (reference < value) {\n // - 2^33\n offset = -8589934592;\n } else {\n // + 2^33\n offset = 8589934592;\n }\n /* PTS is 33bit (from 0 to 2^33 -1)\n if diff between value and reference is bigger than half of the amplitude (2^32) then it means that\n PTS looping occured. fill the gap */\n while (Math.abs(value - reference) > 4294967296) {\n value += offset;\n }\n\n return value;\n}\n\nfunction findKeyframeIndex(samples: Array<AvcSample>): number {\n for (let i = 0; i < samples.length; i++) {\n if (samples[i].key) {\n return i;\n }\n }\n return -1;\n}\n\nexport function flushTextTrackMetadataCueSamples(\n track: DemuxedMetadataTrack,\n timeOffset: number,\n initPTS: RationalTimestamp,\n initDTS: RationalTimestamp\n): RemuxedMetadata | undefined {\n const length = track.samples.length;\n if (!length) {\n return;\n }\n const inputTimeScale = track.inputTimeScale;\n for (let index = 0; index < length; index++) {\n const sample = track.samples[index];\n // setting id3 pts, dts to relative time\n // using this._initPTS and this._initDTS to calculate relative time\n sample.pts =\n normalizePts(\n sample.pts - (initPTS.baseTime * inputTimeScale) / initPTS.timescale,\n timeOffset * inputTimeScale\n ) / inputTimeScale;\n sample.dts =\n normalizePts(\n sample.dts - (initDTS.baseTime * inputTimeScale) / initDTS.timescale,\n timeOffset * inputTimeScale\n ) / inputTimeScale;\n }\n const samples = track.samples;\n track.samples = [];\n return {\n samples,\n };\n}\n\nexport function flushTextTrackUserdataCueSamples(\n track: DemuxedUserdataTrack,\n timeOffset: number,\n initPTS: RationalTimestamp\n): RemuxedUserdata | undefined {\n const length = track.samples.length;\n if (!length) {\n return;\n }\n\n const inputTimeScale = track.inputTimeScale;\n for (let index = 0; index < length; index++) {\n const sample = track.samples[index];\n // setting text pts, dts to relative time\n // using this._initPTS and this._initDTS to calculate relative time\n sample.pts =\n normalizePts(\n sample.pts - (initPTS.baseTime * 90000) / initPTS.timescale,\n timeOffset * inputTimeScale\n ) / inputTimeScale;\n }\n track.samples.sort((a, b) => a.pts - b.pts);\n const samples = track.samples;\n track.samples = [];\n return {\n samples,\n };\n}\n\nclass Mp4Sample {\n public size: number;\n public duration: number;\n public cts: number;\n public flags: Mp4SampleFlags;\n\n constructor(\n isKeyframe: boolean,\n duration: number,\n size: number,\n cts: number\n ) {\n this.duration = duration;\n this.size = size;\n this.cts = cts;\n this.flags = new Mp4SampleFlags(isKeyframe);\n }\n}\n\nclass Mp4SampleFlags {\n public isLeading: 0 = 0;\n public isDependedOn: 0 = 0;\n public hasRedundancy: 0 = 0;\n public degradPrio: 0 = 0;\n public dependsOn: 1 | 2 = 1;\n public isNonSync: 0 | 1 = 1;\n\n constructor(isKeyframe) {\n this.dependsOn = isKeyframe ? 2 : 1;\n this.isNonSync = isKeyframe ? 0 : 1;\n }\n}\n","import type { HlsEventEmitter } from '../events';\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport Decrypter from '../crypt/decrypter';\nimport AACDemuxer from '../demux/aacdemuxer';\nimport MP4Demuxer from '../demux/mp4demuxer';\nimport TSDemuxer, { TypeSupported } from '../demux/tsdemuxer';\nimport MP3Demuxer from '../demux/mp3demuxer';\nimport MP4Remuxer from '../remux/mp4-remuxer';\nimport PassThroughRemuxer from '../remux/passthrough-remuxer';\nimport { logger } from '../utils/logger';\nimport type { Demuxer, DemuxerResult, KeyData } from '../types/demuxer';\nimport type { Remuxer } from '../types/remuxer';\nimport type { TransmuxerResult, ChunkMetadata } from '../types/transmuxer';\nimport type { HlsConfig } from '../config';\nimport type { DecryptData } from '../loader/level-key';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\nlet now;\n// performance.now() not available on WebWorker, at least on Safari Desktop\ntry {\n now = self.performance.now.bind(self.performance);\n} catch (err) {\n logger.debug('Unable to use Performance API on this environment');\n now = typeof self !== 'undefined' && self.Date.now;\n}\n\ntype MuxConfig =\n | { demux: typeof MP4Demuxer; remux: typeof PassThroughRemuxer }\n | { demux: typeof TSDemuxer; remux: typeof MP4Remuxer }\n | { demux: typeof AACDemuxer; remux: typeof MP4Remuxer }\n | { demux: typeof MP3Demuxer; remux: typeof MP4Remuxer };\n\nconst muxConfig: MuxConfig[] = [\n { demux: MP4Demuxer, remux: PassThroughRemuxer },\n { demux: TSDemuxer, remux: MP4Remuxer },\n { demux: AACDemuxer, remux: MP4Remuxer },\n { demux: MP3Demuxer, remux: MP4Remuxer },\n];\n\nexport default class Transmuxer {\n public async: boolean = false;\n private observer: HlsEventEmitter;\n private typeSupported: TypeSupported;\n private config: HlsConfig;\n private vendor: string;\n private id: PlaylistLevelType;\n private demuxer?: Demuxer;\n private remuxer?: Remuxer;\n private decrypter?: Decrypter;\n private probe!: Function;\n private decryptionPromise: Promise<TransmuxerResult> | null = null;\n private transmuxConfig!: TransmuxConfig;\n private currentTransmuxState!: TransmuxState;\n\n constructor(\n observer: HlsEventEmitter,\n typeSupported: TypeSupported,\n config: HlsConfig,\n vendor: string,\n id: PlaylistLevelType\n ) {\n this.observer = observer;\n this.typeSupported = typeSupported;\n this.config = config;\n this.vendor = vendor;\n this.id = id;\n }\n\n configure(transmuxConfig: TransmuxConfig) {\n this.transmuxConfig = transmuxConfig;\n if (this.decrypter) {\n this.decrypter.reset();\n }\n }\n\n push(\n data: ArrayBuffer,\n decryptdata: DecryptData | null,\n chunkMeta: ChunkMetadata,\n state?: TransmuxState\n ): TransmuxerResult | Promise<TransmuxerResult> {\n const stats = chunkMeta.transmuxing;\n stats.executeStart = now();\n\n let uintData: Uint8Array = new Uint8Array(data);\n const { currentTransmuxState, transmuxConfig } = this;\n if (state) {\n this.currentTransmuxState = state;\n }\n\n const {\n contiguous,\n discontinuity,\n trackSwitch,\n accurateTimeOffset,\n timeOffset,\n initSegmentChange,\n } = state || currentTransmuxState;\n const {\n audioCodec,\n videoCodec,\n defaultInitPts,\n duration,\n initSegmentData,\n } = transmuxConfig;\n\n const keyData = getEncryptionType(uintData, decryptdata);\n if (keyData && keyData.method === 'AES-128') {\n const decrypter = this.getDecrypter();\n // Software decryption is synchronous; webCrypto is not\n if (decrypter.isSync()) {\n // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached\n // data is handled in the flush() call\n let decryptedData = decrypter.softwareDecrypt(\n uintData,\n keyData.key.buffer,\n keyData.iv.buffer\n );\n // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress\n const loadingParts = chunkMeta.part > -1;\n if (loadingParts) {\n decryptedData = decrypter.flush();\n }\n if (!decryptedData) {\n stats.executeEnd = now();\n return emptyResult(chunkMeta);\n }\n uintData = new Uint8Array(decryptedData);\n } else {\n this.decryptionPromise = decrypter\n .webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer)\n .then((decryptedData): TransmuxerResult => {\n // Calling push here is important; if flush() is called while this is still resolving, this ensures that\n // the decrypted data has been transmuxed\n const result = this.push(\n decryptedData,\n null,\n chunkMeta\n ) as TransmuxerResult;\n this.decryptionPromise = null;\n return result;\n });\n return this.decryptionPromise!;\n }\n }\n\n const resetMuxers = this.needsProbing(discontinuity, trackSwitch);\n if (resetMuxers) {\n const error = this.configureTransmuxer(uintData);\n if (error) {\n logger.warn(`[transmuxer] ${error.message}`);\n this.observer.emit(Events.ERROR, Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n fatal: false,\n error,\n reason: error.message,\n });\n stats.executeEnd = now();\n return emptyResult(chunkMeta);\n }\n }\n\n if (discontinuity || trackSwitch || initSegmentChange || resetMuxers) {\n this.resetInitSegment(\n initSegmentData,\n audioCodec,\n videoCodec,\n duration,\n decryptdata\n );\n }\n\n if (discontinuity || initSegmentChange || resetMuxers) {\n this.resetInitialTimestamp(defaultInitPts);\n }\n\n if (!contiguous) {\n this.resetContiguity();\n }\n\n const result = this.transmux(\n uintData,\n keyData,\n timeOffset,\n accurateTimeOffset,\n chunkMeta\n );\n const currentState = this.currentTransmuxState;\n\n currentState.contiguous = true;\n currentState.discontinuity = false;\n currentState.trackSwitch = false;\n\n stats.executeEnd = now();\n return result;\n }\n\n // Due to data caching, flush calls can produce more than one TransmuxerResult (hence the Array type)\n flush(\n chunkMeta: ChunkMetadata\n ): TransmuxerResult[] | Promise<TransmuxerResult[]> {\n const stats = chunkMeta.transmuxing;\n stats.executeStart = now();\n\n const { decrypter, currentTransmuxState, decryptionPromise } = this;\n\n if (decryptionPromise) {\n // Upon resolution, the decryption promise calls push() and returns its TransmuxerResult up the stack. Therefore\n // only flushing is required for async decryption\n return decryptionPromise.then(() => {\n return this.flush(chunkMeta);\n });\n }\n\n const transmuxResults: TransmuxerResult[] = [];\n const { timeOffset } = currentTransmuxState;\n if (decrypter) {\n // The decrypter may have data cached, which needs to be demuxed. In this case we'll have two TransmuxResults\n // This happens in the case that we receive only 1 push call for a segment (either for non-progressive downloads,\n // or for progressive downloads with small segments)\n const decryptedData = decrypter.flush();\n if (decryptedData) {\n // Push always returns a TransmuxerResult if decryptdata is null\n transmuxResults.push(\n this.push(decryptedData, null, chunkMeta) as TransmuxerResult\n );\n }\n }\n\n const { demuxer, remuxer } = this;\n if (!demuxer || !remuxer) {\n // If probing failed, then Hls.js has been given content its not able to handle\n stats.executeEnd = now();\n return [emptyResult(chunkMeta)];\n }\n\n const demuxResultOrPromise = demuxer.flush(timeOffset);\n if (isPromise(demuxResultOrPromise)) {\n // Decrypt final SAMPLE-AES samples\n return demuxResultOrPromise.then((demuxResult) => {\n this.flushRemux(transmuxResults, demuxResult, chunkMeta);\n return transmuxResults;\n });\n }\n\n this.flushRemux(transmuxResults, demuxResultOrPromise, chunkMeta);\n return transmuxResults;\n }\n\n private flushRemux(\n transmuxResults: TransmuxerResult[],\n demuxResult: DemuxerResult,\n chunkMeta: ChunkMetadata\n ) {\n const { audioTrack, videoTrack, id3Track, textTrack } = demuxResult;\n const { accurateTimeOffset, timeOffset } = this.currentTransmuxState;\n logger.log(\n `[transmuxer.ts]: Flushed fragment ${chunkMeta.sn}${\n chunkMeta.part > -1 ? ' p: ' + chunkMeta.part : ''\n } of level ${chunkMeta.level}`\n );\n const remuxResult = this.remuxer!.remux(\n audioTrack,\n videoTrack,\n id3Track,\n textTrack,\n timeOffset,\n accurateTimeOffset,\n true,\n this.id\n );\n transmuxResults.push({\n remuxResult,\n chunkMeta,\n });\n\n chunkMeta.transmuxing.executeEnd = now();\n }\n\n resetInitialTimestamp(defaultInitPts: RationalTimestamp | null) {\n const { demuxer, remuxer } = this;\n if (!demuxer || !remuxer) {\n return;\n }\n demuxer.resetTimeStamp(defaultInitPts);\n remuxer.resetTimeStamp(defaultInitPts);\n }\n\n resetContiguity() {\n const { demuxer, remuxer } = this;\n if (!demuxer || !remuxer) {\n return;\n }\n demuxer.resetContiguity();\n remuxer.resetNextTimestamp();\n }\n\n resetInitSegment(\n initSegmentData: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number,\n decryptdata: DecryptData | null\n ) {\n const { demuxer, remuxer } = this;\n if (!demuxer || !remuxer) {\n return;\n }\n demuxer.resetInitSegment(\n initSegmentData,\n audioCodec,\n videoCodec,\n trackDuration\n );\n remuxer.resetInitSegment(\n initSegmentData,\n audioCodec,\n videoCodec,\n decryptdata\n );\n }\n\n destroy(): void {\n if (this.demuxer) {\n this.demuxer.destroy();\n this.demuxer = undefined;\n }\n if (this.remuxer) {\n this.remuxer.destroy();\n this.remuxer = undefined;\n }\n }\n\n private transmux(\n data: Uint8Array,\n keyData: KeyData | null,\n timeOffset: number,\n accurateTimeOffset: boolean,\n chunkMeta: ChunkMetadata\n ): TransmuxerResult | Promise<TransmuxerResult> {\n let result: TransmuxerResult | Promise<TransmuxerResult>;\n if (keyData && keyData.method === 'SAMPLE-AES') {\n result = this.transmuxSampleAes(\n data,\n keyData,\n timeOffset,\n accurateTimeOffset,\n chunkMeta\n );\n } else {\n result = this.transmuxUnencrypted(\n data,\n timeOffset,\n accurateTimeOffset,\n chunkMeta\n );\n }\n return result;\n }\n\n private transmuxUnencrypted(\n data: Uint8Array,\n timeOffset: number,\n accurateTimeOffset: boolean,\n chunkMeta: ChunkMetadata\n ): TransmuxerResult {\n const { audioTrack, videoTrack, id3Track, textTrack } = (\n this.demuxer as Demuxer\n ).demux(data, timeOffset, false, !this.config.progressive);\n const remuxResult = this.remuxer!.remux(\n audioTrack,\n videoTrack,\n id3Track,\n textTrack,\n timeOffset,\n accurateTimeOffset,\n false,\n this.id\n );\n return {\n remuxResult,\n chunkMeta,\n };\n }\n\n private transmuxSampleAes(\n data: Uint8Array,\n decryptData: KeyData,\n timeOffset: number,\n accurateTimeOffset: boolean,\n chunkMeta: ChunkMetadata\n ): Promise<TransmuxerResult> {\n return (this.demuxer as Demuxer)\n .demuxSampleAes(data, decryptData, timeOffset)\n .then((demuxResult) => {\n const remuxResult = this.remuxer!.remux(\n demuxResult.audioTrack,\n demuxResult.videoTrack,\n demuxResult.id3Track,\n demuxResult.textTrack,\n timeOffset,\n accurateTimeOffset,\n false,\n this.id\n );\n return {\n remuxResult,\n chunkMeta,\n };\n });\n }\n\n private configureTransmuxer(data: Uint8Array): void | Error {\n const { config, observer, typeSupported, vendor } = this;\n // probe for content type\n let mux;\n for (let i = 0, len = muxConfig.length; i < len; i++) {\n if (muxConfig[i].demux.probe(data)) {\n mux = muxConfig[i];\n break;\n }\n }\n if (!mux) {\n return new Error('Failed to find demuxer by probing fragment data');\n }\n // so let's check that current remuxer and demuxer are still valid\n const demuxer = this.demuxer;\n const remuxer = this.remuxer;\n const Remuxer: MuxConfig['remux'] = mux.remux;\n const Demuxer: MuxConfig['demux'] = mux.demux;\n if (!remuxer || !(remuxer instanceof Remuxer)) {\n this.remuxer = new Remuxer(observer, config, typeSupported, vendor);\n }\n if (!demuxer || !(demuxer instanceof Demuxer)) {\n this.demuxer = new Demuxer(observer, config, typeSupported);\n this.probe = Demuxer.probe;\n }\n }\n\n private needsProbing(discontinuity: boolean, trackSwitch: boolean): boolean {\n // in case of continuity change, or track switch\n // we might switch from content type (AAC container to TS container, or TS to fmp4 for example)\n return !this.demuxer || !this.remuxer || discontinuity || trackSwitch;\n }\n\n private getDecrypter(): Decrypter {\n let decrypter = this.decrypter;\n if (!decrypter) {\n decrypter = this.decrypter = new Decrypter(this.config);\n }\n return decrypter;\n }\n}\n\nfunction getEncryptionType(\n data: Uint8Array,\n decryptData: DecryptData | null\n): KeyData | null {\n let encryptionType: KeyData | null = null;\n if (\n data.byteLength > 0 &&\n decryptData != null &&\n decryptData.key != null &&\n decryptData.iv !== null &&\n decryptData.method != null\n ) {\n encryptionType = decryptData as KeyData;\n }\n return encryptionType;\n}\n\nconst emptyResult = (chunkMeta): TransmuxerResult => ({\n remuxResult: {},\n chunkMeta,\n});\n\nexport function isPromise<T>(p: Promise<T> | any): p is Promise<T> {\n return 'then' in p && p.then instanceof Function;\n}\n\nexport class TransmuxConfig {\n public audioCodec?: string;\n public videoCodec?: string;\n public initSegmentData?: Uint8Array;\n public duration: number;\n public defaultInitPts: RationalTimestamp | null;\n\n constructor(\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n initSegmentData: Uint8Array | undefined,\n duration: number,\n defaultInitPts?: RationalTimestamp\n ) {\n this.audioCodec = audioCodec;\n this.videoCodec = videoCodec;\n this.initSegmentData = initSegmentData;\n this.duration = duration;\n this.defaultInitPts = defaultInitPts || null;\n }\n}\n\nexport class TransmuxState {\n public discontinuity: boolean;\n public contiguous: boolean;\n public accurateTimeOffset: boolean;\n public trackSwitch: boolean;\n public timeOffset: number;\n public initSegmentChange: boolean;\n\n constructor(\n discontinuity: boolean,\n contiguous: boolean,\n accurateTimeOffset: boolean,\n trackSwitch: boolean,\n timeOffset: number,\n initSegmentChange: boolean\n ) {\n this.discontinuity = discontinuity;\n this.contiguous = contiguous;\n this.accurateTimeOffset = accurateTimeOffset;\n this.trackSwitch = trackSwitch;\n this.timeOffset = timeOffset;\n this.initSegmentChange = initSegmentChange;\n }\n}\n","import {\n flushTextTrackMetadataCueSamples,\n flushTextTrackUserdataCueSamples,\n} from './mp4-remuxer';\nimport {\n InitData,\n InitDataTrack,\n patchEncyptionData,\n} from '../utils/mp4-tools';\nimport {\n getDuration,\n getStartDTS,\n offsetStartDTS,\n parseInitSegment,\n} from '../utils/mp4-tools';\nimport { ElementaryStreamTypes } from '../loader/fragment';\nimport { logger } from '../utils/logger';\nimport type { TrackSet } from '../types/track';\nimport type {\n InitSegmentData,\n RemuxedTrack,\n Remuxer,\n RemuxerResult,\n} from '../types/remuxer';\nimport type {\n DemuxedAudioTrack,\n DemuxedMetadataTrack,\n DemuxedUserdataTrack,\n PassthroughTrack,\n} from '../types/demuxer';\nimport type { DecryptData } from '../loader/level-key';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\nclass PassThroughRemuxer implements Remuxer {\n private emitInitSegment: boolean = false;\n private audioCodec?: string;\n private videoCodec?: string;\n private initData?: InitData;\n private initPTS: RationalTimestamp | null = null;\n private initTracks?: TrackSet;\n private lastEndTime: number | null = null;\n\n public destroy() {}\n\n public resetTimeStamp(defaultInitPTS: RationalTimestamp | null) {\n this.initPTS = defaultInitPTS;\n this.lastEndTime = null;\n }\n\n public resetNextTimestamp() {\n this.lastEndTime = null;\n }\n\n public resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n decryptdata: DecryptData | null\n ) {\n this.audioCodec = audioCodec;\n this.videoCodec = videoCodec;\n this.generateInitSegment(patchEncyptionData(initSegment, decryptdata));\n this.emitInitSegment = true;\n }\n\n private generateInitSegment(initSegment: Uint8Array | undefined): void {\n let { audioCodec, videoCodec } = this;\n if (!initSegment?.byteLength) {\n this.initTracks = undefined;\n this.initData = undefined;\n return;\n }\n const initData = (this.initData = parseInitSegment(initSegment));\n\n // Get codec from initSegment or fallback to default\n if (!audioCodec) {\n audioCodec = getParsedTrackCodec(\n initData.audio,\n ElementaryStreamTypes.AUDIO\n );\n }\n\n if (!videoCodec) {\n videoCodec = getParsedTrackCodec(\n initData.video,\n ElementaryStreamTypes.VIDEO\n );\n }\n\n const tracks: TrackSet = {};\n if (initData.audio && initData.video) {\n tracks.audiovideo = {\n container: 'video/mp4',\n codec: audioCodec + ',' + videoCodec,\n initSegment,\n id: 'main',\n };\n } else if (initData.audio) {\n tracks.audio = {\n container: 'audio/mp4',\n codec: audioCodec,\n initSegment,\n id: 'audio',\n };\n } else if (initData.video) {\n tracks.video = {\n container: 'video/mp4',\n codec: videoCodec,\n initSegment,\n id: 'main',\n };\n } else {\n logger.warn(\n '[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes.'\n );\n }\n this.initTracks = tracks;\n }\n\n public remux(\n audioTrack: DemuxedAudioTrack,\n videoTrack: PassthroughTrack,\n id3Track: DemuxedMetadataTrack,\n textTrack: DemuxedUserdataTrack,\n timeOffset: number,\n accurateTimeOffset: boolean\n ): RemuxerResult {\n let { initPTS, lastEndTime } = this;\n const result: RemuxerResult = {\n audio: undefined,\n video: undefined,\n text: textTrack,\n id3: id3Track,\n initSegment: undefined,\n };\n\n // If we haven't yet set a lastEndDTS, or it was reset, set it to the provided timeOffset. We want to use the\n // lastEndDTS over timeOffset whenever possible; during progressive playback, the media source will not update\n // the media duration (which is what timeOffset is provided as) before we need to process the next chunk.\n if (!Number.isFinite(lastEndTime!)) {\n lastEndTime = this.lastEndTime = timeOffset || 0;\n }\n\n // The binary segment data is added to the videoTrack in the mp4demuxer. We don't check to see if the data is only\n // audio or video (or both); adding it to video was an arbitrary choice.\n const data = videoTrack.samples;\n if (!data?.length) {\n return result;\n }\n\n const initSegment: InitSegmentData = {\n initPTS: undefined,\n timescale: 1,\n };\n let initData = this.initData;\n if (!initData?.length) {\n this.generateInitSegment(data);\n initData = this.initData;\n }\n if (!initData?.length) {\n // We can't remux if the initSegment could not be generated\n logger.warn('[passthrough-remuxer.ts]: Failed to generate initSegment.');\n return result;\n }\n if (this.emitInitSegment) {\n initSegment.tracks = this.initTracks as TrackSet;\n this.emitInitSegment = false;\n }\n\n const duration = getDuration(data, initData);\n const startDTS = getStartDTS(initData, data);\n const decodeTime = startDTS === null ? timeOffset : startDTS;\n if (\n isInvalidInitPts(initPTS, decodeTime, timeOffset, duration) ||\n (initSegment.timescale !== initPTS.timescale && accurateTimeOffset)\n ) {\n initSegment.initPTS = decodeTime - timeOffset;\n if (initPTS && initPTS.timescale === 1) {\n logger.warn(\n `Adjusting initPTS by ${initSegment.initPTS - initPTS.baseTime}`\n );\n }\n this.initPTS = initPTS = {\n baseTime: initSegment.initPTS,\n timescale: 1,\n };\n }\n\n const startTime = audioTrack\n ? decodeTime - initPTS.baseTime / initPTS.timescale\n : (lastEndTime as number);\n const endTime = startTime + duration;\n offsetStartDTS(initData, data, initPTS.baseTime / initPTS.timescale);\n\n if (duration > 0) {\n this.lastEndTime = endTime;\n } else {\n logger.warn('Duration parsed from mp4 should be greater than zero');\n this.resetNextTimestamp();\n }\n\n const hasAudio = !!initData.audio;\n const hasVideo = !!initData.video;\n\n let type: any = '';\n if (hasAudio) {\n type += 'audio';\n }\n\n if (hasVideo) {\n type += 'video';\n }\n\n const track: RemuxedTrack = {\n data1: data,\n startPTS: startTime,\n startDTS: startTime,\n endPTS: endTime,\n endDTS: endTime,\n type,\n hasAudio,\n hasVideo,\n nb: 1,\n dropped: 0,\n };\n\n result.audio = track.type === 'audio' ? track : undefined;\n result.video = track.type !== 'audio' ? track : undefined;\n result.initSegment = initSegment;\n result.id3 = flushTextTrackMetadataCueSamples(\n id3Track,\n timeOffset,\n initPTS,\n initPTS\n );\n\n if (textTrack.samples.length) {\n result.text = flushTextTrackUserdataCueSamples(\n textTrack,\n timeOffset,\n initPTS\n );\n }\n\n return result;\n }\n}\n\nfunction isInvalidInitPts(\n initPTS: RationalTimestamp | null,\n startDTS: number,\n timeOffset: number,\n duration: number\n): initPTS is null {\n if (initPTS === null) {\n return true;\n }\n // InitPTS is invalid when distance from program would be more than segment duration or a minimum of one second\n const minDuration = Math.max(duration, 1);\n const startTime = startDTS - initPTS.baseTime / initPTS.timescale;\n return Math.abs(startTime - timeOffset) > minDuration;\n}\n\nfunction getParsedTrackCodec(\n track: InitDataTrack | undefined,\n type: ElementaryStreamTypes.AUDIO | ElementaryStreamTypes.VIDEO\n): string {\n const parsedCodec = track?.codec;\n if (parsedCodec && parsedCodec.length > 4) {\n return parsedCodec;\n }\n // Since mp4-tools cannot parse full codec string (see 'TODO: Parse codec details'... in mp4-tools)\n // Provide defaults based on codec type\n // This allows for some playback of some fmp4 playlists without CODECS defined in manifest\n if (parsedCodec === 'hvc1' || parsedCodec === 'hev1') {\n return 'hvc1.1.6.L120.90';\n }\n if (parsedCodec === 'av01') {\n return 'av01.0.04M.08';\n }\n if (parsedCodec === 'avc1' || type === ElementaryStreamTypes.VIDEO) {\n return 'avc1.42e01e';\n }\n return 'mp4a.40.5';\n}\nexport default PassThroughRemuxer;\n","/**\n * AAC demuxer\n */\nimport BaseAudioDemuxer from './base-audio-demuxer';\nimport * as ADTS from './adts';\nimport { logger } from '../utils/logger';\nimport * as ID3 from '../demux/id3';\nimport type { HlsEventEmitter } from '../events';\nimport type { HlsConfig } from '../config';\n\nclass AACDemuxer extends BaseAudioDemuxer {\n private readonly observer: HlsEventEmitter;\n private readonly config: HlsConfig;\n\n constructor(observer, config) {\n super();\n this.observer = observer;\n this.config = config;\n }\n\n resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number\n ) {\n super.resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration);\n this._audioTrack = {\n container: 'audio/adts',\n type: 'audio',\n id: 2,\n pid: -1,\n sequenceNumber: 0,\n segmentCodec: 'aac',\n samples: [],\n manifestCodec: audioCodec,\n duration: trackDuration,\n inputTimeScale: 90000,\n dropped: 0,\n };\n }\n\n // Source for probe info - https://wiki.multimedia.cx/index.php?title=ADTS\n static probe(data): boolean {\n if (!data) {\n return false;\n }\n\n // Check for the ADTS sync word\n // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1\n // Layer bits (position 14 and 15) in header should be always 0 for ADTS\n // More info https://wiki.multimedia.cx/index.php?title=ADTS\n const id3Data = ID3.getID3Data(data, 0) || [];\n let offset = id3Data.length;\n\n for (let length = data.length; offset < length; offset++) {\n if (ADTS.probe(data, offset)) {\n logger.log('ADTS sync word found !');\n return true;\n }\n }\n return false;\n }\n\n canParse(data, offset) {\n return ADTS.canParse(data, offset);\n }\n\n appendFrame(track, data, offset) {\n ADTS.initTrackConfig(\n track,\n this.observer,\n data,\n offset,\n track.manifestCodec\n );\n const frame = ADTS.appendFrame(\n track,\n data,\n offset,\n this.basePTS as number,\n this.frameIndex\n );\n if (frame && frame.missing === 0) {\n return frame;\n }\n }\n}\n\nexport default AACDemuxer;\n","/**\n * MP3 demuxer\n */\nimport BaseAudioDemuxer from './base-audio-demuxer';\nimport * as ID3 from '../demux/id3';\nimport { logger } from '../utils/logger';\nimport * as MpegAudio from './mpegaudio';\n\nclass MP3Demuxer extends BaseAudioDemuxer {\n resetInitSegment(\n initSegment: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n trackDuration: number\n ) {\n super.resetInitSegment(initSegment, audioCodec, videoCodec, trackDuration);\n this._audioTrack = {\n container: 'audio/mpeg',\n type: 'audio',\n id: 2,\n pid: -1,\n sequenceNumber: 0,\n segmentCodec: 'mp3',\n samples: [],\n manifestCodec: audioCodec,\n duration: trackDuration,\n inputTimeScale: 90000,\n dropped: 0,\n };\n }\n\n static probe(data): boolean {\n if (!data) {\n return false;\n }\n\n // check if data contains ID3 timestamp and MPEG sync word\n // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1\n // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)\n // More info http://www.mp3-tech.org/programmer/frame_header.html\n const id3Data = ID3.getID3Data(data, 0) || [];\n let offset = id3Data.length;\n\n for (let length = data.length; offset < length; offset++) {\n if (MpegAudio.probe(data, offset)) {\n logger.log('MPEG Audio sync word found !');\n return true;\n }\n }\n return false;\n }\n\n canParse(data, offset) {\n return MpegAudio.canParse(data, offset);\n }\n\n appendFrame(track, data, offset) {\n if (this.basePTS === null) {\n return;\n }\n return MpegAudio.appendFrame(\n track,\n data,\n offset,\n this.basePTS,\n this.frameIndex\n );\n }\n}\n\nexport default MP3Demuxer;\n","'use strict';\n\nvar has = Object.prototype.hasOwnProperty\n , prefix = '~';\n\n/**\n * Constructor to create a storage for our `EE` objects.\n * An `Events` instance is a plain object whose properties are event names.\n *\n * @constructor\n * @private\n */\nfunction Events() {}\n\n//\n// We try to not inherit from `Object.prototype`. In some engines creating an\n// instance in this way is faster than calling `Object.create(null)` directly.\n// If `Object.create(null)` is not supported we prefix the event names with a\n// character to make sure that the built-in object properties are not\n// overridden or used as an attack vector.\n//\nif (Object.create) {\n Events.prototype = Object.create(null);\n\n //\n // This hack is needed because the `__proto__` property is still inherited in\n // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.\n //\n if (!new Events().__proto__) prefix = false;\n}\n\n/**\n * Representation of a single event listener.\n *\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} [once=false] Specify if the listener is a one-time listener.\n * @constructor\n * @private\n */\nfunction EE(fn, context, once) {\n this.fn = fn;\n this.context = context;\n this.once = once || false;\n}\n\n/**\n * Add a listener for a given event.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} context The context to invoke the listener with.\n * @param {Boolean} once Specify if the listener is a one-time listener.\n * @returns {EventEmitter}\n * @private\n */\nfunction addListener(emitter, event, fn, context, once) {\n if (typeof fn !== 'function') {\n throw new TypeError('The listener must be a function');\n }\n\n var listener = new EE(fn, context || emitter, once)\n , evt = prefix ? prefix + event : event;\n\n if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;\n else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);\n else emitter._events[evt] = [emitter._events[evt], listener];\n\n return emitter;\n}\n\n/**\n * Clear event by name.\n *\n * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.\n * @param {(String|Symbol)} evt The Event name.\n * @private\n */\nfunction clearEvent(emitter, evt) {\n if (--emitter._eventsCount === 0) emitter._events = new Events();\n else delete emitter._events[evt];\n}\n\n/**\n * Minimal `EventEmitter` interface that is molded against the Node.js\n * `EventEmitter` interface.\n *\n * @constructor\n * @public\n */\nfunction EventEmitter() {\n this._events = new Events();\n this._eventsCount = 0;\n}\n\n/**\n * Return an array listing the events for which the emitter has registered\n * listeners.\n *\n * @returns {Array}\n * @public\n */\nEventEmitter.prototype.eventNames = function eventNames() {\n var names = []\n , events\n , name;\n\n if (this._eventsCount === 0) return names;\n\n for (name in (events = this._events)) {\n if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);\n }\n\n if (Object.getOwnPropertySymbols) {\n return names.concat(Object.getOwnPropertySymbols(events));\n }\n\n return names;\n};\n\n/**\n * Return the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Array} The registered listeners.\n * @public\n */\nEventEmitter.prototype.listeners = function listeners(event) {\n var evt = prefix ? prefix + event : event\n , handlers = this._events[evt];\n\n if (!handlers) return [];\n if (handlers.fn) return [handlers.fn];\n\n for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {\n ee[i] = handlers[i].fn;\n }\n\n return ee;\n};\n\n/**\n * Return the number of listeners listening to a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Number} The number of listeners.\n * @public\n */\nEventEmitter.prototype.listenerCount = function listenerCount(event) {\n var evt = prefix ? prefix + event : event\n , listeners = this._events[evt];\n\n if (!listeners) return 0;\n if (listeners.fn) return 1;\n return listeners.length;\n};\n\n/**\n * Calls each of the listeners registered for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @returns {Boolean} `true` if the event had listeners, else `false`.\n * @public\n */\nEventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return false;\n\n var listeners = this._events[evt]\n , len = arguments.length\n , args\n , i;\n\n if (listeners.fn) {\n if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);\n\n switch (len) {\n case 1: return listeners.fn.call(listeners.context), true;\n case 2: return listeners.fn.call(listeners.context, a1), true;\n case 3: return listeners.fn.call(listeners.context, a1, a2), true;\n case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;\n case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;\n case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;\n }\n\n for (i = 1, args = new Array(len -1); i < len; i++) {\n args[i - 1] = arguments[i];\n }\n\n listeners.fn.apply(listeners.context, args);\n } else {\n var length = listeners.length\n , j;\n\n for (i = 0; i < length; i++) {\n if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);\n\n switch (len) {\n case 1: listeners[i].fn.call(listeners[i].context); break;\n case 2: listeners[i].fn.call(listeners[i].context, a1); break;\n case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;\n case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;\n default:\n if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {\n args[j - 1] = arguments[j];\n }\n\n listeners[i].fn.apply(listeners[i].context, args);\n }\n }\n }\n\n return true;\n};\n\n/**\n * Add a listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.on = function on(event, fn, context) {\n return addListener(this, event, fn, context, false);\n};\n\n/**\n * Add a one-time listener for a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn The listener function.\n * @param {*} [context=this] The context to invoke the listener with.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.once = function once(event, fn, context) {\n return addListener(this, event, fn, context, true);\n};\n\n/**\n * Remove the listeners of a given event.\n *\n * @param {(String|Symbol)} event The event name.\n * @param {Function} fn Only remove the listeners that match this function.\n * @param {*} context Only remove the listeners that have this context.\n * @param {Boolean} once Only remove one-time listeners.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {\n var evt = prefix ? prefix + event : event;\n\n if (!this._events[evt]) return this;\n if (!fn) {\n clearEvent(this, evt);\n return this;\n }\n\n var listeners = this._events[evt];\n\n if (listeners.fn) {\n if (\n listeners.fn === fn &&\n (!once || listeners.once) &&\n (!context || listeners.context === context)\n ) {\n clearEvent(this, evt);\n }\n } else {\n for (var i = 0, events = [], length = listeners.length; i < length; i++) {\n if (\n listeners[i].fn !== fn ||\n (once && !listeners[i].once) ||\n (context && listeners[i].context !== context)\n ) {\n events.push(listeners[i]);\n }\n }\n\n //\n // Reset the array, or remove it completely if we have no more listeners.\n //\n if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;\n else clearEvent(this, evt);\n }\n\n return this;\n};\n\n/**\n * Remove all listeners, or those of the specified event.\n *\n * @param {(String|Symbol)} [event] The event name.\n * @returns {EventEmitter} `this`.\n * @public\n */\nEventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {\n var evt;\n\n if (event) {\n evt = prefix ? prefix + event : event;\n if (this._events[evt]) clearEvent(this, evt);\n } else {\n this._events = new Events();\n this._eventsCount = 0;\n }\n\n return this;\n};\n\n//\n// Alias methods names because people roll like that.\n//\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n//\n// Expose the prefix.\n//\nEventEmitter.prefixed = prefix;\n\n//\n// Allow `EventEmitter` to be imported as module namespace.\n//\nEventEmitter.EventEmitter = EventEmitter;\n\n//\n// Expose the module.\n//\nif ('undefined' !== typeof module) {\n module.exports = EventEmitter;\n}\n","import {\n WorkerContext,\n hasUMDWorker,\n injectWorker,\n loadWorker,\n} from './inject-worker';\nimport { Events } from '../events';\nimport Transmuxer, {\n TransmuxConfig,\n TransmuxState,\n isPromise,\n} from '../demux/transmuxer';\nimport { logger } from '../utils/logger';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { getMediaSource } from '../utils/mediasource-helper';\nimport { EventEmitter } from 'eventemitter3';\nimport { Fragment, Part } from '../loader/fragment';\nimport type { ChunkMetadata, TransmuxerResult } from '../types/transmuxer';\nimport type Hls from '../hls';\nimport type { HlsEventEmitter } from '../events';\nimport type { PlaylistLevelType } from '../types/loader';\nimport type { TypeSupported } from './tsdemuxer';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\nconst MediaSource = getMediaSource() || { isTypeSupported: () => false };\n\nexport default class TransmuxerInterface {\n public error: Error | null = null;\n private hls: Hls;\n private id: PlaylistLevelType;\n private observer: HlsEventEmitter;\n private frag: Fragment | null = null;\n private part: Part | null = null;\n private useWorker: boolean;\n private workerContext: WorkerContext | null = null;\n private onwmsg?: Function;\n private transmuxer: Transmuxer | null = null;\n private onTransmuxComplete: (transmuxResult: TransmuxerResult) => void;\n private onFlush: (chunkMeta: ChunkMetadata) => void;\n\n constructor(\n hls: Hls,\n id: PlaylistLevelType,\n onTransmuxComplete: (transmuxResult: TransmuxerResult) => void,\n onFlush: (chunkMeta: ChunkMetadata) => void\n ) {\n const config = hls.config;\n this.hls = hls;\n this.id = id;\n this.useWorker = !!config.enableWorker;\n this.onTransmuxComplete = onTransmuxComplete;\n this.onFlush = onFlush;\n\n const forwardMessage = (ev, data) => {\n data = data || {};\n data.frag = this.frag;\n data.id = this.id;\n if (ev === Events.ERROR) {\n this.error = data.error;\n }\n this.hls.trigger(ev, data);\n };\n\n // forward events to main thread\n this.observer = new EventEmitter() as HlsEventEmitter;\n this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);\n this.observer.on(Events.ERROR, forwardMessage);\n\n const typeSupported: TypeSupported = {\n mp4: MediaSource.isTypeSupported('video/mp4'),\n mpeg: MediaSource.isTypeSupported('audio/mpeg'),\n mp3: MediaSource.isTypeSupported('audio/mp4; codecs=\"mp3\"'),\n };\n // navigator.vendor is not always available in Web Worker\n // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator\n const vendor = navigator.vendor;\n if (this.useWorker && typeof Worker !== 'undefined') {\n const canCreateWorker = config.workerPath || hasUMDWorker();\n if (canCreateWorker) {\n try {\n if (config.workerPath) {\n logger.log(`loading Web Worker ${config.workerPath} for \"${id}\"`);\n this.workerContext = loadWorker(config.workerPath);\n } else {\n logger.log(`injecting Web Worker for \"${id}\"`);\n this.workerContext = injectWorker();\n }\n this.onwmsg = (ev: any) => this.onWorkerMessage(ev);\n const { worker } = this.workerContext;\n worker.addEventListener('message', this.onwmsg as any);\n worker.onerror = (event) => {\n const error = new Error(\n `${event.message} (${event.filename}:${event.lineno})`\n );\n config.enableWorker = false;\n logger.warn(`Error in \"${id}\" Web Worker, fallback to inline`);\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.OTHER_ERROR,\n details: ErrorDetails.INTERNAL_EXCEPTION,\n fatal: false,\n event: 'demuxerWorker',\n error,\n });\n };\n worker.postMessage({\n cmd: 'init',\n typeSupported: typeSupported,\n vendor: vendor,\n id: id,\n config: JSON.stringify(config),\n });\n } catch (err) {\n logger.warn(\n `Error setting up \"${id}\" Web Worker, fallback to inline`,\n err\n );\n this.resetWorker();\n this.error = null;\n this.transmuxer = new Transmuxer(\n this.observer,\n typeSupported,\n config,\n vendor,\n id\n );\n }\n return;\n }\n }\n\n this.transmuxer = new Transmuxer(\n this.observer,\n typeSupported,\n config,\n vendor,\n id\n );\n }\n\n resetWorker(): void {\n if (this.workerContext) {\n const { worker, objectURL } = this.workerContext;\n if (objectURL) {\n // revoke the Object URL that was used to create transmuxer worker, so as not to leak it\n self.URL.revokeObjectURL(objectURL);\n }\n worker.removeEventListener('message', this.onwmsg as any);\n worker.onerror = null;\n worker.terminate();\n this.workerContext = null;\n }\n }\n\n destroy(): void {\n if (this.workerContext) {\n this.resetWorker();\n this.onwmsg = undefined;\n } else {\n const transmuxer = this.transmuxer;\n if (transmuxer) {\n transmuxer.destroy();\n this.transmuxer = null;\n }\n }\n const observer = this.observer;\n if (observer) {\n observer.removeAllListeners();\n }\n this.frag = null;\n // @ts-ignore\n this.observer = null;\n // @ts-ignore\n this.hls = null;\n }\n\n push(\n data: ArrayBuffer,\n initSegmentData: Uint8Array | undefined,\n audioCodec: string | undefined,\n videoCodec: string | undefined,\n frag: Fragment,\n part: Part | null,\n duration: number,\n accurateTimeOffset: boolean,\n chunkMeta: ChunkMetadata,\n defaultInitPTS?: RationalTimestamp\n ): void {\n chunkMeta.transmuxing.start = self.performance.now();\n const { transmuxer } = this;\n const timeOffset = part ? part.start : frag.start;\n // TODO: push \"clear-lead\" decrypt data for unencrypted fragments in streams with encrypted ones\n const decryptdata = frag.decryptdata;\n const lastFrag = this.frag;\n\n const discontinuity = !(lastFrag && frag.cc === lastFrag.cc);\n const trackSwitch = !(lastFrag && chunkMeta.level === lastFrag.level);\n const snDiff = lastFrag ? chunkMeta.sn - (lastFrag.sn as number) : -1;\n const partDiff = this.part ? chunkMeta.part - this.part.index : -1;\n const progressive =\n snDiff === 0 &&\n chunkMeta.id > 1 &&\n chunkMeta.id === lastFrag?.stats.chunkCount;\n const contiguous =\n !trackSwitch &&\n (snDiff === 1 ||\n (snDiff === 0 && (partDiff === 1 || (progressive && partDiff <= 0))));\n const now = self.performance.now();\n\n if (trackSwitch || snDiff || frag.stats.parsing.start === 0) {\n frag.stats.parsing.start = now;\n }\n if (part && (partDiff || !contiguous)) {\n part.stats.parsing.start = now;\n }\n const initSegmentChange = !(\n lastFrag && frag.initSegment?.url === lastFrag.initSegment?.url\n );\n const state = new TransmuxState(\n discontinuity,\n contiguous,\n accurateTimeOffset,\n trackSwitch,\n timeOffset,\n initSegmentChange\n );\n if (!contiguous || discontinuity || initSegmentChange) {\n logger.log(`[transmuxer-interface, ${frag.type}]: Starting new transmux session for sn: ${chunkMeta.sn} p: ${chunkMeta.part} level: ${chunkMeta.level} id: ${chunkMeta.id}\n discontinuity: ${discontinuity}\n trackSwitch: ${trackSwitch}\n contiguous: ${contiguous}\n accurateTimeOffset: ${accurateTimeOffset}\n timeOffset: ${timeOffset}\n initSegmentChange: ${initSegmentChange}`);\n const config = new TransmuxConfig(\n audioCodec,\n videoCodec,\n initSegmentData,\n duration,\n defaultInitPTS\n );\n this.configureTransmuxer(config);\n }\n\n this.frag = frag;\n this.part = part;\n\n // Frags with sn of 'initSegment' are not transmuxed\n if (this.workerContext) {\n // post fragment payload as transferable objects for ArrayBuffer (no copy)\n this.workerContext.worker.postMessage(\n {\n cmd: 'demux',\n data,\n decryptdata,\n chunkMeta,\n state,\n },\n data instanceof ArrayBuffer ? [data] : []\n );\n } else if (transmuxer) {\n const transmuxResult = transmuxer.push(\n data,\n decryptdata,\n chunkMeta,\n state\n );\n if (isPromise(transmuxResult)) {\n transmuxer.async = true;\n transmuxResult\n .then((data) => {\n this.handleTransmuxComplete(data);\n })\n .catch((error) => {\n this.transmuxerError(\n error,\n chunkMeta,\n 'transmuxer-interface push error'\n );\n });\n } else {\n transmuxer.async = false;\n this.handleTransmuxComplete(transmuxResult as TransmuxerResult);\n }\n }\n }\n\n flush(chunkMeta: ChunkMetadata) {\n chunkMeta.transmuxing.start = self.performance.now();\n const { transmuxer } = this;\n if (this.workerContext) {\n 1;\n this.workerContext.worker.postMessage({\n cmd: 'flush',\n chunkMeta,\n });\n } else if (transmuxer) {\n let transmuxResult = transmuxer.flush(chunkMeta);\n const asyncFlush = isPromise(transmuxResult);\n if (asyncFlush || transmuxer.async) {\n if (!isPromise(transmuxResult)) {\n transmuxResult = Promise.resolve(transmuxResult);\n }\n transmuxResult\n .then((data) => {\n this.handleFlushResult(data, chunkMeta);\n })\n .catch((error) => {\n this.transmuxerError(\n error,\n chunkMeta,\n 'transmuxer-interface flush error'\n );\n });\n } else {\n this.handleFlushResult(\n transmuxResult as Array<TransmuxerResult>,\n chunkMeta\n );\n }\n }\n }\n\n private transmuxerError(\n error: Error,\n chunkMeta: ChunkMetadata,\n reason: string\n ) {\n if (!this.hls) {\n return;\n }\n this.error = error;\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_PARSING_ERROR,\n chunkMeta,\n fatal: false,\n error,\n err: error,\n reason,\n });\n }\n\n private handleFlushResult(\n results: Array<TransmuxerResult>,\n chunkMeta: ChunkMetadata\n ) {\n results.forEach((result) => {\n this.handleTransmuxComplete(result);\n });\n this.onFlush(chunkMeta);\n }\n\n private onWorkerMessage(ev: any): void {\n const data = ev.data;\n const hls = this.hls;\n switch (data.event) {\n case 'init': {\n const objectURL = this.workerContext?.objectURL;\n if (objectURL) {\n // revoke the Object URL that was used to create transmuxer worker, so as not to leak it\n self.URL.revokeObjectURL(objectURL);\n }\n break;\n }\n\n case 'transmuxComplete': {\n this.handleTransmuxComplete(data.data);\n break;\n }\n\n case 'flush': {\n this.onFlush(data.data);\n break;\n }\n\n // pass logs from the worker thread to the main logger\n case 'workerLog':\n if (logger[data.data.logType]) {\n logger[data.data.logType](data.data.message);\n }\n break;\n\n default: {\n data.data = data.data || {};\n data.data.frag = this.frag;\n data.data.id = this.id;\n hls.trigger(data.event, data.data);\n break;\n }\n }\n }\n\n private configureTransmuxer(config: TransmuxConfig) {\n const { transmuxer } = this;\n if (this.workerContext) {\n this.workerContext.worker.postMessage({\n cmd: 'configure',\n config,\n });\n } else if (transmuxer) {\n transmuxer.configure(config);\n }\n }\n\n private handleTransmuxComplete(result: TransmuxerResult) {\n result.chunkMeta.transmuxing.end = self.performance.now();\n this.onTransmuxComplete(result);\n }\n}\n","// ensure the worker ends up in the bundle\n// If the worker should not be included this gets aliased to empty.js\nimport './transmuxer-worker';\n\nexport function hasUMDWorker(): boolean {\n return typeof __HLS_WORKER_BUNDLE__ === 'function';\n}\n\nexport type WorkerContext = {\n worker: Worker;\n objectURL?: string;\n scriptURL?: string;\n};\n\nexport function injectWorker(): WorkerContext {\n const blob = new self.Blob(\n [\n `var exports={};var module={exports:exports};function define(f){f()};define.amd=true;(${__HLS_WORKER_BUNDLE__.toString()})(true);`,\n ],\n {\n type: 'text/javascript',\n }\n );\n const objectURL = self.URL.createObjectURL(blob);\n const worker = new self.Worker(objectURL);\n\n return {\n worker,\n objectURL,\n };\n}\n\nexport function loadWorker(path: string): WorkerContext {\n const scriptURL = new self.URL(path, self.location.href).href;\n const worker = new self.Worker(scriptURL);\n\n return {\n worker,\n scriptURL,\n };\n}\n","import type { BufferInfo } from '../utils/buffer-helper';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { HlsConfig } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type { FragmentTracker } from './fragment-tracker';\n\nexport const STALL_MINIMUM_DURATION_MS = 250;\nexport const MAX_START_GAP_JUMP = 2.0;\nexport const SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;\nexport const SKIP_BUFFER_RANGE_START = 0.05;\n\nexport default class GapController {\n private config: HlsConfig;\n private media: HTMLMediaElement | null = null;\n private fragmentTracker: FragmentTracker;\n private hls: Hls;\n private nudgeRetry: number = 0;\n private stallReported: boolean = false;\n private stalled: number | null = null;\n private moved: boolean = false;\n private seeking: boolean = false;\n\n constructor(config, media, fragmentTracker, hls) {\n this.config = config;\n this.media = media;\n this.fragmentTracker = fragmentTracker;\n this.hls = hls;\n }\n\n public destroy() {\n this.media = null;\n // @ts-ignore\n this.hls = this.fragmentTracker = null;\n }\n\n /**\n * Checks if the playhead is stuck within a gap, and if so, attempts to free it.\n * A gap is an unbuffered range between two buffered ranges (or the start and the first buffered range).\n *\n * @param lastCurrentTime - Previously read playhead position\n */\n public poll(lastCurrentTime: number, activeFrag: Fragment | null) {\n const { config, media, stalled } = this;\n if (media === null) {\n return;\n }\n const { currentTime, seeking } = media;\n const seeked = this.seeking && !seeking;\n const beginSeek = !this.seeking && seeking;\n\n this.seeking = seeking;\n\n // The playhead is moving, no-op\n if (currentTime !== lastCurrentTime) {\n this.moved = true;\n if (stalled !== null) {\n // The playhead is now moving, but was previously stalled\n if (this.stallReported) {\n const stalledDuration = self.performance.now() - stalled;\n logger.warn(\n `playback not stuck anymore @${currentTime}, after ${Math.round(\n stalledDuration\n )}ms`\n );\n this.stallReported = false;\n }\n this.stalled = null;\n this.nudgeRetry = 0;\n }\n return;\n }\n\n // Clear stalled state when beginning or finishing seeking so that we don't report stalls coming out of a seek\n if (beginSeek || seeked) {\n this.stalled = null;\n return;\n }\n\n // The playhead should not be moving\n if (\n (media.paused && !seeking) ||\n media.ended ||\n media.playbackRate === 0 ||\n !BufferHelper.getBuffered(media).length\n ) {\n return;\n }\n\n const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n const isBuffered = bufferInfo.len > 0;\n const nextStart = bufferInfo.nextStart || 0;\n\n // There is no playable buffer (seeked, waiting for buffer)\n if (!isBuffered && !nextStart) {\n return;\n }\n\n if (seeking) {\n // Waiting for seeking in a buffered range to complete\n const hasEnoughBuffer = bufferInfo.len > MAX_START_GAP_JUMP;\n // Next buffered range is too far ahead to jump to while still seeking\n const noBufferGap =\n !nextStart ||\n (activeFrag && activeFrag.start <= currentTime) ||\n (nextStart - currentTime > MAX_START_GAP_JUMP &&\n !this.fragmentTracker.getPartialFragment(currentTime));\n if (hasEnoughBuffer || noBufferGap) {\n return;\n }\n // Reset moved state when seeking to a point in or before a gap\n this.moved = false;\n }\n\n // Skip start gaps if we haven't played, but the last poll detected the start of a stall\n // The addition poll gives the browser a chance to jump the gap for us\n if (!this.moved && this.stalled !== null) {\n // Jump start gaps within jump threshold\n const startJump =\n Math.max(nextStart, bufferInfo.start || 0) - currentTime;\n\n // When joining a live stream with audio tracks, account for live playlist window sliding by allowing\n // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment\n // that begins over 1 target duration after the video start position.\n const level = this.hls.levels\n ? this.hls.levels[this.hls.currentLevel]\n : null;\n const isLive = level?.details?.live;\n const maxStartGapJump = isLive\n ? level!.details!.targetduration * 2\n : MAX_START_GAP_JUMP;\n const partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);\n if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {\n this._trySkipBufferHole(partialOrGap);\n return;\n }\n }\n\n // Start tracking stall time\n const tnow = self.performance.now();\n if (stalled === null) {\n this.stalled = tnow;\n return;\n }\n\n const stalledDuration = tnow - stalled;\n if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {\n // Report stalling after trying to fix\n this._reportStall(bufferInfo);\n if (!this.media) {\n return;\n }\n }\n\n const bufferedWithHoles = BufferHelper.bufferInfo(\n media,\n currentTime,\n config.maxBufferHole\n );\n this._tryFixBufferStall(bufferedWithHoles, stalledDuration);\n }\n\n /**\n * Detects and attempts to fix known buffer stalling issues.\n * @param bufferInfo - The properties of the current buffer.\n * @param stalledDurationMs - The amount of time Hls.js has been stalling for.\n * @private\n */\n private _tryFixBufferStall(\n bufferInfo: BufferInfo,\n stalledDurationMs: number\n ) {\n const { config, fragmentTracker, media } = this;\n if (media === null) {\n return;\n }\n const currentTime = media.currentTime;\n\n const partial = fragmentTracker.getPartialFragment(currentTime);\n if (partial) {\n // Try to skip over the buffer hole caused by a partial fragment\n // This method isn't limited by the size of the gap between buffered ranges\n const targetTime = this._trySkipBufferHole(partial);\n // we return here in this case, meaning\n // the branch below only executes when we haven't seeked to a new position\n if (targetTime || !this.media) {\n return;\n }\n }\n\n // if we haven't had to skip over a buffer hole of a partial fragment\n // we may just have to \"nudge\" the playlist as the browser decoding/rendering engine\n // needs to cross some sort of threshold covering all source-buffers content\n // to start playing properly.\n if (\n (bufferInfo.len > config.maxBufferHole ||\n (bufferInfo.nextStart &&\n bufferInfo.nextStart - currentTime < config.maxBufferHole)) &&\n stalledDurationMs > config.highBufferWatchdogPeriod * 1000\n ) {\n logger.warn('Trying to nudge playhead over buffer-hole');\n // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds\n // We only try to jump the hole if it's under the configured size\n // Reset stalled so to rearm watchdog timer\n this.stalled = null;\n this._tryNudgeBuffer();\n }\n }\n\n /**\n * Triggers a BUFFER_STALLED_ERROR event, but only once per stall period.\n * @param bufferLen - The playhead distance from the end of the current buffer segment.\n * @private\n */\n private _reportStall(bufferInfo: BufferInfo) {\n const { hls, media, stallReported } = this;\n if (!stallReported && media) {\n // Report stalled error once\n this.stallReported = true;\n const error = new Error(\n `Playback stalling at @${\n media.currentTime\n } due to low buffer (${JSON.stringify(bufferInfo)})`\n );\n logger.warn(error.message);\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_STALLED_ERROR,\n fatal: false,\n error,\n buffer: bufferInfo.len,\n });\n }\n }\n\n /**\n * Attempts to fix buffer stalls by jumping over known gaps caused by partial fragments\n * @param partial - The partial fragment found at the current time (where playback is stalling).\n * @private\n */\n private _trySkipBufferHole(partial: Fragment | null): number {\n const { config, hls, media } = this;\n if (media === null) {\n return 0;\n }\n\n // Check if currentTime is between unbuffered regions of partial fragments\n const currentTime = media.currentTime;\n const bufferInfo = BufferHelper.bufferInfo(media, currentTime, 0);\n const startTime =\n currentTime < bufferInfo.start ? bufferInfo.start : bufferInfo.nextStart;\n if (startTime) {\n const bufferStarved = bufferInfo.len <= config.maxBufferHole;\n const waiting =\n bufferInfo.len > 0 && bufferInfo.len < 1 && media.readyState < 3;\n const gapLength = startTime - currentTime;\n if (gapLength > 0 && (bufferStarved || waiting)) {\n // Only allow large gaps to be skipped if it is a start gap, or all fragments in skip range are partial\n if (gapLength > config.maxBufferHole) {\n const { fragmentTracker } = this;\n let startGap = false;\n if (currentTime === 0) {\n const startFrag = fragmentTracker.getAppendedFrag(\n 0,\n PlaylistLevelType.MAIN\n );\n if (startFrag && startTime < startFrag.end) {\n startGap = true;\n }\n }\n if (!startGap) {\n const startProvisioned =\n partial ||\n fragmentTracker.getAppendedFrag(\n currentTime,\n PlaylistLevelType.MAIN\n );\n if (startProvisioned) {\n let moreToLoad = false;\n let pos = startProvisioned.end;\n while (pos < startTime) {\n const provisioned = fragmentTracker.getPartialFragment(pos);\n if (provisioned) {\n pos += provisioned.duration;\n } else {\n moreToLoad = true;\n break;\n }\n }\n if (moreToLoad) {\n return 0;\n }\n }\n }\n }\n const targetTime = Math.max(\n startTime + SKIP_BUFFER_RANGE_START,\n currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS\n );\n logger.warn(\n `skipping hole, adjusting currentTime from ${currentTime} to ${targetTime}`\n );\n this.moved = true;\n this.stalled = null;\n media.currentTime = targetTime;\n if (partial && !partial.gap) {\n const error = new Error(\n `fragment loaded with buffer holes, seeking from ${currentTime} to ${targetTime}`\n );\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_SEEK_OVER_HOLE,\n fatal: false,\n error,\n reason: error.message,\n frag: partial,\n });\n }\n return targetTime;\n }\n }\n return 0;\n }\n\n /**\n * Attempts to fix buffer stalls by advancing the mediaElement's current time by a small amount.\n * @private\n */\n private _tryNudgeBuffer() {\n const { config, hls, media, nudgeRetry } = this;\n if (media === null) {\n return;\n }\n const currentTime = media.currentTime;\n this.nudgeRetry++;\n\n if (nudgeRetry < config.nudgeMaxRetry) {\n const targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;\n // playback stalled in buffered area ... let's nudge currentTime to try to overcome this\n const error = new Error(\n `Nudging 'currentTime' from ${currentTime} to ${targetTime}`\n );\n logger.warn(error.message);\n media.currentTime = targetTime;\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_NUDGE_ON_STALL,\n error,\n fatal: false,\n });\n } else {\n const error = new Error(\n `Playhead still not moving while enough data buffered @${currentTime} after ${config.nudgeMaxRetry} nudges`\n );\n logger.error(error.message);\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_STALLED_ERROR,\n error,\n fatal: true,\n });\n }\n }\n}\n","import BaseStreamController, { State } from './base-stream-controller';\nimport { changeTypeSupported } from '../is-supported';\nimport { Events } from '../events';\nimport { BufferHelper, BufferInfo } from '../utils/buffer-helper';\nimport { FragmentState } from './fragment-tracker';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { ElementaryStreamTypes, Fragment } from '../loader/fragment';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport GapController from './gap-controller';\nimport { ErrorDetails } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { Level } from '../types/level';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { TransmuxerResult } from '../types/transmuxer';\nimport type { TrackSet } from '../types/track';\nimport type { SourceBufferName } from '../types/buffer';\nimport type {\n AudioTrackSwitchedData,\n AudioTrackSwitchingData,\n BufferCreatedData,\n BufferEOSData,\n BufferFlushedData,\n ErrorData,\n FragBufferedData,\n FragLoadedData,\n FragParsingMetadataData,\n FragParsingUserdataData,\n LevelLoadedData,\n LevelLoadingData,\n LevelsUpdatedData,\n ManifestParsedData,\n MediaAttachedData,\n} from '../types/events';\n\nconst TICK_INTERVAL = 100; // how often to tick in ms\n\nexport default class StreamController\n extends BaseStreamController\n implements NetworkComponentAPI\n{\n private audioCodecSwap: boolean = false;\n private gapController: GapController | null = null;\n private level: number = -1;\n private _forceStartLoad: boolean = false;\n private altAudio: boolean = false;\n private audioOnly: boolean = false;\n private fragPlaying: Fragment | null = null;\n private onvplaying: EventListener | null = null;\n private onvseeked: EventListener | null = null;\n private fragLastKbps: number = 0;\n private couldBacktrack: boolean = false;\n private backtrackFragment: Fragment | null = null;\n private audioCodecSwitch: boolean = false;\n private videoBuffer: any | null = null;\n\n constructor(\n hls: Hls,\n fragmentTracker: FragmentTracker,\n keyLoader: KeyLoader\n ) {\n super(\n hls,\n fragmentTracker,\n keyLoader,\n '[stream-controller]',\n PlaylistLevelType.MAIN\n );\n this._registerListeners();\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.on(\n Events.FRAG_LOAD_EMERGENCY_ABORTED,\n this.onFragLoadEmergencyAborted,\n this\n );\n hls.on(Events.ERROR, this.onError, this);\n hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n hls.on(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n protected _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.off(\n Events.FRAG_LOAD_EMERGENCY_ABORTED,\n this.onFragLoadEmergencyAborted,\n this\n );\n hls.off(Events.ERROR, this.onError, this);\n hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);\n hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n hls.off(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n hls.off(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);\n hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n protected onHandlerDestroying() {\n this._unregisterListeners();\n this.onMediaDetaching();\n }\n\n public startLoad(startPosition: number): void {\n if (this.levels) {\n const { lastCurrentTime, hls } = this;\n this.stopLoad();\n this.setInterval(TICK_INTERVAL);\n this.level = -1;\n if (!this.startFragRequested) {\n // determine load level\n let startLevel = hls.startLevel;\n if (startLevel === -1) {\n if (hls.config.testBandwidth && this.levels.length > 1) {\n // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level\n startLevel = 0;\n this.bitrateTest = true;\n } else {\n startLevel = hls.nextAutoLevel;\n }\n }\n // set new level to playlist loader : this will trigger start level load\n // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded\n this.level = hls.nextLoadLevel = startLevel;\n this.loadedmetadata = false;\n }\n // if startPosition undefined but lastCurrentTime set, set startPosition to last currentTime\n if (lastCurrentTime > 0 && startPosition === -1) {\n this.log(\n `Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(\n 3\n )}`\n );\n startPosition = lastCurrentTime;\n }\n this.state = State.IDLE;\n this.nextLoadPosition =\n this.startPosition =\n this.lastCurrentTime =\n startPosition;\n this.tick();\n } else {\n this._forceStartLoad = true;\n this.state = State.STOPPED;\n }\n }\n\n public stopLoad() {\n this._forceStartLoad = false;\n super.stopLoad();\n }\n\n protected doTick() {\n switch (this.state) {\n case State.WAITING_LEVEL: {\n const { levels, level } = this;\n const details = levels?.[level]?.details;\n if (details && (!details.live || this.levelLastLoaded === this.level)) {\n if (this.waitForCdnTuneIn(details)) {\n break;\n }\n this.state = State.IDLE;\n break;\n } else if (this.hls.nextLoadLevel !== this.level) {\n this.state = State.IDLE;\n break;\n }\n break;\n }\n case State.FRAG_LOADING_WAITING_RETRY:\n {\n const now = self.performance.now();\n const retryDate = this.retryDate;\n // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading\n if (!retryDate || now >= retryDate || this.media?.seeking) {\n this.resetStartWhenNotLoaded(this.level);\n this.state = State.IDLE;\n }\n }\n break;\n default:\n break;\n }\n if (this.state === State.IDLE) {\n this.doTickIdle();\n }\n this.onTickEnd();\n }\n\n protected onTickEnd() {\n super.onTickEnd();\n this.checkBuffer();\n this.checkFragmentChanged();\n }\n\n private doTickIdle() {\n const { hls, levelLastLoaded, levels, media } = this;\n const { config, nextLoadLevel: level } = hls;\n\n // if start level not parsed yet OR\n // if video not attached AND start fragment already requested OR start frag prefetch not enabled\n // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment\n if (\n levelLastLoaded === null ||\n (!media && (this.startFragRequested || !config.startFragPrefetch))\n ) {\n return;\n }\n\n // If the \"main\" level is audio-only but we are loading an alternate track in the same group, do not load anything\n if (this.altAudio && this.audioOnly) {\n return;\n }\n\n if (!levels?.[level]) {\n return;\n }\n\n const levelInfo = levels[level];\n\n // if buffer length is less than maxBufLen try to load a new fragment\n\n const bufferInfo = this.getMainFwdBufferInfo();\n if (bufferInfo === null) {\n return;\n }\n\n const lastDetails = this.getLevelDetails();\n if (lastDetails && this._streamEnded(bufferInfo, lastDetails)) {\n const data: BufferEOSData = {};\n if (this.altAudio) {\n data.type = 'video';\n }\n\n this.hls.trigger(Events.BUFFER_EOS, data);\n this.state = State.ENDED;\n return;\n }\n\n // set next load level : this will trigger a playlist load if needed\n if (hls.loadLevel !== level && hls.manualLevel === -1) {\n this.log(`Adapting to level ${level} from level ${this.level}`);\n }\n this.level = hls.nextLoadLevel = level;\n\n const levelDetails = levelInfo.details;\n // if level info not retrieved yet, switch state and wait for level retrieval\n // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load\n // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)\n if (\n !levelDetails ||\n this.state === State.WAITING_LEVEL ||\n (levelDetails.live && this.levelLastLoaded !== level)\n ) {\n this.level = level;\n this.state = State.WAITING_LEVEL;\n return;\n }\n\n const bufferLen = bufferInfo.len;\n\n // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s\n const maxBufLen = this.getMaxBufferLength(levelInfo.maxBitrate);\n\n // Stay idle if we are still with buffer margins\n if (bufferLen >= maxBufLen) {\n return;\n }\n\n if (\n this.backtrackFragment &&\n this.backtrackFragment.start > bufferInfo.end\n ) {\n this.backtrackFragment = null;\n }\n const targetBufferTime = this.backtrackFragment\n ? this.backtrackFragment.start\n : bufferInfo.end;\n let frag = this.getNextFragment(targetBufferTime, levelDetails);\n // Avoid backtracking by loading an earlier segment in streams with segments that do not start with a key frame (flagged by `couldBacktrack`)\n if (\n this.couldBacktrack &&\n !this.fragPrevious &&\n frag &&\n frag.sn !== 'initSegment' &&\n this.fragmentTracker.getState(frag) !== FragmentState.OK\n ) {\n const backtrackSn = (this.backtrackFragment ?? frag).sn as number;\n const fragIdx = backtrackSn - levelDetails.startSN;\n const backtrackFrag = levelDetails.fragments[fragIdx - 1];\n if (backtrackFrag && frag.cc === backtrackFrag.cc) {\n frag = backtrackFrag;\n this.fragmentTracker.removeFragment(backtrackFrag);\n }\n } else if (this.backtrackFragment && bufferInfo.len) {\n this.backtrackFragment = null;\n }\n // Avoid loop loading by using nextLoadPosition set for backtracking and skipping consecutive GAP tags\n if (frag && this.isLoopLoading(frag, targetBufferTime)) {\n const gapStart = frag.gap;\n if (!gapStart) {\n // Cleanup the fragment tracker before trying to find the next unbuffered fragment\n const type =\n this.audioOnly && !this.altAudio\n ? ElementaryStreamTypes.AUDIO\n : ElementaryStreamTypes.VIDEO;\n const mediaBuffer =\n (type === ElementaryStreamTypes.VIDEO\n ? this.videoBuffer\n : this.mediaBuffer) || this.media;\n if (mediaBuffer) {\n this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.MAIN);\n }\n }\n frag = this.getNextFragmentLoopLoading(\n frag,\n levelDetails,\n bufferInfo,\n PlaylistLevelType.MAIN,\n maxBufLen\n );\n }\n if (!frag) {\n return;\n }\n if (frag.initSegment && !frag.initSegment.data && !this.bitrateTest) {\n frag = frag.initSegment;\n }\n\n this.loadFragment(frag, levelInfo, targetBufferTime);\n }\n\n protected loadFragment(\n frag: Fragment,\n level: Level,\n targetBufferTime: number\n ) {\n // Check if fragment is not loaded\n const fragState = this.fragmentTracker.getState(frag);\n this.fragCurrent = frag;\n if (\n fragState === FragmentState.NOT_LOADED ||\n fragState === FragmentState.PARTIAL\n ) {\n if (frag.sn === 'initSegment') {\n this._loadInitSegment(frag, level);\n } else if (this.bitrateTest) {\n this.log(\n `Fragment ${frag.sn} of level ${frag.level} is being downloaded to test bitrate and will not be buffered`\n );\n this._loadBitrateTestFrag(frag, level);\n } else {\n this.startFragRequested = true;\n super.loadFragment(frag, level, targetBufferTime);\n }\n } else {\n this.clearTrackerIfNeeded(frag);\n }\n }\n\n private getBufferedFrag(position) {\n return this.fragmentTracker.getBufferedFrag(\n position,\n PlaylistLevelType.MAIN\n );\n }\n\n private followingBufferedFrag(frag: Fragment | null) {\n if (frag) {\n // try to get range of next fragment (500ms after this range)\n return this.getBufferedFrag(frag.end + 0.5);\n }\n return null;\n }\n\n /*\n on immediate level switch :\n - pause playback if playing\n - cancel any pending load request\n - and trigger a buffer flush\n */\n public immediateLevelSwitch() {\n this.abortCurrentFrag();\n this.flushMainBuffer(0, Number.POSITIVE_INFINITY);\n }\n\n /**\n * try to switch ASAP without breaking video playback:\n * in order to ensure smooth but quick level switching,\n * we need to find the next flushable buffer range\n * we should take into account new segment fetch time\n */\n public nextLevelSwitch() {\n const { levels, media } = this;\n // ensure that media is defined and that metadata are available (to retrieve currentTime)\n if (media?.readyState) {\n let fetchdelay;\n const fragPlayingCurrent = this.getAppendedFrag(media.currentTime);\n if (fragPlayingCurrent && fragPlayingCurrent.start > 1) {\n // flush buffer preceding current fragment (flush until current fragment start offset)\n // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ...\n this.flushMainBuffer(0, fragPlayingCurrent.start - 1);\n }\n const levelDetails = this.getLevelDetails();\n if (levelDetails?.live) {\n const bufferInfo = this.getMainFwdBufferInfo();\n // Do not flush in live stream with low buffer\n if (!bufferInfo || bufferInfo.len < levelDetails.targetduration * 2) {\n return;\n }\n }\n if (!media.paused && levels) {\n // add a safety delay of 1s\n const nextLevelId = this.hls.nextLoadLevel;\n const nextLevel = levels[nextLevelId];\n const fragLastKbps = this.fragLastKbps;\n if (fragLastKbps && this.fragCurrent) {\n fetchdelay =\n (this.fragCurrent.duration * nextLevel.maxBitrate) /\n (1000 * fragLastKbps) +\n 1;\n } else {\n fetchdelay = 0;\n }\n } else {\n fetchdelay = 0;\n }\n // this.log('fetchdelay:'+fetchdelay);\n // find buffer range that will be reached once new fragment will be fetched\n const bufferedFrag = this.getBufferedFrag(media.currentTime + fetchdelay);\n if (bufferedFrag) {\n // we can flush buffer range following this one without stalling playback\n const nextBufferedFrag = this.followingBufferedFrag(bufferedFrag);\n if (nextBufferedFrag) {\n // if we are here, we can also cancel any loading/demuxing in progress, as they are useless\n this.abortCurrentFrag();\n // start flush position is in next buffered frag. Leave some padding for non-independent segments and smoother playback.\n const maxStart = nextBufferedFrag.maxStartPTS\n ? nextBufferedFrag.maxStartPTS\n : nextBufferedFrag.start;\n const fragDuration = nextBufferedFrag.duration;\n const startPts = Math.max(\n bufferedFrag.end,\n maxStart +\n Math.min(\n Math.max(\n fragDuration - this.config.maxFragLookUpTolerance,\n fragDuration * 0.5\n ),\n fragDuration * 0.75\n )\n );\n this.flushMainBuffer(startPts, Number.POSITIVE_INFINITY);\n }\n }\n }\n }\n\n private abortCurrentFrag() {\n const fragCurrent = this.fragCurrent;\n this.fragCurrent = null;\n this.backtrackFragment = null;\n if (fragCurrent) {\n fragCurrent.abortRequests();\n this.fragmentTracker.removeFragment(fragCurrent);\n }\n switch (this.state) {\n case State.KEY_LOADING:\n case State.FRAG_LOADING:\n case State.FRAG_LOADING_WAITING_RETRY:\n case State.PARSING:\n case State.PARSED:\n this.state = State.IDLE;\n break;\n }\n this.nextLoadPosition = this.getLoadPosition();\n }\n\n protected flushMainBuffer(startOffset: number, endOffset: number) {\n super.flushMainBuffer(\n startOffset,\n endOffset,\n this.altAudio ? 'video' : null\n );\n }\n\n protected onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ) {\n super.onMediaAttached(event, data);\n const media = data.media;\n this.onvplaying = this.onMediaPlaying.bind(this);\n this.onvseeked = this.onMediaSeeked.bind(this);\n media.addEventListener('playing', this.onvplaying as EventListener);\n media.addEventListener('seeked', this.onvseeked as EventListener);\n this.gapController = new GapController(\n this.config,\n media,\n this.fragmentTracker,\n this.hls\n );\n }\n\n protected onMediaDetaching() {\n const { media } = this;\n if (media && this.onvplaying && this.onvseeked) {\n media.removeEventListener('playing', this.onvplaying);\n media.removeEventListener('seeked', this.onvseeked);\n this.onvplaying = this.onvseeked = null;\n this.videoBuffer = null;\n }\n this.fragPlaying = null;\n if (this.gapController) {\n this.gapController.destroy();\n this.gapController = null;\n }\n super.onMediaDetaching();\n }\n\n private onMediaPlaying() {\n // tick to speed up FRAG_CHANGED triggering\n this.tick();\n }\n\n private onMediaSeeked() {\n const media = this.media;\n const currentTime = media ? media.currentTime : null;\n if (Number.isFinite(currentTime)) {\n this.log(`Media seeked to ${(currentTime as number).toFixed(3)}`);\n }\n\n // If seeked was issued before buffer was appended do not tick immediately\n const bufferInfo = this.getMainFwdBufferInfo();\n if (bufferInfo === null || bufferInfo.len === 0) {\n this.warn(\n `Main forward buffer length on \"seeked\" event ${\n bufferInfo ? bufferInfo.len : 'empty'\n })`\n );\n return;\n }\n\n // tick to speed up FRAG_CHANGED triggering\n this.tick();\n }\n\n private onManifestLoading() {\n // reset buffer on manifest loading\n this.log('Trigger BUFFER_RESET');\n this.hls.trigger(Events.BUFFER_RESET, undefined);\n this.fragmentTracker.removeAllFragments();\n this.couldBacktrack = false;\n this.startPosition = this.lastCurrentTime = 0;\n this.levels = this.fragPlaying = this.backtrackFragment = null;\n this.altAudio = this.audioOnly = false;\n }\n\n private onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ) {\n let aac = false;\n let heaac = false;\n let codec;\n data.levels.forEach((level) => {\n // detect if we have different kind of audio codecs used amongst playlists\n codec = level.audioCodec;\n if (codec) {\n if (codec.indexOf('mp4a.40.2') !== -1) {\n aac = true;\n }\n\n if (codec.indexOf('mp4a.40.5') !== -1) {\n heaac = true;\n }\n }\n });\n this.audioCodecSwitch = aac && heaac && !changeTypeSupported();\n if (this.audioCodecSwitch) {\n this.log(\n 'Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'\n );\n }\n\n this.levels = data.levels;\n this.startFragRequested = false;\n }\n\n private onLevelLoading(event: Events.LEVEL_LOADING, data: LevelLoadingData) {\n const { levels } = this;\n if (!levels || this.state !== State.IDLE) {\n return;\n }\n const level = levels[data.level];\n if (\n !level.details ||\n (level.details.live && this.levelLastLoaded !== data.level) ||\n this.waitForCdnTuneIn(level.details)\n ) {\n this.state = State.WAITING_LEVEL;\n }\n }\n\n private onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n const { levels } = this;\n const newLevelId = data.level;\n const newDetails = data.details;\n const duration = newDetails.totalduration;\n\n if (!levels) {\n this.warn(`Levels were reset while loading level ${newLevelId}`);\n return;\n }\n this.log(\n `Level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}]${\n newDetails.lastPartSn\n ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]`\n : ''\n }, cc [${newDetails.startCC}, ${newDetails.endCC}] duration:${duration}`\n );\n\n const curLevel = levels[newLevelId];\n const fragCurrent = this.fragCurrent;\n if (\n fragCurrent &&\n (this.state === State.FRAG_LOADING ||\n this.state === State.FRAG_LOADING_WAITING_RETRY)\n ) {\n if (\n (fragCurrent.level !== data.level ||\n fragCurrent.urlId !== curLevel.urlId) &&\n fragCurrent.loader\n ) {\n this.abortCurrentFrag();\n }\n }\n\n let sliding = 0;\n if (newDetails.live || curLevel.details?.live) {\n if (!newDetails.fragments[0]) {\n newDetails.deltaUpdateFailed = true;\n }\n if (newDetails.deltaUpdateFailed) {\n return;\n }\n sliding = this.alignPlaylists(newDetails, curLevel.details);\n }\n // override level info\n curLevel.details = newDetails;\n this.levelLastLoaded = newLevelId;\n\n this.hls.trigger(Events.LEVEL_UPDATED, {\n details: newDetails,\n level: newLevelId,\n });\n\n // only switch back to IDLE state if we were waiting for level to start downloading a new fragment\n if (this.state === State.WAITING_LEVEL) {\n if (this.waitForCdnTuneIn(newDetails)) {\n // Wait for Low-Latency CDN Tune-in\n return;\n }\n this.state = State.IDLE;\n }\n\n if (!this.startFragRequested) {\n this.setStartPosition(newDetails, sliding);\n } else if (newDetails.live) {\n this.synchronizeToLiveEdge(newDetails);\n }\n\n // trigger handler right now\n this.tick();\n }\n\n protected _handleFragmentLoadProgress(data: FragLoadedData) {\n const { frag, part, payload } = data;\n const { levels } = this;\n if (!levels) {\n this.warn(\n `Levels were reset while fragment load was in progress. Fragment ${frag.sn} of level ${frag.level} will not be buffered`\n );\n return;\n }\n const currentLevel = levels[frag.level];\n const details = currentLevel.details as LevelDetails;\n if (!details) {\n this.warn(\n `Dropping fragment ${frag.sn} of level ${frag.level} after level details were reset`\n );\n this.fragmentTracker.removeFragment(frag);\n return;\n }\n const videoCodec = currentLevel.videoCodec;\n\n // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live)\n const accurateTimeOffset = details.PTSKnown || !details.live;\n const initSegmentData = frag.initSegment?.data;\n const audioCodec = this._getAudioCodec(currentLevel);\n\n // transmux the MPEG-TS data to ISO-BMFF segments\n // this.log(`Transmuxing ${frag.sn} of [${details.startSN} ,${details.endSN}],level ${frag.level}, cc ${frag.cc}`);\n const transmuxer = (this.transmuxer =\n this.transmuxer ||\n new TransmuxerInterface(\n this.hls,\n PlaylistLevelType.MAIN,\n this._handleTransmuxComplete.bind(this),\n this._handleTransmuxerFlush.bind(this)\n ));\n const partIndex = part ? part.index : -1;\n const partial = partIndex !== -1;\n const chunkMeta = new ChunkMetadata(\n frag.level,\n frag.sn as number,\n frag.stats.chunkCount,\n payload.byteLength,\n partIndex,\n partial\n );\n const initPTS = this.initPTS[frag.cc];\n\n transmuxer.push(\n payload,\n initSegmentData,\n audioCodec,\n videoCodec,\n frag,\n part,\n details.totalduration,\n accurateTimeOffset,\n chunkMeta,\n initPTS\n );\n }\n\n private onAudioTrackSwitching(\n event: Events.AUDIO_TRACK_SWITCHING,\n data: AudioTrackSwitchingData\n ) {\n // if any URL found on new audio track, it is an alternate audio track\n const fromAltAudio = this.altAudio;\n const altAudio = !!data.url;\n // if we switch on main audio, ensure that main fragment scheduling is synced with media.buffered\n // don't do anything if we switch to alt audio: audio stream controller is handling it.\n // we will just have to change buffer scheduling on audioTrackSwitched\n if (!altAudio) {\n if (this.mediaBuffer !== this.media) {\n this.log(\n 'Switching on main audio, use media.buffered to schedule main fragment loading'\n );\n this.mediaBuffer = this.media;\n const fragCurrent = this.fragCurrent;\n // we need to refill audio buffer from main: cancel any frag loading to speed up audio switch\n if (fragCurrent) {\n this.log('Switching to main audio track, cancel main fragment load');\n fragCurrent.abortRequests();\n this.fragmentTracker.removeFragment(fragCurrent);\n }\n // destroy transmuxer to force init segment generation (following audio switch)\n this.resetTransmuxer();\n // switch to IDLE state to load new fragment\n this.resetLoadingState();\n } else if (this.audioOnly) {\n // Reset audio transmuxer so when switching back to main audio we're not still appending where we left off\n this.resetTransmuxer();\n }\n const hls = this.hls;\n // If switching from alt to main audio, flush all audio and trigger track switched\n if (fromAltAudio) {\n hls.trigger(Events.BUFFER_FLUSHING, {\n startOffset: 0,\n endOffset: Number.POSITIVE_INFINITY,\n type: null,\n });\n this.fragmentTracker.removeAllFragments();\n }\n hls.trigger(Events.AUDIO_TRACK_SWITCHED, data);\n }\n }\n\n private onAudioTrackSwitched(\n event: Events.AUDIO_TRACK_SWITCHED,\n data: AudioTrackSwitchedData\n ) {\n const trackId = data.id;\n const altAudio = !!this.hls.audioTracks[trackId].url;\n if (altAudio) {\n const videoBuffer = this.videoBuffer;\n // if we switched on alternate audio, ensure that main fragment scheduling is synced with video sourcebuffer buffered\n if (videoBuffer && this.mediaBuffer !== videoBuffer) {\n this.log(\n 'Switching on alternate audio, use video.buffered to schedule main fragment loading'\n );\n this.mediaBuffer = videoBuffer;\n }\n }\n this.altAudio = altAudio;\n this.tick();\n }\n\n private onBufferCreated(\n event: Events.BUFFER_CREATED,\n data: BufferCreatedData\n ) {\n const tracks = data.tracks;\n let mediaTrack;\n let name;\n let alternate = false;\n for (const type in tracks) {\n const track = tracks[type];\n if (track.id === 'main') {\n name = type;\n mediaTrack = track;\n // keep video source buffer reference\n if (type === 'video') {\n const videoTrack = tracks[type];\n if (videoTrack) {\n this.videoBuffer = videoTrack.buffer;\n }\n }\n } else {\n alternate = true;\n }\n }\n if (alternate && mediaTrack) {\n this.log(\n `Alternate track found, use ${name}.buffered to schedule main fragment loading`\n );\n this.mediaBuffer = mediaTrack.buffer;\n } else {\n this.mediaBuffer = this.media;\n }\n }\n\n private onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n const { frag, part } = data;\n if (frag && frag.type !== PlaylistLevelType.MAIN) {\n return;\n }\n if (this.fragContextChanged(frag)) {\n // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion\n // Avoid setting state back to IDLE, since that will interfere with a level switch\n this.warn(\n `Fragment ${frag.sn}${part ? ' p: ' + part.index : ''} of level ${\n frag.level\n } finished buffering, but was aborted. state: ${this.state}`\n );\n if (this.state === State.PARSED) {\n this.state = State.IDLE;\n }\n return;\n }\n const stats = part ? part.stats : frag.stats;\n this.fragLastKbps = Math.round(\n (8 * stats.total) / (stats.buffering.end - stats.loading.first)\n );\n if (frag.sn !== 'initSegment') {\n this.fragPrevious = frag;\n }\n this.fragBufferedComplete(frag, part);\n }\n\n private onError(event: Events.ERROR, data: ErrorData) {\n if (data.fatal) {\n this.state = State.ERROR;\n return;\n }\n switch (data.details) {\n case ErrorDetails.FRAG_GAP:\n case ErrorDetails.FRAG_PARSING_ERROR:\n case ErrorDetails.FRAG_DECRYPT_ERROR:\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n case ErrorDetails.KEY_LOAD_ERROR:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n this.onFragmentOrKeyLoadError(PlaylistLevelType.MAIN, data);\n break;\n case ErrorDetails.LEVEL_LOAD_ERROR:\n case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n case ErrorDetails.LEVEL_PARSING_ERROR:\n // in case of non fatal error while loading level, if level controller is not retrying to load level, switch back to IDLE\n if (\n !data.levelRetry &&\n this.state === State.WAITING_LEVEL &&\n data.context?.type === PlaylistContextType.LEVEL\n ) {\n this.state = State.IDLE;\n }\n break;\n case ErrorDetails.BUFFER_FULL_ERROR:\n if (!data.parent || data.parent !== 'main') {\n return;\n }\n if (this.reduceLengthAndFlushBuffer(data)) {\n this.flushMainBuffer(0, Number.POSITIVE_INFINITY);\n }\n break;\n case ErrorDetails.INTERNAL_EXCEPTION:\n this.recoverWorkerError(data);\n break;\n default:\n break;\n }\n }\n\n // Checks the health of the buffer and attempts to resolve playback stalls.\n private checkBuffer() {\n const { media, gapController } = this;\n if (!media || !gapController || !media.readyState) {\n // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0)\n return;\n }\n\n if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {\n // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers\n const activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;\n gapController.poll(this.lastCurrentTime, activeFrag);\n }\n\n this.lastCurrentTime = media.currentTime;\n }\n\n private onFragLoadEmergencyAborted() {\n this.state = State.IDLE;\n // if loadedmetadata is not set, it means that we are emergency switch down on first frag\n // in that case, reset startFragRequested flag\n if (!this.loadedmetadata) {\n this.startFragRequested = false;\n this.nextLoadPosition = this.startPosition;\n }\n this.tickImmediate();\n }\n\n private onBufferFlushed(\n event: Events.BUFFER_FLUSHED,\n { type }: BufferFlushedData\n ) {\n if (\n type !== ElementaryStreamTypes.AUDIO ||\n (this.audioOnly && !this.altAudio)\n ) {\n const mediaBuffer =\n (type === ElementaryStreamTypes.VIDEO\n ? this.videoBuffer\n : this.mediaBuffer) || this.media;\n this.afterBufferFlushed(mediaBuffer, type, PlaylistLevelType.MAIN);\n }\n }\n\n private onLevelsUpdated(\n event: Events.LEVELS_UPDATED,\n data: LevelsUpdatedData\n ) {\n this.levels = data.levels;\n }\n\n public swapAudioCodec() {\n this.audioCodecSwap = !this.audioCodecSwap;\n }\n\n /**\n * Seeks to the set startPosition if not equal to the mediaElement's current time.\n */\n protected seekToStartPos() {\n const { media } = this;\n if (!media) {\n return;\n }\n const currentTime = media.currentTime;\n let startPosition = this.startPosition;\n // only adjust currentTime if different from startPosition or if startPosition not buffered\n // at that stage, there should be only one buffered range, as we reach that code after first fragment has been buffered\n if (startPosition >= 0 && currentTime < startPosition) {\n if (media.seeking) {\n this.log(\n `could not seek to ${startPosition}, already seeking at ${currentTime}`\n );\n return;\n }\n const buffered = BufferHelper.getBuffered(media);\n const bufferStart = buffered.length ? buffered.start(0) : 0;\n const delta = bufferStart - startPosition;\n if (\n delta > 0 &&\n (delta < this.config.maxBufferHole ||\n delta < this.config.maxFragLookUpTolerance)\n ) {\n this.log(`adjusting start position by ${delta} to match buffer start`);\n startPosition += delta;\n this.startPosition = startPosition;\n }\n this.log(\n `seek to target start position ${startPosition} from current time ${currentTime}`\n );\n media.currentTime = startPosition;\n }\n }\n\n private _getAudioCodec(currentLevel) {\n let audioCodec = this.config.defaultAudioCodec || currentLevel.audioCodec;\n if (this.audioCodecSwap && audioCodec) {\n this.log('Swapping audio codec');\n if (audioCodec.indexOf('mp4a.40.5') !== -1) {\n audioCodec = 'mp4a.40.2';\n } else {\n audioCodec = 'mp4a.40.5';\n }\n }\n\n return audioCodec;\n }\n\n private _loadBitrateTestFrag(frag: Fragment, level: Level) {\n frag.bitrateTest = true;\n this._doFragLoad(frag, level).then((data) => {\n const { hls } = this;\n if (!data || this.fragContextChanged(frag)) {\n return;\n }\n level.fragmentError = 0;\n this.state = State.IDLE;\n this.startFragRequested = false;\n this.bitrateTest = false;\n const stats = frag.stats;\n // Bitrate tests fragments are neither parsed nor buffered\n stats.parsing.start =\n stats.parsing.end =\n stats.buffering.start =\n stats.buffering.end =\n self.performance.now();\n hls.trigger(Events.FRAG_LOADED, data as FragLoadedData);\n frag.bitrateTest = false;\n });\n }\n\n private _handleTransmuxComplete(transmuxResult: TransmuxerResult) {\n const id = 'main';\n const { hls } = this;\n const { remuxResult, chunkMeta } = transmuxResult;\n\n const context = this.getCurrentContext(chunkMeta);\n if (!context) {\n this.resetWhenMissingContext(chunkMeta);\n return;\n }\n const { frag, part, level } = context;\n const { video, text, id3, initSegment } = remuxResult;\n const { details } = level;\n // The audio-stream-controller handles audio buffering if Hls.js is playing an alternate audio track\n const audio = this.altAudio ? undefined : remuxResult.audio;\n\n // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level.\n // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed.\n if (this.fragContextChanged(frag)) {\n this.fragmentTracker.removeFragment(frag);\n return;\n }\n\n this.state = State.PARSING;\n\n if (initSegment) {\n if (initSegment?.tracks) {\n const mapFragment = frag.initSegment || frag;\n this._bufferInitSegment(\n level,\n initSegment.tracks,\n mapFragment,\n chunkMeta\n );\n hls.trigger(Events.FRAG_PARSING_INIT_SEGMENT, {\n frag: mapFragment,\n id,\n tracks: initSegment.tracks,\n });\n }\n\n // This would be nice if Number.isFinite acted as a typeguard, but it doesn't. See: https://github.com/Microsoft/TypeScript/issues/10038\n const initPTS = initSegment.initPTS as number;\n const timescale = initSegment.timescale as number;\n if (Number.isFinite(initPTS)) {\n this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n hls.trigger(Events.INIT_PTS_FOUND, { frag, id, initPTS, timescale });\n }\n }\n\n // Avoid buffering if backtracking this fragment\n if (video && remuxResult.independent !== false) {\n if (details) {\n const { startPTS, endPTS, startDTS, endDTS } = video;\n if (part) {\n part.elementaryStreams[video.type] = {\n startPTS,\n endPTS,\n startDTS,\n endDTS,\n };\n } else {\n if (video.firstKeyFrame && video.independent && chunkMeta.id === 1) {\n this.couldBacktrack = true;\n }\n if (video.dropped && video.independent) {\n // Backtrack if dropped frames create a gap after currentTime\n\n const bufferInfo = this.getMainFwdBufferInfo();\n const targetBufferTime =\n (bufferInfo ? bufferInfo.end : this.getLoadPosition()) +\n this.config.maxBufferHole;\n const startTime = video.firstKeyFramePTS\n ? video.firstKeyFramePTS\n : startPTS;\n if (targetBufferTime < startTime - this.config.maxBufferHole) {\n this.backtrack(frag);\n return;\n }\n // Set video stream start to fragment start so that truncated samples do not distort the timeline, and mark it partial\n frag.setElementaryStreamInfo(\n video.type as ElementaryStreamTypes,\n frag.start,\n endPTS,\n frag.start,\n endDTS,\n true\n );\n }\n }\n frag.setElementaryStreamInfo(\n video.type as ElementaryStreamTypes,\n startPTS,\n endPTS,\n startDTS,\n endDTS\n );\n if (this.backtrackFragment) {\n this.backtrackFragment = frag;\n }\n this.bufferFragmentData(video, frag, part, chunkMeta);\n }\n } else if (remuxResult.independent === false) {\n this.backtrack(frag);\n return;\n }\n\n if (audio) {\n const { startPTS, endPTS, startDTS, endDTS } = audio;\n if (part) {\n part.elementaryStreams[ElementaryStreamTypes.AUDIO] = {\n startPTS,\n endPTS,\n startDTS,\n endDTS,\n };\n }\n frag.setElementaryStreamInfo(\n ElementaryStreamTypes.AUDIO,\n startPTS,\n endPTS,\n startDTS,\n endDTS\n );\n this.bufferFragmentData(audio, frag, part, chunkMeta);\n }\n\n if (details && id3?.samples?.length) {\n const emittedID3: FragParsingMetadataData = {\n id,\n frag,\n details,\n samples: id3.samples,\n };\n hls.trigger(Events.FRAG_PARSING_METADATA, emittedID3);\n }\n if (details && text) {\n const emittedText: FragParsingUserdataData = {\n id,\n frag,\n details,\n samples: text.samples,\n };\n hls.trigger(Events.FRAG_PARSING_USERDATA, emittedText);\n }\n }\n\n private _bufferInitSegment(\n currentLevel: Level,\n tracks: TrackSet,\n frag: Fragment,\n chunkMeta: ChunkMetadata\n ) {\n if (this.state !== State.PARSING) {\n return;\n }\n\n this.audioOnly = !!tracks.audio && !tracks.video;\n\n // if audio track is expected to come from audio stream controller, discard any coming from main\n if (this.altAudio && !this.audioOnly) {\n delete tracks.audio;\n }\n // include levelCodec in audio and video tracks\n const { audio, video, audiovideo } = tracks;\n if (audio) {\n let audioCodec = currentLevel.audioCodec;\n const ua = navigator.userAgent.toLowerCase();\n if (this.audioCodecSwitch) {\n if (audioCodec) {\n if (audioCodec.indexOf('mp4a.40.5') !== -1) {\n audioCodec = 'mp4a.40.2';\n } else {\n audioCodec = 'mp4a.40.5';\n }\n }\n // In the case that AAC and HE-AAC audio codecs are signalled in manifest,\n // force HE-AAC, as it seems that most browsers prefers it.\n // don't force HE-AAC if mono stream, or in Firefox\n if (audio.metadata.channelCount !== 1 && ua.indexOf('firefox') === -1) {\n audioCodec = 'mp4a.40.5';\n }\n }\n // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise\n if (ua.indexOf('android') !== -1 && audio.container !== 'audio/mpeg') {\n // Exclude mpeg audio\n audioCodec = 'mp4a.40.2';\n this.log(`Android: force audio codec to ${audioCodec}`);\n }\n if (currentLevel.audioCodec && currentLevel.audioCodec !== audioCodec) {\n this.log(\n `Swapping manifest audio codec \"${currentLevel.audioCodec}\" for \"${audioCodec}\"`\n );\n }\n audio.levelCodec = audioCodec;\n audio.id = 'main';\n this.log(\n `Init audio buffer, container:${\n audio.container\n }, codecs[selected/level/parsed]=[${audioCodec || ''}/${\n currentLevel.audioCodec || ''\n }/${audio.codec}]`\n );\n }\n if (video) {\n video.levelCodec = currentLevel.videoCodec;\n video.id = 'main';\n this.log(\n `Init video buffer, container:${\n video.container\n }, codecs[level/parsed]=[${currentLevel.videoCodec || ''}/${\n video.codec\n }]`\n );\n }\n if (audiovideo) {\n this.log(\n `Init audiovideo buffer, container:${\n audiovideo.container\n }, codecs[level/parsed]=[${currentLevel.attrs.CODECS || ''}/${\n audiovideo.codec\n }]`\n );\n }\n this.hls.trigger(Events.BUFFER_CODECS, tracks);\n // loop through tracks that are going to be provided to bufferController\n Object.keys(tracks).forEach((trackName) => {\n const track = tracks[trackName];\n const initSegment = track.initSegment;\n if (initSegment?.byteLength) {\n this.hls.trigger(Events.BUFFER_APPENDING, {\n type: trackName as SourceBufferName,\n data: initSegment,\n frag,\n part: null,\n chunkMeta,\n parent: frag.type,\n });\n }\n });\n // trigger handler right now\n this.tick();\n }\n\n public getMainFwdBufferInfo(): BufferInfo | null {\n return this.getFwdBufferInfo(\n this.mediaBuffer ? this.mediaBuffer : this.media,\n PlaylistLevelType.MAIN\n );\n }\n\n private backtrack(frag: Fragment) {\n this.couldBacktrack = true;\n // Causes findFragments to backtrack through fragments to find the keyframe\n this.backtrackFragment = frag;\n this.resetTransmuxer();\n this.flushBufferGap(frag);\n this.fragmentTracker.removeFragment(frag);\n this.fragPrevious = null;\n this.nextLoadPosition = frag.start;\n this.state = State.IDLE;\n }\n\n private checkFragmentChanged() {\n const video = this.media;\n let fragPlayingCurrent: Fragment | null = null;\n if (video && video.readyState > 1 && video.seeking === false) {\n const currentTime = video.currentTime;\n /* if video element is in seeked state, currentTime can only increase.\n (assuming that playback rate is positive ...)\n As sometimes currentTime jumps back to zero after a\n media decode error, check this, to avoid seeking back to\n wrong position after a media decode error\n */\n\n if (BufferHelper.isBuffered(video, currentTime)) {\n fragPlayingCurrent = this.getAppendedFrag(currentTime);\n } else if (BufferHelper.isBuffered(video, currentTime + 0.1)) {\n /* ensure that FRAG_CHANGED event is triggered at startup,\n when first video frame is displayed and playback is paused.\n add a tolerance of 100ms, in case current position is not buffered,\n check if current pos+100ms is buffered and use that buffer range\n for FRAG_CHANGED event reporting */\n fragPlayingCurrent = this.getAppendedFrag(currentTime + 0.1);\n }\n if (fragPlayingCurrent) {\n this.backtrackFragment = null;\n const fragPlaying = this.fragPlaying;\n const fragCurrentLevel = fragPlayingCurrent.level;\n if (\n !fragPlaying ||\n fragPlayingCurrent.sn !== fragPlaying.sn ||\n fragPlaying.level !== fragCurrentLevel ||\n fragPlayingCurrent.urlId !== fragPlaying.urlId\n ) {\n this.fragPlaying = fragPlayingCurrent;\n this.hls.trigger(Events.FRAG_CHANGED, { frag: fragPlayingCurrent });\n if (!fragPlaying || fragPlaying.level !== fragCurrentLevel) {\n this.hls.trigger(Events.LEVEL_SWITCHED, {\n level: fragCurrentLevel,\n });\n }\n }\n }\n }\n }\n\n get nextLevel(): number {\n const frag = this.nextBufferedFrag;\n if (frag) {\n return frag.level;\n }\n return -1;\n }\n\n get currentFrag(): Fragment | null {\n const media = this.media;\n if (media) {\n return this.fragPlaying || this.getAppendedFrag(media.currentTime);\n }\n return null;\n }\n\n get currentProgramDateTime(): Date | null {\n const media = this.media;\n if (media) {\n const currentTime = media.currentTime;\n const frag = this.currentFrag;\n if (\n frag &&\n Number.isFinite(currentTime) &&\n Number.isFinite(frag.programDateTime)\n ) {\n const epocMs =\n (frag.programDateTime as number) + (currentTime - frag.start) * 1000;\n return new Date(epocMs);\n }\n }\n return null;\n }\n\n get currentLevel(): number {\n const frag = this.currentFrag;\n if (frag) {\n return frag.level;\n }\n return -1;\n }\n\n get nextBufferedFrag() {\n const frag = this.currentFrag;\n if (frag) {\n return this.followingBufferedFrag(frag);\n }\n return null;\n }\n\n get forceStartLoad() {\n return this._forceStartLoad;\n }\n}\n","/*\n * compute an Exponential Weighted moving average\n * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n * - heavily inspired from shaka-player\n */\n\nclass EWMA {\n public readonly halfLife: number;\n private alpha_: number;\n private estimate_: number;\n private totalWeight_: number;\n\n // About half of the estimated value will be from the last |halfLife| samples by weight.\n constructor(halfLife: number, estimate: number = 0, weight: number = 0) {\n this.halfLife = halfLife;\n // Larger values of alpha expire historical data more slowly.\n this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0;\n this.estimate_ = estimate;\n this.totalWeight_ = weight;\n }\n\n sample(weight: number, value: number) {\n const adjAlpha = Math.pow(this.alpha_, weight);\n this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_;\n this.totalWeight_ += weight;\n }\n\n getTotalWeight(): number {\n return this.totalWeight_;\n }\n\n getEstimate(): number {\n if (this.alpha_) {\n const zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_);\n if (zeroFactor) {\n return this.estimate_ / zeroFactor;\n }\n }\n return this.estimate_;\n }\n}\n\nexport default EWMA;\n","/*\n * EWMA Bandwidth Estimator\n * - heavily inspired from shaka-player\n * Tracks bandwidth samples and estimates available bandwidth.\n * Based on the minimum of two exponentially-weighted moving averages with\n * different half-lives.\n */\n\nimport EWMA from '../utils/ewma';\n\nclass EwmaBandWidthEstimator {\n private defaultEstimate_: number;\n private minWeight_: number;\n private minDelayMs_: number;\n private slow_: EWMA;\n private fast_: EWMA;\n private defaultTTFB_: number;\n private ttfb_: EWMA;\n\n constructor(\n slow: number,\n fast: number,\n defaultEstimate: number,\n defaultTTFB: number = 100\n ) {\n this.defaultEstimate_ = defaultEstimate;\n this.minWeight_ = 0.001;\n this.minDelayMs_ = 50;\n this.slow_ = new EWMA(slow);\n this.fast_ = new EWMA(fast);\n this.defaultTTFB_ = defaultTTFB;\n this.ttfb_ = new EWMA(slow);\n }\n\n update(slow: number, fast: number) {\n const { slow_, fast_, ttfb_ } = this;\n if (slow_.halfLife !== slow) {\n this.slow_ = new EWMA(slow, slow_.getEstimate(), slow_.getTotalWeight());\n }\n if (fast_.halfLife !== fast) {\n this.fast_ = new EWMA(fast, fast_.getEstimate(), fast_.getTotalWeight());\n }\n if (ttfb_.halfLife !== slow) {\n this.ttfb_ = new EWMA(slow, ttfb_.getEstimate(), ttfb_.getTotalWeight());\n }\n }\n\n sample(durationMs: number, numBytes: number) {\n durationMs = Math.max(durationMs, this.minDelayMs_);\n const numBits = 8 * numBytes;\n // weight is duration in seconds\n const durationS = durationMs / 1000;\n // value is bandwidth in bits/s\n const bandwidthInBps = numBits / durationS;\n this.fast_.sample(durationS, bandwidthInBps);\n this.slow_.sample(durationS, bandwidthInBps);\n }\n\n sampleTTFB(ttfb: number) {\n // weight is frequency curve applied to TTFB in seconds\n // (longer times have less weight with expected input under 1 second)\n const seconds = ttfb / 1000;\n const weight = Math.sqrt(2) * Math.exp(-Math.pow(seconds, 2) / 2);\n this.ttfb_.sample(weight, Math.max(ttfb, 5));\n }\n\n canEstimate(): boolean {\n return this.fast_.getTotalWeight() >= this.minWeight_;\n }\n\n getEstimate(): number {\n if (this.canEstimate()) {\n // console.log('slow estimate:'+ Math.round(this.slow_.getEstimate()));\n // console.log('fast estimate:'+ Math.round(this.fast_.getEstimate()));\n // Take the minimum of these two estimates. This should have the effect of\n // adapting down quickly, but up more slowly.\n return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate());\n } else {\n return this.defaultEstimate_;\n }\n }\n\n getEstimateTTFB(): number {\n if (this.ttfb_.getTotalWeight() >= this.minWeight_) {\n return this.ttfb_.getEstimate();\n } else {\n return this.defaultTTFB_;\n }\n }\n\n destroy() {}\n}\nexport default EwmaBandWidthEstimator;\n","export default class ChunkCache {\n private chunks: Array<Uint8Array> = [];\n public dataLength: number = 0;\n\n push(chunk: Uint8Array) {\n this.chunks.push(chunk);\n this.dataLength += chunk.length;\n }\n\n flush(): Uint8Array {\n const { chunks, dataLength } = this;\n let result;\n if (!chunks.length) {\n return new Uint8Array(0);\n } else if (chunks.length === 1) {\n result = chunks[0];\n } else {\n result = concatUint8Arrays(chunks, dataLength);\n }\n this.reset();\n return result;\n }\n\n reset() {\n this.chunks.length = 0;\n this.dataLength = 0;\n }\n}\n\nfunction concatUint8Arrays(\n chunks: Array<Uint8Array>,\n dataLength: number\n): Uint8Array {\n const result = new Uint8Array(dataLength);\n let offset = 0;\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n","import type { Level } from '../types/level';\nimport type { MediaAttributes, MediaPlaylist } from '../types/media-playlist';\n\nexport function subtitleOptionsIdentical(\n trackList1: MediaPlaylist[] | Level[],\n trackList2: MediaPlaylist[]\n): boolean {\n if (trackList1.length !== trackList2.length) {\n return false;\n }\n for (let i = 0; i < trackList1.length; i++) {\n if (\n !subtitleAttributesIdentical(\n trackList1[i].attrs as MediaAttributes,\n trackList2[i].attrs\n )\n ) {\n return false;\n }\n }\n return true;\n}\n\nexport function subtitleAttributesIdentical(\n attrs1: MediaAttributes,\n attrs2: MediaAttributes\n): boolean {\n // Media options with the same rendition ID must be bit identical\n const stableRenditionId = attrs1['STABLE-RENDITION-ID'];\n if (stableRenditionId) {\n return stableRenditionId === attrs2['STABLE-RENDITION-ID'];\n }\n // When rendition ID is not present, compare attributes\n return ![\n 'LANGUAGE',\n 'NAME',\n 'CHARACTERISTICS',\n 'AUTOSELECT',\n 'DEFAULT',\n 'FORCED',\n ].some(\n (subtitleAttribute) =>\n attrs1[subtitleAttribute] !== attrs2[subtitleAttribute]\n );\n}\n","import { Events } from '../events';\nimport { Bufferable, BufferHelper } from '../utils/buffer-helper';\nimport { findFragmentByPTS } from './fragment-finders';\nimport { alignMediaPlaylistByPDT } from '../utils/discontinuities';\nimport { addSliding } from './level-helper';\nimport { FragmentState } from './fragment-tracker';\nimport BaseStreamController, { State } from './base-stream-controller';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Level } from '../types/level';\nimport { subtitleOptionsIdentical } from '../utils/media-option-attributes';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { Fragment } from '../loader/fragment';\nimport type {\n ErrorData,\n FragLoadedData,\n SubtitleFragProcessed,\n SubtitleTracksUpdatedData,\n TrackLoadedData,\n TrackSwitchedData,\n BufferFlushingData,\n LevelLoadedData,\n FragBufferedData,\n} from '../types/events';\n\nconst TICK_INTERVAL = 500; // how often to tick in ms\n\ninterface TimeRange {\n start: number;\n end: number;\n}\n\nexport class SubtitleStreamController\n extends BaseStreamController\n implements NetworkComponentAPI\n{\n protected levels: Array<Level> = [];\n\n private currentTrackId: number = -1;\n private tracksBuffered: Array<TimeRange[]> = [];\n private mainDetails: LevelDetails | null = null;\n\n constructor(\n hls: Hls,\n fragmentTracker: FragmentTracker,\n keyLoader: KeyLoader\n ) {\n super(\n hls,\n fragmentTracker,\n keyLoader,\n '[subtitle-stream-controller]',\n PlaylistLevelType.SUBTITLE\n );\n this._registerListeners();\n }\n\n protected onHandlerDestroying() {\n this._unregisterListeners();\n this.mainDetails = null;\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.on(Events.ERROR, this.onError, this);\n hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);\n hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n hls.on(Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this);\n hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n private _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.off(Events.ERROR, this.onError, this);\n hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);\n hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n hls.off(Events.SUBTITLE_FRAG_PROCESSED, this.onSubtitleFragProcessed, this);\n hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n startLoad(startPosition: number) {\n this.stopLoad();\n this.state = State.IDLE;\n\n this.setInterval(TICK_INTERVAL);\n\n this.nextLoadPosition =\n this.startPosition =\n this.lastCurrentTime =\n startPosition;\n\n this.tick();\n }\n\n onManifestLoading() {\n this.mainDetails = null;\n this.fragmentTracker.removeAllFragments();\n }\n\n onMediaDetaching(): void {\n this.tracksBuffered = [];\n super.onMediaDetaching();\n }\n\n onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n this.mainDetails = data.details;\n }\n\n onSubtitleFragProcessed(\n event: Events.SUBTITLE_FRAG_PROCESSED,\n data: SubtitleFragProcessed\n ) {\n const { frag, success } = data;\n this.fragPrevious = frag;\n this.state = State.IDLE;\n if (!success) {\n return;\n }\n\n const buffered = this.tracksBuffered[this.currentTrackId];\n if (!buffered) {\n return;\n }\n\n // Create/update a buffered array matching the interface used by BufferHelper.bufferedInfo\n // so we can re-use the logic used to detect how much has been buffered\n let timeRange: TimeRange | undefined;\n const fragStart = frag.start;\n for (let i = 0; i < buffered.length; i++) {\n if (fragStart >= buffered[i].start && fragStart <= buffered[i].end) {\n timeRange = buffered[i];\n break;\n }\n }\n\n const fragEnd = frag.start + frag.duration;\n if (timeRange) {\n timeRange.end = fragEnd;\n } else {\n timeRange = {\n start: fragStart,\n end: fragEnd,\n };\n buffered.push(timeRange);\n }\n this.fragmentTracker.fragBuffered(frag);\n }\n\n onBufferFlushing(event: Events.BUFFER_FLUSHING, data: BufferFlushingData) {\n const { startOffset, endOffset } = data;\n if (startOffset === 0 && endOffset !== Number.POSITIVE_INFINITY) {\n const { currentTrackId, levels } = this;\n if (\n !levels.length ||\n !levels[currentTrackId] ||\n !levels[currentTrackId].details\n ) {\n return;\n }\n const trackDetails = levels[currentTrackId].details as LevelDetails;\n const targetDuration = trackDetails.targetduration;\n const endOffsetSubtitles = endOffset - targetDuration;\n if (endOffsetSubtitles <= 0) {\n return;\n }\n data.endOffsetSubtitles = Math.max(0, endOffsetSubtitles);\n this.tracksBuffered.forEach((buffered) => {\n for (let i = 0; i < buffered.length; ) {\n if (buffered[i].end <= endOffsetSubtitles) {\n buffered.shift();\n continue;\n } else if (buffered[i].start < endOffsetSubtitles) {\n buffered[i].start = endOffsetSubtitles;\n } else {\n break;\n }\n i++;\n }\n });\n this.fragmentTracker.removeFragmentsInRange(\n startOffset,\n endOffsetSubtitles,\n PlaylistLevelType.SUBTITLE\n );\n }\n }\n\n onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n if (!this.loadedmetadata && data.frag.type === PlaylistLevelType.MAIN) {\n if (this.media?.buffered.length) {\n this.loadedmetadata = true;\n }\n }\n }\n\n // If something goes wrong, proceed to next frag, if we were processing one.\n onError(event: Events.ERROR, data: ErrorData) {\n const frag = data.frag;\n\n if (frag?.type === PlaylistLevelType.SUBTITLE) {\n if (this.fragCurrent) {\n this.fragCurrent.abortRequests();\n }\n if (this.state !== State.STOPPED) {\n this.state = State.IDLE;\n }\n }\n }\n\n // Got all new subtitle levels.\n onSubtitleTracksUpdated(\n event: Events.SUBTITLE_TRACKS_UPDATED,\n { subtitleTracks }: SubtitleTracksUpdatedData\n ) {\n if (subtitleOptionsIdentical(this.levels, subtitleTracks)) {\n this.levels = subtitleTracks.map(\n (mediaPlaylist) => new Level(mediaPlaylist)\n );\n return;\n }\n this.tracksBuffered = [];\n this.levels = subtitleTracks.map((mediaPlaylist) => {\n const level = new Level(mediaPlaylist);\n this.tracksBuffered[level.id] = [];\n return level;\n });\n this.fragmentTracker.removeFragmentsInRange(\n 0,\n Number.POSITIVE_INFINITY,\n PlaylistLevelType.SUBTITLE\n );\n this.fragPrevious = null;\n this.mediaBuffer = null;\n }\n\n onSubtitleTrackSwitch(\n event: Events.SUBTITLE_TRACK_SWITCH,\n data: TrackSwitchedData\n ) {\n this.currentTrackId = data.id;\n\n if (!this.levels.length || this.currentTrackId === -1) {\n this.clearInterval();\n return;\n }\n\n // Check if track has the necessary details to load fragments\n const currentTrack = this.levels[this.currentTrackId];\n if (currentTrack?.details) {\n this.mediaBuffer = this.mediaBufferTimeRanges;\n } else {\n this.mediaBuffer = null;\n }\n if (currentTrack) {\n this.setInterval(TICK_INTERVAL);\n }\n }\n\n // Got a new set of subtitle fragments.\n onSubtitleTrackLoaded(\n event: Events.SUBTITLE_TRACK_LOADED,\n data: TrackLoadedData\n ) {\n const { details: newDetails, id: trackId } = data;\n const { currentTrackId, levels } = this;\n if (!levels.length) {\n return;\n }\n const track: Level = levels[currentTrackId];\n if (trackId >= levels.length || trackId !== currentTrackId || !track) {\n return;\n }\n this.mediaBuffer = this.mediaBufferTimeRanges;\n let sliding = 0;\n if (newDetails.live || track.details?.live) {\n const mainDetails = this.mainDetails;\n if (newDetails.deltaUpdateFailed || !mainDetails) {\n return;\n }\n const mainSlidingStartFragment = mainDetails.fragments[0];\n if (!track.details) {\n if (newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) {\n alignMediaPlaylistByPDT(newDetails, mainDetails);\n sliding = newDetails.fragments[0].start;\n } else if (mainSlidingStartFragment) {\n // line up live playlist with main so that fragments in range are loaded\n sliding = mainSlidingStartFragment.start;\n addSliding(newDetails, sliding);\n }\n } else {\n sliding = this.alignPlaylists(newDetails, track.details);\n if (sliding === 0 && mainSlidingStartFragment) {\n // realign with main when there is no overlap with last refresh\n sliding = mainSlidingStartFragment.start;\n addSliding(newDetails, sliding);\n }\n }\n }\n track.details = newDetails;\n this.levelLastLoaded = trackId;\n\n if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {\n this.setStartPosition(track.details, sliding);\n }\n\n // trigger handler right now\n this.tick();\n\n // If playlist is misaligned because of bad PDT or drift, delete details to resync with main on reload\n if (\n newDetails.live &&\n !this.fragCurrent &&\n this.media &&\n this.state === State.IDLE\n ) {\n const foundFrag = findFragmentByPTS(\n null,\n newDetails.fragments,\n this.media.currentTime,\n 0\n );\n if (!foundFrag) {\n this.warn('Subtitle playlist not aligned with playback');\n track.details = undefined;\n }\n }\n }\n\n _handleFragmentLoadComplete(fragLoadedData: FragLoadedData) {\n const { frag, payload } = fragLoadedData;\n const decryptData = frag.decryptdata;\n const hls = this.hls;\n\n if (this.fragContextChanged(frag)) {\n return;\n }\n // check to see if the payload needs to be decrypted\n if (\n payload &&\n payload.byteLength > 0 &&\n decryptData &&\n decryptData.key &&\n decryptData.iv &&\n decryptData.method === 'AES-128'\n ) {\n const startTime = performance.now();\n // decrypt the subtitles\n this.decrypter\n .decrypt(\n new Uint8Array(payload),\n decryptData.key.buffer,\n decryptData.iv.buffer\n )\n .catch((err) => {\n hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.FRAG_DECRYPT_ERROR,\n fatal: false,\n error: err,\n reason: err.message,\n frag,\n });\n throw err;\n })\n .then((decryptedData) => {\n const endTime = performance.now();\n hls.trigger(Events.FRAG_DECRYPTED, {\n frag,\n payload: decryptedData,\n stats: {\n tstart: startTime,\n tdecrypt: endTime,\n },\n });\n })\n .catch((err) => {\n this.warn(`${err.name}: ${err.message}`);\n this.state = State.IDLE;\n });\n }\n }\n\n doTick() {\n if (!this.media) {\n this.state = State.IDLE;\n return;\n }\n\n if (this.state === State.IDLE) {\n const { currentTrackId, levels } = this;\n const track = levels[currentTrackId];\n if (!levels.length || !track || !track.details) {\n return;\n }\n\n // Expand range of subs loaded by one target-duration in either direction to make up for misaligned playlists\n const trackDetails = track.details as LevelDetails;\n const targetDuration = trackDetails.targetduration;\n const { config } = this;\n const currentTime = this.getLoadPosition();\n const bufferedInfo = BufferHelper.bufferedInfo(\n this.tracksBuffered[this.currentTrackId] || [],\n currentTime - targetDuration,\n config.maxBufferHole\n );\n const { end: targetBufferTime, len: bufferLen } = bufferedInfo;\n\n const mainBufferInfo = this.getFwdBufferInfo(\n this.media,\n PlaylistLevelType.MAIN\n );\n const maxBufLen =\n this.getMaxBufferLength(mainBufferInfo?.len) + targetDuration;\n\n if (bufferLen > maxBufLen) {\n return;\n }\n const fragments = trackDetails.fragments;\n const fragLen = fragments.length;\n const end = trackDetails.edge;\n\n let foundFrag: Fragment | null = null;\n const fragPrevious = this.fragPrevious;\n if (targetBufferTime < end) {\n const { maxFragLookUpTolerance } = config;\n foundFrag = findFragmentByPTS(\n fragPrevious,\n fragments,\n Math.max(fragments[0].start, targetBufferTime),\n maxFragLookUpTolerance\n );\n if (\n !foundFrag &&\n fragPrevious &&\n fragPrevious.start < fragments[0].start\n ) {\n foundFrag = fragments[0];\n }\n } else {\n foundFrag = fragments[fragLen - 1];\n }\n if (!foundFrag) {\n return;\n }\n\n foundFrag = this.mapToInitFragWhenRequired(foundFrag) as Fragment;\n if (\n this.fragmentTracker.getState(foundFrag) === FragmentState.NOT_LOADED\n ) {\n // only load if fragment is not loaded\n this.loadFragment(foundFrag, track, targetBufferTime);\n }\n }\n }\n\n protected getMaxBufferLength(mainBufferLength?: number): number {\n const maxConfigBuffer = super.getMaxBufferLength();\n if (!mainBufferLength) {\n return maxConfigBuffer;\n }\n return Math.max(maxConfigBuffer, mainBufferLength);\n }\n\n protected loadFragment(\n frag: Fragment,\n level: Level,\n targetBufferTime: number\n ) {\n this.fragCurrent = frag;\n if (frag.sn === 'initSegment') {\n this._loadInitSegment(frag, level);\n } else {\n this.startFragRequested = true;\n super.loadFragment(frag, level, targetBufferTime);\n }\n }\n\n get mediaBufferTimeRanges(): Bufferable {\n return new BufferableInstance(\n this.tracksBuffered[this.currentTrackId] || []\n );\n }\n}\n\nclass BufferableInstance implements Bufferable {\n public readonly buffered: TimeRanges;\n\n constructor(timeranges: TimeRange[]) {\n const getRange = (\n name: 'start' | 'end',\n index: number,\n length: number\n ): number => {\n index = index >>> 0;\n if (index > length - 1) {\n throw new DOMException(\n `Failed to execute '${name}' on 'TimeRanges': The index provided (${index}) is greater than the maximum bound (${length})`\n );\n }\n return timeranges[index][name];\n };\n this.buffered = {\n get length() {\n return timeranges.length;\n },\n end(index: number): number {\n return getRange('end', index, timeranges.length);\n },\n start(index: number): number {\n return getRange('start', index, timeranges.length);\n },\n };\n }\n}\n","import { Events } from '../events';\nimport { clearCurrentCues } from '../utils/texttrack-utils';\nimport BasePlaylistController from './base-playlist-controller';\nimport type { HlsUrlParameters } from '../types/level';\nimport type Hls from '../hls';\nimport type {\n TrackLoadedData,\n MediaAttachedData,\n SubtitleTracksUpdatedData,\n ManifestParsedData,\n LevelSwitchingData,\n} from '../types/events';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport { ErrorData, LevelLoadingData } from '../types/events';\nimport { PlaylistContextType } from '../types/loader';\n\nclass SubtitleTrackController extends BasePlaylistController {\n private media: HTMLMediaElement | null = null;\n private tracks: MediaPlaylist[] = [];\n private groupId: string | null = null;\n private tracksInGroup: MediaPlaylist[] = [];\n private trackId: number = -1;\n private selectDefaultTrack: boolean = true;\n private queuedDefaultTrack: number = -1;\n private trackChangeListener: () => void = () => this.onTextTracksChanged();\n private asyncPollTrackChange: () => void = () => this.pollTrackChange(0);\n private useTextTrackPolling: boolean = false;\n private subtitlePollingInterval: number = -1;\n private _subtitleDisplay: boolean = true;\n\n constructor(hls: Hls) {\n super(hls, '[subtitle-track-controller]');\n this.registerListeners();\n }\n\n public destroy() {\n this.unregisterListeners();\n this.tracks.length = 0;\n this.tracksInGroup.length = 0;\n this.trackChangeListener = this.asyncPollTrackChange = null as any;\n super.destroy();\n }\n\n public get subtitleDisplay(): boolean {\n return this._subtitleDisplay;\n }\n\n public set subtitleDisplay(value: boolean) {\n this._subtitleDisplay = value;\n if (this.trackId > -1) {\n this.toggleTrackModes(this.trackId);\n }\n }\n\n private registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n hls.on(Events.ERROR, this.onError, this);\n }\n\n private unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);\n hls.off(Events.ERROR, this.onError, this);\n }\n\n // Listen for subtitle track change, then extract the current track ID.\n protected onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ): void {\n this.media = data.media;\n if (!this.media) {\n return;\n }\n\n if (this.queuedDefaultTrack > -1) {\n this.subtitleTrack = this.queuedDefaultTrack;\n this.queuedDefaultTrack = -1;\n }\n\n this.useTextTrackPolling = !(\n this.media.textTracks && 'onchange' in this.media.textTracks\n );\n if (this.useTextTrackPolling) {\n this.pollTrackChange(500);\n } else {\n this.media.textTracks.addEventListener(\n 'change',\n this.asyncPollTrackChange\n );\n }\n }\n\n private pollTrackChange(timeout: number) {\n self.clearInterval(this.subtitlePollingInterval);\n this.subtitlePollingInterval = self.setInterval(\n this.trackChangeListener,\n timeout\n );\n }\n\n protected onMediaDetaching(): void {\n if (!this.media) {\n return;\n }\n\n self.clearInterval(this.subtitlePollingInterval);\n if (!this.useTextTrackPolling) {\n this.media.textTracks.removeEventListener(\n 'change',\n this.asyncPollTrackChange\n );\n }\n\n if (this.trackId > -1) {\n this.queuedDefaultTrack = this.trackId;\n }\n\n const textTracks = filterSubtitleTracks(this.media.textTracks);\n // Clear loaded cues on media detachment from tracks\n textTracks.forEach((track) => {\n clearCurrentCues(track);\n });\n // Disable all subtitle tracks before detachment so when reattached only tracks in that content are enabled.\n this.subtitleTrack = -1;\n this.media = null;\n }\n\n protected onManifestLoading(): void {\n this.tracks = [];\n this.groupId = null;\n this.tracksInGroup = [];\n this.trackId = -1;\n this.selectDefaultTrack = true;\n }\n\n // Fired whenever a new manifest is loaded.\n protected onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ): void {\n this.tracks = data.subtitleTracks;\n }\n\n protected onSubtitleTrackLoaded(\n event: Events.SUBTITLE_TRACK_LOADED,\n data: TrackLoadedData\n ): void {\n const { id, details } = data;\n const { trackId } = this;\n const currentTrack = this.tracksInGroup[trackId];\n\n if (!currentTrack) {\n this.warn(`Invalid subtitle track id ${id}`);\n return;\n }\n\n const curDetails = currentTrack.details;\n currentTrack.details = data.details;\n this.log(\n `subtitle track ${id} loaded [${details.startSN}-${details.endSN}]`\n );\n\n if (id === this.trackId) {\n this.playlistLoaded(id, data, curDetails);\n }\n }\n\n protected onLevelLoading(\n event: Events.LEVEL_LOADING,\n data: LevelLoadingData\n ): void {\n this.switchLevel(data.level);\n }\n\n protected onLevelSwitching(\n event: Events.LEVEL_SWITCHING,\n data: LevelSwitchingData\n ): void {\n this.switchLevel(data.level);\n }\n\n private switchLevel(levelIndex: number) {\n const levelInfo = this.hls.levels[levelIndex];\n if (!levelInfo?.textGroupIds) {\n return;\n }\n const textGroupId = levelInfo.textGroupIds[levelInfo.urlId];\n const lastTrack = this.tracksInGroup\n ? this.tracksInGroup[this.trackId]\n : undefined;\n if (this.groupId !== textGroupId) {\n const subtitleTracks = this.tracks.filter(\n (track): boolean => !textGroupId || track.groupId === textGroupId\n );\n this.tracksInGroup = subtitleTracks;\n const initialTrackId =\n this.findTrackId(lastTrack?.name) || this.findTrackId();\n this.groupId = textGroupId || null;\n\n const subtitleTracksUpdated: SubtitleTracksUpdatedData = {\n subtitleTracks,\n };\n this.log(\n `Updating subtitle tracks, ${subtitleTracks.length} track(s) found in \"${textGroupId}\" group-id`\n );\n this.hls.trigger(Events.SUBTITLE_TRACKS_UPDATED, subtitleTracksUpdated);\n\n if (initialTrackId !== -1) {\n this.setSubtitleTrack(initialTrackId, lastTrack);\n }\n } else if (this.shouldReloadPlaylist(lastTrack)) {\n // Retry playlist loading if no playlist is or has been loaded yet\n this.setSubtitleTrack(this.trackId, lastTrack);\n }\n }\n\n private findTrackId(name?: string): number {\n const textTracks = this.tracksInGroup;\n for (let i = 0; i < textTracks.length; i++) {\n const track = textTracks[i];\n if (!this.selectDefaultTrack || track.default) {\n if (!name || name === track.name) {\n return track.id;\n }\n }\n }\n return -1;\n }\n\n protected onError(event: Events.ERROR, data: ErrorData): void {\n if (data.fatal || !data.context) {\n return;\n }\n\n if (\n data.context.type === PlaylistContextType.SUBTITLE_TRACK &&\n data.context.id === this.trackId &&\n data.context.groupId === this.groupId\n ) {\n this.checkRetry(data);\n }\n }\n\n /** get alternate subtitle tracks list from playlist **/\n get subtitleTracks(): MediaPlaylist[] {\n return this.tracksInGroup;\n }\n\n /** get/set index of the selected subtitle track (based on index in subtitle track lists) **/\n get subtitleTrack(): number {\n return this.trackId;\n }\n\n set subtitleTrack(newId: number) {\n this.selectDefaultTrack = false;\n const lastTrack = this.tracksInGroup\n ? this.tracksInGroup[this.trackId]\n : undefined;\n this.setSubtitleTrack(newId, lastTrack);\n }\n\n protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n super.loadPlaylist();\n const currentTrack = this.tracksInGroup[this.trackId];\n if (this.shouldLoadPlaylist(currentTrack)) {\n const id = currentTrack.id;\n const groupId = currentTrack.groupId as string;\n let url = currentTrack.url;\n if (hlsUrlParameters) {\n try {\n url = hlsUrlParameters.addDirectives(url);\n } catch (error) {\n this.warn(\n `Could not construct new URL with HLS Delivery Directives: ${error}`\n );\n }\n }\n this.log(`Loading subtitle playlist for id ${id}`);\n this.hls.trigger(Events.SUBTITLE_TRACK_LOADING, {\n url,\n id,\n groupId,\n deliveryDirectives: hlsUrlParameters || null,\n });\n }\n }\n\n /**\n * Disables the old subtitleTrack and sets current mode on the next subtitleTrack.\n * This operates on the DOM textTracks.\n * A value of -1 will disable all subtitle tracks.\n */\n private toggleTrackModes(newId: number): void {\n const { media, trackId } = this;\n if (!media) {\n return;\n }\n\n const textTracks = filterSubtitleTracks(media.textTracks);\n const groupTracks = textTracks.filter(\n (track) => (track as any).groupId === this.groupId\n );\n if (newId === -1) {\n [].slice.call(textTracks).forEach((track) => {\n track.mode = 'disabled';\n });\n } else {\n const oldTrack = groupTracks[trackId];\n if (oldTrack) {\n oldTrack.mode = 'disabled';\n }\n }\n\n const nextTrack = groupTracks[newId];\n if (nextTrack) {\n nextTrack.mode = this.subtitleDisplay ? 'showing' : 'hidden';\n }\n }\n\n /**\n * This method is responsible for validating the subtitle index and periodically reloading if live.\n * Dispatches the SUBTITLE_TRACK_SWITCH event, which instructs the subtitle-stream-controller to load the selected track.\n */\n private setSubtitleTrack(\n newId: number,\n lastTrack: MediaPlaylist | undefined\n ): void {\n const tracks = this.tracksInGroup;\n\n // setting this.subtitleTrack will trigger internal logic\n // if media has not been attached yet, it will fail\n // we keep a reference to the default track id\n // and we'll set subtitleTrack when onMediaAttached is triggered\n if (!this.media) {\n this.queuedDefaultTrack = newId;\n return;\n }\n\n if (this.trackId !== newId) {\n this.toggleTrackModes(newId);\n }\n\n // exit if track id as already set or invalid\n if (\n (this.trackId === newId && (newId === -1 || tracks[newId]?.details)) ||\n newId < -1 ||\n newId >= tracks.length\n ) {\n return;\n }\n\n // stopping live reloading timer if any\n this.clearTimer();\n\n const track = tracks[newId];\n\n this.log(\n `Switching to subtitle-track ${newId}` +\n (track\n ? ` \"${track.name}\" lang:${track.lang} group:${track.groupId}`\n : '')\n );\n this.trackId = newId;\n if (track) {\n const { id, groupId = '', name, type, url } = track;\n this.hls.trigger(Events.SUBTITLE_TRACK_SWITCH, {\n id,\n groupId,\n name,\n type,\n url,\n });\n const hlsUrlParameters = this.switchParams(track.url, lastTrack?.details);\n this.loadPlaylist(hlsUrlParameters);\n } else {\n // switch to -1\n this.hls.trigger(Events.SUBTITLE_TRACK_SWITCH, { id: newId });\n }\n }\n\n private onTextTracksChanged(): void {\n if (!this.useTextTrackPolling) {\n self.clearInterval(this.subtitlePollingInterval);\n }\n // Media is undefined when switching streams via loadSource()\n if (!this.media || !this.hls.config.renderTextTracksNatively) {\n return;\n }\n\n let trackId: number = -1;\n const tracks = filterSubtitleTracks(this.media.textTracks);\n for (let id = 0; id < tracks.length; id++) {\n if (tracks[id].mode === 'hidden') {\n // Do not break in case there is a following track with showing.\n trackId = id;\n } else if (tracks[id].mode === 'showing') {\n trackId = id;\n break;\n }\n }\n\n // Setting current subtitleTrack will invoke code.\n if (this.subtitleTrack !== trackId) {\n this.subtitleTrack = trackId;\n }\n }\n}\n\nfunction filterSubtitleTracks(textTrackList: TextTrackList): TextTrack[] {\n const tracks: TextTrack[] = [];\n for (let i = 0; i < textTrackList.length; i++) {\n const track = textTrackList[i];\n // Edge adds a track without a label; we don't want to use it\n if (\n (track.kind === 'subtitles' || track.kind === 'captions') &&\n track.label\n ) {\n tracks.push(textTrackList[i]);\n }\n }\n return tracks;\n}\n\nexport default SubtitleTrackController;\n","import { logger } from '../utils/logger';\nimport type {\n BufferOperation,\n BufferOperationQueues,\n SourceBuffers,\n SourceBufferName,\n} from '../types/buffer';\n\nexport default class BufferOperationQueue {\n private buffers: SourceBuffers;\n private queues: BufferOperationQueues = {\n video: [],\n audio: [],\n audiovideo: [],\n };\n\n constructor(sourceBufferReference: SourceBuffers) {\n this.buffers = sourceBufferReference;\n }\n\n public append(operation: BufferOperation, type: SourceBufferName) {\n const queue = this.queues[type];\n queue.push(operation);\n if (queue.length === 1 && this.buffers[type]) {\n this.executeNext(type);\n }\n }\n\n public insertAbort(operation: BufferOperation, type: SourceBufferName) {\n const queue = this.queues[type];\n queue.unshift(operation);\n this.executeNext(type);\n }\n\n public appendBlocker(type: SourceBufferName): Promise<{}> {\n let execute;\n const promise: Promise<{}> = new Promise((resolve) => {\n execute = resolve;\n });\n const operation: BufferOperation = {\n execute,\n onStart: () => {},\n onComplete: () => {},\n onError: () => {},\n };\n\n this.append(operation, type);\n return promise;\n }\n\n public executeNext(type: SourceBufferName) {\n const { buffers, queues } = this;\n const sb = buffers[type];\n const queue = queues[type];\n if (queue.length) {\n const operation: BufferOperation = queue[0];\n try {\n // Operations are expected to result in an 'updateend' event being fired. If not, the queue will lock. Operations\n // which do not end with this event must call _onSBUpdateEnd manually\n operation.execute();\n } catch (e) {\n logger.warn(\n '[buffer-operation-queue]: Unhandled exception executing the current operation'\n );\n operation.onError(e);\n\n // Only shift the current operation off, otherwise the updateend handler will do this for us\n if (!sb?.updating) {\n queue.shift();\n this.executeNext(type);\n }\n }\n }\n }\n\n public shiftAndExecuteNext(type: SourceBufferName) {\n this.queues[type].shift();\n this.executeNext(type);\n }\n\n public current(type: SourceBufferName) {\n return this.queues[type][0];\n }\n}\n","import { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport { ErrorDetails, ErrorTypes } from '../errors';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport { getMediaSource } from '../utils/mediasource-helper';\nimport { ElementaryStreamTypes } from '../loader/fragment';\nimport type { TrackSet } from '../types/track';\nimport BufferOperationQueue from './buffer-operation-queue';\nimport {\n BufferOperation,\n SourceBuffers,\n SourceBufferName,\n SourceBufferListeners,\n} from '../types/buffer';\nimport type {\n LevelUpdatedData,\n BufferAppendingData,\n MediaAttachingData,\n ManifestParsedData,\n BufferCodecsData,\n BufferEOSData,\n BufferFlushingData,\n FragParsedData,\n FragChangedData,\n} from '../types/events';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { ChunkMetadata } from '../types/transmuxer';\nimport type Hls from '../hls';\nimport type { LevelDetails } from '../loader/level-details';\n\nconst MediaSource = getMediaSource();\nconst VIDEO_CODEC_PROFILE_REPACE = /([ha]vc.)(?:\\.[^.,]+)+/;\n\nexport default class BufferController implements ComponentAPI {\n // The level details used to determine duration, target-duration and live\n private details: LevelDetails | null = null;\n // cache the self generated object url to detect hijack of video tag\n private _objectUrl: string | null = null;\n // A queue of buffer operations which require the SourceBuffer to not be updating upon execution\n private operationQueue!: BufferOperationQueue;\n // References to event listeners for each SourceBuffer, so that they can be referenced for event removal\n private listeners!: SourceBufferListeners;\n\n private hls: Hls;\n\n // The number of BUFFER_CODEC events received before any sourceBuffers are created\n public bufferCodecEventsExpected: number = 0;\n\n // The total number of BUFFER_CODEC events received\n private _bufferCodecEventsTotal: number = 0;\n\n // A reference to the attached media element\n public media: HTMLMediaElement | null = null;\n\n // A reference to the active media source\n public mediaSource: MediaSource | null = null;\n\n // Last MP3 audio chunk appended\n private lastMpegAudioChunk: ChunkMetadata | null = null;\n\n // counters\n public appendError: number = 0;\n\n public tracks: TrackSet = {};\n public pendingTracks: TrackSet = {};\n public sourceBuffer!: SourceBuffers;\n\n constructor(hls: Hls) {\n this.hls = hls;\n this._initSourceBuffer();\n this.registerListeners();\n }\n\n public hasSourceTypes(): boolean {\n return (\n this.getSourceBufferTypes().length > 0 ||\n Object.keys(this.pendingTracks).length > 0\n );\n }\n\n public destroy() {\n this.unregisterListeners();\n this.details = null;\n this.lastMpegAudioChunk = null;\n }\n\n protected registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.BUFFER_RESET, this.onBufferReset, this);\n hls.on(Events.BUFFER_APPENDING, this.onBufferAppending, this);\n hls.on(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n hls.on(Events.BUFFER_EOS, this.onBufferEos, this);\n hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n hls.on(Events.FRAG_PARSED, this.onFragParsed, this);\n hls.on(Events.FRAG_CHANGED, this.onFragChanged, this);\n }\n\n protected unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.BUFFER_RESET, this.onBufferReset, this);\n hls.off(Events.BUFFER_APPENDING, this.onBufferAppending, this);\n hls.off(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n hls.off(Events.BUFFER_EOS, this.onBufferEos, this);\n hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);\n hls.off(Events.FRAG_PARSED, this.onFragParsed, this);\n hls.off(Events.FRAG_CHANGED, this.onFragChanged, this);\n }\n\n private _initSourceBuffer() {\n this.sourceBuffer = {};\n this.operationQueue = new BufferOperationQueue(this.sourceBuffer);\n this.listeners = {\n audio: [],\n video: [],\n audiovideo: [],\n };\n this.lastMpegAudioChunk = null;\n }\n\n private onManifestLoading() {\n this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = 0;\n this.details = null;\n }\n\n protected onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ) {\n // in case of alt audio 2 BUFFER_CODECS events will be triggered, one per stream controller\n // sourcebuffers will be created all at once when the expected nb of tracks will be reached\n // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller\n // it will contain the expected nb of source buffers, no need to compute it\n let codecEvents: number = 2;\n if ((data.audio && !data.video) || !data.altAudio || !__USE_ALT_AUDIO__) {\n codecEvents = 1;\n }\n this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = codecEvents;\n logger.log(\n `${this.bufferCodecEventsExpected} bufferCodec event(s) expected`\n );\n }\n\n protected onMediaAttaching(\n event: Events.MEDIA_ATTACHING,\n data: MediaAttachingData\n ) {\n const media = (this.media = data.media);\n if (media && MediaSource) {\n const ms = (this.mediaSource = new MediaSource());\n // MediaSource listeners are arrow functions with a lexical scope, and do not need to be bound\n ms.addEventListener('sourceopen', this._onMediaSourceOpen);\n ms.addEventListener('sourceended', this._onMediaSourceEnded);\n ms.addEventListener('sourceclose', this._onMediaSourceClose);\n // link video and media Source\n media.src = self.URL.createObjectURL(ms);\n // cache the locally generated object url\n this._objectUrl = media.src;\n media.addEventListener('emptied', this._onMediaEmptied);\n }\n }\n\n protected onMediaDetaching() {\n const { media, mediaSource, _objectUrl } = this;\n if (mediaSource) {\n logger.log('[buffer-controller]: media source detaching');\n if (mediaSource.readyState === 'open') {\n try {\n // endOfStream could trigger exception if any sourcebuffer is in updating state\n // we don't really care about checking sourcebuffer state here,\n // as we are anyway detaching the MediaSource\n // let's just avoid this exception to propagate\n mediaSource.endOfStream();\n } catch (err) {\n logger.warn(\n `[buffer-controller]: onMediaDetaching: ${err.message} while calling endOfStream`\n );\n }\n }\n // Clean up the SourceBuffers by invoking onBufferReset\n this.onBufferReset();\n mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);\n mediaSource.removeEventListener('sourceended', this._onMediaSourceEnded);\n mediaSource.removeEventListener('sourceclose', this._onMediaSourceClose);\n\n // Detach properly the MediaSource from the HTMLMediaElement as\n // suggested in https://github.com/w3c/media-source/issues/53.\n if (media) {\n media.removeEventListener('emptied', this._onMediaEmptied);\n if (_objectUrl) {\n self.URL.revokeObjectURL(_objectUrl);\n }\n\n // clean up video tag src only if it's our own url. some external libraries might\n // hijack the video tag and change its 'src' without destroying the Hls instance first\n if (media.src === _objectUrl) {\n media.removeAttribute('src');\n media.load();\n } else {\n logger.warn(\n '[buffer-controller]: media.src was changed by a third party - skip cleanup'\n );\n }\n }\n\n this.mediaSource = null;\n this.media = null;\n this._objectUrl = null;\n this.bufferCodecEventsExpected = this._bufferCodecEventsTotal;\n this.pendingTracks = {};\n this.tracks = {};\n }\n\n this.hls.trigger(Events.MEDIA_DETACHED, undefined);\n }\n\n protected onBufferReset() {\n this.getSourceBufferTypes().forEach((type) => {\n const sb = this.sourceBuffer[type];\n try {\n if (sb) {\n this.removeBufferListeners(type);\n if (this.mediaSource) {\n this.mediaSource.removeSourceBuffer(sb);\n }\n // Synchronously remove the SB from the map before the next call in order to prevent an async function from\n // accessing it\n this.sourceBuffer[type] = undefined;\n }\n } catch (err) {\n logger.warn(\n `[buffer-controller]: Failed to reset the ${type} buffer`,\n err\n );\n }\n });\n this._initSourceBuffer();\n }\n\n protected onBufferCodecs(\n event: Events.BUFFER_CODECS,\n data: BufferCodecsData\n ) {\n const sourceBufferCount = this.getSourceBufferTypes().length;\n\n Object.keys(data).forEach((trackName) => {\n if (sourceBufferCount) {\n // check if SourceBuffer codec needs to change\n const track = this.tracks[trackName];\n if (track && typeof track.buffer.changeType === 'function') {\n const { id, codec, levelCodec, container, metadata } =\n data[trackName];\n const currentCodec = (track.levelCodec || track.codec).replace(\n VIDEO_CODEC_PROFILE_REPACE,\n '$1'\n );\n const nextCodec = (levelCodec || codec).replace(\n VIDEO_CODEC_PROFILE_REPACE,\n '$1'\n );\n if (currentCodec !== nextCodec) {\n const mimeType = `${container};codecs=${levelCodec || codec}`;\n this.appendChangeType(trackName, mimeType);\n logger.log(\n `[buffer-controller]: switching codec ${currentCodec} to ${nextCodec}`\n );\n this.tracks[trackName] = {\n buffer: track.buffer,\n codec,\n container,\n levelCodec,\n metadata,\n id,\n };\n }\n }\n } else {\n // if source buffer(s) not created yet, appended buffer tracks in this.pendingTracks\n this.pendingTracks[trackName] = data[trackName];\n }\n });\n\n // if sourcebuffers already created, do nothing ...\n if (sourceBufferCount) {\n return;\n }\n\n this.bufferCodecEventsExpected = Math.max(\n this.bufferCodecEventsExpected - 1,\n 0\n );\n if (this.mediaSource && this.mediaSource.readyState === 'open') {\n this.checkPendingTracks();\n }\n }\n\n protected appendChangeType(type, mimeType) {\n const { operationQueue } = this;\n const operation: BufferOperation = {\n execute: () => {\n const sb = this.sourceBuffer[type];\n if (sb) {\n logger.log(\n `[buffer-controller]: changing ${type} sourceBuffer type to ${mimeType}`\n );\n sb.changeType(mimeType);\n }\n operationQueue.shiftAndExecuteNext(type);\n },\n onStart: () => {},\n onComplete: () => {},\n onError: (e) => {\n logger.warn(\n `[buffer-controller]: Failed to change ${type} SourceBuffer type`,\n e\n );\n },\n };\n\n operationQueue.append(operation, type);\n }\n\n protected onBufferAppending(\n event: Events.BUFFER_APPENDING,\n eventData: BufferAppendingData\n ) {\n const { hls, operationQueue, tracks } = this;\n const { data, type, frag, part, chunkMeta } = eventData;\n const chunkStats = chunkMeta.buffering[type];\n\n const bufferAppendingStart = self.performance.now();\n chunkStats.start = bufferAppendingStart;\n const fragBuffering = frag.stats.buffering;\n const partBuffering = part ? part.stats.buffering : null;\n if (fragBuffering.start === 0) {\n fragBuffering.start = bufferAppendingStart;\n }\n if (partBuffering && partBuffering.start === 0) {\n partBuffering.start = bufferAppendingStart;\n }\n\n // TODO: Only update timestampOffset when audio/mpeg fragment or part is not contiguous with previously appended\n // Adjusting `SourceBuffer.timestampOffset` (desired point in the timeline where the next frames should be appended)\n // in Chrome browser when we detect MPEG audio container and time delta between level PTS and `SourceBuffer.timestampOffset`\n // is greater than 100ms (this is enough to handle seek for VOD or level change for LIVE videos).\n // More info here: https://github.com/video-dev/hls.js/issues/332#issuecomment-257986486\n const audioTrack = tracks.audio;\n let checkTimestampOffset = false;\n if (type === 'audio' && audioTrack?.container === 'audio/mpeg') {\n checkTimestampOffset =\n !this.lastMpegAudioChunk ||\n chunkMeta.id === 1 ||\n this.lastMpegAudioChunk.sn !== chunkMeta.sn;\n this.lastMpegAudioChunk = chunkMeta;\n }\n\n const fragStart = frag.start;\n const operation: BufferOperation = {\n execute: () => {\n chunkStats.executeStart = self.performance.now();\n if (checkTimestampOffset) {\n const sb = this.sourceBuffer[type];\n if (sb) {\n const delta = fragStart - sb.timestampOffset;\n if (Math.abs(delta) >= 0.1) {\n logger.log(\n `[buffer-controller]: Updating audio SourceBuffer timestampOffset to ${fragStart} (delta: ${delta}) sn: ${frag.sn})`\n );\n sb.timestampOffset = fragStart;\n }\n }\n }\n this.appendExecutor(data, type);\n },\n onStart: () => {\n // logger.debug(`[buffer-controller]: ${type} SourceBuffer updatestart`);\n },\n onComplete: () => {\n // logger.debug(`[buffer-controller]: ${type} SourceBuffer updateend`);\n const end = self.performance.now();\n chunkStats.executeEnd = chunkStats.end = end;\n if (fragBuffering.first === 0) {\n fragBuffering.first = end;\n }\n if (partBuffering && partBuffering.first === 0) {\n partBuffering.first = end;\n }\n\n const { sourceBuffer } = this;\n const timeRanges = {};\n for (const type in sourceBuffer) {\n timeRanges[type] = BufferHelper.getBuffered(sourceBuffer[type]);\n }\n this.appendError = 0;\n this.hls.trigger(Events.BUFFER_APPENDED, {\n type,\n frag,\n part,\n chunkMeta,\n parent: frag.type,\n timeRanges,\n });\n },\n onError: (err) => {\n // in case any error occured while appending, put back segment in segments table\n logger.error(\n `[buffer-controller]: Error encountered while trying to append to the ${type} SourceBuffer`,\n err\n );\n const event = {\n type: ErrorTypes.MEDIA_ERROR,\n parent: frag.type,\n details: ErrorDetails.BUFFER_APPEND_ERROR,\n frag,\n part,\n chunkMeta,\n error: err,\n err,\n fatal: false,\n };\n\n if (err.code === DOMException.QUOTA_EXCEEDED_ERR) {\n // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror\n // let's stop appending any segments, and report BUFFER_FULL_ERROR error\n event.details = ErrorDetails.BUFFER_FULL_ERROR;\n } else {\n this.appendError++;\n event.details = ErrorDetails.BUFFER_APPEND_ERROR;\n /* with UHD content, we could get loop of quota exceeded error until\n browser is able to evict some data from sourcebuffer. Retrying can help recover.\n */\n if (this.appendError > hls.config.appendErrorMaxRetry) {\n logger.error(\n `[buffer-controller]: Failed ${hls.config.appendErrorMaxRetry} times to append segment in sourceBuffer`\n );\n event.fatal = true;\n }\n }\n hls.trigger(Events.ERROR, event);\n },\n };\n operationQueue.append(operation, type);\n }\n\n protected onBufferFlushing(\n event: Events.BUFFER_FLUSHING,\n data: BufferFlushingData\n ) {\n const { operationQueue } = this;\n const flushOperation = (type: SourceBufferName): BufferOperation => ({\n execute: this.removeExecutor.bind(\n this,\n type,\n data.startOffset,\n data.endOffset\n ),\n onStart: () => {\n // logger.debug(`[buffer-controller]: Started flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);\n },\n onComplete: () => {\n // logger.debug(`[buffer-controller]: Finished flushing ${data.startOffset} -> ${data.endOffset} for ${type} Source Buffer`);\n this.hls.trigger(Events.BUFFER_FLUSHED, { type });\n },\n onError: (e) => {\n logger.warn(\n `[buffer-controller]: Failed to remove from ${type} SourceBuffer`,\n e\n );\n },\n });\n\n if (data.type) {\n operationQueue.append(flushOperation(data.type), data.type);\n } else {\n this.getSourceBufferTypes().forEach((type: SourceBufferName) => {\n operationQueue.append(flushOperation(type), type);\n });\n }\n }\n\n protected onFragParsed(event: Events.FRAG_PARSED, data: FragParsedData) {\n const { frag, part } = data;\n const buffersAppendedTo: Array<SourceBufferName> = [];\n const elementaryStreams = part\n ? part.elementaryStreams\n : frag.elementaryStreams;\n if (elementaryStreams[ElementaryStreamTypes.AUDIOVIDEO]) {\n buffersAppendedTo.push('audiovideo');\n } else {\n if (elementaryStreams[ElementaryStreamTypes.AUDIO]) {\n buffersAppendedTo.push('audio');\n }\n if (elementaryStreams[ElementaryStreamTypes.VIDEO]) {\n buffersAppendedTo.push('video');\n }\n }\n\n const onUnblocked = () => {\n const now = self.performance.now();\n frag.stats.buffering.end = now;\n if (part) {\n part.stats.buffering.end = now;\n }\n const stats = part ? part.stats : frag.stats;\n this.hls.trigger(Events.FRAG_BUFFERED, {\n frag,\n part,\n stats,\n id: frag.type,\n });\n };\n\n if (buffersAppendedTo.length === 0) {\n logger.warn(\n `Fragments must have at least one ElementaryStreamType set. type: ${frag.type} level: ${frag.level} sn: ${frag.sn}`\n );\n }\n\n this.blockBuffers(onUnblocked, buffersAppendedTo);\n }\n\n private onFragChanged(event: Events.FRAG_CHANGED, data: FragChangedData) {\n this.flushBackBuffer();\n }\n\n // on BUFFER_EOS mark matching sourcebuffer(s) as ended and trigger checkEos()\n // an undefined data.type will mark all buffers as EOS.\n protected onBufferEos(event: Events.BUFFER_EOS, data: BufferEOSData) {\n const ended = this.getSourceBufferTypes().reduce((acc, type) => {\n const sb = this.sourceBuffer[type];\n if (sb && (!data.type || data.type === type)) {\n sb.ending = true;\n if (!sb.ended) {\n sb.ended = true;\n logger.log(`[buffer-controller]: ${type} sourceBuffer now EOS`);\n }\n }\n return acc && !!(!sb || sb.ended);\n }, true);\n\n if (ended) {\n logger.log(`[buffer-controller]: Queueing mediaSource.endOfStream()`);\n this.blockBuffers(() => {\n this.getSourceBufferTypes().forEach((type) => {\n const sb = this.sourceBuffer[type];\n if (sb) {\n sb.ending = false;\n }\n });\n const { mediaSource } = this;\n if (!mediaSource || mediaSource.readyState !== 'open') {\n if (mediaSource) {\n logger.info(\n `[buffer-controller]: Could not call mediaSource.endOfStream(). mediaSource.readyState: ${mediaSource.readyState}`\n );\n }\n return;\n }\n logger.log(`[buffer-controller]: Calling mediaSource.endOfStream()`);\n // Allow this to throw and be caught by the enqueueing function\n mediaSource.endOfStream();\n });\n }\n }\n\n protected onLevelUpdated(\n event: Events.LEVEL_UPDATED,\n { details }: LevelUpdatedData\n ) {\n if (!details.fragments.length) {\n return;\n }\n this.details = details;\n\n if (this.getSourceBufferTypes().length) {\n this.blockBuffers(this.updateMediaElementDuration.bind(this));\n } else {\n this.updateMediaElementDuration();\n }\n }\n\n flushBackBuffer() {\n const { hls, details, media, sourceBuffer } = this;\n if (!media || details === null) {\n return;\n }\n\n const sourceBufferTypes = this.getSourceBufferTypes();\n if (!sourceBufferTypes.length) {\n return;\n }\n\n // Support for deprecated liveBackBufferLength\n const backBufferLength =\n details.live && hls.config.liveBackBufferLength !== null\n ? hls.config.liveBackBufferLength\n : hls.config.backBufferLength;\n\n if (!Number.isFinite(backBufferLength) || backBufferLength < 0) {\n return;\n }\n\n const currentTime = media.currentTime;\n const targetDuration = details.levelTargetDuration;\n const maxBackBufferLength = Math.max(backBufferLength, targetDuration);\n const targetBackBufferPosition =\n Math.floor(currentTime / targetDuration) * targetDuration -\n maxBackBufferLength;\n sourceBufferTypes.forEach((type: SourceBufferName) => {\n const sb = sourceBuffer[type];\n if (sb) {\n const buffered = BufferHelper.getBuffered(sb);\n // when target buffer start exceeds actual buffer start\n if (\n buffered.length > 0 &&\n targetBackBufferPosition > buffered.start(0)\n ) {\n hls.trigger(Events.BACK_BUFFER_REACHED, {\n bufferEnd: targetBackBufferPosition,\n });\n\n // Support for deprecated event:\n if (details.live) {\n hls.trigger(Events.LIVE_BACK_BUFFER_REACHED, {\n bufferEnd: targetBackBufferPosition,\n });\n } else if (\n sb.ended &&\n buffered.end(buffered.length - 1) - currentTime < targetDuration * 2\n ) {\n logger.info(\n `[buffer-controller]: Cannot flush ${type} back buffer while SourceBuffer is in ended state`\n );\n return;\n }\n\n hls.trigger(Events.BUFFER_FLUSHING, {\n startOffset: 0,\n endOffset: targetBackBufferPosition,\n type,\n });\n }\n }\n });\n }\n\n /**\n * Update Media Source duration to current level duration or override to Infinity if configuration parameter\n * 'liveDurationInfinity` is set to `true`\n * More details: https://github.com/video-dev/hls.js/issues/355\n */\n private updateMediaElementDuration() {\n if (\n !this.details ||\n !this.media ||\n !this.mediaSource ||\n this.mediaSource.readyState !== 'open'\n ) {\n return;\n }\n const { details, hls, media, mediaSource } = this;\n const levelDuration = details.fragments[0].start + details.totalduration;\n const mediaDuration = media.duration;\n const msDuration = Number.isFinite(mediaSource.duration)\n ? mediaSource.duration\n : 0;\n\n if (details.live && hls.config.liveDurationInfinity) {\n // Override duration to Infinity\n logger.log(\n '[buffer-controller]: Media Source duration is set to Infinity'\n );\n mediaSource.duration = Infinity;\n this.updateSeekableRange(details);\n } else if (\n (levelDuration > msDuration && levelDuration > mediaDuration) ||\n !Number.isFinite(mediaDuration)\n ) {\n // levelDuration was the last value we set.\n // not using mediaSource.duration as the browser may tweak this value\n // only update Media Source duration if its value increase, this is to avoid\n // flushing already buffered portion when switching between quality level\n logger.log(\n `[buffer-controller]: Updating Media Source duration to ${levelDuration.toFixed(\n 3\n )}`\n );\n mediaSource.duration = levelDuration;\n }\n }\n\n updateSeekableRange(levelDetails) {\n const mediaSource = this.mediaSource;\n const fragments = levelDetails.fragments;\n const len = fragments.length;\n if (len && levelDetails.live && mediaSource?.setLiveSeekableRange) {\n const start = Math.max(0, fragments[0].start);\n const end = Math.max(start, start + levelDetails.totalduration);\n mediaSource.setLiveSeekableRange(start, end);\n }\n }\n\n protected checkPendingTracks() {\n const { bufferCodecEventsExpected, operationQueue, pendingTracks } = this;\n\n // Check if we've received all of the expected bufferCodec events. When none remain, create all the sourceBuffers at once.\n // This is important because the MSE spec allows implementations to throw QuotaExceededErrors if creating new sourceBuffers after\n // data has been appended to existing ones.\n // 2 tracks is the max (one for audio, one for video). If we've reach this max go ahead and create the buffers.\n const pendingTracksCount = Object.keys(pendingTracks).length;\n if (\n (pendingTracksCount && !bufferCodecEventsExpected) ||\n pendingTracksCount === 2\n ) {\n // ok, let's create them now !\n this.createSourceBuffers(pendingTracks);\n this.pendingTracks = {};\n // append any pending segments now !\n const buffers = this.getSourceBufferTypes();\n if (buffers.length) {\n this.hls.trigger(Events.BUFFER_CREATED, { tracks: this.tracks });\n buffers.forEach((type: SourceBufferName) => {\n operationQueue.executeNext(type);\n });\n } else {\n const error = new Error(\n 'could not create source buffer for media codec(s)'\n );\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_INCOMPATIBLE_CODECS_ERROR,\n fatal: true,\n error,\n reason: error.message,\n });\n }\n }\n }\n\n protected createSourceBuffers(tracks: TrackSet) {\n const { sourceBuffer, mediaSource } = this;\n if (!mediaSource) {\n throw Error('createSourceBuffers called when mediaSource was null');\n }\n for (const trackName in tracks) {\n if (!sourceBuffer[trackName]) {\n const track = tracks[trackName as keyof TrackSet];\n if (!track) {\n throw Error(\n `source buffer exists for track ${trackName}, however track does not`\n );\n }\n // use levelCodec as first priority\n const codec = track.levelCodec || track.codec;\n const mimeType = `${track.container};codecs=${codec}`;\n logger.log(`[buffer-controller]: creating sourceBuffer(${mimeType})`);\n try {\n const sb = (sourceBuffer[trackName] =\n mediaSource.addSourceBuffer(mimeType));\n const sbName = trackName as SourceBufferName;\n this.addBufferListener(sbName, 'updatestart', this._onSBUpdateStart);\n this.addBufferListener(sbName, 'updateend', this._onSBUpdateEnd);\n this.addBufferListener(sbName, 'error', this._onSBUpdateError);\n this.tracks[trackName] = {\n buffer: sb,\n codec: codec,\n container: track.container,\n levelCodec: track.levelCodec,\n metadata: track.metadata,\n id: track.id,\n };\n } catch (err) {\n logger.error(\n `[buffer-controller]: error while trying to add sourceBuffer: ${err.message}`\n );\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_ADD_CODEC_ERROR,\n fatal: false,\n error: err,\n mimeType: mimeType,\n });\n }\n }\n }\n }\n\n // Keep as arrow functions so that we can directly reference these functions directly as event listeners\n private _onMediaSourceOpen = () => {\n const { media, mediaSource } = this;\n logger.log('[buffer-controller]: Media source opened');\n if (media) {\n media.removeEventListener('emptied', this._onMediaEmptied);\n this.updateMediaElementDuration();\n this.hls.trigger(Events.MEDIA_ATTACHED, { media });\n }\n\n if (mediaSource) {\n // once received, don't listen anymore to sourceopen event\n mediaSource.removeEventListener('sourceopen', this._onMediaSourceOpen);\n }\n this.checkPendingTracks();\n };\n\n private _onMediaSourceClose = () => {\n logger.log('[buffer-controller]: Media source closed');\n };\n\n private _onMediaSourceEnded = () => {\n logger.log('[buffer-controller]: Media source ended');\n };\n\n private _onMediaEmptied = () => {\n const { media, _objectUrl } = this;\n if (media && media.src !== _objectUrl) {\n logger.error(\n `Media element src was set while attaching MediaSource (${_objectUrl} > ${media.src})`\n );\n }\n };\n\n private _onSBUpdateStart(type: SourceBufferName) {\n const { operationQueue } = this;\n const operation = operationQueue.current(type);\n operation.onStart();\n }\n\n private _onSBUpdateEnd(type: SourceBufferName) {\n const { operationQueue } = this;\n const operation = operationQueue.current(type);\n operation.onComplete();\n operationQueue.shiftAndExecuteNext(type);\n }\n\n private _onSBUpdateError(type: SourceBufferName, event: Event) {\n const error = new Error(`${type} SourceBuffer error`);\n logger.error(`[buffer-controller]: ${error}`, event);\n // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error\n // SourceBuffer errors are not necessarily fatal; if so, the HTMLMediaElement will fire an error event\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.BUFFER_APPENDING_ERROR,\n error,\n fatal: false,\n });\n // updateend is always fired after error, so we'll allow that to shift the current operation off of the queue\n const operation = this.operationQueue.current(type);\n if (operation) {\n operation.onError(event);\n }\n }\n\n // This method must result in an updateend event; if remove is not called, _onSBUpdateEnd must be called manually\n private removeExecutor(\n type: SourceBufferName,\n startOffset: number,\n endOffset: number\n ) {\n const { media, mediaSource, operationQueue, sourceBuffer } = this;\n const sb = sourceBuffer[type];\n if (!media || !mediaSource || !sb) {\n logger.warn(\n `[buffer-controller]: Attempting to remove from the ${type} SourceBuffer, but it does not exist`\n );\n operationQueue.shiftAndExecuteNext(type);\n return;\n }\n const mediaDuration = Number.isFinite(media.duration)\n ? media.duration\n : Infinity;\n const msDuration = Number.isFinite(mediaSource.duration)\n ? mediaSource.duration\n : Infinity;\n const removeStart = Math.max(0, startOffset);\n const removeEnd = Math.min(endOffset, mediaDuration, msDuration);\n if (removeEnd > removeStart && !sb.ending) {\n sb.ended = false;\n logger.log(\n `[buffer-controller]: Removing [${removeStart},${removeEnd}] from the ${type} SourceBuffer`\n );\n sb.remove(removeStart, removeEnd);\n } else {\n // Cycle the queue\n operationQueue.shiftAndExecuteNext(type);\n }\n }\n\n // This method must result in an updateend event; if append is not called, _onSBUpdateEnd must be called manually\n private appendExecutor(data: Uint8Array, type: SourceBufferName) {\n const { operationQueue, sourceBuffer } = this;\n const sb = sourceBuffer[type];\n if (!sb) {\n logger.warn(\n `[buffer-controller]: Attempting to append to the ${type} SourceBuffer, but it does not exist`\n );\n operationQueue.shiftAndExecuteNext(type);\n return;\n }\n\n sb.ended = false;\n sb.appendBuffer(data);\n }\n\n // Enqueues an operation to each SourceBuffer queue which, upon execution, resolves a promise. When all promises\n // resolve, the onUnblocked function is executed. Functions calling this method do not need to unblock the queue\n // upon completion, since we already do it here\n private blockBuffers(\n onUnblocked: () => void,\n buffers: Array<SourceBufferName> = this.getSourceBufferTypes()\n ) {\n if (!buffers.length) {\n logger.log(\n '[buffer-controller]: Blocking operation requested, but no SourceBuffers exist'\n );\n Promise.resolve().then(onUnblocked);\n return;\n }\n const { operationQueue } = this;\n\n // logger.debug(`[buffer-controller]: Blocking ${buffers} SourceBuffer`);\n const blockingOperations = buffers.map((type) =>\n operationQueue.appendBlocker(type as SourceBufferName)\n );\n Promise.all(blockingOperations).then(() => {\n // logger.debug(`[buffer-controller]: Blocking operation resolved; unblocking ${buffers} SourceBuffer`);\n onUnblocked();\n buffers.forEach((type) => {\n const sb = this.sourceBuffer[type];\n // Only cycle the queue if the SB is not updating. There's a bug in Chrome which sets the SB updating flag to\n // true when changing the MediaSource duration (https://bugs.chromium.org/p/chromium/issues/detail?id=959359&can=2&q=mediasource%20duration)\n // While this is a workaround, it's probably useful to have around\n if (!sb?.updating) {\n operationQueue.shiftAndExecuteNext(type);\n }\n });\n });\n }\n\n private getSourceBufferTypes(): Array<SourceBufferName> {\n return Object.keys(this.sourceBuffer) as Array<SourceBufferName>;\n }\n\n private addBufferListener(\n type: SourceBufferName,\n event: string,\n fn: Function\n ) {\n const buffer = this.sourceBuffer[type];\n if (!buffer) {\n return;\n }\n const listener = fn.bind(this, type);\n this.listeners[type].push({ event, listener });\n buffer.addEventListener(event, listener);\n }\n\n private removeBufferListeners(type: SourceBufferName) {\n const buffer = this.sourceBuffer[type];\n if (!buffer) {\n return;\n }\n this.listeners[type].forEach((l) => {\n buffer.removeEventListener(l.event, l.listener);\n });\n }\n}\n","import OutputFilter from './output-filter';\nimport { logger } from '../utils/logger';\n\n/**\n *\n * This code was ported from the dash.js project at:\n * https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js\n * https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2\n *\n * The original copyright appears below:\n *\n * The copyright in this software is being made available under the BSD License,\n * included below. This software may be subject to other third party and contributor\n * rights, including patent rights, and no such rights are granted under this license.\n *\n * Copyright (c) 2015-2016, DASH Industry Forum.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation and/or\n * other materials provided with the distribution.\n * 2. Neither the name of Dash Industry Forum nor the names of its\n * contributors may be used to endorse or promote products derived from this software\n * without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n/**\n * Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes\n */\n\nconst specialCea608CharsCodes = {\n 0x2a: 0xe1, // lowercase a, acute accent\n 0x5c: 0xe9, // lowercase e, acute accent\n 0x5e: 0xed, // lowercase i, acute accent\n 0x5f: 0xf3, // lowercase o, acute accent\n 0x60: 0xfa, // lowercase u, acute accent\n 0x7b: 0xe7, // lowercase c with cedilla\n 0x7c: 0xf7, // division symbol\n 0x7d: 0xd1, // uppercase N tilde\n 0x7e: 0xf1, // lowercase n tilde\n 0x7f: 0x2588, // Full block\n // THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n // THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F\n // THIS MEANS THAT \\x50 MUST BE ADDED TO THE VALUES\n 0x80: 0xae, // Registered symbol (R)\n 0x81: 0xb0, // degree sign\n 0x82: 0xbd, // 1/2 symbol\n 0x83: 0xbf, // Inverted (open) question mark\n 0x84: 0x2122, // Trademark symbol (TM)\n 0x85: 0xa2, // Cents symbol\n 0x86: 0xa3, // Pounds sterling\n 0x87: 0x266a, // Music 8'th note\n 0x88: 0xe0, // lowercase a, grave accent\n 0x89: 0x20, // transparent space (regular)\n 0x8a: 0xe8, // lowercase e, grave accent\n 0x8b: 0xe2, // lowercase a, circumflex accent\n 0x8c: 0xea, // lowercase e, circumflex accent\n 0x8d: 0xee, // lowercase i, circumflex accent\n 0x8e: 0xf4, // lowercase o, circumflex accent\n 0x8f: 0xfb, // lowercase u, circumflex accent\n // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n // THAT COME FROM HI BYTE=0x12 AND LOW BETWEEN 0x20 AND 0x3F\n 0x90: 0xc1, // capital letter A with acute\n 0x91: 0xc9, // capital letter E with acute\n 0x92: 0xd3, // capital letter O with acute\n 0x93: 0xda, // capital letter U with acute\n 0x94: 0xdc, // capital letter U with diaresis\n 0x95: 0xfc, // lowercase letter U with diaeresis\n 0x96: 0x2018, // opening single quote\n 0x97: 0xa1, // inverted exclamation mark\n 0x98: 0x2a, // asterisk\n 0x99: 0x2019, // closing single quote\n 0x9a: 0x2501, // box drawings heavy horizontal\n 0x9b: 0xa9, // copyright sign\n 0x9c: 0x2120, // Service mark\n 0x9d: 0x2022, // (round) bullet\n 0x9e: 0x201c, // Left double quotation mark\n 0x9f: 0x201d, // Right double quotation mark\n 0xa0: 0xc0, // uppercase A, grave accent\n 0xa1: 0xc2, // uppercase A, circumflex\n 0xa2: 0xc7, // uppercase C with cedilla\n 0xa3: 0xc8, // uppercase E, grave accent\n 0xa4: 0xca, // uppercase E, circumflex\n 0xa5: 0xcb, // capital letter E with diaresis\n 0xa6: 0xeb, // lowercase letter e with diaresis\n 0xa7: 0xce, // uppercase I, circumflex\n 0xa8: 0xcf, // uppercase I, with diaresis\n 0xa9: 0xef, // lowercase i, with diaresis\n 0xaa: 0xd4, // uppercase O, circumflex\n 0xab: 0xd9, // uppercase U, grave accent\n 0xac: 0xf9, // lowercase u, grave accent\n 0xad: 0xdb, // uppercase U, circumflex\n 0xae: 0xab, // left-pointing double angle quotation mark\n 0xaf: 0xbb, // right-pointing double angle quotation mark\n // THIS BLOCK INCLUDES THE 32 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS\n // THAT COME FROM HI BYTE=0x13 AND LOW BETWEEN 0x20 AND 0x3F\n 0xb0: 0xc3, // Uppercase A, tilde\n 0xb1: 0xe3, // Lowercase a, tilde\n 0xb2: 0xcd, // Uppercase I, acute accent\n 0xb3: 0xcc, // Uppercase I, grave accent\n 0xb4: 0xec, // Lowercase i, grave accent\n 0xb5: 0xd2, // Uppercase O, grave accent\n 0xb6: 0xf2, // Lowercase o, grave accent\n 0xb7: 0xd5, // Uppercase O, tilde\n 0xb8: 0xf5, // Lowercase o, tilde\n 0xb9: 0x7b, // Open curly brace\n 0xba: 0x7d, // Closing curly brace\n 0xbb: 0x5c, // Backslash\n 0xbc: 0x5e, // Caret\n 0xbd: 0x5f, // Underscore\n 0xbe: 0x7c, // Pipe (vertical line)\n 0xbf: 0x223c, // Tilde operator\n 0xc0: 0xc4, // Uppercase A, umlaut\n 0xc1: 0xe4, // Lowercase A, umlaut\n 0xc2: 0xd6, // Uppercase O, umlaut\n 0xc3: 0xf6, // Lowercase o, umlaut\n 0xc4: 0xdf, // Esszett (sharp S)\n 0xc5: 0xa5, // Yen symbol\n 0xc6: 0xa4, // Generic currency sign\n 0xc7: 0x2503, // Box drawings heavy vertical\n 0xc8: 0xc5, // Uppercase A, ring\n 0xc9: 0xe5, // Lowercase A, ring\n 0xca: 0xd8, // Uppercase O, stroke\n 0xcb: 0xf8, // Lowercase o, strok\n 0xcc: 0x250f, // Box drawings heavy down and right\n 0xcd: 0x2513, // Box drawings heavy down and left\n 0xce: 0x2517, // Box drawings heavy up and right\n 0xcf: 0x251b, // Box drawings heavy up and left\n};\n\n/**\n * Utils\n */\nconst getCharForByte = function (byte: number) {\n let charCode = byte;\n if (specialCea608CharsCodes.hasOwnProperty(byte)) {\n charCode = specialCea608CharsCodes[byte];\n }\n\n return String.fromCharCode(charCode);\n};\n\nconst NR_ROWS = 15;\nconst NR_COLS = 100;\n// Tables to look up row from PAC data\nconst rowsLowCh1 = {\n 0x11: 1,\n 0x12: 3,\n 0x15: 5,\n 0x16: 7,\n 0x17: 9,\n 0x10: 11,\n 0x13: 12,\n 0x14: 14,\n};\nconst rowsHighCh1 = {\n 0x11: 2,\n 0x12: 4,\n 0x15: 6,\n 0x16: 8,\n 0x17: 10,\n 0x13: 13,\n 0x14: 15,\n};\nconst rowsLowCh2 = {\n 0x19: 1,\n 0x1a: 3,\n 0x1d: 5,\n 0x1e: 7,\n 0x1f: 9,\n 0x18: 11,\n 0x1b: 12,\n 0x1c: 14,\n};\nconst rowsHighCh2 = {\n 0x19: 2,\n 0x1a: 4,\n 0x1d: 6,\n 0x1e: 8,\n 0x1f: 10,\n 0x1b: 13,\n 0x1c: 15,\n};\n\nconst backgroundColors = [\n 'white',\n 'green',\n 'blue',\n 'cyan',\n 'red',\n 'yellow',\n 'magenta',\n 'black',\n 'transparent',\n];\n\nconst enum VerboseLevel {\n ERROR = 0,\n TEXT = 1,\n WARNING = 2,\n INFO = 2,\n DEBUG = 3,\n DATA = 3,\n}\n\nclass CaptionsLogger {\n public time: number | null = null;\n public verboseLevel: VerboseLevel = VerboseLevel.ERROR;\n\n log(severity: VerboseLevel, msg: string | (() => string)): void {\n if (this.verboseLevel >= severity) {\n const m: string = typeof msg === 'function' ? msg() : msg;\n logger.log(`${this.time} [${severity}] ${m}`);\n }\n }\n}\n\nconst numArrayToHexArray = function (numArray: number[]): string[] {\n const hexArray: string[] = [];\n for (let j = 0; j < numArray.length; j++) {\n hexArray.push(numArray[j].toString(16));\n }\n\n return hexArray;\n};\n\ntype PenStyles = {\n foreground: string | null;\n underline: boolean;\n italics: boolean;\n background: string;\n flash: boolean;\n};\n\nclass PenState {\n public foreground: string;\n public underline: boolean;\n public italics: boolean;\n public background: string;\n public flash: boolean;\n\n constructor(\n foreground?: string,\n underline?: boolean,\n italics?: boolean,\n background?: string,\n flash?: boolean\n ) {\n this.foreground = foreground || 'white';\n this.underline = underline || false;\n this.italics = italics || false;\n this.background = background || 'black';\n this.flash = flash || false;\n }\n\n reset() {\n this.foreground = 'white';\n this.underline = false;\n this.italics = false;\n this.background = 'black';\n this.flash = false;\n }\n\n setStyles(styles: Partial<PenStyles>) {\n const attribs = [\n 'foreground',\n 'underline',\n 'italics',\n 'background',\n 'flash',\n ];\n for (let i = 0; i < attribs.length; i++) {\n const style = attribs[i];\n if (styles.hasOwnProperty(style)) {\n this[style] = styles[style];\n }\n }\n }\n\n isDefault() {\n return (\n this.foreground === 'white' &&\n !this.underline &&\n !this.italics &&\n this.background === 'black' &&\n !this.flash\n );\n }\n\n equals(other: PenState) {\n return (\n this.foreground === other.foreground &&\n this.underline === other.underline &&\n this.italics === other.italics &&\n this.background === other.background &&\n this.flash === other.flash\n );\n }\n\n copy(newPenState: PenState) {\n this.foreground = newPenState.foreground;\n this.underline = newPenState.underline;\n this.italics = newPenState.italics;\n this.background = newPenState.background;\n this.flash = newPenState.flash;\n }\n\n toString(): string {\n return (\n 'color=' +\n this.foreground +\n ', underline=' +\n this.underline +\n ', italics=' +\n this.italics +\n ', background=' +\n this.background +\n ', flash=' +\n this.flash\n );\n }\n}\n\n/**\n * Unicode character with styling and background.\n * @constructor\n */\nclass StyledUnicodeChar {\n uchar: string;\n penState: PenState;\n\n constructor(\n uchar?: string,\n foreground?: string,\n underline?: boolean,\n italics?: boolean,\n background?: string,\n flash?: boolean\n ) {\n this.uchar = uchar || ' '; // unicode character\n this.penState = new PenState(\n foreground,\n underline,\n italics,\n background,\n flash\n );\n }\n\n reset() {\n this.uchar = ' ';\n this.penState.reset();\n }\n\n setChar(uchar: string, newPenState: PenState) {\n this.uchar = uchar;\n this.penState.copy(newPenState);\n }\n\n setPenState(newPenState: PenState) {\n this.penState.copy(newPenState);\n }\n\n equals(other: StyledUnicodeChar) {\n return this.uchar === other.uchar && this.penState.equals(other.penState);\n }\n\n copy(newChar: StyledUnicodeChar) {\n this.uchar = newChar.uchar;\n this.penState.copy(newChar.penState);\n }\n\n isEmpty(): boolean {\n return this.uchar === ' ' && this.penState.isDefault();\n }\n}\n\n/**\n * CEA-608 row consisting of NR_COLS instances of StyledUnicodeChar.\n * @constructor\n */\nexport class Row {\n public chars: StyledUnicodeChar[];\n public pos: number;\n public currPenState: PenState;\n public cueStartTime?: number;\n logger: CaptionsLogger;\n\n constructor(logger: CaptionsLogger) {\n this.chars = [];\n for (let i = 0; i < NR_COLS; i++) {\n this.chars.push(new StyledUnicodeChar());\n }\n\n this.logger = logger;\n this.pos = 0;\n this.currPenState = new PenState();\n }\n\n equals(other: Row) {\n let equal = true;\n for (let i = 0; i < NR_COLS; i++) {\n if (!this.chars[i].equals(other.chars[i])) {\n equal = false;\n break;\n }\n }\n return equal;\n }\n\n copy(other: Row) {\n for (let i = 0; i < NR_COLS; i++) {\n this.chars[i].copy(other.chars[i]);\n }\n }\n\n isEmpty(): boolean {\n let empty = true;\n for (let i = 0; i < NR_COLS; i++) {\n if (!this.chars[i].isEmpty()) {\n empty = false;\n break;\n }\n }\n return empty;\n }\n\n /**\n * Set the cursor to a valid column.\n */\n setCursor(absPos: number) {\n if (this.pos !== absPos) {\n this.pos = absPos;\n }\n\n if (this.pos < 0) {\n this.logger.log(\n VerboseLevel.DEBUG,\n 'Negative cursor position ' + this.pos\n );\n this.pos = 0;\n } else if (this.pos > NR_COLS) {\n this.logger.log(\n VerboseLevel.DEBUG,\n 'Too large cursor position ' + this.pos\n );\n this.pos = NR_COLS;\n }\n }\n\n /**\n * Move the cursor relative to current position.\n */\n moveCursor(relPos: number) {\n const newPos = this.pos + relPos;\n if (relPos > 1) {\n for (let i = this.pos + 1; i < newPos + 1; i++) {\n this.chars[i].setPenState(this.currPenState);\n }\n }\n this.setCursor(newPos);\n }\n\n /**\n * Backspace, move one step back and clear character.\n */\n backSpace() {\n this.moveCursor(-1);\n this.chars[this.pos].setChar(' ', this.currPenState);\n }\n\n insertChar(byte: number) {\n if (byte >= 0x90) {\n // Extended char\n this.backSpace();\n }\n const char = getCharForByte(byte);\n if (this.pos >= NR_COLS) {\n this.logger.log(\n VerboseLevel.ERROR,\n () =>\n 'Cannot insert ' +\n byte.toString(16) +\n ' (' +\n char +\n ') at position ' +\n this.pos +\n '. Skipping it!'\n );\n return;\n }\n this.chars[this.pos].setChar(char, this.currPenState);\n this.moveCursor(1);\n }\n\n clearFromPos(startPos: number) {\n let i: number;\n for (i = startPos; i < NR_COLS; i++) {\n this.chars[i].reset();\n }\n }\n\n clear() {\n this.clearFromPos(0);\n this.pos = 0;\n this.currPenState.reset();\n }\n\n clearToEndOfRow() {\n this.clearFromPos(this.pos);\n }\n\n getTextString() {\n const chars: string[] = [];\n let empty = true;\n for (let i = 0; i < NR_COLS; i++) {\n const char = this.chars[i].uchar;\n if (char !== ' ') {\n empty = false;\n }\n\n chars.push(char);\n }\n if (empty) {\n return '';\n } else {\n return chars.join('');\n }\n }\n\n setPenStyles(styles: Partial<PenStyles>) {\n this.currPenState.setStyles(styles);\n const currChar = this.chars[this.pos];\n currChar.setPenState(this.currPenState);\n }\n}\n\n/**\n * Keep a CEA-608 screen of 32x15 styled characters\n * @constructor\n */\nexport class CaptionScreen {\n rows: Row[];\n currRow: number;\n nrRollUpRows: number | null;\n lastOutputScreen: CaptionScreen | null;\n logger: CaptionsLogger;\n\n constructor(logger: CaptionsLogger) {\n this.rows = [];\n for (let i = 0; i < NR_ROWS; i++) {\n this.rows.push(new Row(logger));\n } // Note that we use zero-based numbering (0-14)\n\n this.logger = logger;\n this.currRow = NR_ROWS - 1;\n this.nrRollUpRows = null;\n this.lastOutputScreen = null;\n this.reset();\n }\n\n reset() {\n for (let i = 0; i < NR_ROWS; i++) {\n this.rows[i].clear();\n }\n\n this.currRow = NR_ROWS - 1;\n }\n\n equals(other: CaptionScreen): boolean {\n let equal = true;\n for (let i = 0; i < NR_ROWS; i++) {\n if (!this.rows[i].equals(other.rows[i])) {\n equal = false;\n break;\n }\n }\n return equal;\n }\n\n copy(other: CaptionScreen) {\n for (let i = 0; i < NR_ROWS; i++) {\n this.rows[i].copy(other.rows[i]);\n }\n }\n\n isEmpty(): boolean {\n let empty = true;\n for (let i = 0; i < NR_ROWS; i++) {\n if (!this.rows[i].isEmpty()) {\n empty = false;\n break;\n }\n }\n return empty;\n }\n\n backSpace() {\n const row = this.rows[this.currRow];\n row.backSpace();\n }\n\n clearToEndOfRow() {\n const row = this.rows[this.currRow];\n row.clearToEndOfRow();\n }\n\n /**\n * Insert a character (without styling) in the current row.\n */\n insertChar(char: number) {\n const row = this.rows[this.currRow];\n row.insertChar(char);\n }\n\n setPen(styles: Partial<PenStyles>) {\n const row = this.rows[this.currRow];\n row.setPenStyles(styles);\n }\n\n moveCursor(relPos: number) {\n const row = this.rows[this.currRow];\n row.moveCursor(relPos);\n }\n\n setCursor(absPos: number) {\n this.logger.log(VerboseLevel.INFO, 'setCursor: ' + absPos);\n const row = this.rows[this.currRow];\n row.setCursor(absPos);\n }\n\n setPAC(pacData: PACData) {\n this.logger.log(\n VerboseLevel.INFO,\n () => 'pacData = ' + JSON.stringify(pacData)\n );\n let newRow = pacData.row - 1;\n if (this.nrRollUpRows && newRow < this.nrRollUpRows - 1) {\n newRow = this.nrRollUpRows - 1;\n }\n\n // Make sure this only affects Roll-up Captions by checking this.nrRollUpRows\n if (this.nrRollUpRows && this.currRow !== newRow) {\n // clear all rows first\n for (let i = 0; i < NR_ROWS; i++) {\n this.rows[i].clear();\n }\n\n // Copy this.nrRollUpRows rows from lastOutputScreen and place it in the newRow location\n // topRowIndex - the start of rows to copy (inclusive index)\n const topRowIndex = this.currRow + 1 - this.nrRollUpRows;\n // We only copy if the last position was already shown.\n // We use the cueStartTime value to check this.\n const lastOutputScreen = this.lastOutputScreen;\n if (lastOutputScreen) {\n const prevLineTime = lastOutputScreen.rows[topRowIndex].cueStartTime;\n const time = this.logger.time;\n if (prevLineTime && time !== null && prevLineTime < time) {\n for (let i = 0; i < this.nrRollUpRows; i++) {\n this.rows[newRow - this.nrRollUpRows + i + 1].copy(\n lastOutputScreen.rows[topRowIndex + i]\n );\n }\n }\n }\n }\n\n this.currRow = newRow;\n const row = this.rows[this.currRow];\n if (pacData.indent !== null) {\n const indent = pacData.indent;\n const prevPos = Math.max(indent - 1, 0);\n row.setCursor(pacData.indent);\n pacData.color = row.chars[prevPos].penState.foreground;\n }\n const styles: PenStyles = {\n foreground: pacData.color,\n underline: pacData.underline,\n italics: pacData.italics,\n background: 'black',\n flash: false,\n };\n this.setPen(styles);\n }\n\n /**\n * Set background/extra foreground, but first do back_space, and then insert space (backwards compatibility).\n */\n setBkgData(bkgData: Partial<PenStyles>) {\n this.logger.log(\n VerboseLevel.INFO,\n () => 'bkgData = ' + JSON.stringify(bkgData)\n );\n this.backSpace();\n this.setPen(bkgData);\n this.insertChar(0x20); // Space\n }\n\n setRollUpRows(nrRows: number | null) {\n this.nrRollUpRows = nrRows;\n }\n\n rollUp() {\n if (this.nrRollUpRows === null) {\n this.logger.log(\n VerboseLevel.DEBUG,\n 'roll_up but nrRollUpRows not set yet'\n );\n return; // Not properly setup\n }\n this.logger.log(VerboseLevel.TEXT, () => this.getDisplayText());\n const topRowIndex = this.currRow + 1 - this.nrRollUpRows;\n const topRow = this.rows.splice(topRowIndex, 1)[0];\n topRow.clear();\n this.rows.splice(this.currRow, 0, topRow);\n this.logger.log(VerboseLevel.INFO, 'Rolling up');\n // this.logger.log(VerboseLevel.TEXT, this.get_display_text())\n }\n\n /**\n * Get all non-empty rows with as unicode text.\n */\n getDisplayText(asOneRow?: boolean) {\n asOneRow = asOneRow || false;\n const displayText: string[] = [];\n let text = '';\n let rowNr = -1;\n for (let i = 0; i < NR_ROWS; i++) {\n const rowText = this.rows[i].getTextString();\n if (rowText) {\n rowNr = i + 1;\n if (asOneRow) {\n displayText.push('Row ' + rowNr + \": '\" + rowText + \"'\");\n } else {\n displayText.push(rowText.trim());\n }\n }\n }\n if (displayText.length > 0) {\n if (asOneRow) {\n text = '[' + displayText.join(' | ') + ']';\n } else {\n text = displayText.join('\\n');\n }\n }\n return text;\n }\n\n getTextAndFormat() {\n return this.rows;\n }\n}\n\n// var modes = ['MODE_ROLL-UP', 'MODE_POP-ON', 'MODE_PAINT-ON', 'MODE_TEXT'];\n\ntype CaptionModes =\n | 'MODE_ROLL-UP'\n | 'MODE_POP-ON'\n | 'MODE_PAINT-ON'\n | 'MODE_TEXT'\n | null;\n\nclass Cea608Channel {\n chNr: number;\n outputFilter: OutputFilter;\n mode: CaptionModes;\n verbose: number;\n displayedMemory: CaptionScreen;\n nonDisplayedMemory: CaptionScreen;\n lastOutputScreen: CaptionScreen;\n currRollUpRow: Row;\n writeScreen: CaptionScreen;\n cueStartTime: number | null;\n logger: CaptionsLogger;\n\n constructor(\n channelNumber: number,\n outputFilter: OutputFilter,\n logger: CaptionsLogger\n ) {\n this.chNr = channelNumber;\n this.outputFilter = outputFilter;\n this.mode = null;\n this.verbose = 0;\n this.displayedMemory = new CaptionScreen(logger);\n this.nonDisplayedMemory = new CaptionScreen(logger);\n this.lastOutputScreen = new CaptionScreen(logger);\n this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];\n this.writeScreen = this.displayedMemory;\n this.mode = null;\n this.cueStartTime = null; // Keeps track of where a cue started.\n this.logger = logger;\n }\n\n reset() {\n this.mode = null;\n this.displayedMemory.reset();\n this.nonDisplayedMemory.reset();\n this.lastOutputScreen.reset();\n this.outputFilter.reset();\n this.currRollUpRow = this.displayedMemory.rows[NR_ROWS - 1];\n this.writeScreen = this.displayedMemory;\n this.mode = null;\n this.cueStartTime = null;\n }\n\n getHandler(): OutputFilter {\n return this.outputFilter;\n }\n\n setHandler(newHandler: OutputFilter) {\n this.outputFilter = newHandler;\n }\n\n setPAC(pacData: PACData) {\n this.writeScreen.setPAC(pacData);\n }\n\n setBkgData(bkgData: Partial<PenStyles>) {\n this.writeScreen.setBkgData(bkgData);\n }\n\n setMode(newMode: CaptionModes) {\n if (newMode === this.mode) {\n return;\n }\n\n this.mode = newMode;\n this.logger.log(VerboseLevel.INFO, () => 'MODE=' + newMode);\n if (this.mode === 'MODE_POP-ON') {\n this.writeScreen = this.nonDisplayedMemory;\n } else {\n this.writeScreen = this.displayedMemory;\n this.writeScreen.reset();\n }\n if (this.mode !== 'MODE_ROLL-UP') {\n this.displayedMemory.nrRollUpRows = null;\n this.nonDisplayedMemory.nrRollUpRows = null;\n }\n this.mode = newMode;\n }\n\n insertChars(chars: number[]) {\n for (let i = 0; i < chars.length; i++) {\n this.writeScreen.insertChar(chars[i]);\n }\n\n const screen =\n this.writeScreen === this.displayedMemory ? 'DISP' : 'NON_DISP';\n this.logger.log(\n VerboseLevel.INFO,\n () => screen + ': ' + this.writeScreen.getDisplayText(true)\n );\n if (this.mode === 'MODE_PAINT-ON' || this.mode === 'MODE_ROLL-UP') {\n this.logger.log(\n VerboseLevel.TEXT,\n () => 'DISPLAYED: ' + this.displayedMemory.getDisplayText(true)\n );\n this.outputDataUpdate();\n }\n }\n\n ccRCL() {\n // Resume Caption Loading (switch mode to Pop On)\n this.logger.log(VerboseLevel.INFO, 'RCL - Resume Caption Loading');\n this.setMode('MODE_POP-ON');\n }\n\n ccBS() {\n // BackSpace\n this.logger.log(VerboseLevel.INFO, 'BS - BackSpace');\n if (this.mode === 'MODE_TEXT') {\n return;\n }\n\n this.writeScreen.backSpace();\n if (this.writeScreen === this.displayedMemory) {\n this.outputDataUpdate();\n }\n }\n\n ccAOF() {\n // Reserved (formerly Alarm Off)\n }\n\n ccAON() {\n // Reserved (formerly Alarm On)\n }\n\n ccDER() {\n // Delete to End of Row\n this.logger.log(VerboseLevel.INFO, 'DER- Delete to End of Row');\n this.writeScreen.clearToEndOfRow();\n this.outputDataUpdate();\n }\n\n ccRU(nrRows: number | null) {\n // Roll-Up Captions-2,3,or 4 Rows\n this.logger.log(VerboseLevel.INFO, 'RU(' + nrRows + ') - Roll Up');\n this.writeScreen = this.displayedMemory;\n this.setMode('MODE_ROLL-UP');\n this.writeScreen.setRollUpRows(nrRows);\n }\n\n ccFON() {\n // Flash On\n this.logger.log(VerboseLevel.INFO, 'FON - Flash On');\n this.writeScreen.setPen({ flash: true });\n }\n\n ccRDC() {\n // Resume Direct Captioning (switch mode to PaintOn)\n this.logger.log(VerboseLevel.INFO, 'RDC - Resume Direct Captioning');\n this.setMode('MODE_PAINT-ON');\n }\n\n ccTR() {\n // Text Restart in text mode (not supported, however)\n this.logger.log(VerboseLevel.INFO, 'TR');\n this.setMode('MODE_TEXT');\n }\n\n ccRTD() {\n // Resume Text Display in Text mode (not supported, however)\n this.logger.log(VerboseLevel.INFO, 'RTD');\n this.setMode('MODE_TEXT');\n }\n\n ccEDM() {\n // Erase Displayed Memory\n this.logger.log(VerboseLevel.INFO, 'EDM - Erase Displayed Memory');\n this.displayedMemory.reset();\n this.outputDataUpdate(true);\n }\n\n ccCR() {\n // Carriage Return\n this.logger.log(VerboseLevel.INFO, 'CR - Carriage Return');\n this.writeScreen.rollUp();\n this.outputDataUpdate(true);\n }\n\n ccENM() {\n // Erase Non-Displayed Memory\n this.logger.log(VerboseLevel.INFO, 'ENM - Erase Non-displayed Memory');\n this.nonDisplayedMemory.reset();\n }\n\n ccEOC() {\n // End of Caption (Flip Memories)\n this.logger.log(VerboseLevel.INFO, 'EOC - End Of Caption');\n if (this.mode === 'MODE_POP-ON') {\n const tmp = this.displayedMemory;\n this.displayedMemory = this.nonDisplayedMemory;\n this.nonDisplayedMemory = tmp;\n this.writeScreen = this.nonDisplayedMemory;\n this.logger.log(\n VerboseLevel.TEXT,\n () => 'DISP: ' + this.displayedMemory.getDisplayText()\n );\n }\n this.outputDataUpdate(true);\n }\n\n ccTO(nrCols: number) {\n // Tab Offset 1,2, or 3 columns\n this.logger.log(VerboseLevel.INFO, 'TO(' + nrCols + ') - Tab Offset');\n this.writeScreen.moveCursor(nrCols);\n }\n\n ccMIDROW(secondByte: number) {\n // Parse MIDROW command\n const styles: Partial<PenStyles> = { flash: false };\n styles.underline = secondByte % 2 === 1;\n styles.italics = secondByte >= 0x2e;\n if (!styles.italics) {\n const colorIndex = Math.floor(secondByte / 2) - 0x10;\n const colors = [\n 'white',\n 'green',\n 'blue',\n 'cyan',\n 'red',\n 'yellow',\n 'magenta',\n ];\n styles.foreground = colors[colorIndex];\n } else {\n styles.foreground = 'white';\n }\n this.logger.log(VerboseLevel.INFO, 'MIDROW: ' + JSON.stringify(styles));\n this.writeScreen.setPen(styles);\n }\n\n outputDataUpdate(dispatch: boolean = false) {\n const time = this.logger.time;\n if (time === null) {\n return;\n }\n\n if (this.outputFilter) {\n if (this.cueStartTime === null && !this.displayedMemory.isEmpty()) {\n // Start of a new cue\n this.cueStartTime = time;\n } else {\n if (!this.displayedMemory.equals(this.lastOutputScreen)) {\n this.outputFilter.newCue(\n this.cueStartTime!,\n time,\n this.lastOutputScreen\n );\n if (dispatch && this.outputFilter.dispatchCue) {\n this.outputFilter.dispatchCue();\n }\n\n this.cueStartTime = this.displayedMemory.isEmpty() ? null : time;\n }\n }\n this.lastOutputScreen.copy(this.displayedMemory);\n }\n }\n\n cueSplitAtTime(t: number) {\n if (this.outputFilter) {\n if (!this.displayedMemory.isEmpty()) {\n if (this.outputFilter.newCue) {\n this.outputFilter.newCue(this.cueStartTime!, t, this.displayedMemory);\n }\n\n this.cueStartTime = t;\n }\n }\n }\n}\n\ninterface PACData {\n row: number;\n indent: number | null;\n color: string | null;\n underline: boolean;\n italics: boolean;\n}\n\ntype SupportedField = 1 | 3;\n\ntype Channels = 0 | 1 | 2; // Will be 1 or 2 when parsing captions\n\ntype CmdHistory = {\n a: number | null;\n b: number | null;\n};\n\nclass Cea608Parser {\n channels: Array<Cea608Channel | null>;\n currentChannel: Channels = 0;\n cmdHistory: CmdHistory;\n logger: CaptionsLogger;\n\n constructor(field: SupportedField, out1: OutputFilter, out2: OutputFilter) {\n const logger = new CaptionsLogger();\n this.channels = [\n null,\n new Cea608Channel(field, out1, logger),\n new Cea608Channel(field + 1, out2, logger),\n ];\n this.cmdHistory = createCmdHistory();\n this.logger = logger;\n }\n\n getHandler(channel: number) {\n return (this.channels[channel] as Cea608Channel).getHandler();\n }\n\n setHandler(channel: number, newHandler: OutputFilter) {\n (this.channels[channel] as Cea608Channel).setHandler(newHandler);\n }\n\n /**\n * Add data for time t in forms of list of bytes (unsigned ints). The bytes are treated as pairs.\n */\n addData(time: number | null, byteList: number[]) {\n let cmdFound: boolean;\n let a: number;\n let b: number;\n let charsFound: number[] | boolean | null = false;\n\n this.logger.time = time;\n\n for (let i = 0; i < byteList.length; i += 2) {\n a = byteList[i] & 0x7f;\n b = byteList[i + 1] & 0x7f;\n if (a === 0 && b === 0) {\n continue;\n } else {\n this.logger.log(\n VerboseLevel.DATA,\n '[' +\n numArrayToHexArray([byteList[i], byteList[i + 1]]) +\n '] -> (' +\n numArrayToHexArray([a, b]) +\n ')'\n );\n }\n\n cmdFound = this.parseCmd(a, b);\n\n if (!cmdFound) {\n cmdFound = this.parseMidrow(a, b);\n }\n\n if (!cmdFound) {\n cmdFound = this.parsePAC(a, b);\n }\n\n if (!cmdFound) {\n cmdFound = this.parseBackgroundAttributes(a, b);\n }\n\n if (!cmdFound) {\n charsFound = this.parseChars(a, b);\n if (charsFound) {\n const currChNr = this.currentChannel;\n if (currChNr && currChNr > 0) {\n const channel = this.channels[currChNr] as Cea608Channel;\n channel.insertChars(charsFound);\n } else {\n this.logger.log(\n VerboseLevel.WARNING,\n 'No channel found yet. TEXT-MODE?'\n );\n }\n }\n }\n if (!cmdFound && !charsFound) {\n this.logger.log(\n VerboseLevel.WARNING,\n \"Couldn't parse cleaned data \" +\n numArrayToHexArray([a, b]) +\n ' orig: ' +\n numArrayToHexArray([byteList[i], byteList[i + 1]])\n );\n }\n }\n }\n\n /**\n * Parse Command.\n * @returns True if a command was found\n */\n parseCmd(a: number, b: number): boolean {\n const { cmdHistory } = this;\n const cond1 =\n (a === 0x14 || a === 0x1c || a === 0x15 || a === 0x1d) &&\n b >= 0x20 &&\n b <= 0x2f;\n const cond2 = (a === 0x17 || a === 0x1f) && b >= 0x21 && b <= 0x23;\n if (!(cond1 || cond2)) {\n return false;\n }\n\n if (hasCmdRepeated(a, b, cmdHistory)) {\n setLastCmd(null, null, cmdHistory);\n this.logger.log(\n VerboseLevel.DEBUG,\n 'Repeated command (' + numArrayToHexArray([a, b]) + ') is dropped'\n );\n return true;\n }\n\n const chNr = a === 0x14 || a === 0x15 || a === 0x17 ? 1 : 2;\n const channel = this.channels[chNr] as Cea608Channel;\n\n if (a === 0x14 || a === 0x15 || a === 0x1c || a === 0x1d) {\n if (b === 0x20) {\n channel.ccRCL();\n } else if (b === 0x21) {\n channel.ccBS();\n } else if (b === 0x22) {\n channel.ccAOF();\n } else if (b === 0x23) {\n channel.ccAON();\n } else if (b === 0x24) {\n channel.ccDER();\n } else if (b === 0x25) {\n channel.ccRU(2);\n } else if (b === 0x26) {\n channel.ccRU(3);\n } else if (b === 0x27) {\n channel.ccRU(4);\n } else if (b === 0x28) {\n channel.ccFON();\n } else if (b === 0x29) {\n channel.ccRDC();\n } else if (b === 0x2a) {\n channel.ccTR();\n } else if (b === 0x2b) {\n channel.ccRTD();\n } else if (b === 0x2c) {\n channel.ccEDM();\n } else if (b === 0x2d) {\n channel.ccCR();\n } else if (b === 0x2e) {\n channel.ccENM();\n } else if (b === 0x2f) {\n channel.ccEOC();\n }\n } else {\n // a == 0x17 || a == 0x1F\n channel.ccTO(b - 0x20);\n }\n setLastCmd(a, b, cmdHistory);\n this.currentChannel = chNr;\n return true;\n }\n\n /**\n * Parse midrow styling command\n */\n parseMidrow(a: number, b: number): boolean {\n let chNr: number = 0;\n\n if ((a === 0x11 || a === 0x19) && b >= 0x20 && b <= 0x2f) {\n if (a === 0x11) {\n chNr = 1;\n } else {\n chNr = 2;\n }\n\n if (chNr !== this.currentChannel) {\n this.logger.log(\n VerboseLevel.ERROR,\n 'Mismatch channel in midrow parsing'\n );\n return false;\n }\n const channel = this.channels[chNr];\n if (!channel) {\n return false;\n }\n channel.ccMIDROW(b);\n this.logger.log(\n VerboseLevel.DEBUG,\n 'MIDROW (' + numArrayToHexArray([a, b]) + ')'\n );\n return true;\n }\n return false;\n }\n\n /**\n * Parse Preable Access Codes (Table 53).\n * @returns {Boolean} Tells if PAC found\n */\n parsePAC(a: number, b: number): boolean {\n let row: number;\n const cmdHistory = this.cmdHistory;\n\n const case1 =\n ((a >= 0x11 && a <= 0x17) || (a >= 0x19 && a <= 0x1f)) &&\n b >= 0x40 &&\n b <= 0x7f;\n const case2 = (a === 0x10 || a === 0x18) && b >= 0x40 && b <= 0x5f;\n if (!(case1 || case2)) {\n return false;\n }\n\n if (hasCmdRepeated(a, b, cmdHistory)) {\n setLastCmd(null, null, cmdHistory);\n return true; // Repeated commands are dropped (once)\n }\n\n const chNr: Channels = a <= 0x17 ? 1 : 2;\n\n if (b >= 0x40 && b <= 0x5f) {\n row = chNr === 1 ? rowsLowCh1[a] : rowsLowCh2[a];\n } else {\n // 0x60 <= b <= 0x7F\n row = chNr === 1 ? rowsHighCh1[a] : rowsHighCh2[a];\n }\n const channel = this.channels[chNr];\n if (!channel) {\n return false;\n }\n channel.setPAC(this.interpretPAC(row, b));\n setLastCmd(a, b, cmdHistory);\n this.currentChannel = chNr;\n return true;\n }\n\n /**\n * Interpret the second byte of the pac, and return the information.\n * @returns pacData with style parameters\n */\n interpretPAC(row: number, byte: number): PACData {\n let pacIndex;\n const pacData: PACData = {\n color: null,\n italics: false,\n indent: null,\n underline: false,\n row: row,\n };\n\n if (byte > 0x5f) {\n pacIndex = byte - 0x60;\n } else {\n pacIndex = byte - 0x40;\n }\n\n pacData.underline = (pacIndex & 1) === 1;\n if (pacIndex <= 0xd) {\n pacData.color = [\n 'white',\n 'green',\n 'blue',\n 'cyan',\n 'red',\n 'yellow',\n 'magenta',\n 'white',\n ][Math.floor(pacIndex / 2)];\n } else if (pacIndex <= 0xf) {\n pacData.italics = true;\n pacData.color = 'white';\n } else {\n pacData.indent = Math.floor((pacIndex - 0x10) / 2) * 4;\n }\n return pacData; // Note that row has zero offset. The spec uses 1.\n }\n\n /**\n * Parse characters.\n * @returns An array with 1 to 2 codes corresponding to chars, if found. null otherwise.\n */\n parseChars(a: number, b: number): number[] | null {\n let channelNr: Channels;\n let charCodes: number[] | null = null;\n let charCode1: number | null = null;\n\n if (a >= 0x19) {\n channelNr = 2;\n charCode1 = a - 8;\n } else {\n channelNr = 1;\n charCode1 = a;\n }\n if (charCode1 >= 0x11 && charCode1 <= 0x13) {\n // Special character\n let oneCode;\n if (charCode1 === 0x11) {\n oneCode = b + 0x50;\n } else if (charCode1 === 0x12) {\n oneCode = b + 0x70;\n } else {\n oneCode = b + 0x90;\n }\n\n this.logger.log(\n VerboseLevel.INFO,\n \"Special char '\" + getCharForByte(oneCode) + \"' in channel \" + channelNr\n );\n charCodes = [oneCode];\n } else if (a >= 0x20 && a <= 0x7f) {\n charCodes = b === 0 ? [a] : [a, b];\n }\n if (charCodes) {\n const hexCodes = numArrayToHexArray(charCodes);\n this.logger.log(\n VerboseLevel.DEBUG,\n 'Char codes = ' + hexCodes.join(',')\n );\n setLastCmd(a, b, this.cmdHistory);\n }\n return charCodes;\n }\n\n /**\n * Parse extended background attributes as well as new foreground color black.\n * @returns True if background attributes are found\n */\n parseBackgroundAttributes(a: number, b: number): boolean {\n const case1 = (a === 0x10 || a === 0x18) && b >= 0x20 && b <= 0x2f;\n const case2 = (a === 0x17 || a === 0x1f) && b >= 0x2d && b <= 0x2f;\n if (!(case1 || case2)) {\n return false;\n }\n let index: number;\n const bkgData: Partial<PenStyles> = {};\n if (a === 0x10 || a === 0x18) {\n index = Math.floor((b - 0x20) / 2);\n bkgData.background = backgroundColors[index];\n if (b % 2 === 1) {\n bkgData.background = bkgData.background + '_semi';\n }\n } else if (b === 0x2d) {\n bkgData.background = 'transparent';\n } else {\n bkgData.foreground = 'black';\n if (b === 0x2f) {\n bkgData.underline = true;\n }\n }\n const chNr: Channels = a <= 0x17 ? 1 : 2;\n const channel: Cea608Channel = this.channels[chNr] as Cea608Channel;\n channel.setBkgData(bkgData);\n setLastCmd(a, b, this.cmdHistory);\n return true;\n }\n\n /**\n * Reset state of parser and its channels.\n */\n reset() {\n for (let i = 0; i < Object.keys(this.channels).length; i++) {\n const channel = this.channels[i];\n if (channel) {\n channel.reset();\n }\n }\n this.cmdHistory = createCmdHistory();\n }\n\n /**\n * Trigger the generation of a cue, and the start of a new one if displayScreens are not empty.\n */\n cueSplitAtTime(t: number) {\n for (let i = 0; i < this.channels.length; i++) {\n const channel = this.channels[i];\n if (channel) {\n channel.cueSplitAtTime(t);\n }\n }\n }\n}\n\nfunction setLastCmd(\n a: number | null,\n b: number | null,\n cmdHistory: CmdHistory\n) {\n cmdHistory.a = a;\n cmdHistory.b = b;\n}\n\nfunction hasCmdRepeated(a: number, b: number, cmdHistory: CmdHistory) {\n return cmdHistory.a === a && cmdHistory.b === b;\n}\n\nfunction createCmdHistory(): CmdHistory {\n return {\n a: null,\n b: null,\n };\n}\n\nexport default Cea608Parser;\n","import type { TimelineController } from '../controller/timeline-controller';\nimport type { CaptionScreen } from './cea-608-parser';\n\nexport default class OutputFilter {\n private timelineController: TimelineController;\n private cueRanges: Array<[number, number]> = [];\n private trackName: string;\n private startTime: number | null = null;\n private endTime: number | null = null;\n private screen: CaptionScreen | null = null;\n\n constructor(timelineController: TimelineController, trackName: string) {\n this.timelineController = timelineController;\n this.trackName = trackName;\n }\n\n dispatchCue() {\n if (this.startTime === null) {\n return;\n }\n\n this.timelineController.addCues(\n this.trackName,\n this.startTime,\n this.endTime as number,\n this.screen as CaptionScreen,\n this.cueRanges\n );\n this.startTime = null;\n }\n\n newCue(startTime: number, endTime: number, screen: CaptionScreen) {\n if (this.startTime === null || this.startTime > startTime) {\n this.startTime = startTime;\n }\n\n this.endTime = endTime;\n this.screen = screen;\n this.timelineController.createCaptionsTrack(this.trackName);\n }\n\n reset() {\n this.cueRanges = [];\n this.startTime = null;\n }\n}\n","/**\n * Copyright 2013 vtt.js Contributors\n *\n * Licensed under the Apache License, Version 2.0 (the 'License');\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an 'AS IS' BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndeclare interface VTTCuePolyfill extends VTTCue {\n new (...args): VTTCuePolyfill;\n hasBeenReset: boolean;\n displayState: void;\n}\n\nexport default (function () {\n if (typeof self !== 'undefined' && self.VTTCue) {\n return self.VTTCue;\n }\n\n const AllowedDirections = ['', 'lr', 'rl'] as const;\n type Direction = (typeof AllowedDirections)[number];\n\n const AllowedAlignments = [\n 'start',\n 'middle',\n 'end',\n 'left',\n 'right',\n ] as const;\n type Alignment = (typeof AllowedAlignments)[number];\n\n function isAllowedValue<T, A>(allowed: T, value: string): A | false {\n if (typeof value !== 'string') {\n return false;\n }\n // necessary for assuring the generic conforms to the Array interface\n if (!Array.isArray(allowed)) {\n return false;\n }\n // reset the type so that the next narrowing works well\n const lcValue = value.toLowerCase() as any;\n // use the allow list to narrow the type to a specific subset of strings\n if (~allowed.indexOf(lcValue)) {\n return lcValue;\n }\n\n return false;\n }\n\n function findDirectionSetting(value: string) {\n return isAllowedValue<typeof AllowedDirections, Direction>(\n AllowedDirections,\n value\n );\n }\n\n function findAlignSetting(value: string) {\n return isAllowedValue<typeof AllowedAlignments, Alignment>(\n AllowedAlignments,\n value\n );\n }\n\n function extend(obj: Record<string, any>, ...rest: Record<string, any>[]) {\n let i = 1;\n for (; i < arguments.length; i++) {\n const cobj = arguments[i];\n for (const p in cobj) {\n obj[p] = cobj[p];\n }\n }\n\n return obj;\n }\n\n function VTTCue(startTime: number, endTime: number, text: string) {\n const cue = this as VTTCuePolyfill;\n const baseObj = { enumerable: true };\n /**\n * Shim implementation specific properties. These properties are not in\n * the spec.\n */\n\n // Lets us know when the VTTCue's data has changed in such a way that we need\n // to recompute its display state. This lets us compute its display state\n // lazily.\n cue.hasBeenReset = false;\n\n /**\n * VTTCue and TextTrackCue properties\n * http://dev.w3.org/html5/webvtt/#vttcue-interface\n */\n\n let _id = '';\n let _pauseOnExit = false;\n let _startTime = startTime;\n let _endTime = endTime;\n let _text = text;\n let _region = null;\n let _vertical: Direction = '';\n let _snapToLines = true;\n let _line: number | 'auto' = 'auto';\n let _lineAlign: Alignment = 'start';\n let _position = 50;\n let _positionAlign: Alignment = 'middle';\n let _size = 50;\n let _align: Alignment = 'middle';\n\n Object.defineProperty(\n cue,\n 'id',\n extend({}, baseObj, {\n get: function () {\n return _id;\n },\n set: function (value: string) {\n _id = '' + value;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'pauseOnExit',\n extend({}, baseObj, {\n get: function () {\n return _pauseOnExit;\n },\n set: function (value: boolean) {\n _pauseOnExit = !!value;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'startTime',\n extend({}, baseObj, {\n get: function () {\n return _startTime;\n },\n set: function (value: number) {\n if (typeof value !== 'number') {\n throw new TypeError('Start time must be set to a number.');\n }\n\n _startTime = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'endTime',\n extend({}, baseObj, {\n get: function () {\n return _endTime;\n },\n set: function (value: number) {\n if (typeof value !== 'number') {\n throw new TypeError('End time must be set to a number.');\n }\n\n _endTime = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'text',\n extend({}, baseObj, {\n get: function () {\n return _text;\n },\n set: function (value: string) {\n _text = '' + value;\n this.hasBeenReset = true;\n },\n })\n );\n\n // todo: implement VTTRegion polyfill?\n Object.defineProperty(\n cue,\n 'region',\n extend({}, baseObj, {\n get: function () {\n return _region;\n },\n set: function (value: any) {\n _region = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'vertical',\n extend({}, baseObj, {\n get: function () {\n return _vertical;\n },\n set: function (value: string) {\n const setting = findDirectionSetting(value);\n // Have to check for false because the setting an be an empty string.\n if (setting === false) {\n throw new SyntaxError(\n 'An invalid or illegal string was specified.'\n );\n }\n\n _vertical = setting;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'snapToLines',\n extend({}, baseObj, {\n get: function () {\n return _snapToLines;\n },\n set: function (value: boolean) {\n _snapToLines = !!value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'line',\n extend({}, baseObj, {\n get: function () {\n return _line;\n },\n set: function (value: number | 'auto') {\n if (typeof value !== 'number' && value !== 'auto') {\n throw new SyntaxError(\n 'An invalid number or illegal string was specified.'\n );\n }\n\n _line = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'lineAlign',\n extend({}, baseObj, {\n get: function () {\n return _lineAlign;\n },\n set: function (value: string) {\n const setting = findAlignSetting(value);\n if (!setting) {\n throw new SyntaxError(\n 'An invalid or illegal string was specified.'\n );\n }\n\n _lineAlign = setting;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'position',\n extend({}, baseObj, {\n get: function () {\n return _position;\n },\n set: function (value: number) {\n if (value < 0 || value > 100) {\n throw new Error('Position must be between 0 and 100.');\n }\n\n _position = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'positionAlign',\n extend({}, baseObj, {\n get: function () {\n return _positionAlign;\n },\n set: function (value: string) {\n const setting = findAlignSetting(value);\n if (!setting) {\n throw new SyntaxError(\n 'An invalid or illegal string was specified.'\n );\n }\n\n _positionAlign = setting;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'size',\n extend({}, baseObj, {\n get: function () {\n return _size;\n },\n set: function (value: number) {\n if (value < 0 || value > 100) {\n throw new Error('Size must be between 0 and 100.');\n }\n\n _size = value;\n this.hasBeenReset = true;\n },\n })\n );\n\n Object.defineProperty(\n cue,\n 'align',\n extend({}, baseObj, {\n get: function () {\n return _align;\n },\n set: function (value: string) {\n const setting = findAlignSetting(value);\n if (!setting) {\n throw new SyntaxError(\n 'An invalid or illegal string was specified.'\n );\n }\n\n _align = setting;\n this.hasBeenReset = true;\n },\n })\n );\n\n /**\n * Other <track> spec defined properties\n */\n\n // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state\n cue.displayState = undefined;\n }\n\n /**\n * VTTCue methods\n */\n\n VTTCue.prototype.getCueAsHTML = function () {\n // Assume WebVTT.convertCueToDOMTree is on the global.\n const WebVTT = (self as any).WebVTT;\n return WebVTT.convertCueToDOMTree(self, this.text);\n };\n // this is a polyfill hack\n return VTTCue as any as VTTCuePolyfill;\n})();\n","/*\n * Source: https://github.com/mozilla/vtt.js/blob/master/dist/vtt.js\n */\n\nimport VTTCue from './vttcue';\n\nclass StringDecoder {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n decode(data: string | any, options?: Object): string | never {\n if (!data) {\n return '';\n }\n\n if (typeof data !== 'string') {\n throw new Error('Error - expected string data.');\n }\n\n return decodeURIComponent(encodeURIComponent(data));\n }\n}\n\n// Try to parse input as a time stamp.\nexport function parseTimeStamp(input: string) {\n function computeSeconds(h, m, s, f) {\n return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + parseFloat(f || 0);\n }\n\n const m = input.match(/^(?:(\\d+):)?(\\d{2}):(\\d{2})(\\.\\d+)?/);\n if (!m) {\n return null;\n }\n\n if (parseFloat(m[2]) > 59) {\n // Timestamp takes the form of [hours]:[minutes].[milliseconds]\n // First position is hours as it's over 59.\n return computeSeconds(m[2], m[3], 0, m[4]);\n }\n // Timestamp takes the form of [hours (optional)]:[minutes]:[seconds].[milliseconds]\n return computeSeconds(m[1], m[2], m[3], m[4]);\n}\n\n// A settings object holds key/value pairs and will ignore anything but the first\n// assignment to a specific key.\nclass Settings {\n private readonly values: { [key: string]: any } = Object.create(null);\n\n // Only accept the first assignment to any key.\n set(k: string, v: any) {\n if (!this.get(k) && v !== '') {\n this.values[k] = v;\n }\n }\n // Return the value for a key, or a default value.\n // If 'defaultKey' is passed then 'dflt' is assumed to be an object with\n // a number of possible default values as properties where 'defaultKey' is\n // the key of the property that will be chosen; otherwise it's assumed to be\n // a single value.\n get(k: string, dflt?: any, defaultKey?: string): any {\n if (defaultKey) {\n return this.has(k) ? this.values[k] : dflt[defaultKey];\n }\n\n return this.has(k) ? this.values[k] : dflt;\n }\n // Check whether we have a value for a key.\n has(k: string): boolean {\n return k in this.values;\n }\n // Accept a setting if its one of the given alternatives.\n alt(k: string, v: any, a: any[]) {\n for (let n = 0; n < a.length; ++n) {\n if (v === a[n]) {\n this.set(k, v);\n break;\n }\n }\n }\n // Accept a setting if its a valid (signed) integer.\n integer(k: string, v: any) {\n if (/^-?\\d+$/.test(v)) {\n // integer\n this.set(k, parseInt(v, 10));\n }\n }\n // Accept a setting if its a valid percentage.\n percent(k: string, v: any): boolean {\n if (/^([\\d]{1,3})(\\.[\\d]*)?%$/.test(v)) {\n const percent = parseFloat(v);\n if (percent >= 0 && percent <= 100) {\n this.set(k, percent);\n return true;\n }\n }\n return false;\n }\n}\n\n// Helper function to parse input into groups separated by 'groupDelim', and\n// interpret each group as a key/value pair separated by 'keyValueDelim'.\nfunction parseOptions(\n input: string,\n callback: (k: string, v: any) => void,\n keyValueDelim: RegExp,\n groupDelim?: RegExp\n) {\n const groups = groupDelim ? input.split(groupDelim) : [input];\n for (const i in groups) {\n if (typeof groups[i] !== 'string') {\n continue;\n }\n\n const kv = groups[i].split(keyValueDelim);\n if (kv.length !== 2) {\n continue;\n }\n\n const k = kv[0];\n const v = kv[1];\n callback(k, v);\n }\n}\n\nconst defaults = new VTTCue(0, 0, '');\n// 'middle' was changed to 'center' in the spec: https://github.com/w3c/webvtt/pull/244\n// Safari doesn't yet support this change, but FF and Chrome do.\nconst center = (defaults.align as string) === 'middle' ? 'middle' : 'center';\n\nfunction parseCue(input: string, cue: VTTCue, regionList: Region[]) {\n // Remember the original input if we need to throw an error.\n const oInput = input;\n // 4.1 WebVTT timestamp\n function consumeTimeStamp(): number | never {\n const ts = parseTimeStamp(input);\n if (ts === null) {\n throw new Error('Malformed timestamp: ' + oInput);\n }\n\n // Remove time stamp from input.\n input = input.replace(/^[^\\sa-zA-Z-]+/, '');\n return ts;\n }\n\n // 4.4.2 WebVTT cue settings\n function consumeCueSettings(input: string, cue: VTTCue) {\n const settings = new Settings();\n\n parseOptions(\n input,\n function (k, v) {\n let vals;\n switch (k) {\n case 'region':\n // Find the last region we parsed with the same region id.\n for (let i = regionList.length - 1; i >= 0; i--) {\n if (regionList[i].id === v) {\n settings.set(k, regionList[i].region);\n break;\n }\n }\n break;\n case 'vertical':\n settings.alt(k, v, ['rl', 'lr']);\n break;\n case 'line':\n vals = v.split(',');\n settings.integer(k, vals[0]);\n if (settings.percent(k, vals[0])) {\n settings.set('snapToLines', false);\n }\n\n settings.alt(k, vals[0], ['auto']);\n if (vals.length === 2) {\n settings.alt('lineAlign', vals[1], ['start', center, 'end']);\n }\n\n break;\n case 'position':\n vals = v.split(',');\n settings.percent(k, vals[0]);\n if (vals.length === 2) {\n settings.alt('positionAlign', vals[1], [\n 'start',\n center,\n 'end',\n 'line-left',\n 'line-right',\n 'auto',\n ]);\n }\n\n break;\n case 'size':\n settings.percent(k, v);\n break;\n case 'align':\n settings.alt(k, v, ['start', center, 'end', 'left', 'right']);\n break;\n }\n },\n /:/,\n /\\s/\n );\n\n // Apply default values for any missing fields.\n cue.region = settings.get('region', null);\n cue.vertical = settings.get('vertical', '');\n let line = settings.get('line', 'auto');\n if (line === 'auto' && defaults.line === -1) {\n // set numeric line number for Safari\n line = -1;\n }\n cue.line = line;\n cue.lineAlign = settings.get('lineAlign', 'start');\n cue.snapToLines = settings.get('snapToLines', true);\n cue.size = settings.get('size', 100);\n cue.align = settings.get('align', center);\n let position = settings.get('position', 'auto');\n if (position === 'auto' && defaults.position === 50) {\n // set numeric position for Safari\n position =\n cue.align === 'start' || cue.align === 'left'\n ? 0\n : cue.align === 'end' || cue.align === 'right'\n ? 100\n : 50;\n }\n cue.position = position;\n }\n\n function skipWhitespace() {\n input = input.replace(/^\\s+/, '');\n }\n\n // 4.1 WebVTT cue timings.\n skipWhitespace();\n cue.startTime = consumeTimeStamp(); // (1) collect cue start time\n skipWhitespace();\n if (input.slice(0, 3) !== '-->') {\n // (3) next characters must match '-->'\n throw new Error(\n \"Malformed time stamp (time stamps must be separated by '-->'): \" + oInput\n );\n }\n input = input.slice(3);\n skipWhitespace();\n cue.endTime = consumeTimeStamp(); // (5) collect cue end time\n\n // 4.1 WebVTT cue settings list.\n skipWhitespace();\n consumeCueSettings(input, cue);\n}\n\nexport function fixLineBreaks(input: string): string {\n return input.replace(/<br(?: \\/)?>/gi, '\\n');\n}\n\ntype Region = {\n id: string;\n region: any;\n};\n\nexport class VTTParser {\n private state:\n | 'INITIAL'\n | 'HEADER'\n | 'ID'\n | 'CUE'\n | 'CUETEXT'\n | 'NOTE'\n | 'BADWEBVTT'\n | 'BADCUE' = 'INITIAL';\n private buffer: string = '';\n private decoder: StringDecoder = new StringDecoder();\n private regionList: Region[] = [];\n private cue: VTTCue | null = null;\n public oncue?: (cue: VTTCue) => void;\n public onparsingerror?: (error: Error) => void;\n public onflush?: () => void;\n\n parse(data?: string): VTTParser {\n const _this = this;\n\n // If there is no data then we won't decode it, but will just try to parse\n // whatever is in buffer already. This may occur in circumstances, for\n // example when flush() is called.\n if (data) {\n // Try to decode the data that we received.\n _this.buffer += _this.decoder.decode(data, { stream: true });\n }\n\n function collectNextLine(): string {\n let buffer: string = _this.buffer;\n let pos = 0;\n\n buffer = fixLineBreaks(buffer);\n\n while (\n pos < buffer.length &&\n buffer[pos] !== '\\r' &&\n buffer[pos] !== '\\n'\n ) {\n ++pos;\n }\n\n const line: string = buffer.slice(0, pos);\n // Advance the buffer early in case we fail below.\n if (buffer[pos] === '\\r') {\n ++pos;\n }\n\n if (buffer[pos] === '\\n') {\n ++pos;\n }\n\n _this.buffer = buffer.slice(pos);\n return line;\n }\n\n // 3.2 WebVTT metadata header syntax\n function parseHeader(input) {\n parseOptions(\n input,\n function (k, v) {\n // switch (k) {\n // case 'region':\n // 3.3 WebVTT region metadata header syntax\n // console.log('parse region', v);\n // parseRegion(v);\n // break;\n // }\n },\n /:/\n );\n }\n\n // 5.1 WebVTT file parsing.\n try {\n let line: string = '';\n if (_this.state === 'INITIAL') {\n // We can't start parsing until we have the first line.\n if (!/\\r\\n|\\n/.test(_this.buffer)) {\n return this;\n }\n\n line = collectNextLine();\n // strip of UTF-8 BOM if any\n // https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8\n const m = line.match(/^()?WEBVTT([ \\t].*)?$/);\n if (!m?.[0]) {\n throw new Error('Malformed WebVTT signature.');\n }\n\n _this.state = 'HEADER';\n }\n\n let alreadyCollectedLine = false;\n while (_this.buffer) {\n // We can't parse a line until we have the full line.\n if (!/\\r\\n|\\n/.test(_this.buffer)) {\n return this;\n }\n\n if (!alreadyCollectedLine) {\n line = collectNextLine();\n } else {\n alreadyCollectedLine = false;\n }\n\n switch (_this.state) {\n case 'HEADER':\n // 13-18 - Allow a header (metadata) under the WEBVTT line.\n if (/:/.test(line)) {\n parseHeader(line);\n } else if (!line) {\n // An empty line terminates the header and starts the body (cues).\n _this.state = 'ID';\n }\n continue;\n case 'NOTE':\n // Ignore NOTE blocks.\n if (!line) {\n _this.state = 'ID';\n }\n\n continue;\n case 'ID':\n // Check for the start of NOTE blocks.\n if (/^NOTE($|[ \\t])/.test(line)) {\n _this.state = 'NOTE';\n break;\n }\n // 19-29 - Allow any number of line terminators, then initialize new cue values.\n if (!line) {\n continue;\n }\n\n _this.cue = new VTTCue(0, 0, '');\n _this.state = 'CUE';\n // 30-39 - Check if self line contains an optional identifier or timing data.\n if (line.indexOf('-->') === -1) {\n _this.cue.id = line;\n continue;\n }\n // Process line as start of a cue.\n /* falls through */\n case 'CUE':\n // 40 - Collect cue timings and settings.\n if (!_this.cue) {\n _this.state = 'BADCUE';\n continue;\n }\n try {\n parseCue(line, _this.cue, _this.regionList);\n } catch (e) {\n // In case of an error ignore rest of the cue.\n _this.cue = null;\n _this.state = 'BADCUE';\n continue;\n }\n _this.state = 'CUETEXT';\n continue;\n case 'CUETEXT':\n {\n const hasSubstring = line.indexOf('-->') !== -1;\n // 34 - If we have an empty line then report the cue.\n // 35 - If we have the special substring '-->' then report the cue,\n // but do not collect the line as we need to process the current\n // one as a new cue.\n if (!line || (hasSubstring && (alreadyCollectedLine = true))) {\n // We are done parsing self cue.\n if (_this.oncue && _this.cue) {\n _this.oncue(_this.cue);\n }\n\n _this.cue = null;\n _this.state = 'ID';\n continue;\n }\n if (_this.cue === null) {\n continue;\n }\n\n if (_this.cue.text) {\n _this.cue.text += '\\n';\n }\n _this.cue.text += line;\n }\n continue;\n case 'BADCUE':\n // 54-62 - Collect and discard the remaining cue.\n if (!line) {\n _this.state = 'ID';\n }\n }\n }\n } catch (e) {\n // If we are currently parsing a cue, report what we have.\n if (_this.state === 'CUETEXT' && _this.cue && _this.oncue) {\n _this.oncue(_this.cue);\n }\n\n _this.cue = null;\n // Enter BADWEBVTT state if header was not parsed correctly otherwise\n // another exception occurred so enter BADCUE state.\n _this.state = _this.state === 'INITIAL' ? 'BADWEBVTT' : 'BADCUE';\n }\n return this;\n }\n\n flush(): VTTParser {\n const _this = this;\n try {\n // Finish decoding the stream.\n // _this.buffer += _this.decoder.decode();\n // Synthesize the end of the current cue or region.\n if (_this.cue || _this.state === 'HEADER') {\n _this.buffer += '\\n\\n';\n _this.parse();\n }\n // If we've flushed, parsed, and we're still on the INITIAL state then\n // that means we don't have enough of the stream to parse the first\n // line.\n if (_this.state === 'INITIAL' || _this.state === 'BADWEBVTT') {\n throw new Error('Malformed WebVTT signature.');\n }\n } catch (e) {\n if (_this.onparsingerror) {\n _this.onparsingerror(e);\n }\n }\n if (_this.onflush) {\n _this.onflush();\n }\n\n return this;\n }\n}\n","import { VTTParser } from './vttparser';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport {\n RationalTimestamp,\n toMpegTsClockFromTimescale,\n} from './timescale-conversion';\nimport { normalizePts } from '../remux/mp4-remuxer';\nimport type { VTTCCs } from '../types/vtt';\n\nconst LINEBREAKS = /\\r\\n|\\n\\r|\\n|\\r/g;\n\n// String.prototype.startsWith is not supported in IE11\nconst startsWith = function (\n inputString: string,\n searchString: string,\n position: number = 0\n) {\n return (\n inputString.slice(position, position + searchString.length) === searchString\n );\n};\n\nconst cueString2millis = function (timeString: string) {\n let ts = parseInt(timeString.slice(-3));\n const secs = parseInt(timeString.slice(-6, -4));\n const mins = parseInt(timeString.slice(-9, -7));\n const hours =\n timeString.length > 9\n ? parseInt(timeString.substring(0, timeString.indexOf(':')))\n : 0;\n\n if (\n !Number.isFinite(ts) ||\n !Number.isFinite(secs) ||\n !Number.isFinite(mins) ||\n !Number.isFinite(hours)\n ) {\n throw Error(`Malformed X-TIMESTAMP-MAP: Local:${timeString}`);\n }\n\n ts += 1000 * secs;\n ts += 60 * 1000 * mins;\n ts += 60 * 60 * 1000 * hours;\n\n return ts;\n};\n\n// From https://github.com/darkskyapp/string-hash\nconst hash = function (text: string) {\n let hash = 5381;\n let i = text.length;\n while (i) {\n hash = (hash * 33) ^ text.charCodeAt(--i);\n }\n\n return (hash >>> 0).toString();\n};\n\n// Create a unique hash id for a cue based on start/end times and text.\n// This helps timeline-controller to avoid showing repeated captions.\nexport function generateCueId(\n startTime: number,\n endTime: number,\n text: string\n) {\n return hash(startTime.toString()) + hash(endTime.toString()) + hash(text);\n}\n\nconst calculateOffset = function (vttCCs: VTTCCs, cc, presentationTime) {\n let currCC = vttCCs[cc];\n let prevCC = vttCCs[currCC.prevCC];\n\n // This is the first discontinuity or cues have been processed since the last discontinuity\n // Offset = current discontinuity time\n if (!prevCC || (!prevCC.new && currCC.new)) {\n vttCCs.ccOffset = vttCCs.presentationOffset = currCC.start;\n currCC.new = false;\n return;\n }\n\n // There have been discontinuities since cues were last parsed.\n // Offset = time elapsed\n while (prevCC?.new) {\n vttCCs.ccOffset += currCC.start - prevCC.start;\n currCC.new = false;\n currCC = prevCC;\n prevCC = vttCCs[currCC.prevCC];\n }\n\n vttCCs.presentationOffset = presentationTime;\n};\n\nexport function parseWebVTT(\n vttByteArray: ArrayBuffer,\n initPTS: RationalTimestamp,\n vttCCs: VTTCCs,\n cc: number,\n timeOffset: number,\n callBack: (cues: VTTCue[]) => void,\n errorCallBack: (error: Error) => void\n) {\n const parser = new VTTParser();\n // Convert byteArray into string, replacing any somewhat exotic linefeeds with \"\\n\", then split on that character.\n // Uint8Array.prototype.reduce is not implemented in IE11\n const vttLines = utf8ArrayToStr(new Uint8Array(vttByteArray))\n .trim()\n .replace(LINEBREAKS, '\\n')\n .split('\\n');\n const cues: VTTCue[] = [];\n const init90kHz = toMpegTsClockFromTimescale(\n initPTS.baseTime,\n initPTS.timescale\n );\n let cueTime = '00:00.000';\n let timestampMapMPEGTS = 0;\n let timestampMapLOCAL = 0;\n let parsingError: Error;\n let inHeader = true;\n\n parser.oncue = function (cue: VTTCue) {\n // Adjust cue timing; clamp cues to start no earlier than - and drop cues that don't end after - 0 on timeline.\n const currCC = vttCCs[cc];\n let cueOffset = vttCCs.ccOffset;\n\n // Calculate subtitle PTS offset\n const webVttMpegTsMapOffset = (timestampMapMPEGTS - init90kHz) / 90000;\n\n // Update offsets for new discontinuities\n if (currCC?.new) {\n if (timestampMapLOCAL !== undefined) {\n // When local time is provided, offset = discontinuity start time - local time\n cueOffset = vttCCs.ccOffset = currCC.start;\n } else {\n calculateOffset(vttCCs, cc, webVttMpegTsMapOffset);\n }\n }\n\n if (webVttMpegTsMapOffset) {\n // If we have MPEGTS, offset = presentation time + discontinuity offset\n cueOffset = webVttMpegTsMapOffset - vttCCs.presentationOffset;\n }\n\n const duration = cue.endTime - cue.startTime;\n const startTime =\n normalizePts(\n (cue.startTime + cueOffset - timestampMapLOCAL) * 90000,\n timeOffset * 90000\n ) / 90000;\n cue.startTime = Math.max(startTime, 0);\n cue.endTime = Math.max(startTime + duration, 0);\n\n //trim trailing webvtt block whitespaces\n const text = cue.text.trim();\n\n // Fix encoding of special characters\n cue.text = decodeURIComponent(encodeURIComponent(text));\n\n // If the cue was not assigned an id from the VTT file (line above the content), create one.\n if (!cue.id) {\n cue.id = generateCueId(cue.startTime, cue.endTime, text);\n }\n\n if (cue.endTime > 0) {\n cues.push(cue);\n }\n };\n\n parser.onparsingerror = function (error: Error) {\n parsingError = error;\n };\n\n parser.onflush = function () {\n if (parsingError) {\n errorCallBack(parsingError);\n return;\n }\n callBack(cues);\n };\n\n // Go through contents line by line.\n vttLines.forEach((line) => {\n if (inHeader) {\n // Look for X-TIMESTAMP-MAP in header.\n if (startsWith(line, 'X-TIMESTAMP-MAP=')) {\n // Once found, no more are allowed anyway, so stop searching.\n inHeader = false;\n // Extract LOCAL and MPEGTS.\n line\n .slice(16)\n .split(',')\n .forEach((timestamp) => {\n if (startsWith(timestamp, 'LOCAL:')) {\n cueTime = timestamp.slice(6);\n } else if (startsWith(timestamp, 'MPEGTS:')) {\n timestampMapMPEGTS = parseInt(timestamp.slice(7));\n }\n });\n try {\n // Convert cue time to seconds\n timestampMapLOCAL = cueString2millis(cueTime) / 1000;\n } catch (error) {\n parsingError = error;\n }\n // Return without parsing X-TIMESTAMP-MAP line.\n return;\n } else if (line === '') {\n inHeader = false;\n }\n }\n // Parse line by default.\n parser.parse(line + '\\n');\n });\n\n parser.flush();\n}\n","import { findBox } from './mp4-tools';\nimport { parseTimeStamp } from './vttparser';\nimport VTTCue from './vttcue';\nimport { utf8ArrayToStr } from '../demux/id3';\nimport {\n RationalTimestamp,\n toTimescaleFromScale,\n} from './timescale-conversion';\nimport { generateCueId } from './webvtt-parser';\n\nexport const IMSC1_CODEC = 'stpp.ttml.im1t';\n\n// Time format: h:m:s:frames(.subframes)\nconst HMSF_REGEX = /^(\\d{2,}):(\\d{2}):(\\d{2}):(\\d{2})\\.?(\\d+)?$/;\n\n// Time format: hours, minutes, seconds, milliseconds, frames, ticks\nconst TIME_UNIT_REGEX = /^(\\d*(?:\\.\\d*)?)(h|m|s|ms|f|t)$/;\n\nconst textAlignToLineAlign: Partial<Record<string, LineAlignSetting>> = {\n left: 'start',\n center: 'center',\n right: 'end',\n start: 'start',\n end: 'end',\n};\n\nexport function parseIMSC1(\n payload: ArrayBuffer,\n initPTS: RationalTimestamp,\n callBack: (cues: Array<VTTCue>) => any,\n errorCallBack: (error: Error) => any\n) {\n const results = findBox(new Uint8Array(payload), ['mdat']);\n if (results.length === 0) {\n errorCallBack(new Error('Could not parse IMSC1 mdat'));\n return;\n }\n\n const ttmlList = results.map((mdat) => utf8ArrayToStr(mdat));\n\n const syncTime = toTimescaleFromScale(initPTS.baseTime, 1, initPTS.timescale);\n\n try {\n ttmlList.forEach((ttml) => callBack(parseTTML(ttml, syncTime)));\n } catch (error) {\n errorCallBack(error);\n }\n}\n\nfunction parseTTML(ttml: string, syncTime: number): Array<VTTCue> {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(ttml, 'text/xml');\n const tt = xmlDoc.getElementsByTagName('tt')[0];\n if (!tt) {\n throw new Error('Invalid ttml');\n }\n const defaultRateInfo = {\n frameRate: 30,\n subFrameRate: 1,\n frameRateMultiplier: 0,\n tickRate: 0,\n };\n const rateInfo: Object = Object.keys(defaultRateInfo).reduce(\n (result, key) => {\n result[key] = tt.getAttribute(`ttp:${key}`) || defaultRateInfo[key];\n return result;\n },\n {}\n );\n\n const trim = tt.getAttribute('xml:space') !== 'preserve';\n\n const styleElements = collectionToDictionary(\n getElementCollection(tt, 'styling', 'style')\n );\n const regionElements = collectionToDictionary(\n getElementCollection(tt, 'layout', 'region')\n );\n const cueElements = getElementCollection(tt, 'body', '[begin]');\n\n return [].map\n .call(cueElements, (cueElement) => {\n const cueText = getTextContent(cueElement, trim);\n\n if (!cueText || !cueElement.hasAttribute('begin')) {\n return null;\n }\n const startTime = parseTtmlTime(\n cueElement.getAttribute('begin'),\n rateInfo\n );\n const duration = parseTtmlTime(cueElement.getAttribute('dur'), rateInfo);\n let endTime = parseTtmlTime(cueElement.getAttribute('end'), rateInfo);\n if (startTime === null) {\n throw timestampParsingError(cueElement);\n }\n if (endTime === null) {\n if (duration === null) {\n throw timestampParsingError(cueElement);\n }\n endTime = startTime + duration;\n }\n const cue = new VTTCue(startTime - syncTime, endTime - syncTime, cueText);\n cue.id = generateCueId(cue.startTime, cue.endTime, cue.text);\n\n const region = regionElements[cueElement.getAttribute('region')];\n const style = styleElements[cueElement.getAttribute('style')];\n\n // Apply styles to cue\n const styles = getTtmlStyles(region, style, styleElements);\n const { textAlign } = styles;\n if (textAlign) {\n // cue.positionAlign not settable in FF~2016\n const lineAlign = textAlignToLineAlign[textAlign];\n if (lineAlign) {\n cue.lineAlign = lineAlign;\n }\n cue.align = textAlign as AlignSetting;\n }\n Object.assign(cue, styles);\n\n return cue;\n })\n .filter((cue) => cue !== null);\n}\n\nfunction getElementCollection(\n fromElement,\n parentName,\n childName\n): Array<HTMLElement> {\n const parent = fromElement.getElementsByTagName(parentName)[0];\n if (parent) {\n return [].slice.call(parent.querySelectorAll(childName));\n }\n return [];\n}\n\nfunction collectionToDictionary(elementsWithId: Array<HTMLElement>): {\n [id: string]: HTMLElement;\n} {\n return elementsWithId.reduce((dict, element: HTMLElement) => {\n const id = element.getAttribute('xml:id');\n if (id) {\n dict[id] = element;\n }\n return dict;\n }, {});\n}\n\nfunction getTextContent(element, trim): string {\n return [].slice.call(element.childNodes).reduce((str, node, i) => {\n if (node.nodeName === 'br' && i) {\n return str + '\\n';\n }\n if (node.childNodes?.length) {\n return getTextContent(node, trim);\n } else if (trim) {\n return str + node.textContent.trim().replace(/\\s+/g, ' ');\n }\n return str + node.textContent;\n }, '');\n}\n\nfunction getTtmlStyles(\n region,\n style,\n styleElements\n): { [style: string]: string } {\n const ttsNs = 'http://www.w3.org/ns/ttml#styling';\n let regionStyle = null;\n const styleAttributes = [\n 'displayAlign',\n 'textAlign',\n 'color',\n 'backgroundColor',\n 'fontSize',\n 'fontFamily',\n // 'fontWeight',\n // 'lineHeight',\n // 'wrapOption',\n // 'fontStyle',\n // 'direction',\n // 'writingMode'\n ];\n\n const regionStyleName = region?.hasAttribute('style')\n ? region.getAttribute('style')\n : null;\n\n if (regionStyleName && styleElements.hasOwnProperty(regionStyleName)) {\n regionStyle = styleElements[regionStyleName];\n }\n\n return styleAttributes.reduce((styles, name) => {\n const value =\n getAttributeNS(style, ttsNs, name) ||\n getAttributeNS(region, ttsNs, name) ||\n getAttributeNS(regionStyle, ttsNs, name);\n if (value) {\n styles[name] = value;\n }\n return styles;\n }, {});\n}\n\nfunction getAttributeNS(element, ns, name): string | null {\n if (!element) {\n return null;\n }\n return element.hasAttributeNS(ns, name)\n ? element.getAttributeNS(ns, name)\n : null;\n}\n\nfunction timestampParsingError(node) {\n return new Error(`Could not parse ttml timestamp ${node}`);\n}\n\nfunction parseTtmlTime(timeAttributeValue, rateInfo): number | null {\n if (!timeAttributeValue) {\n return null;\n }\n let seconds: number | null = parseTimeStamp(timeAttributeValue);\n if (seconds === null) {\n if (HMSF_REGEX.test(timeAttributeValue)) {\n seconds = parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo);\n } else if (TIME_UNIT_REGEX.test(timeAttributeValue)) {\n seconds = parseTimeUnits(timeAttributeValue, rateInfo);\n }\n }\n return seconds;\n}\n\nfunction parseHoursMinutesSecondsFrames(timeAttributeValue, rateInfo): number {\n const m = HMSF_REGEX.exec(timeAttributeValue) as Array<any>;\n const frames = (m[4] | 0) + (m[5] | 0) / rateInfo.subFrameRate;\n return (\n (m[1] | 0) * 3600 +\n (m[2] | 0) * 60 +\n (m[3] | 0) +\n frames / rateInfo.frameRate\n );\n}\n\nfunction parseTimeUnits(timeAttributeValue, rateInfo): number {\n const m = TIME_UNIT_REGEX.exec(timeAttributeValue) as Array<any>;\n const value = Number(m[1]);\n const unit = m[2];\n switch (unit) {\n case 'h':\n return value * 3600;\n case 'm':\n return value * 60;\n case 'ms':\n return value * 1000;\n case 'f':\n return value / rateInfo.frameRate;\n case 't':\n return value / rateInfo.tickRate;\n }\n return value;\n}\n","import { Events } from '../events';\nimport Cea608Parser, { CaptionScreen } from '../utils/cea-608-parser';\nimport OutputFilter from '../utils/output-filter';\nimport { parseWebVTT } from '../utils/webvtt-parser';\nimport {\n sendAddTrackEvent,\n clearCurrentCues,\n addCueToTrack,\n removeCuesInRange,\n} from '../utils/texttrack-utils';\nimport { subtitleOptionsIdentical } from '../utils/media-option-attributes';\nimport { parseIMSC1, IMSC1_CODEC } from '../utils/imsc1-ttml-parser';\nimport { appendUint8Array } from '../utils/mp4-tools';\nimport { PlaylistLevelType } from '../types/loader';\nimport { Fragment } from '../loader/fragment';\nimport {\n FragParsingUserdataData,\n FragLoadedData,\n FragDecryptedData,\n MediaAttachingData,\n ManifestLoadedData,\n InitPTSFoundData,\n SubtitleTracksUpdatedData,\n BufferFlushingData,\n FragLoadingData,\n} from '../types/events';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { HlsConfig } from '../config';\nimport type { CuesInterface } from '../utils/cues';\nimport type { MediaPlaylist } from '../types/media-playlist';\nimport type { VTTCCs } from '../types/vtt';\nimport type { RationalTimestamp } from '../utils/timescale-conversion';\n\ntype TrackProperties = {\n label: string;\n languageCode: string;\n media?: MediaPlaylist;\n};\n\ntype NonNativeCaptionsTrack = {\n _id?: string;\n label: string;\n kind: string;\n default: boolean;\n closedCaptions?: MediaPlaylist;\n subtitleTrack?: MediaPlaylist;\n};\n\nexport class TimelineController implements ComponentAPI {\n private hls: Hls;\n private media: HTMLMediaElement | null = null;\n private config: HlsConfig;\n private enabled: boolean = true;\n private Cues: CuesInterface;\n private textTracks: Array<TextTrack> = [];\n private tracks: Array<MediaPlaylist> = [];\n private initPTS: RationalTimestamp[] = [];\n private unparsedVttFrags: Array<FragLoadedData | FragDecryptedData> = [];\n private captionsTracks: Record<string, TextTrack> = {};\n private nonNativeCaptionsTracks: Record<string, NonNativeCaptionsTrack> = {};\n private cea608Parser1!: Cea608Parser;\n private cea608Parser2!: Cea608Parser;\n private lastSn: number = -1;\n private lastPartIndex: number = -1;\n private prevCC: number = -1;\n private vttCCs: VTTCCs = newVTTCCs();\n private captionsProperties: {\n textTrack1: TrackProperties;\n textTrack2: TrackProperties;\n textTrack3: TrackProperties;\n textTrack4: TrackProperties;\n };\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.config = hls.config;\n this.Cues = hls.config.cueHandler;\n\n this.captionsProperties = {\n textTrack1: {\n label: this.config.captionsTextTrack1Label,\n languageCode: this.config.captionsTextTrack1LanguageCode,\n },\n textTrack2: {\n label: this.config.captionsTextTrack2Label,\n languageCode: this.config.captionsTextTrack2LanguageCode,\n },\n textTrack3: {\n label: this.config.captionsTextTrack3Label,\n languageCode: this.config.captionsTextTrack3LanguageCode,\n },\n textTrack4: {\n label: this.config.captionsTextTrack4Label,\n languageCode: this.config.captionsTextTrack4LanguageCode,\n },\n };\n\n if (this.config.enableCEA708Captions) {\n const channel1 = new OutputFilter(this, 'textTrack1');\n const channel2 = new OutputFilter(this, 'textTrack2');\n const channel3 = new OutputFilter(this, 'textTrack3');\n const channel4 = new OutputFilter(this, 'textTrack4');\n this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);\n this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);\n }\n\n hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n hls.on(Events.FRAG_LOADING, this.onFragLoading, this);\n hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.on(Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this);\n hls.on(Events.FRAG_DECRYPTED, this.onFragDecrypted, this);\n hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n hls.on(Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this);\n hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n }\n\n public destroy(): void {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);\n hls.off(Events.FRAG_LOADING, this.onFragLoading, this);\n hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.off(Events.FRAG_PARSING_USERDATA, this.onFragParsingUserdata, this);\n hls.off(Events.FRAG_DECRYPTED, this.onFragDecrypted, this);\n hls.off(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n hls.off(Events.SUBTITLE_TRACKS_CLEARED, this.onSubtitleTracksCleared, this);\n hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);\n // @ts-ignore\n this.hls = this.config = this.cea608Parser1 = this.cea608Parser2 = null;\n }\n\n public addCues(\n trackName: string,\n startTime: number,\n endTime: number,\n screen: CaptionScreen,\n cueRanges: Array<[number, number]>\n ) {\n // skip cues which overlap more than 50% with previously parsed time ranges\n let merged = false;\n for (let i = cueRanges.length; i--; ) {\n const cueRange = cueRanges[i];\n const overlap = intersection(\n cueRange[0],\n cueRange[1],\n startTime,\n endTime\n );\n if (overlap >= 0) {\n cueRange[0] = Math.min(cueRange[0], startTime);\n cueRange[1] = Math.max(cueRange[1], endTime);\n merged = true;\n if (overlap / (endTime - startTime) > 0.5) {\n return;\n }\n }\n }\n if (!merged) {\n cueRanges.push([startTime, endTime]);\n }\n\n if (this.config.renderTextTracksNatively) {\n const track = this.captionsTracks[trackName];\n this.Cues.newCue(track, startTime, endTime, screen);\n } else {\n const cues = this.Cues.newCue(null, startTime, endTime, screen);\n this.hls.trigger(Events.CUES_PARSED, {\n type: 'captions',\n cues,\n track: trackName,\n });\n }\n }\n\n // Triggered when an initial PTS is found; used for synchronisation of WebVTT.\n private onInitPtsFound(\n event: Events.INIT_PTS_FOUND,\n { frag, id, initPTS, timescale }: InitPTSFoundData\n ) {\n const { unparsedVttFrags } = this;\n if (id === 'main') {\n this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n }\n\n // Due to asynchronous processing, initial PTS may arrive later than the first VTT fragments are loaded.\n // Parse any unparsed fragments upon receiving the initial PTS.\n if (unparsedVttFrags.length) {\n this.unparsedVttFrags = [];\n unparsedVttFrags.forEach((frag) => {\n this.onFragLoaded(Events.FRAG_LOADED, frag as FragLoadedData);\n });\n }\n }\n\n private getExistingTrack(trackName: string): TextTrack | null {\n const { media } = this;\n if (media) {\n for (let i = 0; i < media.textTracks.length; i++) {\n const textTrack = media.textTracks[i];\n if (textTrack[trackName]) {\n return textTrack;\n }\n }\n }\n return null;\n }\n\n public createCaptionsTrack(trackName: string) {\n if (this.config.renderTextTracksNatively) {\n this.createNativeTrack(trackName);\n } else {\n this.createNonNativeTrack(trackName);\n }\n }\n\n private createNativeTrack(trackName: string) {\n if (this.captionsTracks[trackName]) {\n return;\n }\n const { captionsProperties, captionsTracks, media } = this;\n const { label, languageCode } = captionsProperties[trackName];\n // Enable reuse of existing text track.\n const existingTrack = this.getExistingTrack(trackName);\n if (!existingTrack) {\n const textTrack = this.createTextTrack('captions', label, languageCode);\n if (textTrack) {\n // Set a special property on the track so we know it's managed by Hls.js\n textTrack[trackName] = true;\n captionsTracks[trackName] = textTrack;\n }\n } else {\n captionsTracks[trackName] = existingTrack;\n clearCurrentCues(captionsTracks[trackName]);\n sendAddTrackEvent(captionsTracks[trackName], media as HTMLMediaElement);\n }\n }\n\n private createNonNativeTrack(trackName: string) {\n if (this.nonNativeCaptionsTracks[trackName]) {\n return;\n }\n // Create a list of a single track for the provider to consume\n const trackProperties: TrackProperties = this.captionsProperties[trackName];\n if (!trackProperties) {\n return;\n }\n const label = trackProperties.label as string;\n const track = {\n _id: trackName,\n label,\n kind: 'captions',\n default: trackProperties.media ? !!trackProperties.media.default : false,\n closedCaptions: trackProperties.media,\n };\n this.nonNativeCaptionsTracks[trackName] = track;\n this.hls.trigger(Events.NON_NATIVE_TEXT_TRACKS_FOUND, { tracks: [track] });\n }\n\n private createTextTrack(\n kind: TextTrackKind,\n label: string,\n lang?: string\n ): TextTrack | undefined {\n const media = this.media;\n if (!media) {\n return;\n }\n return media.addTextTrack(kind, label, lang);\n }\n\n private onMediaAttaching(\n event: Events.MEDIA_ATTACHING,\n data: MediaAttachingData\n ) {\n this.media = data.media;\n this._cleanTracks();\n }\n\n private onMediaDetaching() {\n const { captionsTracks } = this;\n Object.keys(captionsTracks).forEach((trackName) => {\n clearCurrentCues(captionsTracks[trackName]);\n delete captionsTracks[trackName];\n });\n this.nonNativeCaptionsTracks = {};\n }\n\n private onManifestLoading() {\n this.lastSn = -1; // Detect discontinuity in fragment parsing\n this.lastPartIndex = -1;\n this.prevCC = -1;\n this.vttCCs = newVTTCCs(); // Detect discontinuity in subtitle manifests\n this._cleanTracks();\n this.tracks = [];\n this.captionsTracks = {};\n this.nonNativeCaptionsTracks = {};\n this.textTracks = [];\n this.unparsedVttFrags = this.unparsedVttFrags || [];\n this.initPTS = [];\n if (this.cea608Parser1 && this.cea608Parser2) {\n this.cea608Parser1.reset();\n this.cea608Parser2.reset();\n }\n }\n\n private _cleanTracks() {\n // clear outdated subtitles\n const { media } = this;\n if (!media) {\n return;\n }\n const textTracks = media.textTracks;\n if (textTracks) {\n for (let i = 0; i < textTracks.length; i++) {\n clearCurrentCues(textTracks[i]);\n }\n }\n }\n\n private onSubtitleTracksUpdated(\n event: Events.SUBTITLE_TRACKS_UPDATED,\n data: SubtitleTracksUpdatedData\n ) {\n const tracks: Array<MediaPlaylist> = data.subtitleTracks || [];\n const hasIMSC1 = tracks.some((track) => track.textCodec === IMSC1_CODEC);\n if (this.config.enableWebVTT || (hasIMSC1 && this.config.enableIMSC1)) {\n const listIsIdentical = subtitleOptionsIdentical(this.tracks, tracks);\n if (listIsIdentical) {\n this.tracks = tracks;\n return;\n }\n this.textTracks = [];\n this.tracks = tracks;\n\n if (this.config.renderTextTracksNatively) {\n const inUseTracks = this.media ? this.media.textTracks : null;\n\n this.tracks.forEach((track, index) => {\n let textTrack: TextTrack | undefined;\n if (inUseTracks && index < inUseTracks.length) {\n let inUseTrack: TextTrack | null = null;\n\n for (let i = 0; i < inUseTracks.length; i++) {\n if (canReuseVttTextTrack(inUseTracks[i], track)) {\n inUseTrack = inUseTracks[i];\n break;\n }\n }\n\n // Reuse tracks with the same label, but do not reuse 608/708 tracks\n if (inUseTrack) {\n textTrack = inUseTrack;\n }\n }\n if (textTrack) {\n clearCurrentCues(textTrack);\n } else {\n const textTrackKind =\n this._captionsOrSubtitlesFromCharacteristics(track);\n textTrack = this.createTextTrack(\n textTrackKind,\n track.name,\n track.lang\n );\n if (textTrack) {\n textTrack.mode = 'disabled';\n }\n }\n if (textTrack) {\n (textTrack as any).groupId = track.groupId;\n this.textTracks.push(textTrack);\n }\n });\n } else if (this.tracks.length) {\n // Create a list of tracks for the provider to consume\n const tracksList = this.tracks.map((track) => {\n return {\n label: track.name,\n kind: track.type.toLowerCase(),\n default: track.default,\n subtitleTrack: track,\n };\n });\n this.hls.trigger(Events.NON_NATIVE_TEXT_TRACKS_FOUND, {\n tracks: tracksList,\n });\n }\n }\n }\n\n private _captionsOrSubtitlesFromCharacteristics(\n track: MediaPlaylist\n ): TextTrackKind {\n if (track.attrs.CHARACTERISTICS) {\n const transcribesSpokenDialog = /transcribes-spoken-dialog/gi.test(\n track.attrs.CHARACTERISTICS\n );\n const describesMusicAndSound = /describes-music-and-sound/gi.test(\n track.attrs.CHARACTERISTICS\n );\n\n if (transcribesSpokenDialog && describesMusicAndSound) {\n return 'captions';\n }\n }\n\n return 'subtitles';\n }\n\n private onManifestLoaded(\n event: Events.MANIFEST_LOADED,\n data: ManifestLoadedData\n ) {\n if (this.config.enableCEA708Captions && data.captions) {\n data.captions.forEach((captionsTrack) => {\n const instreamIdMatch = /(?:CC|SERVICE)([1-4])/.exec(\n captionsTrack.instreamId as string\n );\n if (!instreamIdMatch) {\n return;\n }\n const trackName = `textTrack${instreamIdMatch[1]}`;\n const trackProperties: TrackProperties =\n this.captionsProperties[trackName];\n if (!trackProperties) {\n return;\n }\n trackProperties.label = captionsTrack.name;\n if (captionsTrack.lang) {\n // optional attribute\n trackProperties.languageCode = captionsTrack.lang;\n }\n trackProperties.media = captionsTrack;\n });\n }\n }\n\n private closedCaptionsForLevel(frag: Fragment): string | undefined {\n const level = this.hls.levels[frag.level];\n return level?.attrs['CLOSED-CAPTIONS'];\n }\n\n private onFragLoading(event: Events.FRAG_LOADING, data: FragLoadingData) {\n const { cea608Parser1, cea608Parser2, lastSn, lastPartIndex } = this;\n if (!this.enabled || !(cea608Parser1 && cea608Parser2)) {\n return;\n }\n // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack\n if (data.frag.type === PlaylistLevelType.MAIN) {\n const sn = data.frag.sn;\n const partIndex = data?.part?.index ?? -1;\n if (\n !(\n sn === lastSn + 1 ||\n (sn === lastSn && partIndex === lastPartIndex + 1)\n )\n ) {\n cea608Parser1.reset();\n cea608Parser2.reset();\n }\n this.lastSn = sn as number;\n this.lastPartIndex = partIndex;\n }\n }\n\n private onFragLoaded(\n event: Events.FRAG_LOADED,\n data: FragDecryptedData | FragLoadedData\n ) {\n const { frag, payload } = data;\n const { initPTS, unparsedVttFrags } = this;\n if (frag.type === PlaylistLevelType.SUBTITLE) {\n // If fragment is subtitle type, parse as WebVTT.\n if (payload.byteLength) {\n // We need an initial synchronisation PTS. Store fragments as long as none has arrived.\n if (!initPTS[frag.cc]) {\n unparsedVttFrags.push(data);\n if (initPTS.length) {\n // finish unsuccessfully, otherwise the subtitle-stream-controller could be blocked from loading new frags.\n this.hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: false,\n frag,\n error: new Error('Missing initial subtitle PTS'),\n });\n }\n return;\n }\n\n const decryptData = frag.decryptdata;\n // fragment after decryption has a stats object\n const decrypted = 'stats' in data;\n // If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait.\n if (decryptData == null || !decryptData.encrypted || decrypted) {\n const trackPlaylistMedia = this.tracks[frag.level];\n const vttCCs = this.vttCCs;\n if (!vttCCs[frag.cc]) {\n vttCCs[frag.cc] = {\n start: frag.start,\n prevCC: this.prevCC,\n new: true,\n };\n this.prevCC = frag.cc;\n }\n if (\n trackPlaylistMedia &&\n trackPlaylistMedia.textCodec === IMSC1_CODEC\n ) {\n this._parseIMSC1(frag, payload);\n } else {\n this._parseVTTs(frag, payload, vttCCs);\n }\n }\n } else {\n // In case there is no payload, finish unsuccessfully.\n this.hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: false,\n frag,\n error: new Error('Empty subtitle payload'),\n });\n }\n }\n }\n\n private _parseIMSC1(frag: Fragment, payload: ArrayBuffer) {\n const hls = this.hls;\n parseIMSC1(\n payload,\n this.initPTS[frag.cc],\n (cues) => {\n this._appendCues(cues, frag.level);\n hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: true,\n frag: frag,\n });\n },\n (error) => {\n logger.log(`Failed to parse IMSC1: ${error}`);\n hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: false,\n frag: frag,\n error,\n });\n }\n );\n }\n\n private _parseVTTs(frag: Fragment, payload: ArrayBuffer, vttCCs: any) {\n const hls = this.hls;\n // Parse the WebVTT file contents.\n const payloadWebVTT = frag.initSegment?.data\n ? appendUint8Array(frag.initSegment.data, new Uint8Array(payload))\n : payload;\n parseWebVTT(\n payloadWebVTT,\n this.initPTS[frag.cc],\n vttCCs,\n frag.cc,\n frag.start,\n (cues) => {\n this._appendCues(cues, frag.level);\n hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: true,\n frag: frag,\n });\n },\n (error) => {\n this._fallbackToIMSC1(frag, payload);\n // Something went wrong while parsing. Trigger event with success false.\n logger.log(`Failed to parse VTT cue: ${error}`);\n hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {\n success: false,\n frag: frag,\n error,\n });\n }\n );\n }\n\n private _fallbackToIMSC1(frag: Fragment, payload: ArrayBuffer) {\n // If textCodec is unknown, try parsing as IMSC1. Set textCodec based on the result\n const trackPlaylistMedia = this.tracks[frag.level];\n if (!trackPlaylistMedia.textCodec) {\n parseIMSC1(\n payload,\n this.initPTS[frag.cc],\n () => {\n trackPlaylistMedia.textCodec = IMSC1_CODEC;\n this._parseIMSC1(frag, payload);\n },\n () => {\n trackPlaylistMedia.textCodec = 'wvtt';\n }\n );\n }\n }\n\n private _appendCues(cues: VTTCue[], fragLevel: number) {\n const hls = this.hls;\n if (this.config.renderTextTracksNatively) {\n const textTrack = this.textTracks[fragLevel];\n // WebVTTParser.parse is an async method and if the currently selected text track mode is set to \"disabled\"\n // before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null\n // and trying to access getCueById method of cues will throw an exception\n // Because we check if the mode is disabled, we can force check `cues` below. They can't be null.\n if (!textTrack || textTrack.mode === 'disabled') {\n return;\n }\n cues.forEach((cue) => addCueToTrack(textTrack, cue));\n } else {\n const currentTrack = this.tracks[fragLevel];\n if (!currentTrack) {\n return;\n }\n const track = currentTrack.default ? 'default' : 'subtitles' + fragLevel;\n hls.trigger(Events.CUES_PARSED, { type: 'subtitles', cues, track });\n }\n }\n\n private onFragDecrypted(\n event: Events.FRAG_DECRYPTED,\n data: FragDecryptedData\n ) {\n const { frag } = data;\n if (frag.type === PlaylistLevelType.SUBTITLE) {\n if (!this.initPTS[frag.cc]) {\n this.unparsedVttFrags.push(data as unknown as FragLoadedData);\n return;\n }\n this.onFragLoaded(Events.FRAG_LOADED, data as unknown as FragLoadedData);\n }\n }\n\n private onSubtitleTracksCleared() {\n this.tracks = [];\n this.captionsTracks = {};\n }\n\n private onFragParsingUserdata(\n event: Events.FRAG_PARSING_USERDATA,\n data: FragParsingUserdataData\n ) {\n const { cea608Parser1, cea608Parser2 } = this;\n if (!this.enabled || !(cea608Parser1 && cea608Parser2)) {\n return;\n }\n\n const { frag, samples } = data;\n if (\n frag.type === PlaylistLevelType.MAIN &&\n this.closedCaptionsForLevel(frag) === 'NONE'\n ) {\n return;\n }\n // If the event contains captions (found in the bytes property), push all bytes into the parser immediately\n // It will create the proper timestamps based on the PTS value\n for (let i = 0; i < samples.length; i++) {\n const ccBytes = samples[i].bytes;\n if (ccBytes) {\n const ccdatas = this.extractCea608Data(ccBytes);\n cea608Parser1.addData(samples[i].pts, ccdatas[0]);\n cea608Parser2.addData(samples[i].pts, ccdatas[1]);\n }\n }\n }\n\n onBufferFlushing(\n event: Events.BUFFER_FLUSHING,\n { startOffset, endOffset, endOffsetSubtitles, type }: BufferFlushingData\n ) {\n const { media } = this;\n if (!media || media.currentTime < endOffset) {\n return;\n }\n // Clear 608 caption cues from the captions TextTracks when the video back buffer is flushed\n // Forward cues are never removed because we can loose streamed 608 content from recent fragments\n if (!type || type === 'video') {\n const { captionsTracks } = this;\n Object.keys(captionsTracks).forEach((trackName) =>\n removeCuesInRange(captionsTracks[trackName], startOffset, endOffset)\n );\n }\n if (this.config.renderTextTracksNatively) {\n // Clear VTT/IMSC1 subtitle cues from the subtitle TextTracks when the back buffer is flushed\n if (startOffset === 0 && endOffsetSubtitles !== undefined) {\n const { textTracks } = this;\n Object.keys(textTracks).forEach((trackName) =>\n removeCuesInRange(\n textTracks[trackName],\n startOffset,\n endOffsetSubtitles\n )\n );\n }\n }\n }\n\n private extractCea608Data(byteArray: Uint8Array): number[][] {\n const actualCCBytes: number[][] = [[], []];\n const count = byteArray[0] & 0x1f;\n let position = 2;\n\n for (let j = 0; j < count; j++) {\n const tmpByte = byteArray[position++];\n const ccbyte1 = 0x7f & byteArray[position++];\n const ccbyte2 = 0x7f & byteArray[position++];\n if (ccbyte1 === 0 && ccbyte2 === 0) {\n continue;\n }\n const ccValid = (0x04 & tmpByte) !== 0; // Support all four channels\n if (ccValid) {\n const ccType = 0x03 & tmpByte;\n if (\n 0x00 /* CEA608 field1*/ === ccType ||\n 0x01 /* CEA608 field2*/ === ccType\n ) {\n // Exclude CEA708 CC data.\n actualCCBytes[ccType].push(ccbyte1);\n actualCCBytes[ccType].push(ccbyte2);\n }\n }\n }\n return actualCCBytes;\n }\n}\n\nfunction canReuseVttTextTrack(\n inUseTrack: (TextTrack & { textTrack1?; textTrack2? }) | null,\n manifestTrack: MediaPlaylist\n): boolean {\n return (\n !!inUseTrack &&\n inUseTrack.label === manifestTrack.name &&\n !(inUseTrack.textTrack1 || inUseTrack.textTrack2)\n );\n}\n\nfunction intersection(x1: number, x2: number, y1: number, y2: number): number {\n return Math.min(x2, y2) - Math.max(x1, y1);\n}\n\nfunction newVTTCCs(): VTTCCs {\n return {\n ccOffset: 0,\n presentationOffset: 0,\n 0: {\n start: 0,\n prevCC: -1,\n new: true,\n },\n };\n}\n","/*\n * cap stream level to media size dimension controller\n */\n\nimport { Events } from '../events';\nimport type { Level } from '../types/level';\nimport type {\n ManifestParsedData,\n BufferCodecsData,\n MediaAttachingData,\n FPSDropLevelCappingData,\n} from '../types/events';\nimport StreamController from './stream-controller';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\n\ntype RestrictedLevel = { width: number; height: number; bitrate: number };\nclass CapLevelController implements ComponentAPI {\n private hls: Hls;\n private autoLevelCapping: number;\n private firstLevel: number;\n private media: HTMLVideoElement | null;\n private restrictedLevels: RestrictedLevel[];\n private timer: number | undefined;\n private clientRect: { width: number; height: number } | null;\n private streamController?: StreamController;\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\n this.firstLevel = -1;\n this.media = null;\n this.restrictedLevels = [];\n this.timer = undefined;\n this.clientRect = null;\n\n this.registerListeners();\n }\n\n public setStreamController(streamController: StreamController) {\n this.streamController = streamController;\n }\n\n public destroy() {\n this.unregisterListener();\n if (this.hls.config.capLevelToPlayerSize) {\n this.stopCapping();\n }\n this.media = null;\n this.clientRect = null;\n // @ts-ignore\n this.hls = this.streamController = null;\n }\n\n protected registerListeners() {\n const { hls } = this;\n hls.on(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\n hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n }\n\n protected unregisterListener() {\n const { hls } = this;\n hls.off(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\n hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.BUFFER_CODECS, this.onBufferCodecs, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n }\n\n protected onFpsDropLevelCapping(\n event: Events.FPS_DROP_LEVEL_CAPPING,\n data: FPSDropLevelCappingData\n ) {\n // Don't add a restricted level more than once\n const level = this.hls.levels[data.droppedLevel];\n if (this.isLevelAllowed(level)) {\n this.restrictedLevels.push({\n bitrate: level.bitrate,\n height: level.height,\n width: level.width,\n });\n }\n }\n\n protected onMediaAttaching(\n event: Events.MEDIA_ATTACHING,\n data: MediaAttachingData\n ) {\n this.media = data.media instanceof HTMLVideoElement ? data.media : null;\n this.clientRect = null;\n }\n\n protected onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ) {\n const hls = this.hls;\n this.restrictedLevels = [];\n this.firstLevel = data.firstLevel;\n if (hls.config.capLevelToPlayerSize && data.video) {\n // Start capping immediately if the manifest has signaled video codecs\n this.startCapping();\n }\n }\n\n // Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted\n // to the first level\n protected onBufferCodecs(\n event: Events.BUFFER_CODECS,\n data: BufferCodecsData\n ) {\n const hls = this.hls;\n if (hls.config.capLevelToPlayerSize && data.video) {\n // If the manifest did not signal a video codec capping has been deferred until we're certain video is present\n this.startCapping();\n }\n }\n\n protected onMediaDetaching() {\n this.stopCapping();\n }\n\n detectPlayerSize() {\n if (this.media && this.mediaHeight > 0 && this.mediaWidth > 0) {\n const levels = this.hls.levels;\n if (levels.length) {\n const hls = this.hls;\n hls.autoLevelCapping = this.getMaxLevel(levels.length - 1);\n if (\n hls.autoLevelCapping > this.autoLevelCapping &&\n this.streamController\n ) {\n // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch\n // usually happen when the user go to the fullscreen mode.\n this.streamController.nextLevelSwitch();\n }\n this.autoLevelCapping = hls.autoLevelCapping;\n }\n }\n }\n\n /*\n * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)\n */\n getMaxLevel(capLevelIndex: number): number {\n const levels = this.hls.levels;\n if (!levels.length) {\n return -1;\n }\n\n const validLevels = levels.filter(\n (level, index) => this.isLevelAllowed(level) && index <= capLevelIndex\n );\n\n this.clientRect = null;\n return CapLevelController.getMaxLevelByMediaSize(\n validLevels,\n this.mediaWidth,\n this.mediaHeight\n );\n }\n\n startCapping() {\n if (this.timer) {\n // Don't reset capping if started twice; this can happen if the manifest signals a video codec\n return;\n }\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\n this.hls.firstLevel = this.getMaxLevel(this.firstLevel);\n self.clearInterval(this.timer);\n this.timer = self.setInterval(this.detectPlayerSize.bind(this), 1000);\n this.detectPlayerSize();\n }\n\n stopCapping() {\n this.restrictedLevels = [];\n this.firstLevel = -1;\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\n if (this.timer) {\n self.clearInterval(this.timer);\n this.timer = undefined;\n }\n }\n\n getDimensions(): { width: number; height: number } {\n if (this.clientRect) {\n return this.clientRect;\n }\n const media = this.media;\n const boundsRect = {\n width: 0,\n height: 0,\n };\n\n if (media) {\n const clientRect = media.getBoundingClientRect();\n boundsRect.width = clientRect.width;\n boundsRect.height = clientRect.height;\n if (!boundsRect.width && !boundsRect.height) {\n // When the media element has no width or height (equivalent to not being in the DOM),\n // then use its width and height attributes (media.width, media.height)\n boundsRect.width =\n clientRect.right - clientRect.left || media.width || 0;\n boundsRect.height =\n clientRect.bottom - clientRect.top || media.height || 0;\n }\n }\n this.clientRect = boundsRect;\n return boundsRect;\n }\n\n get mediaWidth(): number {\n return this.getDimensions().width * this.contentScaleFactor;\n }\n\n get mediaHeight(): number {\n return this.getDimensions().height * this.contentScaleFactor;\n }\n\n get contentScaleFactor(): number {\n let pixelRatio = 1;\n if (!this.hls.config.ignoreDevicePixelRatio) {\n try {\n pixelRatio = self.devicePixelRatio;\n } catch (e) {\n /* no-op */\n }\n }\n\n return pixelRatio;\n }\n\n private isLevelAllowed(level: Level): boolean {\n const restrictedLevels = this.restrictedLevels;\n return !restrictedLevels.some((restrictedLevel) => {\n return (\n level.bitrate === restrictedLevel.bitrate &&\n level.width === restrictedLevel.width &&\n level.height === restrictedLevel.height\n );\n });\n }\n\n static getMaxLevelByMediaSize(\n levels: Array<Level>,\n width: number,\n height: number\n ): number {\n if (!levels?.length) {\n return -1;\n }\n\n // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next\n // to determine whether we've chosen the greatest bandwidth for the media's dimensions\n const atGreatestBandwidth = (curLevel, nextLevel) => {\n if (!nextLevel) {\n return true;\n }\n\n return (\n curLevel.width !== nextLevel.width ||\n curLevel.height !== nextLevel.height\n );\n };\n\n // If we run through the loop without breaking, the media's dimensions are greater than every level, so default to\n // the max level\n let maxLevelIndex = levels.length - 1;\n\n for (let i = 0; i < levels.length; i += 1) {\n const level = levels[i];\n if (\n (level.width >= width || level.height >= height) &&\n atGreatestBandwidth(level, levels[i + 1])\n ) {\n maxLevelIndex = i;\n break;\n }\n }\n\n return maxLevelIndex;\n }\n}\n\nexport default CapLevelController;\n","/**\n * @author Stephan Hesse <disparat@gmail.com> | <tchakabam@gmail.com>\n *\n * DRM support for Hls.js\n */\nimport { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport { logger } from '../utils/logger';\nimport {\n getKeySystemsForConfig,\n getSupportedMediaKeySystemConfigurations,\n keySystemDomainToKeySystemFormat as keySystemToKeySystemFormat,\n KeySystemFormats,\n keySystemFormatToKeySystemDomain,\n KeySystemIds,\n keySystemIdToKeySystemDomain,\n} from '../utils/mediakeys-helper';\nimport {\n KeySystems,\n requestMediaKeySystemAccess,\n} from '../utils/mediakeys-helper';\nimport { strToUtf8array } from '../utils/keysystem-util';\nimport { base64Decode } from '../utils/numeric-encoding-utils';\nimport { DecryptData, LevelKey } from '../loader/level-key';\nimport Hex from '../utils/hex';\nimport { bin2str, parsePssh, parseSinf } from '../utils/mp4-tools';\nimport { EventEmitter } from 'eventemitter3';\nimport type Hls from '../hls';\nimport type { ComponentAPI } from '../types/component-api';\nimport type {\n MediaAttachedData,\n KeyLoadedData,\n ErrorData,\n ManifestLoadedData,\n} from '../types/events';\nimport type { EMEControllerConfig, HlsConfig, LoadPolicy } from '../config';\nimport type { Fragment } from '../loader/fragment';\nimport type {\n Loader,\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n} from '../types/loader';\n\nconst LOGGER_PREFIX = '[eme]';\n\ninterface KeySystemAccessPromises {\n keySystemAccess: Promise<MediaKeySystemAccess>;\n mediaKeys?: Promise<MediaKeys>;\n certificate?: Promise<BufferSource | void>;\n}\n\nexport interface MediaKeySessionContext {\n keySystem: KeySystems;\n mediaKeys: MediaKeys;\n decryptdata: LevelKey;\n mediaKeysSession: MediaKeySession;\n keyStatus: MediaKeyStatus;\n licenseXhr?: XMLHttpRequest;\n}\n\n/**\n * Controller to deal with encrypted media extensions (EME)\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API\n *\n * @class\n * @constructor\n */\nclass EMEController implements ComponentAPI {\n public static CDMCleanupPromise: Promise<void> | void;\n\n private readonly hls: Hls;\n private readonly config: EMEControllerConfig & {\n loader: { new (confg: HlsConfig): Loader<LoaderContext> };\n certLoadPolicy: LoadPolicy;\n keyLoadPolicy: LoadPolicy;\n };\n private media: HTMLMediaElement | null = null;\n private keyFormatPromise: Promise<KeySystemFormats> | null = null;\n private keySystemAccessPromises: {\n [keysystem: string]: KeySystemAccessPromises;\n } = {};\n private _requestLicenseFailureCount: number = 0;\n private mediaKeySessions: MediaKeySessionContext[] = [];\n private keyIdToKeySessionPromise: {\n [keyId: string]: Promise<MediaKeySessionContext>;\n } = {};\n private setMediaKeysQueue: Promise<void>[] = EMEController.CDMCleanupPromise\n ? [EMEController.CDMCleanupPromise]\n : [];\n private onMediaEncrypted = this._onMediaEncrypted.bind(this);\n private onWaitingForKey = this._onWaitingForKey.bind(this);\n\n private debug: (msg: any) => void = logger.debug.bind(logger, LOGGER_PREFIX);\n private log: (msg: any) => void = logger.log.bind(logger, LOGGER_PREFIX);\n private warn: (msg: any) => void = logger.warn.bind(logger, LOGGER_PREFIX);\n private error: (msg: any) => void = logger.error.bind(logger, LOGGER_PREFIX);\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.config = hls.config;\n this.registerListeners();\n }\n\n public destroy() {\n this.unregisterListeners();\n this.onMediaDetached();\n // Remove any references that could be held in config options or callbacks\n const config = this.config;\n config.requestMediaKeySystemAccessFunc = null;\n config.licenseXhrSetup = config.licenseResponseCallback = undefined;\n config.drmSystems = config.drmSystemOptions = {};\n // @ts-ignore\n this.hls =\n this.onMediaEncrypted =\n this.onWaitingForKey =\n this.keyIdToKeySessionPromise =\n null as any;\n // @ts-ignore\n this.config = null;\n }\n\n private registerListeners() {\n this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n this.hls.on(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n this.hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n this.hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n }\n\n private unregisterListeners() {\n this.hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n this.hls.off(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n this.hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n this.hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n }\n\n private getLicenseServerUrl(keySystem: KeySystems): string | never {\n const { drmSystems, widevineLicenseUrl } = this.config;\n const keySystemConfiguration = drmSystems[keySystem];\n\n if (keySystemConfiguration) {\n return keySystemConfiguration.licenseUrl;\n }\n\n // For backward compatibility\n if (keySystem === KeySystems.WIDEVINE && widevineLicenseUrl) {\n return widevineLicenseUrl;\n }\n\n throw new Error(\n `no license server URL configured for key-system \"${keySystem}\"`\n );\n }\n\n private getServerCertificateUrl(keySystem: KeySystems): string | void {\n const { drmSystems } = this.config;\n const keySystemConfiguration = drmSystems[keySystem];\n\n if (keySystemConfiguration) {\n return keySystemConfiguration.serverCertificateUrl;\n } else {\n this.log(`No Server Certificate in config.drmSystems[\"${keySystem}\"]`);\n }\n }\n\n private attemptKeySystemAccess(\n keySystemsToAttempt: KeySystems[]\n ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> {\n const levels = this.hls.levels;\n const uniqueCodec = (value: string | undefined, i, a): value is string =>\n !!value && a.indexOf(value) === i;\n const audioCodecs = levels\n .map((level) => level.audioCodec)\n .filter(uniqueCodec);\n const videoCodecs = levels\n .map((level) => level.videoCodec)\n .filter(uniqueCodec);\n if (audioCodecs.length + videoCodecs.length === 0) {\n videoCodecs.push('avc1.42e01e');\n }\n\n return new Promise(\n (\n resolve: (result: {\n keySystem: KeySystems;\n mediaKeys: MediaKeys;\n }) => void,\n reject: (Error) => void\n ) => {\n const attempt = (keySystems) => {\n const keySystem = keySystems.shift();\n this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs)\n .then((mediaKeys) => resolve({ keySystem, mediaKeys }))\n .catch((error) => {\n if (keySystems.length) {\n attempt(keySystems);\n } else if (error instanceof EMEKeyError) {\n reject(error);\n } else {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_NO_ACCESS,\n error,\n fatal: true,\n },\n error.message\n )\n );\n }\n });\n };\n attempt(keySystemsToAttempt);\n }\n );\n }\n\n private requestMediaKeySystemAccess(\n keySystem: KeySystems,\n supportedConfigurations: MediaKeySystemConfiguration[]\n ): Promise<MediaKeySystemAccess> {\n const { requestMediaKeySystemAccessFunc } = this.config;\n if (!(typeof requestMediaKeySystemAccessFunc === 'function')) {\n let errMessage = `Configured requestMediaKeySystemAccess is not a function ${requestMediaKeySystemAccessFunc}`;\n if (\n requestMediaKeySystemAccess === null &&\n self.location.protocol === 'http:'\n ) {\n errMessage = `navigator.requestMediaKeySystemAccess is not available over insecure protocol ${location.protocol}`;\n }\n return Promise.reject(new Error(errMessage));\n }\n\n return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);\n }\n\n private getMediaKeysPromise(\n keySystem: KeySystems,\n audioCodecs: string[],\n videoCodecs: string[]\n ): Promise<MediaKeys> {\n // This can throw, but is caught in event handler callpath\n const mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(\n keySystem,\n audioCodecs,\n videoCodecs,\n this.config.drmSystemOptions\n );\n const keySystemAccessPromises: KeySystemAccessPromises =\n this.keySystemAccessPromises[keySystem];\n let keySystemAccess = keySystemAccessPromises?.keySystemAccess;\n if (!keySystemAccess) {\n this.log(\n `Requesting encrypted media \"${keySystem}\" key-system access with config: ${JSON.stringify(\n mediaKeySystemConfigs\n )}`\n );\n keySystemAccess = this.requestMediaKeySystemAccess(\n keySystem,\n mediaKeySystemConfigs\n );\n const keySystemAccessPromises: KeySystemAccessPromises =\n (this.keySystemAccessPromises[keySystem] = {\n keySystemAccess,\n });\n keySystemAccess.catch((error) => {\n this.log(\n `Failed to obtain access to key-system \"${keySystem}\": ${error}`\n );\n });\n return keySystemAccess.then((mediaKeySystemAccess) => {\n this.log(\n `Access for key-system \"${mediaKeySystemAccess.keySystem}\" obtained`\n );\n\n const certificateRequest = this.fetchServerCertificate(keySystem);\n\n this.log(`Create media-keys for \"${keySystem}\"`);\n keySystemAccessPromises.mediaKeys = mediaKeySystemAccess\n .createMediaKeys()\n .then((mediaKeys) => {\n this.log(`Media-keys created for \"${keySystem}\"`);\n return certificateRequest.then((certificate) => {\n if (certificate) {\n return this.setMediaKeysServerCertificate(\n mediaKeys,\n keySystem,\n certificate\n );\n }\n return mediaKeys;\n });\n });\n\n keySystemAccessPromises.mediaKeys.catch((error) => {\n this.error(\n `Failed to create media-keys for \"${keySystem}\"}: ${error}`\n );\n });\n\n return keySystemAccessPromises.mediaKeys;\n });\n }\n return keySystemAccess.then(() => keySystemAccessPromises.mediaKeys!);\n }\n\n private createMediaKeySessionContext({\n decryptdata,\n keySystem,\n mediaKeys,\n }: {\n decryptdata: LevelKey;\n keySystem: KeySystems;\n mediaKeys: MediaKeys;\n }): MediaKeySessionContext {\n this.log(\n `Creating key-system session \"${keySystem}\" keyId: ${Hex.hexDump(\n decryptdata.keyId! || []\n )}`\n );\n\n const mediaKeysSession = mediaKeys.createSession();\n\n const mediaKeySessionContext: MediaKeySessionContext = {\n decryptdata,\n keySystem,\n mediaKeys,\n mediaKeysSession,\n keyStatus: 'status-pending',\n };\n\n this.mediaKeySessions.push(mediaKeySessionContext);\n\n return mediaKeySessionContext;\n }\n\n private renewKeySession(mediaKeySessionContext: MediaKeySessionContext) {\n const decryptdata = mediaKeySessionContext.decryptdata;\n if (decryptdata.pssh) {\n const keySessionContext = this.createMediaKeySessionContext(\n mediaKeySessionContext\n );\n const keyId = this.getKeyIdString(decryptdata);\n const scheme = 'cenc';\n this.keyIdToKeySessionPromise[keyId] =\n this.generateRequestWithPreferredKeySession(\n keySessionContext,\n scheme,\n decryptdata.pssh,\n 'expired'\n );\n } else {\n this.warn(`Could not renew expired session. Missing pssh initData.`);\n }\n this.removeSession(mediaKeySessionContext);\n }\n\n private getKeyIdString(decryptdata: DecryptData | undefined): string | never {\n if (!decryptdata) {\n throw new Error('Could not read keyId of undefined decryptdata');\n }\n if (decryptdata.keyId === null) {\n throw new Error('keyId is null');\n }\n return Hex.hexDump(decryptdata.keyId);\n }\n\n private updateKeySession(\n mediaKeySessionContext: MediaKeySessionContext,\n data: Uint8Array\n ): Promise<void> {\n const keySession = mediaKeySessionContext.mediaKeysSession;\n this.log(\n `Updating key-session \"${keySession.sessionId}\" for keyID ${Hex.hexDump(\n mediaKeySessionContext.decryptdata?.keyId! || []\n )}\n } (data length: ${data ? data.byteLength : data})`\n );\n return keySession.update(data);\n }\n\n public selectKeySystemFormat(frag: Fragment): Promise<KeySystemFormats> {\n const keyFormats = Object.keys(frag.levelkeys || {}) as KeySystemFormats[];\n if (!this.keyFormatPromise) {\n this.log(\n `Selecting key-system from fragment (sn: ${frag.sn} ${frag.type}: ${\n frag.level\n }) key formats ${keyFormats.join(', ')}`\n );\n this.keyFormatPromise = this.getKeyFormatPromise(keyFormats);\n }\n return this.keyFormatPromise;\n }\n\n private getKeyFormatPromise(\n keyFormats: KeySystemFormats[]\n ): Promise<KeySystemFormats> {\n return new Promise((resolve, reject) => {\n const keySystemsInConfig = getKeySystemsForConfig(this.config);\n const keySystemsToAttempt = keyFormats\n .map(keySystemFormatToKeySystemDomain)\n .filter(\n (value) => !!value && keySystemsInConfig.indexOf(value) !== -1\n ) as any as KeySystems[];\n return this.getKeySystemSelectionPromise(keySystemsToAttempt)\n .then(({ keySystem }) => {\n const keySystemFormat = keySystemToKeySystemFormat(keySystem);\n if (keySystemFormat) {\n resolve(keySystemFormat);\n } else {\n reject(\n new Error(`Unable to find format for key-system \"${keySystem}\"`)\n );\n }\n })\n .catch(reject);\n });\n }\n\n public loadKey(data: KeyLoadedData): Promise<MediaKeySessionContext> {\n const decryptdata = data.keyInfo.decryptdata;\n\n const keyId = this.getKeyIdString(decryptdata);\n const keyDetails = `(keyId: ${keyId} format: \"${decryptdata.keyFormat}\" method: ${decryptdata.method} uri: ${decryptdata.uri})`;\n\n this.log(`Starting session for key ${keyDetails}`);\n\n let keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];\n if (!keySessionContextPromise) {\n keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] =\n this.getKeySystemForKeyPromise(decryptdata).then(\n ({ keySystem, mediaKeys }) => {\n this.throwIfDestroyed();\n this.log(\n `Handle encrypted media sn: ${data.frag.sn} ${data.frag.type}: ${data.frag.level} using key ${keyDetails}`\n );\n\n return this.attemptSetMediaKeys(keySystem, mediaKeys).then(() => {\n this.throwIfDestroyed();\n const keySessionContext = this.createMediaKeySessionContext({\n keySystem,\n mediaKeys,\n decryptdata,\n });\n const scheme = 'cenc';\n return this.generateRequestWithPreferredKeySession(\n keySessionContext,\n scheme,\n decryptdata.pssh,\n 'playlist-key'\n );\n });\n }\n );\n\n keySessionContextPromise.catch((error) => this.handleError(error));\n }\n\n return keySessionContextPromise;\n }\n\n private throwIfDestroyed(message = 'Invalid state'): void | never {\n if (!this.hls) {\n throw new Error('invalid state');\n }\n }\n\n private handleError(error: EMEKeyError | Error) {\n if (!this.hls) {\n return;\n }\n this.error(error.message);\n if (error instanceof EMEKeyError) {\n this.hls.trigger(Events.ERROR, error.data);\n } else {\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_NO_KEYS,\n error,\n fatal: true,\n });\n }\n }\n\n private getKeySystemForKeyPromise(\n decryptdata: LevelKey\n ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> {\n const keyId = this.getKeyIdString(decryptdata);\n const mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];\n if (!mediaKeySessionContext) {\n const keySystem = keySystemFormatToKeySystemDomain(\n decryptdata.keyFormat as KeySystemFormats\n );\n const keySystemsToAttempt = keySystem\n ? [keySystem]\n : getKeySystemsForConfig(this.config);\n return this.attemptKeySystemAccess(keySystemsToAttempt);\n }\n return mediaKeySessionContext;\n }\n\n private getKeySystemSelectionPromise(\n keySystemsToAttempt: KeySystems[]\n ): Promise<{ keySystem: KeySystems; mediaKeys: MediaKeys }> | never {\n if (!keySystemsToAttempt.length) {\n keySystemsToAttempt = getKeySystemsForConfig(this.config);\n }\n if (keySystemsToAttempt.length === 0) {\n throw new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,\n fatal: true,\n },\n `Missing key-system license configuration options ${JSON.stringify({\n drmSystems: this.config.drmSystems,\n })}`\n );\n }\n return this.attemptKeySystemAccess(keySystemsToAttempt);\n }\n\n private _onMediaEncrypted(event: MediaEncryptedEvent) {\n const { initDataType, initData } = event;\n this.debug(`\"${event.type}\" event: init data type: \"${initDataType}\"`);\n\n // Ignore event when initData is null\n if (initData === null) {\n return;\n }\n\n let keyId: Uint8Array | undefined;\n let keySystemDomain: KeySystems | undefined;\n\n if (\n initDataType === 'sinf' &&\n this.config.drmSystems[KeySystems.FAIRPLAY]\n ) {\n // Match sinf keyId to playlist skd://keyId=\n const json = bin2str(new Uint8Array(initData));\n try {\n const sinf = base64Decode(JSON.parse(json).sinf);\n const tenc = parseSinf(new Uint8Array(sinf));\n if (!tenc) {\n return;\n }\n keyId = tenc.subarray(8, 24);\n keySystemDomain = KeySystems.FAIRPLAY;\n } catch (error) {\n this.warn('Failed to parse sinf \"encrypted\" event message initData');\n return;\n }\n } else {\n // Support clear-lead key-session creation (otherwise depend on playlist keys)\n const psshInfo = parsePssh(initData);\n if (psshInfo === null) {\n return;\n }\n if (\n psshInfo.version === 0 &&\n psshInfo.systemId === KeySystemIds.WIDEVINE &&\n psshInfo.data\n ) {\n keyId = psshInfo.data.subarray(8, 24);\n }\n keySystemDomain = keySystemIdToKeySystemDomain(\n psshInfo.systemId as KeySystemIds\n );\n }\n\n if (!keySystemDomain || !keyId) {\n return;\n }\n\n const keyIdHex = Hex.hexDump(keyId);\n const { keyIdToKeySessionPromise, mediaKeySessions } = this;\n\n let keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];\n for (let i = 0; i < mediaKeySessions.length; i++) {\n // Match playlist key\n const keyContext = mediaKeySessions[i];\n const decryptdata = keyContext.decryptdata;\n if (decryptdata.pssh || !decryptdata.keyId) {\n continue;\n }\n const oldKeyIdHex = Hex.hexDump(decryptdata.keyId);\n if (\n keyIdHex === oldKeyIdHex ||\n decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1\n ) {\n keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];\n delete keyIdToKeySessionPromise[oldKeyIdHex];\n decryptdata.pssh = new Uint8Array(initData);\n decryptdata.keyId = keyId;\n keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] =\n keySessionContextPromise.then(() => {\n return this.generateRequestWithPreferredKeySession(\n keyContext,\n initDataType,\n initData,\n 'encrypted-event-key-match'\n );\n });\n break;\n }\n }\n\n if (!keySessionContextPromise) {\n // Clear-lead key (not encountered in playlist)\n keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] =\n this.getKeySystemSelectionPromise([keySystemDomain]).then(\n ({ keySystem, mediaKeys }) => {\n this.throwIfDestroyed();\n const decryptdata = new LevelKey(\n 'ISO-23001-7',\n keyIdHex,\n keySystemToKeySystemFormat(keySystem) ?? ''\n );\n decryptdata.pssh = new Uint8Array(initData);\n decryptdata.keyId = keyId as Uint8Array;\n return this.attemptSetMediaKeys(keySystem, mediaKeys).then(() => {\n this.throwIfDestroyed();\n const keySessionContext = this.createMediaKeySessionContext({\n decryptdata,\n keySystem,\n mediaKeys,\n });\n return this.generateRequestWithPreferredKeySession(\n keySessionContext,\n initDataType,\n initData,\n 'encrypted-event-no-match'\n );\n });\n }\n );\n }\n keySessionContextPromise.catch((error) => this.handleError(error));\n }\n\n private _onWaitingForKey(event: Event) {\n this.log(`\"${event.type}\" event`);\n }\n\n private attemptSetMediaKeys(\n keySystem: KeySystems,\n mediaKeys: MediaKeys\n ): Promise<void> {\n const queue = this.setMediaKeysQueue.slice();\n\n this.log(`Setting media-keys for \"${keySystem}\"`);\n // Only one setMediaKeys() can run at one time, and multiple setMediaKeys() operations\n // can be queued for execution for multiple key sessions.\n const setMediaKeysPromise = Promise.all(queue).then(() => {\n if (!this.media) {\n throw new Error(\n 'Attempted to set mediaKeys without media element attached'\n );\n }\n return this.media.setMediaKeys(mediaKeys);\n });\n this.setMediaKeysQueue.push(setMediaKeysPromise);\n return setMediaKeysPromise.then(() => {\n this.log(`Media-keys set for \"${keySystem}\"`);\n queue.push(setMediaKeysPromise!);\n this.setMediaKeysQueue = this.setMediaKeysQueue.filter(\n (p) => queue.indexOf(p) === -1\n );\n });\n }\n\n private generateRequestWithPreferredKeySession(\n context: MediaKeySessionContext,\n initDataType: string,\n initData: ArrayBuffer | null,\n reason:\n | 'playlist-key'\n | 'encrypted-event-key-match'\n | 'encrypted-event-no-match'\n | 'expired'\n ): Promise<MediaKeySessionContext> | never {\n const generateRequestFilter =\n this.config.drmSystems?.[context.keySystem]?.generateRequest;\n if (generateRequestFilter) {\n try {\n const mappedInitData: ReturnType<typeof generateRequestFilter> =\n generateRequestFilter.call(this.hls, initDataType, initData, context);\n if (!mappedInitData) {\n throw new Error(\n 'Invalid response from configured generateRequest filter'\n );\n }\n initDataType = mappedInitData.initDataType;\n initData = context.decryptdata.pssh = mappedInitData.initData\n ? new Uint8Array(mappedInitData.initData)\n : null;\n } catch (error) {\n this.warn(error.message);\n if (this.hls?.config.debug) {\n throw error;\n }\n }\n }\n\n if (initData === null) {\n this.log(`Skipping key-session request for \"${reason}\" (no initData)`);\n return Promise.resolve(context);\n }\n\n const keyId = this.getKeyIdString(context.decryptdata);\n this.log(\n `Generating key-session request for \"${reason}\": ${keyId} (init data type: ${initDataType} length: ${\n initData ? initData.byteLength : null\n })`\n );\n\n const licenseStatus = new EventEmitter();\n\n context.mediaKeysSession.onmessage = (event: MediaKeyMessageEvent) => {\n const keySession = context.mediaKeysSession;\n if (!keySession) {\n licenseStatus.emit('error', new Error('invalid state'));\n return;\n }\n const { messageType, message } = event;\n this.log(\n `\"${messageType}\" message event for session \"${keySession.sessionId}\" message size: ${message.byteLength}`\n );\n if (\n messageType === 'license-request' ||\n messageType === 'license-renewal'\n ) {\n this.renewLicense(context, message).catch((error) => {\n this.handleError(error);\n licenseStatus.emit('error', error);\n });\n } else if (messageType === 'license-release') {\n if (context.keySystem === KeySystems.FAIRPLAY) {\n this.updateKeySession(context, strToUtf8array('acknowledged'));\n this.removeSession(context);\n }\n } else {\n this.warn(`unhandled media key message type \"${messageType}\"`);\n }\n };\n\n context.mediaKeysSession.onkeystatuseschange = (\n event: MediaKeyMessageEvent\n ) => {\n const keySession = context.mediaKeysSession;\n if (!keySession) {\n licenseStatus.emit('error', new Error('invalid state'));\n return;\n }\n this.onKeyStatusChange(context);\n const keyStatus = context.keyStatus;\n licenseStatus.emit('keyStatus', keyStatus);\n if (keyStatus === 'expired') {\n this.warn(`${context.keySystem} expired for key ${keyId}`);\n this.renewKeySession(context);\n }\n };\n\n const keyUsablePromise = new Promise(\n (resolve: (value?: void) => void, reject) => {\n licenseStatus.on('error', reject);\n\n licenseStatus.on('keyStatus', (keyStatus) => {\n if (keyStatus.startsWith('usable')) {\n resolve();\n } else if (keyStatus === 'output-restricted') {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED,\n fatal: false,\n },\n 'HDCP level output restricted'\n )\n );\n } else if (keyStatus === 'internal-error') {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_STATUS_INTERNAL_ERROR,\n fatal: true,\n },\n `key status changed to \"${keyStatus}\"`\n )\n );\n } else if (keyStatus === 'expired') {\n reject(new Error('key expired while generating request'));\n } else {\n this.warn(`unhandled key status change \"${keyStatus}\"`);\n }\n });\n }\n );\n\n return context.mediaKeysSession\n .generateRequest(initDataType, initData)\n .then(() => {\n this.log(\n `Request generated for key-session \"${context.mediaKeysSession?.sessionId}\" keyId: ${keyId}`\n );\n })\n .catch((error) => {\n throw new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_NO_SESSION,\n error,\n fatal: false,\n },\n `Error generating key-session request: ${error}`\n );\n })\n .then(() => keyUsablePromise)\n .catch((error) => {\n licenseStatus.removeAllListeners();\n this.removeSession(context);\n throw error;\n })\n .then(() => {\n licenseStatus.removeAllListeners();\n return context;\n });\n }\n\n private onKeyStatusChange(mediaKeySessionContext: MediaKeySessionContext) {\n mediaKeySessionContext.mediaKeysSession.keyStatuses.forEach(\n (status: MediaKeyStatus, keyId: BufferSource) => {\n this.log(\n `key status change \"${status}\" for keyStatuses keyId: ${Hex.hexDump(\n 'buffer' in keyId\n ? new Uint8Array(keyId.buffer, keyId.byteOffset, keyId.byteLength)\n : new Uint8Array(keyId)\n )} session keyId: ${Hex.hexDump(\n new Uint8Array(mediaKeySessionContext.decryptdata.keyId || [])\n )} uri: ${mediaKeySessionContext.decryptdata.uri}`\n );\n mediaKeySessionContext.keyStatus = status;\n }\n );\n }\n\n private fetchServerCertificate(\n keySystem: KeySystems\n ): Promise<BufferSource | void> {\n const config = this.config;\n const Loader = config.loader;\n const certLoader = new Loader(config as HlsConfig) as Loader<LoaderContext>;\n const url = this.getServerCertificateUrl(keySystem);\n if (!url) {\n return Promise.resolve();\n }\n this.log(`Fetching serverCertificate for \"${keySystem}\"`);\n return new Promise((resolve, reject) => {\n const loaderContext: LoaderContext = {\n responseType: 'arraybuffer',\n url,\n };\n const loadPolicy = config.certLoadPolicy.default;\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: 0,\n retryDelay: 0,\n maxRetryDelay: 0,\n };\n const loaderCallbacks: LoaderCallbacks<LoaderContext> = {\n onSuccess: (response, stats, context, networkDetails) => {\n resolve(response.data as ArrayBuffer);\n },\n onError: (response, contex, networkDetails, stats) => {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details:\n ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n fatal: true,\n networkDetails,\n response: {\n url: loaderContext.url,\n data: undefined,\n ...response,\n },\n },\n `\"${keySystem}\" certificate request failed (${url}). Status: ${response.code} (${response.text})`\n )\n );\n },\n onTimeout: (stats, context, networkDetails) => {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details:\n ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED,\n fatal: true,\n networkDetails,\n response: {\n url: loaderContext.url,\n data: undefined,\n },\n },\n `\"${keySystem}\" certificate request timed out (${url})`\n )\n );\n },\n onAbort: (stats, context, networkDetails) => {\n reject(new Error('aborted'));\n },\n };\n certLoader.load(loaderContext, loaderConfig, loaderCallbacks);\n });\n }\n\n private setMediaKeysServerCertificate(\n mediaKeys: MediaKeys,\n keySystem: KeySystems,\n cert: BufferSource\n ): Promise<MediaKeys> {\n return new Promise((resolve, reject) => {\n mediaKeys\n .setServerCertificate(cert)\n .then((success) => {\n this.log(\n `setServerCertificate ${\n success ? 'success' : 'not supported by CDM'\n } (${cert?.byteLength}) on \"${keySystem}\"`\n );\n resolve(mediaKeys);\n })\n .catch((error) => {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details:\n ErrorDetails.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED,\n error,\n fatal: true,\n },\n error.message\n )\n );\n });\n });\n }\n\n private renewLicense(\n context: MediaKeySessionContext,\n keyMessage: ArrayBuffer\n ): Promise<void> {\n return this.requestLicense(context, new Uint8Array(keyMessage)).then(\n (data: ArrayBuffer) => {\n return this.updateKeySession(context, new Uint8Array(data)).catch(\n (error) => {\n throw new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_SESSION_UPDATE_FAILED,\n error,\n fatal: true,\n },\n error.message\n );\n }\n );\n }\n );\n }\n\n private setupLicenseXHR(\n xhr: XMLHttpRequest,\n url: string,\n keysListItem: MediaKeySessionContext,\n licenseChallenge: Uint8Array\n ): Promise<{ xhr: XMLHttpRequest; licenseChallenge: Uint8Array }> {\n const licenseXhrSetup = this.config.licenseXhrSetup;\n\n if (!licenseXhrSetup) {\n xhr.open('POST', url, true);\n\n return Promise.resolve({ xhr, licenseChallenge });\n }\n\n return Promise.resolve()\n .then(() => {\n if (!keysListItem.decryptdata) {\n throw new Error('Key removed');\n }\n return licenseXhrSetup.call(\n this.hls,\n xhr,\n url,\n keysListItem,\n licenseChallenge\n );\n })\n .catch((error: Error) => {\n if (!keysListItem.decryptdata) {\n // Key session removed. Cancel license request.\n throw error;\n }\n // let's try to open before running setup\n xhr.open('POST', url, true);\n\n return licenseXhrSetup.call(\n this.hls,\n xhr,\n url,\n keysListItem,\n licenseChallenge\n );\n })\n .then((licenseXhrSetupResult) => {\n // if licenseXhrSetup did not yet call open, let's do it now\n if (!xhr.readyState) {\n xhr.open('POST', url, true);\n }\n const finalLicenseChallenge = licenseXhrSetupResult\n ? licenseXhrSetupResult\n : licenseChallenge;\n return { xhr, licenseChallenge: finalLicenseChallenge };\n });\n }\n\n private requestLicense(\n keySessionContext: MediaKeySessionContext,\n licenseChallenge: Uint8Array\n ): Promise<ArrayBuffer> {\n const keyLoadPolicy = this.config.keyLoadPolicy.default;\n return new Promise((resolve, reject) => {\n const url = this.getLicenseServerUrl(keySessionContext.keySystem);\n this.log(`Sending license request to URL: ${url}`);\n const xhr = new XMLHttpRequest();\n xhr.responseType = 'arraybuffer';\n xhr.onreadystatechange = () => {\n if (!this.hls || !keySessionContext.mediaKeysSession) {\n return reject(new Error('invalid state'));\n }\n if (xhr.readyState === 4) {\n if (xhr.status === 200) {\n this._requestLicenseFailureCount = 0;\n let data = xhr.response;\n this.log(\n `License received ${\n data instanceof ArrayBuffer ? data.byteLength : data\n }`\n );\n const licenseResponseCallback = this.config.licenseResponseCallback;\n if (licenseResponseCallback) {\n try {\n data = licenseResponseCallback.call(\n this.hls,\n xhr,\n url,\n keySessionContext\n );\n } catch (error) {\n this.error(error);\n }\n }\n resolve(data);\n } else {\n const retryConfig = keyLoadPolicy.errorRetry;\n const maxNumRetry = retryConfig ? retryConfig.maxNumRetry : 0;\n this._requestLicenseFailureCount++;\n if (\n this._requestLicenseFailureCount > maxNumRetry ||\n (xhr.status >= 400 && xhr.status < 500)\n ) {\n reject(\n new EMEKeyError(\n {\n type: ErrorTypes.KEY_SYSTEM_ERROR,\n details: ErrorDetails.KEY_SYSTEM_LICENSE_REQUEST_FAILED,\n fatal: true,\n networkDetails: xhr,\n response: {\n url,\n data: undefined as any,\n code: xhr.status,\n text: xhr.statusText,\n },\n },\n `License Request XHR failed (${url}). Status: ${xhr.status} (${xhr.statusText})`\n )\n );\n } else {\n const attemptsLeft =\n maxNumRetry - this._requestLicenseFailureCount + 1;\n this.warn(\n `Retrying license request, ${attemptsLeft} attempts left`\n );\n this.requestLicense(keySessionContext, licenseChallenge).then(\n resolve,\n reject\n );\n }\n }\n }\n };\n if (\n keySessionContext.licenseXhr &&\n keySessionContext.licenseXhr.readyState !== XMLHttpRequest.DONE\n ) {\n keySessionContext.licenseXhr.abort();\n }\n keySessionContext.licenseXhr = xhr;\n\n this.setupLicenseXHR(xhr, url, keySessionContext, licenseChallenge).then(\n ({ xhr, licenseChallenge }) => {\n xhr.send(licenseChallenge);\n }\n );\n });\n }\n\n private onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ) {\n if (!this.config.emeEnabled) {\n return;\n }\n\n const media = data.media;\n\n // keep reference of media\n this.media = media;\n\n media.addEventListener('encrypted', this.onMediaEncrypted);\n media.addEventListener('waitingforkey', this.onWaitingForKey);\n }\n\n private onMediaDetached() {\n const media = this.media;\n const mediaKeysList = this.mediaKeySessions;\n if (media) {\n media.removeEventListener('encrypted', this.onMediaEncrypted);\n media.removeEventListener('waitingforkey', this.onWaitingForKey);\n this.media = null;\n }\n\n this._requestLicenseFailureCount = 0;\n this.setMediaKeysQueue = [];\n this.mediaKeySessions = [];\n this.keyIdToKeySessionPromise = {};\n LevelKey.clearKeyUriToKeyIdMap();\n\n // Close all sessions and remove media keys from the video element.\n const keySessionCount = mediaKeysList.length;\n EMEController.CDMCleanupPromise = Promise.all(\n mediaKeysList\n .map((mediaKeySessionContext) =>\n this.removeSession(mediaKeySessionContext)\n )\n .concat(\n media?.setMediaKeys(null).catch((error) => {\n this.log(\n `Could not clear media keys: ${error}. media.src: ${media?.src}`\n );\n })\n )\n )\n .then(() => {\n if (keySessionCount) {\n this.log('finished closing key sessions and clearing media keys');\n mediaKeysList.length = 0;\n }\n })\n .catch((error) => {\n this.log(\n `Could not close sessions and clear media keys: ${error}. media.src: ${media?.src}`\n );\n });\n }\n\n private onManifestLoading() {\n this.keyFormatPromise = null;\n }\n\n private onManifestLoaded(\n event: Events.MANIFEST_LOADED,\n { sessionKeys }: ManifestLoadedData\n ) {\n if (!sessionKeys || !this.config.emeEnabled) {\n return;\n }\n if (!this.keyFormatPromise) {\n const keyFormats: KeySystemFormats[] = sessionKeys.reduce(\n (formats: KeySystemFormats[], sessionKey: LevelKey) => {\n if (\n formats.indexOf(sessionKey.keyFormat as KeySystemFormats) === -1\n ) {\n formats.push(sessionKey.keyFormat as KeySystemFormats);\n }\n return formats;\n },\n []\n );\n this.log(\n `Selecting key-system from session-keys ${keyFormats.join(', ')}`\n );\n this.keyFormatPromise = this.getKeyFormatPromise(keyFormats);\n }\n }\n\n private removeSession(\n mediaKeySessionContext: MediaKeySessionContext\n ): Promise<void> | void {\n const { mediaKeysSession, licenseXhr } = mediaKeySessionContext;\n if (mediaKeysSession) {\n this.log(\n `Remove licenses and keys and close session ${mediaKeysSession.sessionId}`\n );\n mediaKeysSession.onmessage = null;\n mediaKeysSession.onkeystatuseschange = null;\n if (licenseXhr && licenseXhr.readyState !== XMLHttpRequest.DONE) {\n licenseXhr.abort();\n }\n mediaKeySessionContext.mediaKeysSession =\n mediaKeySessionContext.decryptdata =\n mediaKeySessionContext.licenseXhr =\n undefined!;\n const index = this.mediaKeySessions.indexOf(mediaKeySessionContext);\n if (index > -1) {\n this.mediaKeySessions.splice(index, 1);\n }\n return mediaKeysSession\n .remove()\n .catch((error) => {\n this.log(`Could not remove session: ${error}`);\n })\n .then(() => {\n return mediaKeysSession.close();\n })\n .catch((error) => {\n this.log(`Could not close session: ${error}`);\n });\n }\n }\n}\n\nclass EMEKeyError extends Error {\n public readonly data: ErrorData;\n constructor(\n data: Omit<ErrorData, 'error'> & { error?: Error },\n message: string\n ) {\n super(message);\n data.error ||= new Error(message);\n this.data = data as ErrorData;\n data.err = data.error;\n }\n}\n\nexport default EMEController;\n","import { Events } from '../events';\nimport Hls from '../hls';\nimport {\n CMCD,\n CMCDHeaders,\n CMCDObjectType,\n CMCDStreamingFormatHLS,\n CMCDVersion,\n} from '../types/cmcd';\nimport { BufferHelper } from '../utils/buffer-helper';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type { Fragment } from '../loader/fragment';\nimport type { BufferCreatedData, MediaAttachedData } from '../types/events';\nimport type {\n FragmentLoaderContext,\n Loader,\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n PlaylistLoaderContext,\n} from '../types/loader';\nimport type {\n FragmentLoaderConstructor,\n HlsConfig,\n PlaylistLoaderConstructor,\n} from '../config';\n\n/**\n * Controller to deal with Common Media Client Data (CMCD)\n * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf\n */\nexport default class CMCDController implements ComponentAPI {\n private hls: Hls;\n private config: HlsConfig;\n private media?: HTMLMediaElement;\n private sid?: string;\n private cid?: string;\n private useHeaders: boolean = false;\n private initialized: boolean = false;\n private starved: boolean = false;\n private buffering: boolean = true;\n private audioBuffer?: SourceBuffer; // eslint-disable-line no-restricted-globals\n private videoBuffer?: SourceBuffer; // eslint-disable-line no-restricted-globals\n\n constructor(hls: Hls) {\n this.hls = hls;\n const config = (this.config = hls.config);\n const { cmcd } = config;\n\n if (cmcd != null) {\n config.pLoader = this.createPlaylistLoader();\n config.fLoader = this.createFragmentLoader();\n\n this.sid = cmcd.sessionId || CMCDController.uuid();\n this.cid = cmcd.contentId;\n this.useHeaders = cmcd.useHeaders === true;\n this.registerListeners();\n }\n }\n\n private registerListeners() {\n const hls = this.hls;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n }\n\n private unregisterListeners() {\n const hls = this.hls;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHED, this.onMediaDetached, this);\n hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n }\n\n destroy() {\n this.unregisterListeners();\n this.onMediaDetached();\n\n // @ts-ignore\n this.hls = this.config = this.audioBuffer = this.videoBuffer = null;\n }\n\n private onMediaAttached(\n event: Events.MEDIA_ATTACHED,\n data: MediaAttachedData\n ) {\n this.media = data.media;\n this.media.addEventListener('waiting', this.onWaiting);\n this.media.addEventListener('playing', this.onPlaying);\n }\n\n private onMediaDetached() {\n if (!this.media) {\n return;\n }\n\n this.media.removeEventListener('waiting', this.onWaiting);\n this.media.removeEventListener('playing', this.onPlaying);\n\n // @ts-ignore\n this.media = null;\n }\n\n private onBufferCreated(\n event: Events.BUFFER_CREATED,\n data: BufferCreatedData\n ) {\n this.audioBuffer = data.tracks.audio?.buffer;\n this.videoBuffer = data.tracks.video?.buffer;\n }\n\n private onWaiting = () => {\n if (this.initialized) {\n this.starved = true;\n }\n\n this.buffering = true;\n };\n\n private onPlaying = () => {\n if (!this.initialized) {\n this.initialized = true;\n }\n\n this.buffering = false;\n };\n\n /**\n * Create baseline CMCD data\n */\n private createData(): CMCD {\n return {\n v: CMCDVersion,\n sf: CMCDStreamingFormatHLS,\n sid: this.sid,\n cid: this.cid,\n pr: this.media?.playbackRate,\n mtp: this.hls.bandwidthEstimate / 1000,\n };\n }\n\n /**\n * Apply CMCD data to a request.\n */\n private apply(context: LoaderContext, data: CMCD = {}) {\n // apply baseline data\n Object.assign(data, this.createData());\n\n const isVideo =\n data.ot === CMCDObjectType.INIT ||\n data.ot === CMCDObjectType.VIDEO ||\n data.ot === CMCDObjectType.MUXED;\n\n if (this.starved && isVideo) {\n data.bs = true;\n data.su = true;\n this.starved = false;\n }\n\n if (data.su == null) {\n data.su = this.buffering;\n }\n\n // TODO: Implement rtp, nrr, nor, dl\n\n if (this.useHeaders) {\n const headers = CMCDController.toHeaders(data);\n if (!Object.keys(headers).length) {\n return;\n }\n\n if (!context.headers) {\n context.headers = {};\n }\n\n Object.assign(context.headers, headers);\n } else {\n const query = CMCDController.toQuery(data);\n if (!query) {\n return;\n }\n\n context.url = CMCDController.appendQueryToUri(context.url, query);\n }\n }\n\n /**\n * Apply CMCD data to a manifest request.\n */\n private applyPlaylistData = (context: PlaylistLoaderContext) => {\n try {\n this.apply(context, {\n ot: CMCDObjectType.MANIFEST,\n su: !this.initialized,\n });\n } catch (error) {\n logger.warn('Could not generate manifest CMCD data.', error);\n }\n };\n\n /**\n * Apply CMCD data to a segment request\n */\n private applyFragmentData = (context: FragmentLoaderContext) => {\n try {\n const fragment = context.frag;\n const level = this.hls.levels[fragment.level];\n const ot = this.getObjectType(fragment);\n const data: CMCD = {\n d: fragment.duration * 1000,\n ot,\n };\n\n if (\n ot === CMCDObjectType.VIDEO ||\n ot === CMCDObjectType.AUDIO ||\n ot == CMCDObjectType.MUXED\n ) {\n data.br = level.bitrate / 1000;\n data.tb = this.getTopBandwidth(ot) / 1000;\n data.bl = this.getBufferLength(ot);\n }\n\n this.apply(context, data);\n } catch (error) {\n logger.warn('Could not generate segment CMCD data.', error);\n }\n };\n\n /**\n * The CMCD object type.\n */\n private getObjectType(fragment: Fragment): CMCDObjectType | undefined {\n const { type } = fragment;\n\n if (type === 'subtitle') {\n return CMCDObjectType.TIMED_TEXT;\n }\n\n if (fragment.sn === 'initSegment') {\n return CMCDObjectType.INIT;\n }\n\n if (type === 'audio') {\n return CMCDObjectType.AUDIO;\n }\n\n if (type === 'main') {\n if (!this.hls.audioTracks.length) {\n return CMCDObjectType.MUXED;\n }\n\n return CMCDObjectType.VIDEO;\n }\n\n return undefined;\n }\n\n /**\n * Get the highest bitrate.\n */\n private getTopBandwidth(type: CMCDObjectType) {\n let bitrate: number = 0;\n let levels;\n const hls = this.hls;\n\n if (type === CMCDObjectType.AUDIO) {\n levels = hls.audioTracks;\n } else {\n const max = hls.maxAutoLevel;\n const len = max > -1 ? max + 1 : hls.levels.length;\n levels = hls.levels.slice(0, len);\n }\n\n for (const level of levels) {\n if (level.bitrate > bitrate) {\n bitrate = level.bitrate;\n }\n }\n\n return bitrate > 0 ? bitrate : NaN;\n }\n\n /**\n * Get the buffer length for a media type in milliseconds\n */\n private getBufferLength(type: CMCDObjectType) {\n const media = this.hls.media;\n const buffer =\n type === CMCDObjectType.AUDIO ? this.audioBuffer : this.videoBuffer;\n\n if (!buffer || !media) {\n return NaN;\n }\n\n const info = BufferHelper.bufferInfo(\n buffer,\n media.currentTime,\n this.config.maxBufferHole\n );\n\n return info.len * 1000;\n }\n\n /**\n * Create a playlist loader\n */\n private createPlaylistLoader(): PlaylistLoaderConstructor | undefined {\n const { pLoader } = this.config;\n const apply = this.applyPlaylistData;\n const Ctor = pLoader || (this.config.loader as PlaylistLoaderConstructor);\n\n return class CmcdPlaylistLoader {\n private loader: Loader<PlaylistLoaderContext>;\n\n constructor(config: HlsConfig) {\n this.loader = new Ctor(config);\n }\n\n get stats() {\n return this.loader.stats;\n }\n\n get context() {\n return this.loader.context;\n }\n\n destroy() {\n this.loader.destroy();\n }\n\n abort() {\n this.loader.abort();\n }\n\n load(\n context: PlaylistLoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<PlaylistLoaderContext>\n ) {\n apply(context);\n this.loader.load(context, config, callbacks);\n }\n };\n }\n\n /**\n * Create a playlist loader\n */\n private createFragmentLoader(): FragmentLoaderConstructor | undefined {\n const { fLoader } = this.config;\n const apply = this.applyFragmentData;\n const Ctor = fLoader || (this.config.loader as FragmentLoaderConstructor);\n\n return class CmcdFragmentLoader {\n private loader: Loader<FragmentLoaderContext>;\n\n constructor(config: HlsConfig) {\n this.loader = new Ctor(config);\n }\n\n get stats() {\n return this.loader.stats;\n }\n\n get context() {\n return this.loader.context;\n }\n\n destroy() {\n this.loader.destroy();\n }\n\n abort() {\n this.loader.abort();\n }\n\n load(\n context: FragmentLoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<FragmentLoaderContext>\n ) {\n apply(context);\n this.loader.load(context, config, callbacks);\n }\n };\n }\n\n /**\n * Generate a random v4 UUI\n *\n * @returns {string}\n */\n static uuid(): string {\n const url = URL.createObjectURL(new Blob());\n const uuid = url.toString();\n URL.revokeObjectURL(url);\n return uuid.slice(uuid.lastIndexOf('/') + 1);\n }\n\n /**\n * Serialize a CMCD data object according to the rules defined in the\n * section 3.2 of\n * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).\n */\n static serialize(data: CMCD): string {\n const results: string[] = [];\n const isValid = (value: any) =>\n !Number.isNaN(value) && value != null && value !== '' && value !== false;\n const toRounded = (value: number) => Math.round(value);\n const toHundred = (value: number) => toRounded(value / 100) * 100;\n const toUrlSafe = (value: string) => encodeURIComponent(value);\n const formatters = {\n br: toRounded,\n d: toRounded,\n bl: toHundred,\n dl: toHundred,\n mtp: toHundred,\n nor: toUrlSafe,\n rtp: toHundred,\n tb: toRounded,\n };\n\n const keys = Object.keys(data || {}).sort();\n\n for (const key of keys) {\n let value = data[key];\n\n // ignore invalid values\n if (!isValid(value)) {\n continue;\n }\n\n // Version should only be reported if not equal to 1.\n if (key === 'v' && value === 1) {\n continue;\n }\n\n // Playback rate should only be sent if not equal to 1.\n if (key == 'pr' && value === 1) {\n continue;\n }\n\n // Certain values require special formatting\n const formatter = formatters[key];\n if (formatter) {\n value = formatter(value);\n }\n\n // Serialize the key/value pair\n const type = typeof value;\n let result: string;\n\n if (key === 'ot' || key === 'sf' || key === 'st') {\n result = `${key}=${value}`;\n } else if (type === 'boolean') {\n result = key;\n } else if (type === 'number') {\n result = `${key}=${value}`;\n } else {\n result = `${key}=${JSON.stringify(value)}`;\n }\n\n results.push(result);\n }\n\n return results.join(',');\n }\n\n /**\n * Convert a CMCD data object to request headers according to the rules\n * defined in the section 2.1 and 3.2 of\n * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).\n */\n static toHeaders(data: CMCD): Partial<CMCDHeaders> {\n const keys = Object.keys(data);\n const headers = {};\n const headerNames = ['Object', 'Request', 'Session', 'Status'];\n const headerGroups = [{}, {}, {}, {}];\n const headerMap = {\n br: 0,\n d: 0,\n ot: 0,\n tb: 0,\n bl: 1,\n dl: 1,\n mtp: 1,\n nor: 1,\n nrr: 1,\n su: 1,\n cid: 2,\n pr: 2,\n sf: 2,\n sid: 2,\n st: 2,\n v: 2,\n bs: 3,\n rtp: 3,\n };\n\n for (const key of keys) {\n // Unmapped fields are mapped to the Request header\n const index = headerMap[key] != null ? headerMap[key] : 1;\n headerGroups[index][key] = data[key];\n }\n\n for (let i = 0; i < headerGroups.length; i++) {\n const value = CMCDController.serialize(headerGroups[i]);\n if (value) {\n headers[`CMCD-${headerNames[i]}`] = value;\n }\n }\n\n return headers;\n }\n\n /**\n * Convert a CMCD data object to query args according to the rules\n * defined in the section 2.2 and 3.2 of\n * [CTA-5004](https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf).\n */\n static toQuery(data: CMCD): string {\n return `CMCD=${encodeURIComponent(CMCDController.serialize(data))}`;\n }\n\n /**\n * Append query args to a uri.\n */\n static appendQueryToUri(uri, query) {\n if (!query) {\n return uri;\n }\n\n const separator = uri.includes('?') ? '&' : '?';\n return `${uri}${separator}${query}`;\n }\n}\n","/**\n * CMCD spec version\n */\nexport const CMCDVersion = 1;\n\n/**\n * CMCD Object Type\n */\nexport const enum CMCDObjectType {\n MANIFEST = 'm',\n AUDIO = 'a',\n VIDEO = 'v',\n MUXED = 'av',\n INIT = 'i',\n CAPTION = 'c',\n TIMED_TEXT = 'tt',\n KEY = 'k',\n OTHER = 'o',\n}\n\n/**\n * CMCD Streaming Format\n */\nexport const CMCDStreamingFormatHLS = 'h';\n\n/**\n * CMCD Streaming Type\n */\nconst enum CMCDStreamType {\n VOD = 'v',\n LIVE = 'l',\n}\n\n/**\n * CMCD Headers\n */\nexport interface CMCDHeaders {\n 'CMCD-Object': string;\n 'CMCD-Request': string;\n 'CMCD-Session': string;\n 'CMCD-Status': string;\n}\n\n/**\n * CMCD\n */\nexport interface CMCD {\n /////////////////\n // CMCD Object //\n /////////////////\n\n /**\n * Encoded bitrate\n *\n * The encoded bitrate of the audio or video object being requested. This may not be known precisely by the player; however,\n * it MAY be estimated based upon playlist/manifest declarations. If the playlist declares both peak and average bitrate values,\n * the peak value should be transmitted.\n *\n * Integer kbps\n */\n br?: number;\n\n /**\n * Object duration\n *\n * The playback duration in milliseconds of the object being requested. If a partial segment is being requested, then this value\n * MUST indicate the playback duration of that part and not that of its parent segment. This value can be an approximation of the\n * estimated duration if the explicit value is not known.\n *\n * Integer milliseconds\n */\n d?: number;\n\n /**\n * Object type\n *\n * The media type of the current object being requested:\n * - `m` = text file, such as a manifest or playlist\n * - `a` = audio only\n * - `v` = video only\n * - `av` = muxed audio and video\n * - `i` = init segment\n * - `c` = caption or subtitle\n * - `tt` = ISOBMFF timed text track\n * - `k` = cryptographic key, license or certificate.\n * - `o` = other\n *\n * If the object type being requested is unknown, then this key MUST NOT be used.\n */\n ot?: CMCDObjectType;\n\n /**\n * Top bitrate\n *\n * The highest bitrate rendition in the manifest or playlist that the client is allowed to play, given current codec, licensing and\n * sizing constraints.\n *\n * Integer Kbps\n */\n tb?: number;\n\n //////////////////\n // CMCD Request //\n //////////////////\n /**\n * Buffer length\n *\n * The buffer length associated with the media object being requested. This value MUST be rounded to the nearest 100 ms. This key SHOULD only be\n * sent with an object type of ‘a’, ‘v’ or ‘av’.\n *\n * Integer milliseconds\n */\n bl?: number;\n\n /**\n * Deadline\n *\n * Deadline from the request time until the first sample of this Segment/Object needs to be available in order to not create a buffer underrun or\n * any other playback problems. This value MUST be rounded to the nearest 100ms. For a playback rate of 1, this may be equivalent to the player’s\n * remaining buffer length.\n *\n * Integer milliseconds\n */\n dl?: number;\n\n /**\n * Measured mtp CMCD throughput\n *\n * The throughput between client and server, as measured by the client and MUST be rounded to the nearest 100 kbps. This value, however derived,\n * SHOULD be the value that the client is using to make its next Adaptive Bitrate switching decision. If the client is connected to multiple\n * servers concurrently, it must take care to report only the throughput measured against the receiving server. If the client has multiple concurrent\n * connections to the server, then the intent is that this value communicates the aggregate throughput the client sees across all those connections.\n *\n * Integer kbps\n */\n mtp?: number;\n\n /**\n * Next object request\n *\n * Relative path of the next object to be requested. This can be used to trigger pre-fetching by the CDN. This MUST be a path relative to the current\n * request. This string MUST be URLEncoded. The client SHOULD NOT depend upon any pre-fetch action being taken - it is merely a request for such a\n * pre-fetch to take place.\n *\n * String\n */\n nor?: string;\n\n /**\n * Next range request\n *\n * If the next request will be a partial object request, then this string denotes the byte range to be requested. If the ‘nor’ field is not set, then the\n * object is assumed to match the object currently being requested. The client SHOULD NOT depend upon any pre-fetch action being taken – it is merely a\n * request for such a pre-fetch to take place. Formatting is similar to the HTTP Range header, except that the unit MUST be ‘byte’, the ‘Range:’ prefix is\n * NOT required and specifying multiple ranges is NOT allowed. Valid combinations are:\n *\n * - `\"\\<range-start\\>-\"`\n * - `\"\\<range-start\\>-\\<range-end\\>\"`\n * - `\"-\\<suffix-length\\>\"`\n *\n * String\n */\n nrr?: string;\n\n /**\n * Startup\n *\n * Key is included without a value if the object is needed urgently due to startup, seeking or recovery after a buffer-empty event. The media SHOULD not be\n * rendering when this request is made. This key MUST not be sent if it is FALSE.\n *\n * Boolean\n */\n su?: boolean;\n\n //////////////////\n // CMCD Session //\n //////////////////\n\n /**\n * Content ID\n *\n * A unique string identifying the current content. Maximum length is 64 characters. This value is consistent across multiple different\n * sessions and devices and is defined and updated at the discretion of the service provider.\n *\n * String\n */\n cid?: string;\n\n /**\n * Playback rate\n *\n * `1` if real-time, `2` if double speed, `0` if not playing. SHOULD only be sent if not equal to `1`.\n *\n * Decimal\n */\n pr?: number;\n\n /**\n * Streaming format\n *\n * The streaming format that defines the current request.\n *\n * - `d` = MPEG DASH\n * - `h` = HTTP Live Streaming (HLS)\n * - `s` = Smooth Streaming\n * - `o` = other\n *\n * If the streaming format being requested is unknown, then this key MUST NOT be used.\n */\n sf?: typeof CMCDStreamingFormatHLS;\n\n /**\n * Session ID\n *\n * A GUID identifying the current playback session. A playback session typically ties together segments belonging to a single media asset.\n * Maximum length is 64 characters. It is RECOMMENDED to conform to the UUID specification.\n *\n * String\n */\n sid?: string;\n\n /**\n * Stream type\n * - `v` = all segments are available – e.g., VOD\n * - `l` = segments become available over time – e.g., LIVE\n */\n st?: CMCDStreamType;\n\n /**\n * CMCD version\n *\n * The version of this specification used for interpreting the defined key names and values. If this key is omitted, the client and server MUST\n * interpret the values as being defined by version 1. Client SHOULD omit this field if the version is 1.\n *\n * Integer\n */\n v?: number;\n\n /////////////////\n // CMCD Status //\n /////////////////\n\n /**\n * Buffer starvation\n *\n * Key is included without a value if the buffer was starved at some point between the prior request and this object request,\n * resulting in the player being in a rebuffering state and the video or audio playback being stalled. This key MUST NOT be\n * sent if the buffer was not starved since the prior request.\n *\n * If the object type `ot` key is sent along with this key, then the `bs` key refers to the buffer associated with the particular\n * object type. If no object type is communicated, then the buffer state applies to the current session.\n *\n * Boolean\n */\n bs?: boolean;\n\n /**\n * Requested maximum throughput\n *\n * The requested maximum throughput that the client considers sufficient for delivery of the asset. Values MUST be rounded to the\n * nearest 100kbps. For example, a client would indicate that the current segment, encoded at 2Mbps, is to be delivered at no more\n * than 10Mbps, by using rtp=10000.\n *\n * Note: This can benefit clients by preventing buffer saturation through over-delivery and can also deliver a community benefit\n * through fair-share delivery. The concept is that each client receives the throughput necessary for great performance, but no more.\n * The CDN may not support the rtp feature.\n *\n * Integer kbps\n */\n rtp?: number;\n}\n","import { Events } from '../events';\nimport { Level } from '../types/level';\nimport { AttrList } from '../utils/attr-list';\nimport { addGroupId } from './level-controller';\nimport { ErrorActionFlags, NetworkErrorAction } from './error-controller';\nimport { logger } from '../utils/logger';\nimport type Hls from '../hls';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type {\n ErrorData,\n ManifestLoadedData,\n ManifestParsedData,\n} from '../types/events';\nimport type { RetryConfig } from '../config';\nimport type {\n Loader,\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n LoaderResponse,\n LoaderStats,\n} from '../types/loader';\nimport type { LevelParsed } from '../types/level';\nimport type { MediaAttributes, MediaPlaylist } from '../types/media-playlist';\n\nexport type SteeringManifest = {\n VERSION: 1;\n TTL: number;\n 'RELOAD-URI'?: string;\n 'PATHWAY-PRIORITY': string[];\n 'PATHWAY-CLONES'?: PathwayClone[];\n};\n\ntype PathwayClone = {\n 'BASE-ID': string;\n ID: string;\n 'URI-REPLACEMENT': UriReplacement;\n};\n\ntype UriReplacement = {\n HOST?: string;\n PARAMS?: { [queryParameter: string]: string };\n 'PER-VARIANT-URIS'?: { [stableVariantId: string]: string };\n 'PER-RENDITION-URIS'?: { [stableRenditionId: string]: string };\n};\n\nconst PATHWAY_PENALTY_DURATION_MS = 300000;\n\nexport default class ContentSteeringController implements NetworkComponentAPI {\n private readonly hls: Hls;\n private log: (msg: any) => void;\n private loader: Loader<LoaderContext> | null = null;\n private uri: string | null = null;\n private pathwayId: string = '.';\n private pathwayPriority: string[] | null = null;\n private timeToLoad: number = 300;\n private reloadTimer: number = -1;\n private updated: number = 0;\n private started: boolean = false;\n private enabled: boolean = true;\n private levels: Level[] | null = null;\n private audioTracks: MediaPlaylist[] | null = null;\n private subtitleTracks: MediaPlaylist[] | null = null;\n private penalizedPathways: { [pathwayId: string]: number } = {};\n\n constructor(hls: Hls) {\n this.hls = hls;\n this.log = logger.log.bind(logger, `[content-steering]:`);\n this.registerListeners();\n }\n\n private registerListeners() {\n const hls = this.hls;\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.ERROR, this.onError, this);\n }\n\n private unregisterListeners() {\n const hls = this.hls;\n if (!hls) {\n return;\n }\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.ERROR, this.onError, this);\n }\n\n startLoad(): void {\n this.started = true;\n self.clearTimeout(this.reloadTimer);\n if (this.enabled && this.uri) {\n if (this.updated) {\n const ttl = Math.max(\n this.timeToLoad * 1000 - (performance.now() - this.updated),\n 0\n );\n this.scheduleRefresh(this.uri, ttl);\n } else {\n this.loadSteeringManifest(this.uri);\n }\n }\n }\n\n stopLoad(): void {\n this.started = false;\n if (this.loader) {\n this.loader.destroy();\n this.loader = null;\n }\n self.clearTimeout(this.reloadTimer);\n }\n\n destroy() {\n this.unregisterListeners();\n this.stopLoad();\n // @ts-ignore\n this.hls = null;\n this.levels = this.audioTracks = this.subtitleTracks = null;\n }\n\n removeLevel(levelToRemove: Level) {\n const levels = this.levels;\n if (levels) {\n this.levels = levels.filter((level) => level !== levelToRemove);\n }\n }\n\n private onManifestLoading() {\n this.stopLoad();\n this.enabled = true;\n this.timeToLoad = 300;\n this.updated = 0;\n this.uri = null;\n this.pathwayId = '.';\n this.levels = this.audioTracks = this.subtitleTracks = null;\n }\n\n private onManifestLoaded(\n event: Events.MANIFEST_LOADED,\n data: ManifestLoadedData\n ) {\n const { contentSteering } = data;\n if (contentSteering === null) {\n return;\n }\n this.pathwayId = contentSteering.pathwayId;\n this.uri = contentSteering.uri;\n if (this.started) {\n this.startLoad();\n }\n }\n\n private onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ) {\n this.audioTracks = data.audioTracks;\n this.subtitleTracks = data.subtitleTracks;\n }\n\n private onError(event: Events.ERROR, data: ErrorData) {\n const { errorAction } = data;\n if (\n errorAction?.action === NetworkErrorAction.SendAlternateToPenaltyBox &&\n errorAction.flags === ErrorActionFlags.MoveAllAlternatesMatchingHost\n ) {\n let pathwayPriority = this.pathwayPriority;\n const pathwayId = this.pathwayId;\n if (!this.penalizedPathways[pathwayId]) {\n this.penalizedPathways[pathwayId] = performance.now();\n }\n if (!pathwayPriority && this.levels) {\n // If PATHWAY-PRIORITY was not provided, list pathways for error handling\n pathwayPriority = this.levels.reduce((pathways, level) => {\n if (pathways.indexOf(level.pathwayId) === -1) {\n pathways.push(level.pathwayId);\n }\n return pathways;\n }, [] as string[]);\n }\n if (pathwayPriority && pathwayPriority.length > 1) {\n this.updatePathwayPriority(pathwayPriority);\n errorAction.resolved = this.pathwayId !== pathwayId;\n }\n }\n }\n\n public filterParsedLevels(levels: Level[]): Level[] {\n // Filter levels to only include those that are in the initial pathway\n this.levels = levels;\n let pathwayLevels = this.getLevelsForPathway(this.pathwayId);\n if (pathwayLevels.length === 0) {\n const pathwayId = levels[0].pathwayId;\n this.log(\n `No levels found in Pathway ${this.pathwayId}. Setting initial Pathway to \"${pathwayId}\"`\n );\n pathwayLevels = this.getLevelsForPathway(pathwayId);\n this.pathwayId = pathwayId;\n }\n if (pathwayLevels.length !== levels.length) {\n this.log(\n `Found ${pathwayLevels.length}/${levels.length} levels in Pathway \"${this.pathwayId}\"`\n );\n return pathwayLevels;\n }\n return levels;\n }\n\n private getLevelsForPathway(pathwayId: string): Level[] {\n if (this.levels === null) {\n return [];\n }\n return this.levels.filter((level) => pathwayId === level.pathwayId);\n }\n\n private updatePathwayPriority(pathwayPriority: string[]) {\n this.pathwayPriority = pathwayPriority;\n let levels: Level[] | undefined;\n\n // Evaluate if we should remove the pathway from the penalized list\n const penalizedPathways = this.penalizedPathways;\n const now = performance.now();\n Object.keys(penalizedPathways).forEach((pathwayId) => {\n if (now - penalizedPathways[pathwayId] > PATHWAY_PENALTY_DURATION_MS) {\n delete penalizedPathways[pathwayId];\n }\n });\n for (let i = 0; i < pathwayPriority.length; i++) {\n const pathwayId = pathwayPriority[i];\n if (penalizedPathways[pathwayId]) {\n continue;\n }\n if (pathwayId === this.pathwayId) {\n return;\n }\n const selectedIndex = this.hls.nextLoadLevel;\n const selectedLevel: Level = this.hls.levels[selectedIndex];\n levels = this.getLevelsForPathway(pathwayId);\n if (levels.length > 0) {\n this.log(`Setting Pathway to \"${pathwayId}\"`);\n this.pathwayId = pathwayId;\n this.hls.trigger(Events.LEVELS_UPDATED, { levels });\n // Set LevelController's level to trigger LEVEL_SWITCHING which loads playlist if needed\n const levelAfterChange = this.hls.levels[selectedIndex];\n if (selectedLevel && levelAfterChange && this.levels) {\n if (\n levelAfterChange.attrs['STABLE-VARIANT-ID'] !==\n selectedLevel.attrs['STABLE-VARIANT-ID'] &&\n levelAfterChange.bitrate !== selectedLevel.bitrate\n ) {\n this.log(\n `Unstable Pathways change from bitrate ${selectedLevel.bitrate} to ${levelAfterChange.bitrate}`\n );\n }\n this.hls.nextLoadLevel = selectedIndex;\n }\n break;\n }\n }\n }\n\n private clonePathways(pathwayClones: PathwayClone[]) {\n const levels = this.levels;\n if (!levels) {\n return;\n }\n const audioGroupCloneMap: Record<string, string> = {};\n const subtitleGroupCloneMap: Record<string, string> = {};\n pathwayClones.forEach((pathwayClone) => {\n const {\n ID: cloneId,\n 'BASE-ID': baseId,\n 'URI-REPLACEMENT': uriReplacement,\n } = pathwayClone;\n if (levels.some((level) => level.pathwayId === cloneId)) {\n return;\n }\n const clonedVariants = this.getLevelsForPathway(baseId).map(\n (baseLevel) => {\n const levelParsed: LevelParsed = Object.assign({}, baseLevel as any);\n levelParsed.details = undefined;\n levelParsed.url = performUriReplacement(\n baseLevel.uri,\n baseLevel.attrs['STABLE-VARIANT-ID'],\n 'PER-VARIANT-URIS',\n uriReplacement\n );\n const attributes = new AttrList(baseLevel.attrs);\n attributes['PATHWAY-ID'] = cloneId;\n const clonedAudioGroupId: string | undefined =\n attributes.AUDIO && `${attributes.AUDIO}_clone_${cloneId}`;\n const clonedSubtitleGroupId: string | undefined =\n attributes.SUBTITLES && `${attributes.SUBTITLES}_clone_${cloneId}`;\n if (clonedAudioGroupId) {\n audioGroupCloneMap[attributes.AUDIO] = clonedAudioGroupId;\n attributes.AUDIO = clonedAudioGroupId;\n }\n if (clonedSubtitleGroupId) {\n subtitleGroupCloneMap[attributes.SUBTITLES] = clonedSubtitleGroupId;\n attributes.SUBTITLES = clonedSubtitleGroupId;\n }\n levelParsed.attrs = attributes;\n const clonedLevel = new Level(levelParsed);\n addGroupId(clonedLevel, 'audio', clonedAudioGroupId);\n addGroupId(clonedLevel, 'text', clonedSubtitleGroupId);\n return clonedLevel;\n }\n );\n levels.push(...clonedVariants);\n cloneRenditionGroups(\n this.audioTracks,\n audioGroupCloneMap,\n uriReplacement,\n cloneId\n );\n cloneRenditionGroups(\n this.subtitleTracks,\n subtitleGroupCloneMap,\n uriReplacement,\n cloneId\n );\n });\n }\n\n private loadSteeringManifest(uri: string) {\n const config = this.hls.config;\n const Loader = config.loader;\n if (this.loader) {\n this.loader.destroy();\n }\n this.loader = new Loader(config) as Loader<LoaderContext>;\n\n let url: URL;\n try {\n url = new self.URL(uri);\n } catch (error) {\n this.enabled = false;\n this.log(`Failed to parse Steering Manifest URI: ${uri}`);\n return;\n }\n if (url.protocol !== 'data:') {\n const throughput =\n (this.hls.bandwidthEstimate || config.abrEwmaDefaultEstimate) | 0;\n url.searchParams.set('_HLS_pathway', this.pathwayId);\n url.searchParams.set('_HLS_throughput', '' + throughput);\n }\n const context: LoaderContext = {\n responseType: 'json',\n url: url.href,\n };\n\n const loadPolicy = config.steeringManifestLoadPolicy.default;\n const legacyRetryCompatibility: RetryConfig | Record<string, void> =\n loadPolicy.errorRetry || loadPolicy.timeoutRetry || {};\n const loaderConfig: LoaderConfiguration = {\n loadPolicy,\n timeout: loadPolicy.maxLoadTimeMs,\n maxRetry: legacyRetryCompatibility.maxNumRetry || 0,\n retryDelay: legacyRetryCompatibility.retryDelayMs || 0,\n maxRetryDelay: legacyRetryCompatibility.maxRetryDelayMs || 0,\n };\n\n const callbacks: LoaderCallbacks<LoaderContext> = {\n onSuccess: (\n response: LoaderResponse,\n stats: LoaderStats,\n context: LoaderContext,\n networkDetails: any\n ) => {\n this.log(`Loaded steering manifest: \"${url}\"`);\n const steeringData = response.data as SteeringManifest;\n if (steeringData.VERSION !== 1) {\n this.log(`Steering VERSION ${steeringData.VERSION} not supported!`);\n return;\n }\n this.updated = performance.now();\n this.timeToLoad = steeringData.TTL;\n const {\n 'RELOAD-URI': reloadUri,\n 'PATHWAY-CLONES': pathwayClones,\n 'PATHWAY-PRIORITY': pathwayPriority,\n } = steeringData;\n if (reloadUri) {\n try {\n this.uri = new self.URL(reloadUri, url).href;\n } catch (error) {\n this.enabled = false;\n this.log(\n `Failed to parse Steering Manifest RELOAD-URI: ${reloadUri}`\n );\n return;\n }\n }\n this.scheduleRefresh(this.uri || context.url);\n if (pathwayClones) {\n this.clonePathways(pathwayClones);\n }\n if (pathwayPriority) {\n this.updatePathwayPriority(pathwayPriority);\n }\n },\n\n onError: (\n error: { code: number; text: string },\n context: LoaderContext,\n networkDetails: any,\n stats: LoaderStats\n ) => {\n this.log(\n `Error loading steering manifest: ${error.code} ${error.text} (${context.url})`\n );\n this.stopLoad();\n if (error.code === 410) {\n this.enabled = false;\n this.log(`Steering manifest ${context.url} no longer available`);\n return;\n }\n let ttl = this.timeToLoad * 1000;\n if (error.code === 429) {\n const loader = this.loader;\n if (typeof loader?.getResponseHeader === 'function') {\n const retryAfter = loader.getResponseHeader('Retry-After');\n if (retryAfter) {\n ttl = parseFloat(retryAfter) * 1000;\n }\n }\n this.log(`Steering manifest ${context.url} rate limited`);\n return;\n }\n this.scheduleRefresh(this.uri || context.url, ttl);\n },\n\n onTimeout: (\n stats: LoaderStats,\n context: LoaderContext,\n networkDetails: any\n ) => {\n this.log(`Timeout loading steering manifest (${context.url})`);\n this.scheduleRefresh(this.uri || context.url);\n },\n };\n\n this.log(`Requesting steering manifest: ${url}`);\n this.loader.load(context, loaderConfig, callbacks);\n }\n\n private scheduleRefresh(uri: string, ttlMs: number = this.timeToLoad * 1000) {\n self.clearTimeout(this.reloadTimer);\n this.reloadTimer = self.setTimeout(() => {\n this.loadSteeringManifest(uri);\n }, ttlMs);\n }\n}\n\nfunction cloneRenditionGroups(\n tracks: MediaPlaylist[] | null,\n groupCloneMap: Record<string, string>,\n uriReplacement: UriReplacement,\n cloneId: string\n) {\n if (!tracks) {\n return;\n }\n Object.keys(groupCloneMap).forEach((audioGroupId) => {\n const clonedTracks = tracks\n .filter((track) => track.groupId === audioGroupId)\n .map((track) => {\n const clonedTrack = Object.assign({}, track);\n clonedTrack.details = undefined;\n clonedTrack.attrs = new AttrList(clonedTrack.attrs) as MediaAttributes;\n clonedTrack.url = clonedTrack.attrs.URI = performUriReplacement(\n track.url,\n track.attrs['STABLE-RENDITION-ID'],\n 'PER-RENDITION-URIS',\n uriReplacement\n );\n clonedTrack.groupId = clonedTrack.attrs['GROUP-ID'] =\n groupCloneMap[audioGroupId];\n clonedTrack.attrs['PATHWAY-ID'] = cloneId;\n return clonedTrack;\n });\n tracks.push(...clonedTracks);\n });\n}\n\nfunction performUriReplacement(\n uri: string,\n stableId: string | undefined,\n perOptionKey: 'PER-VARIANT-URIS' | 'PER-RENDITION-URIS',\n uriReplacement: UriReplacement\n): string {\n const {\n HOST: host,\n PARAMS: params,\n [perOptionKey]: perOptionUris,\n } = uriReplacement;\n let perVariantUri;\n if (stableId) {\n perVariantUri = perOptionUris?.[stableId];\n if (perVariantUri) {\n uri = perVariantUri;\n }\n }\n const url = new self.URL(uri);\n if (host && !perVariantUri) {\n url.host = host;\n }\n if (params) {\n Object.keys(params)\n .sort()\n .forEach((key) => {\n if (key) {\n url.searchParams.set(key, params[key]);\n }\n });\n }\n return url.href;\n}\n","import { logger } from '../utils/logger';\nimport type {\n LoaderCallbacks,\n LoaderContext,\n LoaderStats,\n Loader,\n LoaderConfiguration,\n LoaderResponse,\n} from '../types/loader';\nimport { LoadStats } from '../loader/load-stats';\nimport { type HlsConfig, RetryConfig } from '../config';\nimport { getRetryDelay, shouldRetry } from './error-helper';\n\nconst AGE_HEADER_LINE_REGEX = /^age:\\s*[\\d.]+\\s*$/im;\n\nclass XhrLoader implements Loader<LoaderContext> {\n private xhrSetup:\n | ((xhr: XMLHttpRequest, url: string) => Promise<void> | void)\n | null;\n private requestTimeout?: number;\n private retryTimeout?: number;\n private retryDelay: number;\n private config: LoaderConfiguration | null = null;\n private callbacks: LoaderCallbacks<LoaderContext> | null = null;\n public context!: LoaderContext;\n\n private loader: XMLHttpRequest | null = null;\n public stats: LoaderStats;\n\n constructor(config: HlsConfig) {\n this.xhrSetup = config ? config.xhrSetup || null : null;\n this.stats = new LoadStats();\n this.retryDelay = 0;\n }\n\n destroy() {\n this.callbacks = null;\n this.abortInternal();\n this.loader = null;\n this.config = null;\n }\n\n abortInternal() {\n const loader = this.loader;\n self.clearTimeout(this.requestTimeout);\n self.clearTimeout(this.retryTimeout);\n if (loader) {\n loader.onreadystatechange = null;\n loader.onprogress = null;\n if (loader.readyState !== 4) {\n this.stats.aborted = true;\n loader.abort();\n }\n }\n }\n\n abort() {\n this.abortInternal();\n if (this.callbacks?.onAbort) {\n this.callbacks.onAbort(this.stats, this.context, this.loader);\n }\n }\n\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>\n ) {\n if (this.stats.loading.start) {\n throw new Error('Loader can only be used once.');\n }\n this.stats.loading.start = self.performance.now();\n this.context = context;\n this.config = config;\n this.callbacks = callbacks;\n this.loadInternal();\n }\n\n loadInternal() {\n const { config, context } = this;\n if (!config) {\n return;\n }\n const xhr = (this.loader = new self.XMLHttpRequest());\n\n const stats = this.stats;\n stats.loading.first = 0;\n stats.loaded = 0;\n const xhrSetup = this.xhrSetup;\n\n if (xhrSetup) {\n Promise.resolve()\n .then(() => {\n if (this.stats.aborted) return;\n return xhrSetup(xhr, context.url);\n })\n .catch((error: Error) => {\n xhr.open('GET', context.url, true);\n return xhrSetup(xhr, context.url);\n })\n .then(() => {\n if (this.stats.aborted) return;\n this.openAndSendXhr(xhr, context, config);\n })\n .catch((error: Error) => {\n // IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS\n this.callbacks!.onError(\n { code: xhr.status, text: error.message },\n context,\n xhr,\n stats\n );\n return;\n });\n } else {\n this.openAndSendXhr(xhr, context, config);\n }\n }\n\n openAndSendXhr(\n xhr: XMLHttpRequest,\n context: LoaderContext,\n config: LoaderConfiguration\n ) {\n if (!xhr.readyState) {\n xhr.open('GET', context.url, true);\n }\n\n const headers = this.context.headers;\n const { maxTimeToFirstByteMs, maxLoadTimeMs } = config.loadPolicy;\n if (headers) {\n for (const header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n\n if (context.rangeEnd) {\n xhr.setRequestHeader(\n 'Range',\n 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1)\n );\n }\n\n xhr.onreadystatechange = this.readystatechange.bind(this);\n xhr.onprogress = this.loadprogress.bind(this);\n xhr.responseType = context.responseType as XMLHttpRequestResponseType;\n // setup timeout before we perform request\n self.clearTimeout(this.requestTimeout);\n config.timeout =\n maxTimeToFirstByteMs && Number.isFinite(maxTimeToFirstByteMs)\n ? maxTimeToFirstByteMs\n : maxLoadTimeMs;\n this.requestTimeout = self.setTimeout(\n this.loadtimeout.bind(this),\n config.timeout\n );\n xhr.send();\n }\n\n readystatechange() {\n const { context, loader: xhr, stats } = this;\n if (!context || !xhr) {\n return;\n }\n const readyState = xhr.readyState;\n const config = this.config as LoaderConfiguration;\n\n // don't proceed if xhr has been aborted\n if (stats.aborted) {\n return;\n }\n\n // >= HEADERS_RECEIVED\n if (readyState >= 2) {\n if (stats.loading.first === 0) {\n stats.loading.first = Math.max(\n self.performance.now(),\n stats.loading.start\n );\n // readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet\n if (config.timeout !== config.loadPolicy.maxLoadTimeMs) {\n self.clearTimeout(this.requestTimeout);\n config.timeout = config.loadPolicy.maxLoadTimeMs;\n this.requestTimeout = self.setTimeout(\n this.loadtimeout.bind(this),\n config.loadPolicy.maxLoadTimeMs -\n (stats.loading.first - stats.loading.start)\n );\n }\n }\n\n if (readyState === 4) {\n self.clearTimeout(this.requestTimeout);\n xhr.onreadystatechange = null;\n xhr.onprogress = null;\n const status = xhr.status;\n // http status between 200 to 299 are all successful\n const useResponse = xhr.responseType !== 'text';\n if (\n status >= 200 &&\n status < 300 &&\n ((useResponse && xhr.response) || xhr.responseText !== null)\n ) {\n stats.loading.end = Math.max(\n self.performance.now(),\n stats.loading.first\n );\n const data = useResponse ? xhr.response : xhr.responseText;\n const len =\n xhr.responseType === 'arraybuffer' ? data.byteLength : data.length;\n stats.loaded = stats.total = len;\n stats.bwEstimate =\n (stats.total * 8000) / (stats.loading.end - stats.loading.first);\n if (!this.callbacks) {\n return;\n }\n const onProgress = this.callbacks.onProgress;\n if (onProgress) {\n onProgress(stats, context, data, xhr);\n }\n if (!this.callbacks) {\n return;\n }\n const response: LoaderResponse = {\n url: xhr.responseURL,\n data: data,\n code: status,\n };\n\n this.callbacks.onSuccess(response, stats, context, xhr);\n } else {\n const retryConfig = config.loadPolicy.errorRetry;\n const retryCount = stats.retry;\n // if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error\n if (shouldRetry(retryConfig, retryCount, false, status)) {\n this.retry(retryConfig);\n } else {\n logger.error(`${status} while loading ${context.url}`);\n this.callbacks!.onError(\n { code: status, text: xhr.statusText },\n context,\n xhr,\n stats\n );\n }\n }\n }\n }\n }\n\n loadtimeout() {\n const retryConfig = this.config?.loadPolicy.timeoutRetry;\n const retryCount = this.stats.retry;\n if (shouldRetry(retryConfig, retryCount, true)) {\n this.retry(retryConfig);\n } else {\n logger.warn(`timeout while loading ${this.context.url}`);\n const callbacks = this.callbacks;\n if (callbacks) {\n this.abortInternal();\n callbacks.onTimeout(this.stats, this.context, this.loader);\n }\n }\n }\n\n retry(retryConfig: RetryConfig) {\n const { context, stats } = this;\n this.retryDelay = getRetryDelay(retryConfig, stats.retry);\n stats.retry++;\n logger.warn(\n `${status ? 'HTTP Status ' + status : 'Timeout'} while loading ${\n context.url\n }, retrying ${stats.retry}/${retryConfig.maxNumRetry} in ${\n this.retryDelay\n }ms`\n );\n // abort and reset internal state\n this.abortInternal();\n this.loader = null;\n // schedule retry\n self.clearTimeout(this.retryTimeout);\n this.retryTimeout = self.setTimeout(\n this.loadInternal.bind(this),\n this.retryDelay\n );\n }\n\n loadprogress(event: ProgressEvent) {\n const stats = this.stats;\n\n stats.loaded = event.loaded;\n if (event.lengthComputable) {\n stats.total = event.total;\n }\n }\n\n getCacheAge(): number | null {\n let result: number | null = null;\n if (\n this.loader &&\n AGE_HEADER_LINE_REGEX.test(this.loader.getAllResponseHeaders())\n ) {\n const ageHeader = this.loader.getResponseHeader('age');\n result = ageHeader ? parseFloat(ageHeader) : null;\n }\n return result;\n }\n\n getResponseHeader(name: string): string | null {\n if (\n this.loader &&\n new RegExp(`^${name}:\\\\s*[\\\\d.]+\\\\s*$`, 'im').test(\n this.loader.getAllResponseHeaders()\n )\n ) {\n return this.loader.getResponseHeader(name);\n }\n return null;\n }\n}\n\nexport default XhrLoader;\n","import {\n LoaderCallbacks,\n LoaderContext,\n Loader,\n LoaderStats,\n LoaderConfiguration,\n LoaderOnProgress,\n LoaderResponse,\n} from '../types/loader';\nimport { LoadStats } from '../loader/load-stats';\nimport ChunkCache from '../demux/chunk-cache';\n\nexport function fetchSupported() {\n if (\n // @ts-ignore\n self.fetch &&\n self.AbortController &&\n self.ReadableStream &&\n self.Request\n ) {\n try {\n new self.ReadableStream({}); // eslint-disable-line no-new\n return true;\n } catch (e) {\n /* noop */\n }\n }\n return false;\n}\n\nconst BYTERANGE = /(\\d+)-(\\d+)\\/(\\d+)/;\n\nclass FetchLoader implements Loader<LoaderContext> {\n private fetchSetup: Function;\n private requestTimeout?: number;\n private request!: Request;\n private response!: Response;\n private controller: AbortController;\n public context!: LoaderContext;\n private config: LoaderConfiguration | null = null;\n private callbacks: LoaderCallbacks<LoaderContext> | null = null;\n public stats: LoaderStats;\n private loader: Response | null = null;\n\n constructor(config /* HlsConfig */) {\n this.fetchSetup = config.fetchSetup || getRequest;\n this.controller = new self.AbortController();\n this.stats = new LoadStats();\n }\n\n destroy(): void {\n this.loader = this.callbacks = null;\n this.abortInternal();\n }\n\n abortInternal(): void {\n const response = this.response;\n if (!response?.ok) {\n this.stats.aborted = true;\n this.controller.abort();\n }\n }\n\n abort(): void {\n this.abortInternal();\n if (this.callbacks?.onAbort) {\n this.callbacks.onAbort(this.stats, this.context, this.response);\n }\n }\n\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>\n ): void {\n const stats = this.stats;\n if (stats.loading.start) {\n throw new Error('Loader can only be used once.');\n }\n stats.loading.start = self.performance.now();\n\n const initParams = getRequestParameters(context, this.controller.signal);\n const onProgress: LoaderOnProgress<LoaderContext> | undefined =\n callbacks.onProgress;\n const isArrayBuffer = context.responseType === 'arraybuffer';\n const LENGTH = isArrayBuffer ? 'byteLength' : 'length';\n const { maxTimeToFirstByteMs, maxLoadTimeMs } = config.loadPolicy;\n\n this.context = context;\n this.config = config;\n this.callbacks = callbacks;\n this.request = this.fetchSetup(context, initParams);\n self.clearTimeout(this.requestTimeout);\n config.timeout =\n maxTimeToFirstByteMs && Number.isFinite(maxTimeToFirstByteMs)\n ? maxTimeToFirstByteMs\n : maxLoadTimeMs;\n this.requestTimeout = self.setTimeout(() => {\n this.abortInternal();\n callbacks.onTimeout(stats, context, this.response);\n }, config.timeout);\n\n self\n .fetch(this.request)\n .then((response: Response): Promise<string | ArrayBuffer> => {\n this.response = this.loader = response;\n\n const first = Math.max(self.performance.now(), stats.loading.start);\n\n self.clearTimeout(this.requestTimeout);\n config.timeout = maxLoadTimeMs;\n this.requestTimeout = self.setTimeout(() => {\n this.abortInternal();\n callbacks.onTimeout(stats, context, this.response);\n }, maxLoadTimeMs - (first - stats.loading.start));\n\n if (!response.ok) {\n const { status, statusText } = response;\n throw new FetchError(\n statusText || 'fetch, bad network response',\n status,\n response\n );\n }\n stats.loading.first = first;\n\n stats.total = getContentLength(response.headers) || stats.total;\n\n if (onProgress && Number.isFinite(config.highWaterMark)) {\n return this.loadProgressively(\n response,\n stats,\n context,\n config.highWaterMark,\n onProgress\n );\n }\n\n if (isArrayBuffer) {\n return response.arrayBuffer();\n }\n if (context.responseType === 'json') {\n return response.json();\n }\n return response.text();\n })\n .then((responseData: string | ArrayBuffer) => {\n const { response } = this;\n self.clearTimeout(this.requestTimeout);\n stats.loading.end = Math.max(\n self.performance.now(),\n stats.loading.first\n );\n const total = responseData[LENGTH];\n if (total) {\n stats.loaded = stats.total = total;\n }\n\n const loaderResponse: LoaderResponse = {\n url: response.url,\n data: responseData,\n code: response.status,\n };\n\n if (onProgress && !Number.isFinite(config.highWaterMark)) {\n onProgress(stats, context, responseData, response);\n }\n\n callbacks.onSuccess(loaderResponse, stats, context, response);\n })\n .catch((error) => {\n self.clearTimeout(this.requestTimeout);\n if (stats.aborted) {\n return;\n }\n // CORS errors result in an undefined code. Set it to 0 here to align with XHR's behavior\n // when destroying, 'error' itself can be undefined\n const code: number = !error ? 0 : error.code || 0;\n const text: string = !error ? null : error.message;\n callbacks.onError(\n { code, text },\n context,\n error ? error.details : null,\n stats\n );\n });\n }\n\n getCacheAge(): number | null {\n let result: number | null = null;\n if (this.response) {\n const ageHeader = this.response.headers.get('age');\n result = ageHeader ? parseFloat(ageHeader) : null;\n }\n return result;\n }\n\n getResponseHeader(name: string): string | null {\n return this.response ? this.response.headers.get(name) : null;\n }\n\n private loadProgressively(\n response: Response,\n stats: LoaderStats,\n context: LoaderContext,\n highWaterMark: number = 0,\n onProgress: LoaderOnProgress<LoaderContext>\n ): Promise<ArrayBuffer> {\n const chunkCache = new ChunkCache();\n const reader = (response.body as ReadableStream).getReader();\n\n const pump = (): Promise<ArrayBuffer> => {\n return reader\n .read()\n .then((data) => {\n if (data.done) {\n if (chunkCache.dataLength) {\n onProgress(stats, context, chunkCache.flush(), response);\n }\n\n return Promise.resolve(new ArrayBuffer(0));\n }\n const chunk: Uint8Array = data.value;\n const len = chunk.length;\n stats.loaded += len;\n if (len < highWaterMark || chunkCache.dataLength) {\n // The current chunk is too small to to be emitted or the cache already has data\n // Push it to the cache\n chunkCache.push(chunk);\n if (chunkCache.dataLength >= highWaterMark) {\n // flush in order to join the typed arrays\n onProgress(stats, context, chunkCache.flush(), response);\n }\n } else {\n // If there's nothing cached already, and the chache is large enough\n // just emit the progress event\n onProgress(stats, context, chunk, response);\n }\n return pump();\n })\n .catch(() => {\n /* aborted */\n return Promise.reject();\n });\n };\n\n return pump();\n }\n}\n\nfunction getRequestParameters(context: LoaderContext, signal): any {\n const initParams: any = {\n method: 'GET',\n mode: 'cors',\n credentials: 'same-origin',\n signal,\n headers: new self.Headers(Object.assign({}, context.headers)),\n };\n\n if (context.rangeEnd) {\n initParams.headers.set(\n 'Range',\n 'bytes=' + context.rangeStart + '-' + String(context.rangeEnd - 1)\n );\n }\n\n return initParams;\n}\n\nfunction getByteRangeLength(byteRangeHeader: string): number | undefined {\n const result = BYTERANGE.exec(byteRangeHeader);\n if (result) {\n return parseInt(result[2]) - parseInt(result[1]) + 1;\n }\n}\n\nfunction getContentLength(headers: Headers): number | undefined {\n const contentRange = headers.get('Content-Range');\n if (contentRange) {\n const byteRangeLength = getByteRangeLength(contentRange);\n if (Number.isFinite(byteRangeLength)) {\n return byteRangeLength;\n }\n }\n const contentLength = headers.get('Content-Length');\n if (contentLength) {\n return parseInt(contentLength);\n }\n}\n\nfunction getRequest(context: LoaderContext, initParams: any): Request {\n return new self.Request(context.url, initParams);\n}\n\nclass FetchError extends Error {\n public code: number;\n public details: any;\n constructor(message: string, code: number, details: any) {\n super(message);\n this.code = code;\n this.details = details;\n }\n}\n\nexport default FetchLoader;\n","import { fixLineBreaks } from './vttparser';\nimport type { CaptionScreen, Row } from './cea-608-parser';\nimport { generateCueId } from './webvtt-parser';\nimport { addCueToTrack } from './texttrack-utils';\n\nconst WHITESPACE_CHAR = /\\s/;\n\nexport interface CuesInterface {\n newCue(\n track: TextTrack | null,\n startTime: number,\n endTime: number,\n captionScreen: CaptionScreen\n ): VTTCue[];\n}\n\nconst Cues: CuesInterface = {\n newCue(\n track: TextTrack | null,\n startTime: number,\n endTime: number,\n captionScreen: CaptionScreen\n ): VTTCue[] {\n const result: VTTCue[] = [];\n let row: Row;\n // the type data states this is VTTCue, but it can potentially be a TextTrackCue on old browsers\n let cue: VTTCue;\n let indenting: boolean;\n let indent: number;\n let text: string;\n const Cue = (self.VTTCue || self.TextTrackCue) as any;\n\n for (let r = 0; r < captionScreen.rows.length; r++) {\n row = captionScreen.rows[r];\n indenting = true;\n indent = 0;\n text = '';\n\n if (!row.isEmpty()) {\n for (let c = 0; c < row.chars.length; c++) {\n if (WHITESPACE_CHAR.test(row.chars[c].uchar) && indenting) {\n indent++;\n } else {\n text += row.chars[c].uchar;\n indenting = false;\n }\n }\n // To be used for cleaning-up orphaned roll-up captions\n row.cueStartTime = startTime;\n\n // Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE\n if (startTime === endTime) {\n endTime += 0.0001;\n }\n\n if (indent >= 16) {\n indent--;\n } else {\n indent++;\n }\n\n const cueText = fixLineBreaks(text.trim());\n const id = generateCueId(startTime, endTime, cueText);\n\n // If this cue already exists in the track do not push it\n if (!track?.cues?.getCueById(id)) {\n cue = new Cue(startTime, endTime, cueText);\n cue.id = id;\n cue.line = r + 1;\n cue.align = 'left';\n // Clamp the position between 10 and 80 percent (CEA-608 PAC indent code)\n // https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#positioning-in-cea-608\n // Firefox throws an exception and captions break with out of bounds 0-100 values\n cue.position = 10 + Math.min(80, Math.floor((indent * 8) / 32) * 10);\n result.push(cue);\n }\n }\n }\n if (track && result.length) {\n // Sort bottom cues in reverse order so that they render in line order when overlapping in Chrome\n result.sort((cueA, cueB) => {\n if (cueA.line === 'auto' || cueB.line === 'auto') {\n return 0;\n }\n if (cueA.line > 8 && cueB.line > 8) {\n return cueB.line - cueA.line;\n }\n return cueA.line - cueB.line;\n });\n result.forEach((cue) => addCueToTrack(track, cue));\n }\n return result;\n },\n};\n\nexport default Cues;\n","import AbrController from './controller/abr-controller';\nimport AudioStreamController from './controller/audio-stream-controller';\nimport AudioTrackController from './controller/audio-track-controller';\nimport { SubtitleStreamController } from './controller/subtitle-stream-controller';\nimport SubtitleTrackController from './controller/subtitle-track-controller';\nimport BufferController from './controller/buffer-controller';\nimport { TimelineController } from './controller/timeline-controller';\nimport CapLevelController from './controller/cap-level-controller';\nimport FPSController from './controller/fps-controller';\nimport EMEController, {\n MediaKeySessionContext,\n} from './controller/eme-controller';\nimport CMCDController from './controller/cmcd-controller';\nimport ContentSteeringController from './controller/content-steering-controller';\nimport ErrorController from './controller/error-controller';\nimport XhrLoader from './utils/xhr-loader';\nimport FetchLoader, { fetchSupported } from './utils/fetch-loader';\nimport Cues from './utils/cues';\nimport { requestMediaKeySystemAccess } from './utils/mediakeys-helper';\nimport { ILogger, logger } from './utils/logger';\n\nimport type Hls from './hls';\nimport type { CuesInterface } from './utils/cues';\nimport type { MediaKeyFunc, KeySystems } from './utils/mediakeys-helper';\nimport type {\n FragmentLoaderContext,\n Loader,\n LoaderContext,\n PlaylistLoaderContext,\n} from './types/loader';\n\nexport type ABRControllerConfig = {\n abrEwmaFastLive: number;\n abrEwmaSlowLive: number;\n abrEwmaFastVoD: number;\n abrEwmaSlowVoD: number;\n /**\n * Default bandwidth estimate in bits/s prior to collecting fragment bandwidth samples\n */\n abrEwmaDefaultEstimate: number;\n abrBandWidthFactor: number;\n abrBandWidthUpFactor: number;\n abrMaxWithRealBitrate: boolean;\n maxStarvationDelay: number;\n maxLoadingDelay: number;\n};\n\nexport type BufferControllerConfig = {\n appendErrorMaxRetry: number;\n backBufferLength: number;\n liveDurationInfinity: boolean;\n /**\n * @deprecated use backBufferLength\n */\n liveBackBufferLength: number | null;\n};\n\nexport type CapLevelControllerConfig = {\n capLevelToPlayerSize: boolean;\n};\n\nexport type CMCDControllerConfig = {\n sessionId?: string;\n contentId?: string;\n useHeaders?: boolean;\n};\n\nexport type DRMSystemOptions = {\n audioRobustness?: string;\n videoRobustness?: string;\n audioEncryptionScheme?: string | null;\n videoEncryptionScheme?: string | null;\n persistentState?: MediaKeysRequirement;\n distinctiveIdentifier?: MediaKeysRequirement;\n sessionTypes?: string[];\n sessionType?: string;\n};\n\nexport type DRMSystemConfiguration = {\n licenseUrl: string;\n serverCertificateUrl?: string;\n generateRequest?: (\n this: Hls,\n initDataType: string,\n initData: ArrayBuffer | null,\n keyContext: MediaKeySessionContext\n ) =>\n | { initDataType: string; initData: ArrayBuffer | null }\n | undefined\n | never;\n};\n\nexport type DRMSystemsConfiguration = Partial<\n Record<KeySystems, DRMSystemConfiguration>\n>;\n\nexport type EMEControllerConfig = {\n licenseXhrSetup?: (\n this: Hls,\n xhr: XMLHttpRequest,\n url: string,\n keyContext: MediaKeySessionContext,\n licenseChallenge: Uint8Array\n ) => void | Uint8Array | Promise<Uint8Array | void>;\n licenseResponseCallback?: (\n this: Hls,\n xhr: XMLHttpRequest,\n url: string,\n keyContext: MediaKeySessionContext\n ) => ArrayBuffer;\n emeEnabled: boolean;\n widevineLicenseUrl?: string;\n drmSystems: DRMSystemsConfiguration;\n drmSystemOptions: DRMSystemOptions;\n requestMediaKeySystemAccessFunc: MediaKeyFunc | null;\n};\n\nexport interface FragmentLoaderConstructor {\n new (confg: HlsConfig): Loader<FragmentLoaderContext>;\n}\n\n/**\n * @deprecated use fragLoadPolicy.default\n */\nexport type FragmentLoaderConfig = {\n fragLoadingTimeOut: number;\n fragLoadingMaxRetry: number;\n fragLoadingRetryDelay: number;\n fragLoadingMaxRetryTimeout: number;\n};\n\nexport type FPSControllerConfig = {\n capLevelOnFPSDrop: boolean;\n fpsDroppedMonitoringPeriod: number;\n fpsDroppedMonitoringThreshold: number;\n};\n\nexport type LevelControllerConfig = {\n startLevel?: number;\n};\n\nexport type MP4RemuxerConfig = {\n stretchShortVideoTrack: boolean;\n maxAudioFramesDrift: number;\n};\n\nexport interface PlaylistLoaderConstructor {\n new (confg: HlsConfig): Loader<PlaylistLoaderContext>;\n}\n\n/**\n * @deprecated use manifestLoadPolicy.default and playlistLoadPolicy.default\n */\nexport type PlaylistLoaderConfig = {\n manifestLoadingTimeOut: number;\n manifestLoadingMaxRetry: number;\n manifestLoadingRetryDelay: number;\n manifestLoadingMaxRetryTimeout: number;\n\n levelLoadingTimeOut: number;\n levelLoadingMaxRetry: number;\n levelLoadingRetryDelay: number;\n levelLoadingMaxRetryTimeout: number;\n};\n\nexport type HlsLoadPolicies = {\n fragLoadPolicy: LoadPolicy;\n keyLoadPolicy: LoadPolicy;\n certLoadPolicy: LoadPolicy;\n playlistLoadPolicy: LoadPolicy;\n manifestLoadPolicy: LoadPolicy;\n steeringManifestLoadPolicy: LoadPolicy;\n};\n\nexport type LoadPolicy = {\n default: LoaderConfig;\n};\n\nexport type LoaderConfig = {\n maxTimeToFirstByteMs: number; // Max time to first byte\n maxLoadTimeMs: number; // Max time for load completion\n timeoutRetry: RetryConfig | null;\n errorRetry: RetryConfig | null;\n};\n\nexport type RetryConfig = {\n maxNumRetry: number; // Maximum number of retries\n retryDelayMs: number; // Retry delay = 2^retryCount * retryDelayMs (exponential) or retryCount * retryDelayMs (linear)\n maxRetryDelayMs: number; // Maximum delay between retries\n backoff?: 'exponential' | 'linear'; // used to determine retry backoff duration (see retryDelayMs)\n};\n\nexport type StreamControllerConfig = {\n autoStartLoad: boolean;\n startPosition: number;\n defaultAudioCodec?: string;\n initialLiveManifestSize: number;\n maxBufferLength: number;\n maxBufferSize: number;\n maxBufferHole: number;\n highBufferWatchdogPeriod: number;\n nudgeOffset: number;\n nudgeMaxRetry: number;\n maxFragLookUpTolerance: number;\n maxMaxBufferLength: number;\n startFragPrefetch: boolean;\n testBandwidth: boolean;\n};\n\nexport type LatencyControllerConfig = {\n liveSyncDurationCount: number;\n liveMaxLatencyDurationCount: number;\n liveSyncDuration?: number;\n liveMaxLatencyDuration?: number;\n maxLiveSyncPlaybackRate: number;\n};\n\nexport type MetadataControllerConfig = {\n enableDateRangeMetadataCues: boolean;\n enableEmsgMetadataCues: boolean;\n enableID3MetadataCues: boolean;\n};\n\nexport type TimelineControllerConfig = {\n cueHandler: CuesInterface;\n enableWebVTT: boolean;\n enableIMSC1: boolean;\n enableCEA708Captions: boolean;\n captionsTextTrack1Label: string;\n captionsTextTrack1LanguageCode: string;\n captionsTextTrack2Label: string;\n captionsTextTrack2LanguageCode: string;\n captionsTextTrack3Label: string;\n captionsTextTrack3LanguageCode: string;\n captionsTextTrack4Label: string;\n captionsTextTrack4LanguageCode: string;\n renderTextTracksNatively: boolean;\n};\n\nexport type TSDemuxerConfig = {\n forceKeyFrameOnDiscontinuity: boolean;\n};\n\nexport type HlsConfig = {\n debug: boolean | ILogger;\n enableWorker: boolean;\n workerPath: null | string;\n enableSoftwareAES: boolean;\n minAutoBitrate: number;\n ignoreDevicePixelRatio: boolean;\n loader: { new (confg: HlsConfig): Loader<LoaderContext> };\n fLoader?: FragmentLoaderConstructor;\n pLoader?: PlaylistLoaderConstructor;\n fetchSetup?: (context: LoaderContext, initParams: any) => Request;\n xhrSetup?: (xhr: XMLHttpRequest, url: string) => Promise<void> | void;\n\n // Alt Audio\n audioStreamController?: typeof AudioStreamController;\n audioTrackController?: typeof AudioTrackController;\n // Subtitle\n subtitleStreamController?: typeof SubtitleStreamController;\n subtitleTrackController?: typeof SubtitleTrackController;\n timelineController?: typeof TimelineController;\n // EME\n emeController?: typeof EMEController;\n // CMCD\n cmcd?: CMCDControllerConfig;\n cmcdController?: typeof CMCDController;\n // Content Steering\n contentSteeringController?: typeof ContentSteeringController;\n\n abrController: typeof AbrController;\n bufferController: typeof BufferController;\n capLevelController: typeof CapLevelController;\n errorController: typeof ErrorController;\n fpsController: typeof FPSController;\n progressive: boolean;\n lowLatencyMode: boolean;\n} & ABRControllerConfig &\n BufferControllerConfig &\n CapLevelControllerConfig &\n EMEControllerConfig &\n FPSControllerConfig &\n LevelControllerConfig &\n MP4RemuxerConfig &\n StreamControllerConfig &\n LatencyControllerConfig &\n MetadataControllerConfig &\n TimelineControllerConfig &\n TSDemuxerConfig &\n HlsLoadPolicies &\n FragmentLoaderConfig &\n PlaylistLoaderConfig;\n\nconst defaultLoadPolicy: LoaderConfig = {\n maxTimeToFirstByteMs: 8000,\n maxLoadTimeMs: 20000,\n timeoutRetry: null,\n errorRetry: null,\n};\n\n/**\n * @ignore\n * If possible, keep hlsDefaultConfig shallow\n * It is cloned whenever a new Hls instance is created, by keeping the config\n * shallow the properties are cloned, and we don't end up manipulating the default\n */\nexport const hlsDefaultConfig: HlsConfig = {\n autoStartLoad: true, // used by stream-controller\n startPosition: -1, // used by stream-controller\n defaultAudioCodec: undefined, // used by stream-controller\n debug: false, // used by logger\n capLevelOnFPSDrop: false, // used by fps-controller\n capLevelToPlayerSize: false, // used by cap-level-controller\n ignoreDevicePixelRatio: false, // used by cap-level-controller\n initialLiveManifestSize: 1, // used by stream-controller\n maxBufferLength: 30, // used by stream-controller\n backBufferLength: Infinity, // used by buffer-controller\n maxBufferSize: 60 * 1000 * 1000, // used by stream-controller\n maxBufferHole: 0.1, // used by stream-controller\n highBufferWatchdogPeriod: 2, // used by stream-controller\n nudgeOffset: 0.1, // used by stream-controller\n nudgeMaxRetry: 3, // used by stream-controller\n maxFragLookUpTolerance: 0.25, // used by stream-controller\n liveSyncDurationCount: 3, // used by latency-controller\n liveMaxLatencyDurationCount: Infinity, // used by latency-controller\n liveSyncDuration: undefined, // used by latency-controller\n liveMaxLatencyDuration: undefined, // used by latency-controller\n maxLiveSyncPlaybackRate: 1, // used by latency-controller\n liveDurationInfinity: false, // used by buffer-controller\n /**\n * @deprecated use backBufferLength\n */\n liveBackBufferLength: null, // used by buffer-controller\n maxMaxBufferLength: 600, // used by stream-controller\n enableWorker: true, // used by transmuxer\n workerPath: null, // used by transmuxer\n enableSoftwareAES: true, // used by decrypter\n startLevel: undefined, // used by level-controller\n startFragPrefetch: false, // used by stream-controller\n fpsDroppedMonitoringPeriod: 5000, // used by fps-controller\n fpsDroppedMonitoringThreshold: 0.2, // used by fps-controller\n appendErrorMaxRetry: 3, // used by buffer-controller\n loader: XhrLoader,\n // loader: FetchLoader,\n fLoader: undefined, // used by fragment-loader\n pLoader: undefined, // used by playlist-loader\n xhrSetup: undefined, // used by xhr-loader\n licenseXhrSetup: undefined, // used by eme-controller\n licenseResponseCallback: undefined, // used by eme-controller\n abrController: AbrController,\n bufferController: BufferController,\n capLevelController: CapLevelController,\n errorController: ErrorController,\n fpsController: FPSController,\n stretchShortVideoTrack: false, // used by mp4-remuxer\n maxAudioFramesDrift: 1, // used by mp4-remuxer\n forceKeyFrameOnDiscontinuity: true, // used by ts-demuxer\n abrEwmaFastLive: 3, // used by abr-controller\n abrEwmaSlowLive: 9, // used by abr-controller\n abrEwmaFastVoD: 3, // used by abr-controller\n abrEwmaSlowVoD: 9, // used by abr-controller\n abrEwmaDefaultEstimate: 5e5, // 500 kbps // used by abr-controller\n abrBandWidthFactor: 0.95, // used by abr-controller\n abrBandWidthUpFactor: 0.7, // used by abr-controller\n abrMaxWithRealBitrate: false, // used by abr-controller\n maxStarvationDelay: 4, // used by abr-controller\n maxLoadingDelay: 4, // used by abr-controller\n minAutoBitrate: 0, // used by hls\n emeEnabled: false, // used by eme-controller\n widevineLicenseUrl: undefined, // used by eme-controller\n drmSystems: {}, // used by eme-controller\n drmSystemOptions: {}, // used by eme-controller\n requestMediaKeySystemAccessFunc: __USE_EME_DRM__\n ? requestMediaKeySystemAccess\n : null, // used by eme-controller\n testBandwidth: true,\n progressive: false,\n lowLatencyMode: true,\n cmcd: undefined,\n enableDateRangeMetadataCues: true,\n enableEmsgMetadataCues: true,\n enableID3MetadataCues: true,\n\n certLoadPolicy: {\n default: defaultLoadPolicy,\n },\n keyLoadPolicy: {\n default: {\n maxTimeToFirstByteMs: 8000,\n maxLoadTimeMs: 20000,\n timeoutRetry: {\n maxNumRetry: 1,\n retryDelayMs: 1000,\n maxRetryDelayMs: 20000,\n backoff: 'linear',\n },\n errorRetry: {\n maxNumRetry: 8,\n retryDelayMs: 1000,\n maxRetryDelayMs: 20000,\n backoff: 'linear',\n },\n },\n },\n manifestLoadPolicy: {\n default: {\n maxTimeToFirstByteMs: Infinity,\n maxLoadTimeMs: 20000,\n timeoutRetry: {\n maxNumRetry: 2,\n retryDelayMs: 0,\n maxRetryDelayMs: 0,\n },\n errorRetry: {\n maxNumRetry: 1,\n retryDelayMs: 1000,\n maxRetryDelayMs: 8000,\n },\n },\n },\n playlistLoadPolicy: {\n default: {\n maxTimeToFirstByteMs: 10000,\n maxLoadTimeMs: 20000,\n timeoutRetry: {\n maxNumRetry: 2,\n retryDelayMs: 0,\n maxRetryDelayMs: 0,\n },\n errorRetry: {\n maxNumRetry: 2,\n retryDelayMs: 1000,\n maxRetryDelayMs: 8000,\n },\n },\n },\n fragLoadPolicy: {\n default: {\n maxTimeToFirstByteMs: 10000,\n maxLoadTimeMs: 120000,\n timeoutRetry: {\n maxNumRetry: 4,\n retryDelayMs: 0,\n maxRetryDelayMs: 0,\n },\n errorRetry: {\n maxNumRetry: 6,\n retryDelayMs: 1000,\n maxRetryDelayMs: 8000,\n },\n },\n },\n steeringManifestLoadPolicy: {\n default: __USE_CONTENT_STEERING__\n ? {\n maxTimeToFirstByteMs: 10000,\n maxLoadTimeMs: 20000,\n timeoutRetry: {\n maxNumRetry: 2,\n retryDelayMs: 0,\n maxRetryDelayMs: 0,\n },\n errorRetry: {\n maxNumRetry: 1,\n retryDelayMs: 1000,\n maxRetryDelayMs: 8000,\n },\n }\n : defaultLoadPolicy,\n },\n\n // These default settings are deprecated in favor of the above policies\n // and are maintained for backwards compatibility\n manifestLoadingTimeOut: 10000,\n manifestLoadingMaxRetry: 1,\n manifestLoadingRetryDelay: 1000,\n manifestLoadingMaxRetryTimeout: 64000,\n levelLoadingTimeOut: 10000,\n levelLoadingMaxRetry: 4,\n levelLoadingRetryDelay: 1000,\n levelLoadingMaxRetryTimeout: 64000,\n fragLoadingTimeOut: 20000,\n fragLoadingMaxRetry: 6,\n fragLoadingRetryDelay: 1000,\n fragLoadingMaxRetryTimeout: 64000,\n\n // Dynamic Modules\n ...timelineConfig(),\n subtitleStreamController: __USE_SUBTITLES__\n ? SubtitleStreamController\n : undefined,\n subtitleTrackController: __USE_SUBTITLES__\n ? SubtitleTrackController\n : undefined,\n timelineController: __USE_SUBTITLES__ ? TimelineController : undefined,\n audioStreamController: __USE_ALT_AUDIO__ ? AudioStreamController : undefined,\n audioTrackController: __USE_ALT_AUDIO__ ? AudioTrackController : undefined,\n emeController: __USE_EME_DRM__ ? EMEController : undefined,\n cmcdController: __USE_CMCD__ ? CMCDController : undefined,\n contentSteeringController: __USE_CONTENT_STEERING__\n ? ContentSteeringController\n : undefined,\n};\n\nfunction timelineConfig(): TimelineControllerConfig {\n return {\n cueHandler: Cues, // used by timeline-controller\n enableWebVTT: __USE_SUBTITLES__, // used by timeline-controller\n enableIMSC1: __USE_SUBTITLES__, // used by timeline-controller\n enableCEA708Captions: __USE_SUBTITLES__, // used by timeline-controller\n captionsTextTrack1Label: 'English', // used by timeline-controller\n captionsTextTrack1LanguageCode: 'en', // used by timeline-controller\n captionsTextTrack2Label: 'Spanish', // used by timeline-controller\n captionsTextTrack2LanguageCode: 'es', // used by timeline-controller\n captionsTextTrack3Label: 'Unknown CC', // used by timeline-controller\n captionsTextTrack3LanguageCode: '', // used by timeline-controller\n captionsTextTrack4Label: 'Unknown CC', // used by timeline-controller\n captionsTextTrack4LanguageCode: '', // used by timeline-controller\n renderTextTracksNatively: true,\n };\n}\n\n/**\n * @ignore\n */\nexport function mergeConfig(\n defaultConfig: HlsConfig,\n userConfig: Partial<HlsConfig>\n): HlsConfig {\n if (\n (userConfig.liveSyncDurationCount ||\n userConfig.liveMaxLatencyDurationCount) &&\n (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)\n ) {\n throw new Error(\n \"Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration\"\n );\n }\n\n if (\n userConfig.liveMaxLatencyDurationCount !== undefined &&\n (userConfig.liveSyncDurationCount === undefined ||\n userConfig.liveMaxLatencyDurationCount <=\n userConfig.liveSyncDurationCount)\n ) {\n throw new Error(\n 'Illegal hls.js config: \"liveMaxLatencyDurationCount\" must be greater than \"liveSyncDurationCount\"'\n );\n }\n\n if (\n userConfig.liveMaxLatencyDuration !== undefined &&\n (userConfig.liveSyncDuration === undefined ||\n userConfig.liveMaxLatencyDuration <= userConfig.liveSyncDuration)\n ) {\n throw new Error(\n 'Illegal hls.js config: \"liveMaxLatencyDuration\" must be greater than \"liveSyncDuration\"'\n );\n }\n\n const defaultsCopy = deepCpy(defaultConfig);\n\n // Backwards compatibility with deprecated config values\n const deprecatedSettingTypes = ['manifest', 'level', 'frag'];\n const deprecatedSettings = [\n 'TimeOut',\n 'MaxRetry',\n 'RetryDelay',\n 'MaxRetryTimeout',\n ];\n deprecatedSettingTypes.forEach((type) => {\n const policyName = `${type === 'level' ? 'playlist' : type}LoadPolicy`;\n const policyNotSet = userConfig[policyName] === undefined;\n const report: string[] = [];\n deprecatedSettings.forEach((setting) => {\n const deprecatedSetting = `${type}Loading${setting}`;\n const value = userConfig[deprecatedSetting];\n if (value !== undefined && policyNotSet) {\n report.push(deprecatedSetting);\n const settings: LoaderConfig = defaultsCopy[policyName].default;\n userConfig[policyName] = { default: settings };\n switch (setting) {\n case 'TimeOut':\n settings.maxLoadTimeMs = value;\n settings.maxTimeToFirstByteMs = value;\n break;\n case 'MaxRetry':\n settings.errorRetry!.maxNumRetry = value;\n settings.timeoutRetry!.maxNumRetry = value;\n break;\n case 'RetryDelay':\n settings.errorRetry!.retryDelayMs = value;\n settings.timeoutRetry!.retryDelayMs = value;\n break;\n case 'MaxRetryTimeout':\n settings.errorRetry!.maxRetryDelayMs = value;\n settings.timeoutRetry!.maxRetryDelayMs = value;\n break;\n }\n }\n });\n if (report.length) {\n logger.warn(\n `hls.js config: \"${report.join(\n '\", \"'\n )}\" setting(s) are deprecated, use \"${policyName}\": ${JSON.stringify(\n userConfig[policyName]\n )}`\n );\n }\n });\n\n return {\n ...defaultsCopy,\n ...userConfig,\n };\n}\n\nfunction deepCpy(obj: any): any {\n if (obj && typeof obj === 'object') {\n if (Array.isArray(obj)) {\n return obj.map(deepCpy);\n }\n return Object.keys(obj).reduce((result, key) => {\n result[key] = deepCpy(obj[key]);\n return result;\n }, {});\n }\n return obj;\n}\n\n/**\n * @ignore\n */\nexport function enableStreamingMode(config) {\n const currentLoader = config.loader;\n if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {\n // If a developer has configured their own loader, respect that choice\n logger.log(\n '[config]: Custom loader detected, cannot enable progressive streaming'\n );\n config.progressive = false;\n } else {\n const canStreamProgressively = fetchSupported();\n if (canStreamProgressively) {\n config.loader = FetchLoader;\n config.progressive = true;\n config.enableSoftwareAES = true;\n logger.log('[config]: Progressive streaming enabled, using FetchLoader');\n }\n }\n}\n","import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';\nimport { Events } from '../events';\nimport { PlaylistLevelType } from '../types/loader';\nimport { logger } from '../utils/logger';\nimport type { Fragment } from '../loader/fragment';\nimport type { Part } from '../loader/fragment';\nimport type { LoaderStats } from '../types/loader';\nimport type Hls from '../hls';\nimport type {\n FragLoadingData,\n FragLoadedData,\n FragBufferedData,\n LevelLoadedData,\n LevelSwitchingData,\n} from '../types/events';\nimport type { AbrComponentAPI } from '../types/component-api';\n\nclass AbrController implements AbrComponentAPI {\n protected hls: Hls;\n private lastLevelLoadSec: number = 0;\n private lastLoadedFragLevel: number = 0;\n private _nextAutoLevel: number = -1;\n private timer: number = -1;\n private onCheck: Function = this._abandonRulesCheck.bind(this);\n private fragCurrent: Fragment | null = null;\n private partCurrent: Part | null = null;\n private bitrateTestDelay: number = 0;\n\n public readonly bwEstimator: EwmaBandWidthEstimator;\n\n constructor(hls: Hls) {\n this.hls = hls;\n\n const config = hls.config;\n this.bwEstimator = new EwmaBandWidthEstimator(\n config.abrEwmaSlowVoD,\n config.abrEwmaFastVoD,\n config.abrEwmaDefaultEstimate\n );\n\n this.registerListeners();\n }\n\n protected registerListeners() {\n const { hls } = this;\n hls.on(Events.FRAG_LOADING, this.onFragLoading, this);\n hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n }\n\n protected unregisterListeners() {\n const { hls } = this;\n hls.off(Events.FRAG_LOADING, this.onFragLoading, this);\n hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);\n hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n }\n\n public destroy() {\n this.unregisterListeners();\n this.clearTimer();\n // @ts-ignore\n this.hls = this.onCheck = null;\n this.fragCurrent = this.partCurrent = null;\n }\n\n protected onFragLoading(event: Events.FRAG_LOADING, data: FragLoadingData) {\n const frag = data.frag;\n if (this.ignoreFragment(frag)) {\n return;\n }\n this.fragCurrent = frag;\n this.partCurrent = data.part ?? null;\n this.clearTimer();\n this.timer = self.setInterval(this.onCheck, 100);\n }\n\n protected onLevelSwitching(\n event: Events.LEVEL_SWITCHING,\n data: LevelSwitchingData\n ): void {\n this.clearTimer();\n }\n\n private getTimeToLoadFrag(\n timeToFirstByteSec: number,\n bandwidth: number,\n fragSizeBits: number,\n isSwitch: boolean\n ) {\n const fragLoadSec = timeToFirstByteSec + fragSizeBits / bandwidth;\n const playlistLoadSec = isSwitch ? this.lastLevelLoadSec : 0;\n return fragLoadSec + playlistLoadSec;\n }\n\n protected onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n const config = this.hls.config;\n const { total, bwEstimate } = data.stats;\n // Total is the bytelength and bwEstimate in bits/sec\n if (Number.isFinite(total) && Number.isFinite(bwEstimate)) {\n this.lastLevelLoadSec = (8 * total) / bwEstimate;\n }\n if (data.details.live) {\n this.bwEstimator.update(config.abrEwmaSlowLive, config.abrEwmaFastLive);\n } else {\n this.bwEstimator.update(config.abrEwmaSlowVoD, config.abrEwmaFastVoD);\n }\n }\n\n /*\n This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load\n quickly enough to prevent underbuffering\n */\n private _abandonRulesCheck() {\n const { fragCurrent: frag, partCurrent: part, hls } = this;\n const { autoLevelEnabled, media } = hls;\n if (!frag || !media) {\n return;\n }\n\n const now = performance.now();\n const stats: LoaderStats = part ? part.stats : frag.stats;\n const duration = part ? part.duration : frag.duration;\n const timeLoading = now - stats.loading.start;\n // If frag loading is aborted, complete, or from lowest level, stop timer and return\n if (\n stats.aborted ||\n (stats.loaded && stats.loaded === stats.total) ||\n frag.level === 0\n ) {\n this.clearTimer();\n // reset forced auto level value so that next level will be selected\n this._nextAutoLevel = -1;\n return;\n }\n\n // This check only runs if we're in ABR mode and actually playing\n if (\n !autoLevelEnabled ||\n media.paused ||\n !media.playbackRate ||\n !media.readyState\n ) {\n return;\n }\n\n const bufferInfo = hls.mainForwardBufferInfo;\n if (bufferInfo === null) {\n return;\n }\n\n const ttfbEstimate = this.bwEstimator.getEstimateTTFB();\n const playbackRate = Math.abs(media.playbackRate);\n // To maintain stable adaptive playback, only begin monitoring frag loading after half or more of its playback duration has passed\n if (\n timeLoading <=\n Math.max(ttfbEstimate, 1000 * (duration / (playbackRate * 2)))\n ) {\n return;\n }\n\n // bufferStarvationDelay is an estimate of the amount time (in seconds) it will take to exhaust the buffer\n const bufferStarvationDelay = bufferInfo.len / playbackRate;\n // Only downswitch if less than 2 fragment lengths are buffered\n if (bufferStarvationDelay >= (2 * duration) / playbackRate) {\n return;\n }\n\n const ttfb = stats.loading.first\n ? stats.loading.first - stats.loading.start\n : -1;\n const loadedFirstByte = stats.loaded && ttfb > -1;\n const bwEstimate: number = this.bwEstimator.getEstimate();\n const { levels, minAutoLevel } = hls;\n const level = levels[frag.level];\n const expectedLen =\n stats.total ||\n Math.max(stats.loaded, Math.round((duration * level.maxBitrate) / 8));\n let timeStreaming = timeLoading - ttfb;\n if (timeStreaming < 1 && loadedFirstByte) {\n timeStreaming = Math.min(timeLoading, (stats.loaded * 8) / bwEstimate);\n }\n const loadRate = loadedFirstByte\n ? (stats.loaded * 1000) / timeStreaming\n : 0;\n // fragLoadDelay is an estimate of the time (in seconds) it will take to buffer the remainder of the fragment\n const fragLoadedDelay = loadRate\n ? (expectedLen - stats.loaded) / loadRate\n : (expectedLen * 8) / bwEstimate + ttfbEstimate / 1000;\n // Only downswitch if the time to finish loading the current fragment is greater than the amount of buffer left\n if (fragLoadedDelay <= bufferStarvationDelay) {\n return;\n }\n\n const bwe = loadRate ? loadRate * 8 : bwEstimate;\n let fragLevelNextLoadedDelay: number = Number.POSITIVE_INFINITY;\n let nextLoadLevel: number;\n // Iterate through lower level and try to find the largest one that avoids rebuffering\n for (\n nextLoadLevel = frag.level - 1;\n nextLoadLevel > minAutoLevel;\n nextLoadLevel--\n ) {\n // compute time to load next fragment at lower level\n // 8 = bits per byte (bps/Bps)\n const levelNextBitrate = levels[nextLoadLevel].maxBitrate;\n fragLevelNextLoadedDelay = this.getTimeToLoadFrag(\n ttfbEstimate / 1000,\n bwe,\n duration * levelNextBitrate,\n !levels[nextLoadLevel].details\n );\n if (fragLevelNextLoadedDelay < bufferStarvationDelay) {\n break;\n }\n }\n // Only emergency switch down if it takes less time to load a new fragment at lowest level instead of continuing\n // to load the current one\n if (fragLevelNextLoadedDelay >= fragLoadedDelay) {\n return;\n }\n\n // if estimated load time of new segment is completely unreasonable, ignore and do not emergency switch down\n if (fragLevelNextLoadedDelay > duration * 10) {\n return;\n }\n hls.nextLoadLevel = nextLoadLevel;\n if (loadedFirstByte) {\n // If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time\n this.bwEstimator.sample(\n timeLoading - Math.min(ttfbEstimate, ttfb),\n stats.loaded\n );\n } else {\n // If there has been no loading progress, sample TTFB\n this.bwEstimator.sampleTTFB(timeLoading);\n }\n\n this.clearTimer();\n logger.warn(`[abr] Fragment ${frag.sn}${\n part ? ' part ' + part.index : ''\n } of level ${frag.level} is loading too slowly;\n Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s\n Estimated load time for current fragment: ${fragLoadedDelay.toFixed(3)} s\n Estimated load time for down switch fragment: ${fragLevelNextLoadedDelay.toFixed(\n 3\n )} s\n TTFB estimate: ${ttfb}\n Current BW estimate: ${\n Number.isFinite(bwEstimate) ? (bwEstimate / 1024).toFixed(3) : 'Unknown'\n } Kb/s\n New BW estimate: ${(this.bwEstimator.getEstimate() / 1024).toFixed(\n 3\n )} Kb/s\n Aborting and switching to level ${nextLoadLevel}`);\n if (frag.loader) {\n this.fragCurrent = this.partCurrent = null;\n frag.abortRequests();\n }\n hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, { frag, part, stats });\n }\n\n protected onFragLoaded(\n event: Events.FRAG_LOADED,\n { frag, part }: FragLoadedData\n ) {\n const stats = part ? part.stats : frag.stats;\n if (frag.type === PlaylistLevelType.MAIN) {\n this.bwEstimator.sampleTTFB(stats.loading.first - stats.loading.start);\n }\n if (this.ignoreFragment(frag)) {\n return;\n }\n // stop monitoring bw once frag loaded\n this.clearTimer();\n // store level id after successful fragment load\n this.lastLoadedFragLevel = frag.level;\n // reset forced auto level value so that next level will be selected\n this._nextAutoLevel = -1;\n\n // compute level average bitrate\n if (this.hls.config.abrMaxWithRealBitrate) {\n const duration = part ? part.duration : frag.duration;\n const level = this.hls.levels[frag.level];\n const loadedBytes =\n (level.loaded ? level.loaded.bytes : 0) + stats.loaded;\n const loadedDuration =\n (level.loaded ? level.loaded.duration : 0) + duration;\n level.loaded = { bytes: loadedBytes, duration: loadedDuration };\n level.realBitrate = Math.round((8 * loadedBytes) / loadedDuration);\n }\n if (frag.bitrateTest) {\n const fragBufferedData: FragBufferedData = {\n stats,\n frag,\n part,\n id: frag.type,\n };\n this.onFragBuffered(Events.FRAG_BUFFERED, fragBufferedData);\n frag.bitrateTest = false;\n }\n }\n\n protected onFragBuffered(\n event: Events.FRAG_BUFFERED,\n data: FragBufferedData\n ) {\n const { frag, part } = data;\n const stats = part?.stats.loaded ? part.stats : frag.stats;\n\n if (stats.aborted) {\n return;\n }\n if (this.ignoreFragment(frag)) {\n return;\n }\n // Use the difference between parsing and request instead of buffering and request to compute fragLoadingProcessing;\n // rationale is that buffer appending only happens once media is attached. This can happen when config.startFragPrefetch\n // is used. If we used buffering in that case, our BW estimate sample will be very large.\n const processingMs =\n stats.parsing.end -\n stats.loading.start -\n Math.min(\n stats.loading.first - stats.loading.start,\n this.bwEstimator.getEstimateTTFB()\n );\n this.bwEstimator.sample(processingMs, stats.loaded);\n stats.bwEstimate = this.bwEstimator.getEstimate();\n if (frag.bitrateTest) {\n this.bitrateTestDelay = processingMs / 1000;\n } else {\n this.bitrateTestDelay = 0;\n }\n }\n\n private ignoreFragment(frag: Fragment): boolean {\n // Only count non-alt-audio frags which were actually buffered in our BW calculations\n return frag.type !== PlaylistLevelType.MAIN || frag.sn === 'initSegment';\n }\n\n public clearTimer() {\n self.clearInterval(this.timer);\n }\n\n // return next auto level\n get nextAutoLevel() {\n const forcedAutoLevel = this._nextAutoLevel;\n const bwEstimator = this.bwEstimator;\n // in case next auto level has been forced, and bw not available or not reliable, return forced value\n if (forcedAutoLevel !== -1 && !bwEstimator.canEstimate()) {\n return forcedAutoLevel;\n }\n\n // compute next level using ABR logic\n let nextABRAutoLevel = this.getNextABRAutoLevel();\n // use forced auto level when ABR selected level has errored\n if (forcedAutoLevel !== -1) {\n const levels = this.hls.levels;\n if (\n levels.length > Math.max(forcedAutoLevel, nextABRAutoLevel) &&\n levels[forcedAutoLevel].loadError <= levels[nextABRAutoLevel].loadError\n ) {\n return forcedAutoLevel;\n }\n }\n // if forced auto level has been defined, use it to cap ABR computed quality level\n if (forcedAutoLevel !== -1) {\n nextABRAutoLevel = Math.min(forcedAutoLevel, nextABRAutoLevel);\n }\n\n return nextABRAutoLevel;\n }\n\n private getNextABRAutoLevel(): number {\n const { fragCurrent, partCurrent, hls } = this;\n const { maxAutoLevel, config, minAutoLevel, media } = hls;\n const currentFragDuration = partCurrent\n ? partCurrent.duration\n : fragCurrent\n ? fragCurrent.duration\n : 0;\n\n // playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as\n // if we're playing back at the normal rate.\n const playbackRate =\n media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0;\n const avgbw = this.bwEstimator\n ? this.bwEstimator.getEstimate()\n : config.abrEwmaDefaultEstimate;\n // bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted.\n const bufferInfo = hls.mainForwardBufferInfo;\n const bufferStarvationDelay =\n (bufferInfo ? bufferInfo.len : 0) / playbackRate;\n\n // First, look to see if we can find a level matching with our avg bandwidth AND that could also guarantee no rebuffering at all\n let bestLevel = this.findBestLevel(\n avgbw,\n minAutoLevel,\n maxAutoLevel,\n bufferStarvationDelay,\n config.abrBandWidthFactor,\n config.abrBandWidthUpFactor\n );\n if (bestLevel >= 0) {\n return bestLevel;\n }\n logger.trace(\n `[abr] ${\n bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty'\n }, finding optimal quality level`\n );\n // not possible to get rid of rebuffering ... let's try to find level that will guarantee less than maxStarvationDelay of rebuffering\n // if no matching level found, logic will return 0\n let maxStarvationDelay = currentFragDuration\n ? Math.min(currentFragDuration, config.maxStarvationDelay)\n : config.maxStarvationDelay;\n let bwFactor = config.abrBandWidthFactor;\n let bwUpFactor = config.abrBandWidthUpFactor;\n\n if (!bufferStarvationDelay) {\n // in case buffer is empty, let's check if previous fragment was loaded to perform a bitrate test\n const bitrateTestDelay = this.bitrateTestDelay;\n if (bitrateTestDelay) {\n // if it is the case, then we need to adjust our max starvation delay using maxLoadingDelay config value\n // max video loading delay used in automatic start level selection :\n // in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level +\n // the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` )\n // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration\n const maxLoadingDelay = currentFragDuration\n ? Math.min(currentFragDuration, config.maxLoadingDelay)\n : config.maxLoadingDelay;\n maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;\n logger.trace(\n `[abr] bitrate test took ${Math.round(\n 1000 * bitrateTestDelay\n )}ms, set first fragment max fetchDuration to ${Math.round(\n 1000 * maxStarvationDelay\n )} ms`\n );\n // don't use conservative factor on bitrate test\n bwFactor = bwUpFactor = 1;\n }\n }\n bestLevel = this.findBestLevel(\n avgbw,\n minAutoLevel,\n maxAutoLevel,\n bufferStarvationDelay + maxStarvationDelay,\n bwFactor,\n bwUpFactor\n );\n return Math.max(bestLevel, 0);\n }\n\n private findBestLevel(\n currentBw: number,\n minAutoLevel: number,\n maxAutoLevel: number,\n maxFetchDuration: number,\n bwFactor: number,\n bwUpFactor: number\n ): number {\n const {\n fragCurrent,\n partCurrent,\n lastLoadedFragLevel: currentLevel,\n } = this;\n const { levels } = this.hls;\n const level = levels[currentLevel];\n const live = !!level?.details?.live;\n const currentCodecSet = level?.codecSet;\n\n const currentFragDuration = partCurrent\n ? partCurrent.duration\n : fragCurrent\n ? fragCurrent.duration\n : 0;\n\n const ttfbEstimateSec = this.bwEstimator.getEstimateTTFB() / 1000;\n let levelSkippedMin = minAutoLevel;\n let levelSkippedMax = -1;\n for (let i = maxAutoLevel; i >= minAutoLevel; i--) {\n const levelInfo = levels[i];\n\n if (\n !levelInfo ||\n (currentCodecSet && levelInfo.codecSet !== currentCodecSet)\n ) {\n if (levelInfo) {\n levelSkippedMin = Math.min(i, levelSkippedMin);\n levelSkippedMax = Math.max(i, levelSkippedMax);\n }\n continue;\n }\n if (levelSkippedMax !== -1) {\n logger.trace(\n `[abr] Skipped level(s) ${levelSkippedMin}-${levelSkippedMax} with CODECS:\"${levels[levelSkippedMax].attrs.CODECS}\"; not compatible with \"${level.attrs.CODECS}\"`\n );\n }\n\n const levelDetails = levelInfo.details;\n const avgDuration =\n (partCurrent\n ? levelDetails?.partTarget\n : levelDetails?.averagetargetduration) || currentFragDuration;\n\n let adjustedbw: number;\n // follow algorithm captured from stagefright :\n // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp\n // Pick the highest bandwidth stream below or equal to estimated bandwidth.\n // consider only 80% of the available bandwidth, but if we are switching up,\n // be even more conservative (70%) to avoid overestimating and immediately\n // switching back.\n if (i <= currentLevel) {\n adjustedbw = bwFactor * currentBw;\n } else {\n adjustedbw = bwUpFactor * currentBw;\n }\n\n const bitrate: number = levels[i].maxBitrate;\n const fetchDuration: number = this.getTimeToLoadFrag(\n ttfbEstimateSec,\n adjustedbw,\n bitrate * avgDuration,\n levelDetails === undefined\n );\n\n logger.trace(\n `[abr] level:${i} adjustedbw-bitrate:${Math.round(\n adjustedbw - bitrate\n )} avgDuration:${avgDuration.toFixed(\n 1\n )} maxFetchDuration:${maxFetchDuration.toFixed(\n 1\n )} fetchDuration:${fetchDuration.toFixed(1)}`\n );\n // if adjusted bw is greater than level bitrate AND\n if (\n adjustedbw > bitrate &&\n // fragment fetchDuration unknown OR live stream OR fragment fetchDuration less than max allowed fetch duration, then this level matches\n // we don't account for max Fetch Duration for live streams, this is to avoid switching down when near the edge of live sliding window ...\n // special case to support startLevel = -1 (bitrateTest) on live streams : in that case we should not exit loop so that findBestLevel will return -1\n (fetchDuration === 0 ||\n !Number.isFinite(fetchDuration) ||\n (live && !this.bitrateTestDelay) ||\n fetchDuration < maxFetchDuration)\n ) {\n // as we are looping from highest to lowest, this will return the best achievable quality level\n return i;\n }\n }\n // not enough time budget even with quality level 0 ... rebuffering might happen\n return -1;\n }\n\n set nextAutoLevel(nextLevel) {\n this._nextAutoLevel = nextLevel;\n }\n}\n\nexport default AbrController;\n","import { Events } from '../events';\nimport { logger } from '../utils/logger';\nimport type { ComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { MediaAttachingData } from '../types/events';\nimport StreamController from './stream-controller';\n\nclass FPSController implements ComponentAPI {\n private hls: Hls;\n private isVideoPlaybackQualityAvailable: boolean = false;\n private timer?: number;\n private media: HTMLVideoElement | null = null;\n private lastTime: any;\n private lastDroppedFrames: number = 0;\n private lastDecodedFrames: number = 0;\n // stream controller must be provided as a dependency!\n private streamController!: StreamController;\n\n constructor(hls: Hls) {\n this.hls = hls;\n\n this.registerListeners();\n }\n\n public setStreamController(streamController: StreamController) {\n this.streamController = streamController;\n }\n\n protected registerListeners() {\n this.hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n }\n\n protected unregisterListeners() {\n this.hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\n }\n\n destroy() {\n if (this.timer) {\n clearInterval(this.timer);\n }\n\n this.unregisterListeners();\n this.isVideoPlaybackQualityAvailable = false;\n this.media = null;\n }\n\n protected onMediaAttaching(\n event: Events.MEDIA_ATTACHING,\n data: MediaAttachingData\n ) {\n const config = this.hls.config;\n if (config.capLevelOnFPSDrop) {\n const media =\n data.media instanceof self.HTMLVideoElement ? data.media : null;\n this.media = media;\n if (media && typeof media.getVideoPlaybackQuality === 'function') {\n this.isVideoPlaybackQualityAvailable = true;\n }\n\n self.clearInterval(this.timer);\n this.timer = self.setInterval(\n this.checkFPSInterval.bind(this),\n config.fpsDroppedMonitoringPeriod\n );\n }\n }\n\n checkFPS(\n video: HTMLVideoElement,\n decodedFrames: number,\n droppedFrames: number\n ) {\n const currentTime = performance.now();\n if (decodedFrames) {\n if (this.lastTime) {\n const currentPeriod = currentTime - this.lastTime;\n const currentDropped = droppedFrames - this.lastDroppedFrames;\n const currentDecoded = decodedFrames - this.lastDecodedFrames;\n const droppedFPS = (1000 * currentDropped) / currentPeriod;\n const hls = this.hls;\n hls.trigger(Events.FPS_DROP, {\n currentDropped: currentDropped,\n currentDecoded: currentDecoded,\n totalDroppedFrames: droppedFrames,\n });\n if (droppedFPS > 0) {\n // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));\n if (\n currentDropped >\n hls.config.fpsDroppedMonitoringThreshold * currentDecoded\n ) {\n let currentLevel = hls.currentLevel;\n logger.warn(\n 'drop FPS ratio greater than max allowed value for currentLevel: ' +\n currentLevel\n );\n if (\n currentLevel > 0 &&\n (hls.autoLevelCapping === -1 ||\n hls.autoLevelCapping >= currentLevel)\n ) {\n currentLevel = currentLevel - 1;\n hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {\n level: currentLevel,\n droppedLevel: hls.currentLevel,\n });\n hls.autoLevelCapping = currentLevel;\n this.streamController.nextLevelSwitch();\n }\n }\n }\n }\n this.lastTime = currentTime;\n this.lastDroppedFrames = droppedFrames;\n this.lastDecodedFrames = decodedFrames;\n }\n }\n\n checkFPSInterval() {\n const video = this.media;\n if (video) {\n if (this.isVideoPlaybackQualityAvailable) {\n const videoPlaybackQuality = video.getVideoPlaybackQuality();\n this.checkFPS(\n video,\n videoPlaybackQuality.totalVideoFrames,\n videoPlaybackQuality.droppedVideoFrames\n );\n } else {\n // HTMLVideoElement doesn't include the webkit types\n this.checkFPS(\n video,\n (video as any).webkitDecodedFrameCount as number,\n (video as any).webkitDroppedFrameCount as number\n );\n }\n }\n }\n}\n\nexport default FPSController;\n","import BaseStreamController, { State } from './base-stream-controller';\nimport { Events } from '../events';\nimport { Bufferable, BufferHelper } from '../utils/buffer-helper';\nimport { FragmentState } from './fragment-tracker';\nimport { Level } from '../types/level';\nimport { PlaylistContextType, PlaylistLevelType } from '../types/loader';\nimport { Fragment, ElementaryStreamTypes, Part } from '../loader/fragment';\nimport ChunkCache from '../demux/chunk-cache';\nimport TransmuxerInterface from '../demux/transmuxer-interface';\nimport { ChunkMetadata } from '../types/transmuxer';\nimport { fragmentWithinToleranceTest } from './fragment-finders';\nimport { alignMediaPlaylistByPDT } from '../utils/discontinuities';\nimport { ErrorDetails } from '../errors';\nimport type { NetworkComponentAPI } from '../types/component-api';\nimport type Hls from '../hls';\nimport type { FragmentTracker } from './fragment-tracker';\nimport type KeyLoader from '../loader/key-loader';\nimport type { TransmuxerResult } from '../types/transmuxer';\nimport type { LevelDetails } from '../loader/level-details';\nimport type { TrackSet } from '../types/track';\nimport type {\n BufferCreatedData,\n AudioTracksUpdatedData,\n AudioTrackSwitchingData,\n LevelLoadedData,\n TrackLoadedData,\n BufferAppendingData,\n BufferFlushedData,\n InitPTSFoundData,\n FragLoadedData,\n FragParsingMetadataData,\n FragParsingUserdataData,\n FragBufferedData,\n ErrorData,\n} from '../types/events';\nimport type { MediaPlaylist } from '../types/media-playlist';\n\nconst TICK_INTERVAL = 100; // how often to tick in ms\n\ntype WaitingForPTSData = {\n frag: Fragment;\n part: Part | null;\n cache: ChunkCache;\n complete: boolean;\n};\n\nclass AudioStreamController\n extends BaseStreamController\n implements NetworkComponentAPI\n{\n private videoBuffer: Bufferable | null = null;\n private videoTrackCC: number = -1;\n private waitingVideoCC: number = -1;\n private bufferedTrack: MediaPlaylist | null = null;\n private switchingTrack: MediaPlaylist | null = null;\n private trackId: number = -1;\n private waitingData: WaitingForPTSData | null = null;\n private mainDetails: LevelDetails | null = null;\n private bufferFlushed: boolean = false;\n private cachedTrackLoadedData: TrackLoadedData | null = null;\n\n constructor(\n hls: Hls,\n fragmentTracker: FragmentTracker,\n keyLoader: KeyLoader\n ) {\n super(\n hls,\n fragmentTracker,\n keyLoader,\n '[audio-stream-controller]',\n PlaylistLevelType.AUDIO\n );\n this._registerListeners();\n }\n\n protected onHandlerDestroying() {\n this._unregisterListeners();\n this.mainDetails = null;\n this.bufferedTrack = null;\n this.switchingTrack = null;\n }\n\n private _registerListeners() {\n const { hls } = this;\n hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);\n hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n hls.on(Events.ERROR, this.onError, this);\n hls.on(Events.BUFFER_RESET, this.onBufferReset, this);\n hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);\n hls.on(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n private _unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);\n hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);\n hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);\n hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n hls.off(Events.ERROR, this.onError, this);\n hls.off(Events.BUFFER_RESET, this.onBufferReset, this);\n hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);\n hls.off(Events.BUFFER_FLUSHED, this.onBufferFlushed, this);\n hls.off(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);\n hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);\n }\n\n // INIT_PTS_FOUND is triggered when the video track parsed in the stream-controller has a new PTS value\n onInitPtsFound(\n event: Events.INIT_PTS_FOUND,\n { frag, id, initPTS, timescale }: InitPTSFoundData\n ) {\n // Always update the new INIT PTS\n // Can change due level switch\n if (id === 'main') {\n const cc = frag.cc;\n this.initPTS[frag.cc] = { baseTime: initPTS, timescale };\n this.log(`InitPTS for cc: ${cc} found from main: ${initPTS}`);\n this.videoTrackCC = cc;\n // If we are waiting, tick immediately to unblock audio fragment transmuxing\n if (this.state === State.WAITING_INIT_PTS) {\n this.tick();\n }\n }\n }\n\n startLoad(startPosition: number) {\n if (!this.levels) {\n this.startPosition = startPosition;\n this.state = State.STOPPED;\n return;\n }\n const lastCurrentTime = this.lastCurrentTime;\n this.stopLoad();\n this.setInterval(TICK_INTERVAL);\n if (lastCurrentTime > 0 && startPosition === -1) {\n this.log(\n `Override startPosition with lastCurrentTime @${lastCurrentTime.toFixed(\n 3\n )}`\n );\n startPosition = lastCurrentTime;\n this.state = State.IDLE;\n } else {\n this.loadedmetadata = false;\n this.state = State.WAITING_TRACK;\n }\n this.nextLoadPosition =\n this.startPosition =\n this.lastCurrentTime =\n startPosition;\n\n this.tick();\n }\n\n doTick() {\n switch (this.state) {\n case State.IDLE:\n this.doTickIdle();\n break;\n case State.WAITING_TRACK: {\n const { levels, trackId } = this;\n const details = levels?.[trackId]?.details;\n if (details) {\n if (this.waitForCdnTuneIn(details)) {\n break;\n }\n this.state = State.WAITING_INIT_PTS;\n }\n break;\n }\n case State.FRAG_LOADING_WAITING_RETRY: {\n const now = performance.now();\n const retryDate = this.retryDate;\n // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading\n if (!retryDate || now >= retryDate || this.media?.seeking) {\n this.log('RetryDate reached, switch back to IDLE state');\n this.resetStartWhenNotLoaded(this.trackId);\n this.state = State.IDLE;\n }\n break;\n }\n case State.WAITING_INIT_PTS: {\n // Ensure we don't get stuck in the WAITING_INIT_PTS state if the waiting frag CC doesn't match any initPTS\n const waitingData = this.waitingData;\n if (waitingData) {\n const { frag, part, cache, complete } = waitingData;\n if (this.initPTS[frag.cc] !== undefined) {\n this.waitingData = null;\n this.waitingVideoCC = -1;\n this.state = State.FRAG_LOADING;\n const payload = cache.flush();\n const data: FragLoadedData = {\n frag,\n part,\n payload,\n networkDetails: null,\n };\n this._handleFragmentLoadProgress(data);\n if (complete) {\n super._handleFragmentLoadComplete(data);\n }\n } else if (this.videoTrackCC !== this.waitingVideoCC) {\n // Drop waiting fragment if videoTrackCC has changed since waitingFragment was set and initPTS was not found\n this.log(\n `Waiting fragment cc (${frag.cc}) cancelled because video is at cc ${this.videoTrackCC}`\n );\n this.clearWaitingFragment();\n } else {\n // Drop waiting fragment if an earlier fragment is needed\n const pos = this.getLoadPosition();\n const bufferInfo = BufferHelper.bufferInfo(\n this.mediaBuffer,\n pos,\n this.config.maxBufferHole\n );\n const waitingFragmentAtPosition = fragmentWithinToleranceTest(\n bufferInfo.end,\n this.config.maxFragLookUpTolerance,\n frag\n );\n if (waitingFragmentAtPosition < 0) {\n this.log(\n `Waiting fragment cc (${frag.cc}) @ ${frag.start} cancelled because another fragment at ${bufferInfo.end} is needed`\n );\n this.clearWaitingFragment();\n }\n }\n } else {\n this.state = State.IDLE;\n }\n }\n }\n\n this.onTickEnd();\n }\n\n clearWaitingFragment() {\n const waitingData = this.waitingData;\n if (waitingData) {\n this.fragmentTracker.removeFragment(waitingData.frag);\n this.waitingData = null;\n this.waitingVideoCC = -1;\n this.state = State.IDLE;\n }\n }\n\n protected resetLoadingState() {\n this.clearWaitingFragment();\n super.resetLoadingState();\n }\n\n protected onTickEnd() {\n const { media } = this;\n if (!media?.readyState) {\n // Exit early if we don't have media or if the media hasn't buffered anything yet (readyState 0)\n return;\n }\n\n this.lastCurrentTime = media.currentTime;\n }\n\n private doTickIdle() {\n const { hls, levels, media, trackId } = this;\n const config = hls.config;\n\n if (!levels?.[trackId]) {\n return;\n }\n\n // if video not attached AND\n // start fragment already requested OR start frag prefetch not enabled\n // exit loop\n // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop\n if (!media && (this.startFragRequested || !config.startFragPrefetch)) {\n return;\n }\n\n const levelInfo = levels[trackId];\n\n const trackDetails = levelInfo.details;\n if (\n !trackDetails ||\n (trackDetails.live && this.levelLastLoaded !== trackId) ||\n this.waitForCdnTuneIn(trackDetails)\n ) {\n this.state = State.WAITING_TRACK;\n return;\n }\n\n const bufferable = this.mediaBuffer ? this.mediaBuffer : this.media;\n if (this.bufferFlushed && bufferable) {\n this.bufferFlushed = false;\n this.afterBufferFlushed(\n bufferable,\n ElementaryStreamTypes.AUDIO,\n PlaylistLevelType.AUDIO\n );\n }\n\n const bufferInfo = this.getFwdBufferInfo(\n bufferable,\n PlaylistLevelType.AUDIO\n );\n if (bufferInfo === null) {\n return;\n }\n const { bufferedTrack, switchingTrack } = this;\n\n if (!switchingTrack && this._streamEnded(bufferInfo, trackDetails)) {\n hls.trigger(Events.BUFFER_EOS, { type: 'audio' });\n this.state = State.ENDED;\n return;\n }\n\n const mainBufferInfo = this.getFwdBufferInfo(\n this.videoBuffer ? this.videoBuffer : this.media,\n PlaylistLevelType.MAIN\n );\n const bufferLen = bufferInfo.len;\n const maxBufLen = this.getMaxBufferLength(mainBufferInfo?.len);\n\n // if buffer length is less than maxBufLen try to load a new fragment\n if (bufferLen >= maxBufLen && !switchingTrack) {\n return;\n }\n const fragments = trackDetails.fragments;\n const start = fragments[0].start;\n let targetBufferTime = bufferInfo.end;\n\n if (switchingTrack && media) {\n const pos = this.getLoadPosition();\n if (bufferedTrack && switchingTrack.attrs !== bufferedTrack.attrs) {\n targetBufferTime = pos;\n }\n // if currentTime (pos) is less than alt audio playlist start time, it means that alt audio is ahead of currentTime\n if (trackDetails.PTSKnown && pos < start) {\n // if everything is buffered from pos to start or if audio buffer upfront, let's seek to start\n if (bufferInfo.end > start || bufferInfo.nextStart) {\n this.log(\n 'Alt audio track ahead of main track, seek to start of alt audio track'\n );\n media.currentTime = start + 0.05;\n }\n }\n }\n\n let frag = this.getNextFragment(targetBufferTime, trackDetails);\n let atGap = false;\n // Avoid loop loading by using nextLoadPosition set for backtracking and skipping consecutive GAP tags\n if (frag && this.isLoopLoading(frag, targetBufferTime)) {\n atGap = !!frag.gap;\n frag = this.getNextFragmentLoopLoading(\n frag,\n trackDetails,\n bufferInfo,\n PlaylistLevelType.MAIN,\n maxBufLen\n );\n }\n if (!frag) {\n this.bufferFlushed = true;\n return;\n }\n\n // Buffer audio up to one target duration ahead of main buffer\n const atBufferSyncLimit =\n mainBufferInfo &&\n frag.start > mainBufferInfo.end + trackDetails.targetduration;\n if (\n atBufferSyncLimit ||\n // Or wait for main buffer after buffing some audio\n (!mainBufferInfo?.len && bufferInfo.len)\n ) {\n // Check fragment-tracker for main fragments since GAP segments do not show up in bufferInfo\n const mainFrag = this.getAppendedFrag(frag.start, PlaylistLevelType.MAIN);\n if (mainFrag === null) {\n return;\n }\n // Bridge gaps in main buffer\n atGap ||=\n !!mainFrag.gap || (!!atBufferSyncLimit && mainBufferInfo.len === 0);\n if (\n (atBufferSyncLimit && !atGap) ||\n (atGap && bufferInfo.nextStart && bufferInfo.nextStart < mainFrag.end)\n ) {\n return;\n }\n }\n\n this.loadFragment(frag, levelInfo, targetBufferTime);\n }\n\n protected getMaxBufferLength(mainBufferLength?: number): number {\n const maxConfigBuffer = super.getMaxBufferLength();\n if (!mainBufferLength) {\n return maxConfigBuffer;\n }\n return Math.min(\n Math.max(maxConfigBuffer, mainBufferLength),\n this.config.maxMaxBufferLength\n );\n }\n\n onMediaDetaching() {\n this.videoBuffer = null;\n super.onMediaDetaching();\n }\n\n onAudioTracksUpdated(\n event: Events.AUDIO_TRACKS_UPDATED,\n { audioTracks }: AudioTracksUpdatedData\n ) {\n this.resetTransmuxer();\n this.levels = audioTracks.map((mediaPlaylist) => new Level(mediaPlaylist));\n }\n\n onAudioTrackSwitching(\n event: Events.AUDIO_TRACK_SWITCHING,\n data: AudioTrackSwitchingData\n ) {\n // if any URL found on new audio track, it is an alternate audio track\n const altAudio = !!data.url;\n this.trackId = data.id;\n const { fragCurrent } = this;\n\n if (fragCurrent) {\n fragCurrent.abortRequests();\n this.removeUnbufferedFrags(fragCurrent.start);\n }\n this.resetLoadingState();\n // destroy useless transmuxer when switching audio to main\n if (!altAudio) {\n this.resetTransmuxer();\n } else {\n // switching to audio track, start timer if not already started\n this.setInterval(TICK_INTERVAL);\n }\n\n // should we switch tracks ?\n if (altAudio) {\n this.switchingTrack = data;\n // main audio track are handled by stream-controller, just do something if switching to alt audio track\n this.state = State.IDLE;\n } else {\n this.switchingTrack = null;\n this.bufferedTrack = data;\n this.state = State.STOPPED;\n }\n this.tick();\n }\n\n onManifestLoading() {\n this.fragmentTracker.removeAllFragments();\n this.startPosition = this.lastCurrentTime = 0;\n this.bufferFlushed = false;\n this.levels =\n this.mainDetails =\n this.waitingData =\n this.bufferedTrack =\n this.cachedTrackLoadedData =\n this.switchingTrack =\n null;\n this.startFragRequested = false;\n this.trackId = this.videoTrackCC = this.waitingVideoCC = -1;\n }\n\n onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) {\n this.mainDetails = data.details;\n if (this.cachedTrackLoadedData !== null) {\n this.hls.trigger(Events.AUDIO_TRACK_LOADED, this.cachedTrackLoadedData);\n this.cachedTrackLoadedData = null;\n }\n }\n\n onAudioTrackLoaded(event: Events.AUDIO_TRACK_LOADED, data: TrackLoadedData) {\n if (this.mainDetails == null) {\n this.cachedTrackLoadedData = data;\n return;\n }\n const { levels } = this;\n const { details: newDetails, id: trackId } = data;\n if (!levels) {\n this.warn(`Audio tracks were reset while loading level ${trackId}`);\n return;\n }\n this.log(\n `Track ${trackId} loaded [${newDetails.startSN},${newDetails.endSN}]${\n newDetails.lastPartSn\n ? `[part-${newDetails.lastPartSn}-${newDetails.lastPartIndex}]`\n : ''\n },duration:${newDetails.totalduration}`\n );\n\n const track = levels[trackId];\n let sliding = 0;\n if (newDetails.live || track.details?.live) {\n const mainDetails = this.mainDetails;\n if (!newDetails.fragments[0]) {\n newDetails.deltaUpdateFailed = true;\n }\n if (newDetails.deltaUpdateFailed || !mainDetails) {\n return;\n }\n if (\n !track.details &&\n newDetails.hasProgramDateTime &&\n mainDetails.hasProgramDateTime\n ) {\n // Make sure our audio rendition is aligned with the \"main\" rendition, using\n // pdt as our reference times.\n alignMediaPlaylistByPDT(newDetails, mainDetails);\n sliding = newDetails.fragments[0].start;\n } else {\n sliding = this.alignPlaylists(newDetails, track.details);\n }\n }\n track.details = newDetails;\n this.levelLastLoaded = trackId;\n\n // compute start position if we are aligned with the main playlist\n if (!this.startFragRequested && (this.mainDetails || !newDetails.live)) {\n this.setStartPosition(track.details, sliding);\n }\n // only switch back to IDLE state if we were waiting for track to start downloading a new fragment\n if (\n this.state === State.WAITING_TRACK &&\n !this.waitForCdnTuneIn(newDetails)\n ) {\n this.state = State.IDLE;\n }\n\n // trigger handler right now\n this.tick();\n }\n\n _handleFragmentLoadProgress(data: FragLoadedData) {\n const { frag, part, payload } = data;\n const { config, trackId, levels } = this;\n if (!levels) {\n this.warn(\n `Audio tracks were reset while fragment load was in progress. Fragment ${frag.sn} of level ${frag.level} will not be buffered`\n );\n return;\n }\n\n const track = levels[trackId] as Level;\n if (!track) {\n this.warn('Audio track is undefined on fragment load progress');\n return;\n }\n const details = track.details as LevelDetails;\n if (!details) {\n this.warn('Audio track details undefined on fragment load progress');\n this.removeUnbufferedFrags(frag.start);\n return;\n }\n const audioCodec =\n config.defaultAudioCodec || track.audioCodec || 'mp4a.40.2';\n\n let transmuxer = this.transmuxer;\n if (!transmuxer) {\n transmuxer = this.transmuxer = new TransmuxerInterface(\n this.hls,\n PlaylistLevelType.AUDIO,\n this._handleTransmuxComplete.bind(this),\n this._handleTransmuxerFlush.bind(this)\n );\n }\n\n // Check if we have video initPTS\n // If not we need to wait for it\n const initPTS = this.initPTS[frag.cc];\n const initSegmentData = frag.initSegment?.data;\n if (initPTS !== undefined) {\n // this.log(`Transmuxing ${sn} of [${details.startSN} ,${details.endSN}],track ${trackId}`);\n // time Offset is accurate if level PTS is known, or if playlist is not sliding (not live)\n const accurateTimeOffset = false; // details.PTSKnown || !details.live;\n const partIndex = part ? part.index : -1;\n const partial = partIndex !== -1;\n const chunkMeta = new ChunkMetadata(\n frag.level,\n frag.sn as number,\n frag.stats.chunkCount,\n payload.byteLength,\n partIndex,\n partial\n );\n transmuxer.push(\n payload,\n initSegmentData,\n audioCodec,\n '',\n frag,\n part,\n details.totalduration,\n accurateTimeOffset,\n chunkMeta,\n initPTS\n );\n } else {\n this.log(\n `Unknown video PTS for cc ${frag.cc}, waiting for video PTS before demuxing audio frag ${frag.sn} of [${details.startSN} ,${details.endSN}],track ${trackId}`\n );\n const { cache } = (this.waitingData = this.waitingData || {\n frag,\n part,\n cache: new ChunkCache(),\n complete: false,\n });\n cache.push(new Uint8Array(payload));\n this.waitingVideoCC = this.videoTrackCC;\n this.state = State.WAITING_INIT_PTS;\n }\n }\n\n protected _handleFragmentLoadComplete(fragLoadedData: FragLoadedData) {\n if (this.waitingData) {\n this.waitingData.complete = true;\n return;\n }\n super._handleFragmentLoadComplete(fragLoadedData);\n }\n\n onBufferReset(/* event: Events.BUFFER_RESET */) {\n // reset reference to sourcebuffers\n this.mediaBuffer = this.videoBuffer = null;\n this.loadedmetadata = false;\n }\n\n onBufferCreated(event: Events.BUFFER_CREATED, data: BufferCreatedData) {\n const audioTrack = data.tracks.audio;\n if (audioTrack) {\n this.mediaBuffer = audioTrack.buffer || null;\n }\n if (data.tracks.video) {\n this.videoBuffer = data.tracks.video.buffer || null;\n }\n }\n\n onFragBuffered(event: Events.FRAG_BUFFERED, data: FragBufferedData) {\n const { frag, part } = data;\n if (frag.type !== PlaylistLevelType.AUDIO) {\n if (!this.loadedmetadata && frag.type === PlaylistLevelType.MAIN) {\n const bufferable = this.videoBuffer || this.media;\n if (bufferable) {\n const bufferedTimeRanges = BufferHelper.getBuffered(bufferable);\n if (bufferedTimeRanges.length) {\n this.loadedmetadata = true;\n }\n }\n }\n return;\n }\n if (this.fragContextChanged(frag)) {\n // If a level switch was requested while a fragment was buffering, it will emit the FRAG_BUFFERED event upon completion\n // Avoid setting state back to IDLE or concluding the audio switch; otherwise, the switched-to track will not buffer\n this.warn(\n `Fragment ${frag.sn}${part ? ' p: ' + part.index : ''} of level ${\n frag.level\n } finished buffering, but was aborted. state: ${\n this.state\n }, audioSwitch: ${\n this.switchingTrack ? this.switchingTrack.name : 'false'\n }`\n );\n return;\n }\n if (frag.sn !== 'initSegment') {\n this.fragPrevious = frag;\n const track = this.switchingTrack;\n if (track) {\n this.bufferedTrack = track;\n this.switchingTrack = null;\n this.hls.trigger(Events.AUDIO_TRACK_SWITCHED, { ...track });\n }\n }\n this.fragBufferedComplete(frag, part);\n }\n\n private onError(event: Events.ERROR, data: ErrorData) {\n if (data.fatal) {\n this.state = State.ERROR;\n return;\n }\n switch (data.details) {\n case ErrorDetails.FRAG_GAP:\n case ErrorDetails.FRAG_PARSING_ERROR:\n case ErrorDetails.FRAG_DECRYPT_ERROR:\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n case ErrorDetails.KEY_LOAD_ERROR:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n this.onFragmentOrKeyLoadError(PlaylistLevelType.AUDIO, data);\n break;\n case ErrorDetails.AUDIO_TRACK_LOAD_ERROR:\n case ErrorDetails.AUDIO_TRACK_LOAD_TIMEOUT:\n case ErrorDetails.LEVEL_PARSING_ERROR:\n // in case of non fatal error while loading track, if not retrying to load track, switch back to IDLE\n if (\n !data.levelRetry &&\n this.state === State.WAITING_TRACK &&\n data.context?.type === PlaylistContextType.AUDIO_TRACK\n ) {\n this.state = State.IDLE;\n }\n break;\n case ErrorDetails.BUFFER_FULL_ERROR:\n if (!data.parent || data.parent !== 'audio') {\n return;\n }\n if (this.reduceLengthAndFlushBuffer(data)) {\n this.bufferedTrack = null;\n super.flushMainBuffer(0, Number.POSITIVE_INFINITY, 'audio');\n }\n break;\n case ErrorDetails.INTERNAL_EXCEPTION:\n this.recoverWorkerError(data);\n break;\n default:\n break;\n }\n }\n\n private onBufferFlushed(\n event: Events.BUFFER_FLUSHED,\n { type }: BufferFlushedData\n ) {\n if (type === ElementaryStreamTypes.AUDIO) {\n this.bufferFlushed = true;\n if (this.state === State.ENDED) {\n this.state = State.IDLE;\n }\n }\n }\n\n private _handleTransmuxComplete(transmuxResult: TransmuxerResult) {\n const id = 'audio';\n const { hls } = this;\n const { remuxResult, chunkMeta } = transmuxResult;\n\n const context = this.getCurrentContext(chunkMeta);\n if (!context) {\n this.resetWhenMissingContext(chunkMeta);\n return;\n }\n const { frag, part, level } = context;\n const { details } = level;\n const { audio, text, id3, initSegment } = remuxResult;\n\n // Check if the current fragment has been aborted. We check this by first seeing if we're still playing the current level.\n // If we are, subsequently check if the currently loading fragment (fragCurrent) has changed.\n if (this.fragContextChanged(frag) || !details) {\n this.fragmentTracker.removeFragment(frag);\n return;\n }\n\n this.state = State.PARSING;\n if (this.switchingTrack && audio) {\n this.completeAudioSwitch(this.switchingTrack);\n }\n\n if (initSegment?.tracks) {\n const mapFragment = frag.initSegment || frag;\n this._bufferInitSegment(initSegment.tracks, mapFragment, chunkMeta);\n hls.trigger(Events.FRAG_PARSING_INIT_SEGMENT, {\n frag: mapFragment,\n id,\n tracks: initSegment.tracks,\n });\n // Only flush audio from old audio tracks when PTS is known on new audio track\n }\n if (audio) {\n const { startPTS, endPTS, startDTS, endDTS } = audio;\n if (part) {\n part.elementaryStreams[ElementaryStreamTypes.AUDIO] = {\n startPTS,\n endPTS,\n startDTS,\n endDTS,\n };\n }\n frag.setElementaryStreamInfo(\n ElementaryStreamTypes.AUDIO,\n startPTS,\n endPTS,\n startDTS,\n endDTS\n );\n this.bufferFragmentData(audio, frag, part, chunkMeta);\n }\n\n if (id3?.samples?.length) {\n const emittedID3: FragParsingMetadataData = Object.assign(\n {\n id,\n frag,\n details,\n },\n id3\n );\n hls.trigger(Events.FRAG_PARSING_METADATA, emittedID3);\n }\n if (text) {\n const emittedText: FragParsingUserdataData = Object.assign(\n {\n id,\n frag,\n details,\n },\n text\n );\n hls.trigger(Events.FRAG_PARSING_USERDATA, emittedText);\n }\n }\n\n private _bufferInitSegment(\n tracks: TrackSet,\n frag: Fragment,\n chunkMeta: ChunkMetadata\n ) {\n if (this.state !== State.PARSING) {\n return;\n }\n // delete any video track found on audio transmuxer\n if (tracks.video) {\n delete tracks.video;\n }\n\n // include levelCodec in audio and video tracks\n const track = tracks.audio;\n if (!track) {\n return;\n }\n\n track.levelCodec = track.codec;\n track.id = 'audio';\n this.log(\n `Init audio buffer, container:${track.container}, codecs[parsed]=[${track.codec}]`\n );\n this.hls.trigger(Events.BUFFER_CODECS, tracks);\n const initSegment = track.initSegment;\n if (initSegment?.byteLength) {\n const segment: BufferAppendingData = {\n type: 'audio',\n frag,\n part: null,\n chunkMeta,\n parent: frag.type,\n data: initSegment,\n };\n this.hls.trigger(Events.BUFFER_APPENDING, segment);\n }\n // trigger handler right now\n this.tick();\n }\n\n protected loadFragment(\n frag: Fragment,\n track: Level,\n targetBufferTime: number\n ) {\n // only load if fragment is not loaded or if in audio switch\n const fragState = this.fragmentTracker.getState(frag);\n this.fragCurrent = frag;\n\n // we force a frag loading in audio switch as fragment tracker might not have evicted previous frags in case of quick audio switch\n if (\n this.switchingTrack ||\n fragState === FragmentState.NOT_LOADED ||\n fragState === FragmentState.PARTIAL\n ) {\n if (frag.sn === 'initSegment') {\n this._loadInitSegment(frag, track);\n } else if (track.details?.live && !this.initPTS[frag.cc]) {\n this.log(\n `Waiting for video PTS in continuity counter ${frag.cc} of live stream before loading audio fragment ${frag.sn} of level ${this.trackId}`\n );\n this.state = State.WAITING_INIT_PTS;\n } else {\n this.startFragRequested = true;\n super.loadFragment(frag, track, targetBufferTime);\n }\n } else {\n this.clearTrackerIfNeeded(frag);\n }\n }\n\n private completeAudioSwitch(switchingTrack: MediaPlaylist) {\n const { hls, media, bufferedTrack } = this;\n const bufferedAttributes = bufferedTrack?.attrs;\n const switchAttributes = switchingTrack.attrs;\n if (\n media &&\n bufferedAttributes &&\n (bufferedAttributes.CHANNELS !== switchAttributes.CHANNELS ||\n bufferedAttributes.NAME !== switchAttributes.NAME ||\n bufferedAttributes.LANGUAGE !== switchAttributes.LANGUAGE)\n ) {\n this.log('Switching audio track : flushing all audio');\n super.flushMainBuffer(0, Number.POSITIVE_INFINITY, 'audio');\n }\n this.bufferedTrack = switchingTrack;\n this.switchingTrack = null;\n hls.trigger(Events.AUDIO_TRACK_SWITCHED, { ...switchingTrack });\n }\n}\nexport default AudioStreamController;\n","import { Events } from '../events';\nimport { ErrorTypes, ErrorDetails } from '../errors';\nimport {\n ManifestParsedData,\n AudioTracksUpdatedData,\n ErrorData,\n LevelLoadingData,\n AudioTrackLoadedData,\n LevelSwitchingData,\n} from '../types/events';\nimport BasePlaylistController from './base-playlist-controller';\nimport { PlaylistContextType } from '../types/loader';\nimport type Hls from '../hls';\nimport type { HlsUrlParameters } from '../types/level';\nimport type { MediaPlaylist } from '../types/media-playlist';\n\nclass AudioTrackController extends BasePlaylistController {\n private tracks: MediaPlaylist[] = [];\n private groupId: string | null = null;\n private tracksInGroup: MediaPlaylist[] = [];\n private trackId: number = -1;\n private currentTrack: MediaPlaylist | null = null;\n private selectDefaultTrack: boolean = true;\n\n constructor(hls: Hls) {\n super(hls, '[audio-track-controller]');\n this.registerListeners();\n }\n\n private registerListeners() {\n const { hls } = this;\n hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.on(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n hls.on(Events.ERROR, this.onError, this);\n }\n\n private unregisterListeners() {\n const { hls } = this;\n hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\n hls.off(Events.LEVEL_LOADING, this.onLevelLoading, this);\n hls.off(Events.LEVEL_SWITCHING, this.onLevelSwitching, this);\n hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);\n hls.off(Events.ERROR, this.onError, this);\n }\n\n public destroy() {\n this.unregisterListeners();\n this.tracks.length = 0;\n this.tracksInGroup.length = 0;\n this.currentTrack = null;\n super.destroy();\n }\n\n protected onManifestLoading(): void {\n this.tracks = [];\n this.groupId = null;\n this.tracksInGroup = [];\n this.trackId = -1;\n this.currentTrack = null;\n this.selectDefaultTrack = true;\n }\n\n protected onManifestParsed(\n event: Events.MANIFEST_PARSED,\n data: ManifestParsedData\n ): void {\n this.tracks = data.audioTracks || [];\n }\n\n protected onAudioTrackLoaded(\n event: Events.AUDIO_TRACK_LOADED,\n data: AudioTrackLoadedData\n ): void {\n const { id, groupId, details } = data;\n const trackInActiveGroup = this.tracksInGroup[id];\n\n if (!trackInActiveGroup || trackInActiveGroup.groupId !== groupId) {\n this.warn(\n `Track with id:${id} and group:${groupId} not found in active group ${trackInActiveGroup.groupId}`\n );\n return;\n }\n\n const curDetails = trackInActiveGroup.details;\n trackInActiveGroup.details = data.details;\n this.log(\n `audio-track ${id} \"${trackInActiveGroup.name}\" lang:${trackInActiveGroup.lang} group:${groupId} loaded [${details.startSN}-${details.endSN}]`\n );\n\n if (id === this.trackId) {\n this.playlistLoaded(id, data, curDetails);\n }\n }\n\n protected onLevelLoading(\n event: Events.LEVEL_LOADING,\n data: LevelLoadingData\n ): void {\n this.switchLevel(data.level);\n }\n\n protected onLevelSwitching(\n event: Events.LEVEL_SWITCHING,\n data: LevelSwitchingData\n ): void {\n this.switchLevel(data.level);\n }\n\n private switchLevel(levelIndex: number) {\n const levelInfo = this.hls.levels[levelIndex];\n\n if (!levelInfo?.audioGroupIds) {\n return;\n }\n\n const audioGroupId = levelInfo.audioGroupIds[levelInfo.urlId];\n if (this.groupId !== audioGroupId) {\n this.groupId = audioGroupId || null;\n\n const audioTracks = this.tracks.filter(\n (track): boolean => !audioGroupId || track.groupId === audioGroupId\n );\n\n // Disable selectDefaultTrack if there are no default tracks\n if (\n this.selectDefaultTrack &&\n !audioTracks.some((track) => track.default)\n ) {\n this.selectDefaultTrack = false;\n }\n\n this.tracksInGroup = audioTracks;\n const audioTracksUpdated: AudioTracksUpdatedData = { audioTracks };\n this.log(\n `Updating audio tracks, ${audioTracks.length} track(s) found in group:${audioGroupId}`\n );\n this.hls.trigger(Events.AUDIO_TRACKS_UPDATED, audioTracksUpdated);\n\n this.selectInitialTrack();\n } else if (this.shouldReloadPlaylist(this.currentTrack)) {\n // Retry playlist loading if no playlist is or has been loaded yet\n this.setAudioTrack(this.trackId);\n }\n }\n\n protected onError(event: Events.ERROR, data: ErrorData): void {\n if (data.fatal || !data.context) {\n return;\n }\n\n if (\n data.context.type === PlaylistContextType.AUDIO_TRACK &&\n data.context.id === this.trackId &&\n data.context.groupId === this.groupId\n ) {\n this.requestScheduled = -1;\n this.checkRetry(data);\n }\n }\n\n get audioTracks(): MediaPlaylist[] {\n return this.tracksInGroup;\n }\n\n get audioTrack(): number {\n return this.trackId;\n }\n\n set audioTrack(newId: number) {\n // If audio track is selected from API then don't choose from the manifest default track\n this.selectDefaultTrack = false;\n this.setAudioTrack(newId);\n }\n\n private setAudioTrack(newId: number): void {\n const tracks = this.tracksInGroup;\n\n // check if level idx is valid\n if (newId < 0 || newId >= tracks.length) {\n this.warn('Invalid id passed to audio-track controller');\n return;\n }\n\n // stopping live reloading timer if any\n this.clearTimer();\n\n const lastTrack = this.currentTrack;\n tracks[this.trackId];\n const track = tracks[newId];\n const { groupId, name } = track;\n this.log(\n `Switching to audio-track ${newId} \"${name}\" lang:${track.lang} group:${groupId}`\n );\n this.trackId = newId;\n this.currentTrack = track;\n this.selectDefaultTrack = false;\n this.hls.trigger(Events.AUDIO_TRACK_SWITCHING, { ...track });\n // Do not reload track unless live\n if (track.details && !track.details.live) {\n return;\n }\n const hlsUrlParameters = this.switchParams(track.url, lastTrack?.details);\n this.loadPlaylist(hlsUrlParameters);\n }\n\n private selectInitialTrack(): void {\n const audioTracks = this.tracksInGroup;\n const trackId =\n this.findTrackId(this.currentTrack) | this.findTrackId(null);\n\n if (trackId !== -1) {\n this.setAudioTrack(trackId);\n } else {\n const error = new Error(\n `No track found for running audio group-ID: ${this.groupId} track count: ${audioTracks.length}`\n );\n this.warn(error.message);\n\n this.hls.trigger(Events.ERROR, {\n type: ErrorTypes.MEDIA_ERROR,\n details: ErrorDetails.AUDIO_TRACK_LOAD_ERROR,\n fatal: true,\n error,\n });\n }\n }\n\n private findTrackId(currentTrack: MediaPlaylist | null): number {\n const audioTracks = this.tracksInGroup;\n for (let i = 0; i < audioTracks.length; i++) {\n const track = audioTracks[i];\n if (!this.selectDefaultTrack || track.default) {\n if (\n !currentTrack ||\n (currentTrack.attrs['STABLE-RENDITION-ID'] !== undefined &&\n currentTrack.attrs['STABLE-RENDITION-ID'] ===\n track.attrs['STABLE-RENDITION-ID'])\n ) {\n return track.id;\n }\n if (\n currentTrack.name === track.name &&\n currentTrack.lang === track.lang\n ) {\n return track.id;\n }\n }\n }\n return -1;\n }\n\n protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void {\n super.loadPlaylist();\n const audioTrack = this.tracksInGroup[this.trackId];\n if (this.shouldLoadPlaylist(audioTrack)) {\n const id = audioTrack.id;\n const groupId = audioTrack.groupId as string;\n let url = audioTrack.url;\n if (hlsUrlParameters) {\n try {\n url = hlsUrlParameters.addDirectives(url);\n } catch (error) {\n this.warn(\n `Could not construct new URL with HLS Delivery Directives: ${error}`\n );\n }\n }\n // track not retrieved yet, or live playlist we need to (re)load it\n this.log(\n `loading audio-track playlist ${id} \"${audioTrack.name}\" lang:${audioTrack.lang} group:${groupId}`\n );\n this.clearTimer();\n this.hls.trigger(Events.AUDIO_TRACK_LOADING, {\n url,\n id,\n groupId,\n deliveryDirectives: hlsUrlParameters || null,\n });\n }\n }\n}\n\nexport default AudioTrackController;\n","import { buildAbsoluteURL } from 'url-toolkit';\nimport PlaylistLoader from './loader/playlist-loader';\nimport ID3TrackController from './controller/id3-track-controller';\nimport LatencyController from './controller/latency-controller';\nimport LevelController from './controller/level-controller';\nimport { FragmentTracker } from './controller/fragment-tracker';\nimport KeyLoader from './loader/key-loader';\nimport StreamController from './controller/stream-controller';\nimport { isSupported } from './is-supported';\nimport { logger, enableLogs } from './utils/logger';\nimport { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';\nimport { EventEmitter } from 'eventemitter3';\nimport { Events } from './events';\nimport { ErrorTypes, ErrorDetails } from './errors';\nimport { HdcpLevels } from './types/level';\nimport type { HlsEventEmitter, HlsListeners } from './events';\nimport type AudioTrackController from './controller/audio-track-controller';\nimport type AbrController from './controller/abr-controller';\nimport type BufferController from './controller/buffer-controller';\nimport type CapLevelController from './controller/cap-level-controller';\nimport type CMCDController from './controller/cmcd-controller';\nimport type EMEController from './controller/eme-controller';\nimport type SubtitleTrackController from './controller/subtitle-track-controller';\nimport type { ComponentAPI, NetworkComponentAPI } from './types/component-api';\nimport type { MediaPlaylist } from './types/media-playlist';\nimport type { HlsConfig } from './config';\nimport type { HdcpLevel, Level } from './types/level';\nimport type { BufferInfo } from './utils/buffer-helper';\nimport type AudioStreamController from './controller/audio-stream-controller';\nimport type BasePlaylistController from './controller/base-playlist-controller';\nimport type BaseStreamController from './controller/base-stream-controller';\nimport type ContentSteeringController from './controller/content-steering-controller';\nimport type ErrorController from './controller/error-controller';\nimport type FPSController from './controller/fps-controller';\n\n/**\n * The `Hls` class is the core of the HLS.js library used to instantiate player instances.\n * @public\n */\nexport default class Hls implements HlsEventEmitter {\n private static defaultConfig: HlsConfig | undefined;\n\n /**\n * The runtime configuration used by the player. At instantiation this is combination of `hls.userConfig` merged over `Hls.DefaultConfig`.\n */\n public readonly config: HlsConfig;\n\n /**\n * The configuration object provided on player instantiation.\n */\n public readonly userConfig: Partial<HlsConfig>;\n\n private coreComponents: ComponentAPI[];\n private networkControllers: NetworkComponentAPI[];\n private _emitter: HlsEventEmitter = new EventEmitter();\n private _autoLevelCapping: number;\n private _maxHdcpLevel: HdcpLevel = null;\n private abrController: AbrController;\n private bufferController: BufferController;\n private capLevelController: CapLevelController;\n private latencyController: LatencyController;\n private levelController: LevelController;\n private streamController: StreamController;\n private audioTrackController: AudioTrackController;\n private subtitleTrackController: SubtitleTrackController;\n private emeController: EMEController;\n private cmcdController: CMCDController;\n private _media: HTMLMediaElement | null = null;\n private url: string | null = null;\n\n /**\n * Get the video-dev/hls.js package version.\n */\n static get version(): string {\n return __VERSION__;\n }\n\n /**\n * Check if the required MediaSource Extensions are available.\n */\n static isSupported(): boolean {\n return isSupported();\n }\n\n static get Events(): typeof Events {\n return Events;\n }\n\n static get ErrorTypes(): typeof ErrorTypes {\n return ErrorTypes;\n }\n\n static get ErrorDetails(): typeof ErrorDetails {\n return ErrorDetails;\n }\n\n /**\n * Get the default configuration applied to new instances.\n */\n static get DefaultConfig(): HlsConfig {\n if (!Hls.defaultConfig) {\n return hlsDefaultConfig;\n }\n\n return Hls.defaultConfig;\n }\n\n /**\n * Replace the default configuration applied to new instances.\n */\n static set DefaultConfig(defaultConfig: HlsConfig) {\n Hls.defaultConfig = defaultConfig;\n }\n\n /**\n * Creates an instance of an HLS client that can attach to exactly one `HTMLMediaElement`.\n * @param userConfig - Configuration options applied over `Hls.DefaultConfig`\n */\n constructor(userConfig: Partial<HlsConfig> = {}) {\n enableLogs(userConfig.debug || false, 'Hls instance');\n const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig));\n this.userConfig = userConfig;\n\n this._autoLevelCapping = -1;\n\n if (config.progressive) {\n enableStreamingMode(config);\n }\n\n // core controllers and network loaders\n const {\n abrController: ConfigAbrController,\n bufferController: ConfigBufferController,\n capLevelController: ConfigCapLevelController,\n errorController: ConfigErrorController,\n fpsController: ConfigFpsController,\n } = config;\n const errorController = new ConfigErrorController(this);\n const abrController = (this.abrController = new ConfigAbrController(this));\n const bufferController = (this.bufferController =\n new ConfigBufferController(this));\n const capLevelController = (this.capLevelController =\n new ConfigCapLevelController(this));\n\n const fpsController = new ConfigFpsController(this);\n const playListLoader = new PlaylistLoader(this);\n const id3TrackController = new ID3TrackController(this);\n\n const ConfigContentSteeringController = config.contentSteeringController;\n // ConentSteeringController is defined before LevelController to receive Multivariant Playlist events first\n const contentSteering = ConfigContentSteeringController\n ? new ConfigContentSteeringController(this)\n : null;\n const levelController = (this.levelController = new LevelController(\n this,\n contentSteering\n ));\n // FragmentTracker must be defined before StreamController because the order of event handling is important\n const fragmentTracker = new FragmentTracker(this);\n const keyLoader = new KeyLoader(this.config);\n const streamController = (this.streamController = new StreamController(\n this,\n fragmentTracker,\n keyLoader\n ));\n\n // Cap level controller uses streamController to flush the buffer\n capLevelController.setStreamController(streamController);\n // fpsController uses streamController to switch when frames are being dropped\n fpsController.setStreamController(streamController);\n\n const networkControllers: NetworkComponentAPI[] = [\n playListLoader,\n levelController,\n streamController,\n ];\n if (contentSteering) {\n networkControllers.splice(1, 0, contentSteering);\n }\n\n this.networkControllers = networkControllers;\n const coreComponents: ComponentAPI[] = [\n abrController,\n bufferController,\n capLevelController,\n fpsController,\n id3TrackController,\n fragmentTracker,\n ];\n\n this.audioTrackController = this.createController(\n config.audioTrackController,\n networkControllers\n );\n const AudioStreamControllerClass = config.audioStreamController;\n if (AudioStreamControllerClass) {\n networkControllers.push(\n new AudioStreamControllerClass(this, fragmentTracker, keyLoader)\n );\n }\n // subtitleTrackController must be defined before subtitleStreamController because the order of event handling is important\n this.subtitleTrackController = this.createController(\n config.subtitleTrackController,\n networkControllers\n );\n const SubtitleStreamControllerClass = config.subtitleStreamController;\n if (SubtitleStreamControllerClass) {\n networkControllers.push(\n new SubtitleStreamControllerClass(this, fragmentTracker, keyLoader)\n );\n }\n this.createController(config.timelineController, coreComponents);\n keyLoader.emeController = this.emeController = this.createController(\n config.emeController,\n coreComponents\n );\n this.cmcdController = this.createController(\n config.cmcdController,\n coreComponents\n );\n this.latencyController = this.createController(\n LatencyController,\n coreComponents\n );\n\n this.coreComponents = coreComponents;\n\n // Error controller handles errors before and after all other controllers\n // This listener will be invoked after all other controllers error listeners\n networkControllers.push(errorController);\n const onErrorOut = errorController.onErrorOut;\n if (typeof onErrorOut === 'function') {\n this.on(Events.ERROR, onErrorOut, errorController);\n }\n }\n\n createController(ControllerClass, components) {\n if (ControllerClass) {\n const controllerInstance = new ControllerClass(this);\n if (components) {\n components.push(controllerInstance);\n }\n return controllerInstance;\n }\n return null;\n }\n\n // Delegate the EventEmitter through the public API of Hls.js\n on<E extends keyof HlsListeners, Context = undefined>(\n event: E,\n listener: HlsListeners[E],\n context: Context = this as any\n ) {\n this._emitter.on(event, listener, context);\n }\n\n once<E extends keyof HlsListeners, Context = undefined>(\n event: E,\n listener: HlsListeners[E],\n context: Context = this as any\n ) {\n this._emitter.once(event, listener, context);\n }\n\n removeAllListeners<E extends keyof HlsListeners>(event?: E | undefined) {\n this._emitter.removeAllListeners(event);\n }\n\n off<E extends keyof HlsListeners, Context = undefined>(\n event: E,\n listener?: HlsListeners[E] | undefined,\n context: Context = this as any,\n once?: boolean | undefined\n ) {\n this._emitter.off(event, listener, context, once);\n }\n\n listeners<E extends keyof HlsListeners>(event: E): HlsListeners[E][] {\n return this._emitter.listeners(event);\n }\n\n emit<E extends keyof HlsListeners>(\n event: E,\n name: E,\n eventObject: Parameters<HlsListeners[E]>[1]\n ): boolean {\n return this._emitter.emit(event, name, eventObject);\n }\n\n trigger<E extends keyof HlsListeners>(\n event: E,\n eventObject: Parameters<HlsListeners[E]>[1]\n ): boolean {\n if (this.config.debug) {\n return this.emit(event, event, eventObject);\n } else {\n try {\n return this.emit(event, event, eventObject);\n } catch (e) {\n logger.error(\n 'An internal error happened while handling event ' +\n event +\n '. Error message: \"' +\n e.message +\n '\". Here is a stacktrace:',\n e\n );\n this.trigger(Events.ERROR, {\n type: ErrorTypes.OTHER_ERROR,\n details: ErrorDetails.INTERNAL_EXCEPTION,\n fatal: false,\n event: event,\n error: e,\n });\n }\n }\n return false;\n }\n\n listenerCount<E extends keyof HlsListeners>(event: E): number {\n return this._emitter.listenerCount(event);\n }\n\n /**\n * Dispose of the instance\n */\n destroy() {\n logger.log('destroy');\n this.trigger(Events.DESTROYING, undefined);\n this.detachMedia();\n this.removeAllListeners();\n this._autoLevelCapping = -1;\n this.url = null;\n\n this.networkControllers.forEach((component) => component.destroy());\n this.networkControllers.length = 0;\n\n this.coreComponents.forEach((component) => component.destroy());\n this.coreComponents.length = 0;\n // Remove any references that could be held in config options or callbacks\n const config = this.config;\n config.xhrSetup = config.fetchSetup = undefined;\n // @ts-ignore\n this.userConfig = null;\n }\n\n /**\n * Attaches Hls.js to a media element\n */\n attachMedia(media: HTMLMediaElement) {\n logger.log('attachMedia');\n this._media = media;\n this.trigger(Events.MEDIA_ATTACHING, { media: media });\n }\n\n /**\n * Detach Hls.js from the media\n */\n detachMedia() {\n logger.log('detachMedia');\n this.trigger(Events.MEDIA_DETACHING, undefined);\n this._media = null;\n }\n\n /**\n * Set the source URL. Can be relative or absolute.\n */\n loadSource(url: string) {\n this.stopLoad();\n const media = this.media;\n const loadedSource = this.url;\n const loadingSource = (this.url = buildAbsoluteURL(\n self.location.href,\n url,\n {\n alwaysNormalize: true,\n }\n ));\n logger.log(`loadSource:${loadingSource}`);\n if (\n media &&\n loadedSource &&\n (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())\n ) {\n this.detachMedia();\n this.attachMedia(media);\n }\n // when attaching to a source URL, trigger a playlist load\n this.trigger(Events.MANIFEST_LOADING, { url: url });\n }\n\n /**\n * Start loading data from the stream source.\n * Depending on default config, client starts loading automatically when a source is set.\n *\n * @param startPosition - Set the start position to stream from.\n * Defaults to -1 (None: starts from earliest point)\n */\n startLoad(startPosition: number = -1) {\n logger.log(`startLoad(${startPosition})`);\n this.networkControllers.forEach((controller) => {\n controller.startLoad(startPosition);\n });\n }\n\n /**\n * Stop loading of any stream data.\n */\n stopLoad() {\n logger.log('stopLoad');\n this.networkControllers.forEach((controller) => {\n controller.stopLoad();\n });\n }\n\n /**\n * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)\n */\n swapAudioCodec() {\n logger.log('swapAudioCodec');\n this.streamController.swapAudioCodec();\n }\n\n /**\n * When the media-element fails, this allows to detach and then re-attach it\n * as one call (convenience method).\n *\n * Automatic recovery of media-errors by this process is configurable.\n */\n recoverMediaError() {\n logger.log('recoverMediaError');\n const media = this._media;\n this.detachMedia();\n if (media) {\n this.attachMedia(media);\n }\n }\n\n removeLevel(levelIndex, urlId = 0) {\n this.levelController.removeLevel(levelIndex, urlId);\n }\n\n /**\n * @returns an array of levels (variants) sorted by HDCP-LEVEL, BANDWIDTH, SCORE, and RESOLUTION (height)\n */\n get levels(): Level[] {\n const levels = this.levelController.levels;\n return levels ? levels : [];\n }\n\n /**\n * Index of quality level (variant) currently played\n */\n get currentLevel(): number {\n return this.streamController.currentLevel;\n }\n\n /**\n * Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.\n */\n set currentLevel(newLevel: number) {\n logger.log(`set currentLevel:${newLevel}`);\n this.loadLevel = newLevel;\n this.abrController.clearTimer();\n this.streamController.immediateLevelSwitch();\n }\n\n /**\n * Index of next quality level loaded as scheduled by stream controller.\n */\n get nextLevel(): number {\n return this.streamController.nextLevel;\n }\n\n /**\n * Set quality level index for next loaded data.\n * This will switch the video quality asap, without interrupting playback.\n * May abort current loading of data, and flush parts of buffer (outside currently played fragment region).\n * @param newLevel - Pass -1 for automatic level selection\n */\n set nextLevel(newLevel: number) {\n logger.log(`set nextLevel:${newLevel}`);\n this.levelController.manualLevel = newLevel;\n this.streamController.nextLevelSwitch();\n }\n\n /**\n * Return the quality level of the currently or last (of none is loaded currently) segment\n */\n get loadLevel(): number {\n return this.levelController.level;\n }\n\n /**\n * Set quality level index for next loaded data in a conservative way.\n * This will switch the quality without flushing, but interrupt current loading.\n * Thus the moment when the quality switch will appear in effect will only be after the already existing buffer.\n * @param newLevel - Pass -1 for automatic level selection\n */\n set loadLevel(newLevel: number) {\n logger.log(`set loadLevel:${newLevel}`);\n this.levelController.manualLevel = newLevel;\n }\n\n /**\n * get next quality level loaded\n */\n get nextLoadLevel(): number {\n return this.levelController.nextLoadLevel;\n }\n\n /**\n * Set quality level of next loaded segment in a fully \"non-destructive\" way.\n * Same as `loadLevel` but will wait for next switch (until current loading is done).\n */\n set nextLoadLevel(level: number) {\n this.levelController.nextLoadLevel = level;\n }\n\n /**\n * Return \"first level\": like a default level, if not set,\n * falls back to index of first level referenced in manifest\n */\n get firstLevel(): number {\n return Math.max(this.levelController.firstLevel, this.minAutoLevel);\n }\n\n /**\n * Sets \"first-level\", see getter.\n */\n set firstLevel(newLevel: number) {\n logger.log(`set firstLevel:${newLevel}`);\n this.levelController.firstLevel = newLevel;\n }\n\n /**\n * Return start level (level of first fragment that will be played back)\n * if not overrided by user, first level appearing in manifest will be used as start level\n * if -1 : automatic start level selection, playback will start from level matching download bandwidth\n * (determined from download of first segment)\n */\n get startLevel(): number {\n return this.levelController.startLevel;\n }\n\n /**\n * set start level (level of first fragment that will be played back)\n * if not overrided by user, first level appearing in manifest will be used as start level\n * if -1 : automatic start level selection, playback will start from level matching download bandwidth\n * (determined from download of first segment)\n */\n set startLevel(newLevel: number) {\n logger.log(`set startLevel:${newLevel}`);\n // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel\n if (newLevel !== -1) {\n newLevel = Math.max(newLevel, this.minAutoLevel);\n }\n\n this.levelController.startLevel = newLevel;\n }\n\n /**\n * Whether level capping is enabled.\n * Default value is set via `config.capLevelToPlayerSize`.\n */\n get capLevelToPlayerSize(): boolean {\n return this.config.capLevelToPlayerSize;\n }\n\n /**\n * Enables or disables level capping. If disabled after previously enabled, `nextLevelSwitch` will be immediately called.\n */\n set capLevelToPlayerSize(shouldStartCapping: boolean) {\n const newCapLevelToPlayerSize = !!shouldStartCapping;\n\n if (newCapLevelToPlayerSize !== this.config.capLevelToPlayerSize) {\n if (newCapLevelToPlayerSize) {\n this.capLevelController.startCapping(); // If capping occurs, nextLevelSwitch will happen based on size.\n } else {\n this.capLevelController.stopCapping();\n this.autoLevelCapping = -1;\n this.streamController.nextLevelSwitch(); // Now we're uncapped, get the next level asap.\n }\n\n this.config.capLevelToPlayerSize = newCapLevelToPlayerSize;\n }\n }\n\n /**\n * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)\n */\n get autoLevelCapping(): number {\n return this._autoLevelCapping;\n }\n\n /**\n * Returns the current bandwidth estimate in bits per second, when available. Otherwise, `NaN` is returned.\n */\n get bandwidthEstimate(): number {\n const { bwEstimator } = this.abrController;\n if (!bwEstimator) {\n return NaN;\n }\n return bwEstimator.getEstimate();\n }\n\n /**\n * get time to first byte estimate\n * @type {number}\n */\n get ttfbEstimate(): number {\n const { bwEstimator } = this.abrController;\n if (!bwEstimator) {\n return NaN;\n }\n return bwEstimator.getEstimateTTFB();\n }\n\n /**\n * Capping/max level value that should be used by automatic level selection algorithm (`ABRController`)\n */\n set autoLevelCapping(newLevel: number) {\n if (this._autoLevelCapping !== newLevel) {\n logger.log(`set autoLevelCapping:${newLevel}`);\n this._autoLevelCapping = newLevel;\n }\n }\n\n get maxHdcpLevel(): HdcpLevel {\n return this._maxHdcpLevel;\n }\n\n set maxHdcpLevel(value: HdcpLevel) {\n if (HdcpLevels.indexOf(value) > -1) {\n this._maxHdcpLevel = value;\n }\n }\n\n /**\n * True when automatic level selection enabled\n */\n get autoLevelEnabled(): boolean {\n return this.levelController.manualLevel === -1;\n }\n\n /**\n * Level set manually (if any)\n */\n get manualLevel(): number {\n return this.levelController.manualLevel;\n }\n\n /**\n * min level selectable in auto mode according to config.minAutoBitrate\n */\n get minAutoLevel(): number {\n const {\n levels,\n config: { minAutoBitrate },\n } = this;\n if (!levels) return 0;\n\n const len = levels.length;\n for (let i = 0; i < len; i++) {\n if (levels[i].maxBitrate >= minAutoBitrate) {\n return i;\n }\n }\n\n return 0;\n }\n\n /**\n * max level selectable in auto mode according to autoLevelCapping\n */\n get maxAutoLevel(): number {\n const { levels, autoLevelCapping, maxHdcpLevel } = this;\n\n let maxAutoLevel;\n if (autoLevelCapping === -1 && levels && levels.length) {\n maxAutoLevel = levels.length - 1;\n } else {\n maxAutoLevel = autoLevelCapping;\n }\n\n if (maxHdcpLevel) {\n for (let i = maxAutoLevel; i--; ) {\n const hdcpLevel = levels[i].attrs['HDCP-LEVEL'];\n if (hdcpLevel && hdcpLevel <= maxHdcpLevel) {\n return i;\n }\n }\n }\n\n return maxAutoLevel;\n }\n\n /**\n * next automatically selected quality level\n */\n get nextAutoLevel(): number {\n // ensure next auto level is between min and max auto level\n return Math.min(\n Math.max(this.abrController.nextAutoLevel, this.minAutoLevel),\n this.maxAutoLevel\n );\n }\n\n /**\n * this setter is used to force next auto level.\n * this is useful to force a switch down in auto mode:\n * in case of load error on level N, hls.js can set nextAutoLevel to N-1 for example)\n * forced value is valid for one fragment. upon successful frag loading at forced level,\n * this value will be resetted to -1 by ABR controller.\n */\n set nextAutoLevel(nextLevel: number) {\n this.abrController.nextAutoLevel = Math.max(this.minAutoLevel, nextLevel);\n }\n\n /**\n * get the datetime value relative to media.currentTime for the active level Program Date Time if present\n */\n public get playingDate(): Date | null {\n return this.streamController.currentProgramDateTime;\n }\n\n public get mainForwardBufferInfo(): BufferInfo | null {\n return this.streamController.getMainFwdBufferInfo();\n }\n\n /**\n * Get the list of selectable audio tracks\n */\n get audioTracks(): Array<MediaPlaylist> {\n const audioTrackController = this.audioTrackController;\n return audioTrackController ? audioTrackController.audioTracks : [];\n }\n\n /**\n * index of the selected audio track (index in audio track lists)\n */\n get audioTrack(): number {\n const audioTrackController = this.audioTrackController;\n return audioTrackController ? audioTrackController.audioTrack : -1;\n }\n\n /**\n * selects an audio track, based on its index in audio track lists\n */\n set audioTrack(audioTrackId: number) {\n const audioTrackController = this.audioTrackController;\n if (audioTrackController) {\n audioTrackController.audioTrack = audioTrackId;\n }\n }\n\n /**\n * get alternate subtitle tracks list from playlist\n */\n get subtitleTracks(): Array<MediaPlaylist> {\n const subtitleTrackController = this.subtitleTrackController;\n return subtitleTrackController\n ? subtitleTrackController.subtitleTracks\n : [];\n }\n\n /**\n * index of the selected subtitle track (index in subtitle track lists)\n */\n get subtitleTrack(): number {\n const subtitleTrackController = this.subtitleTrackController;\n return subtitleTrackController ? subtitleTrackController.subtitleTrack : -1;\n }\n\n get media() {\n return this._media;\n }\n\n /**\n * select an subtitle track, based on its index in subtitle track lists\n */\n set subtitleTrack(subtitleTrackId: number) {\n const subtitleTrackController = this.subtitleTrackController;\n if (subtitleTrackController) {\n subtitleTrackController.subtitleTrack = subtitleTrackId;\n }\n }\n\n /**\n * Whether subtitle display is enabled or not\n */\n get subtitleDisplay(): boolean {\n const subtitleTrackController = this.subtitleTrackController;\n return subtitleTrackController\n ? subtitleTrackController.subtitleDisplay\n : false;\n }\n\n /**\n * Enable/disable subtitle display rendering\n */\n set subtitleDisplay(value: boolean) {\n const subtitleTrackController = this.subtitleTrackController;\n if (subtitleTrackController) {\n subtitleTrackController.subtitleDisplay = value;\n }\n }\n\n /**\n * get mode for Low-Latency HLS loading\n */\n get lowLatencyMode(): boolean {\n return this.config.lowLatencyMode;\n }\n\n /**\n * Enable/disable Low-Latency HLS part playlist and segment loading, and start live streams at playlist PART-HOLD-BACK rather than HOLD-BACK.\n */\n set lowLatencyMode(mode: boolean) {\n this.config.lowLatencyMode = mode;\n }\n\n /**\n * Position (in seconds) of live sync point (ie edge of live position minus safety delay defined by ```hls.config.liveSyncDuration```)\n * @returns null prior to loading live Playlist\n */\n get liveSyncPosition(): number | null {\n return this.latencyController.liveSyncPosition;\n }\n\n /**\n * Estimated position (in seconds) of live edge (ie edge of live playlist plus time sync playlist advanced)\n * @returns 0 before first playlist is loaded\n */\n get latency(): number {\n return this.latencyController.latency;\n }\n\n /**\n * maximum distance from the edge before the player seeks forward to ```hls.liveSyncPosition```\n * configured using ```liveMaxLatencyDurationCount``` (multiple of target duration) or ```liveMaxLatencyDuration```\n * @returns 0 before first playlist is loaded\n */\n get maxLatency(): number {\n return this.latencyController.maxLatency;\n }\n\n /**\n * target distance from the edge as calculated by the latency controller\n */\n get targetLatency(): number | null {\n return this.latencyController.targetLatency;\n }\n\n /**\n * the rate at which the edge of the current live playlist is advancing or 1 if there is none\n */\n get drift(): number | null {\n return this.latencyController.drift;\n }\n\n /**\n * set to true when startLoad is called before MANIFEST_PARSED event\n */\n get forceStartLoad(): boolean {\n return this.streamController.forceStartLoad;\n }\n}\n\nexport type {\n MediaPlaylist,\n ErrorDetails,\n ErrorTypes,\n Events,\n Level,\n HlsListeners,\n HlsEventEmitter,\n HlsConfig,\n BufferInfo,\n HdcpLevels,\n HdcpLevel,\n AbrController,\n AudioStreamController,\n AudioTrackController,\n BasePlaylistController,\n BaseStreamController,\n BufferController,\n CapLevelController,\n CMCDController,\n ContentSteeringController,\n EMEController,\n ErrorController,\n FPSController,\n SubtitleTrackController,\n};\nexport type {\n ComponentAPI,\n AbrComponentAPI,\n NetworkComponentAPI,\n} from './types/component-api';\nexport type {\n ABRControllerConfig,\n BufferControllerConfig,\n CapLevelControllerConfig,\n CMCDControllerConfig,\n EMEControllerConfig,\n DRMSystemsConfiguration,\n DRMSystemOptions,\n FPSControllerConfig,\n FragmentLoaderConfig,\n FragmentLoaderConstructor,\n HlsLoadPolicies,\n LevelControllerConfig,\n LoaderConfig,\n LoadPolicy,\n MP4RemuxerConfig,\n PlaylistLoaderConfig,\n PlaylistLoaderConstructor,\n RetryConfig,\n StreamControllerConfig,\n LatencyControllerConfig,\n MetadataControllerConfig,\n TimelineControllerConfig,\n TSDemuxerConfig,\n} from './config';\nexport type { MediaKeySessionContext } from './controller/eme-controller';\nexport type { ILogger } from './utils/logger';\nexport type { SubtitleStreamController } from './controller/subtitle-stream-controller';\nexport type { TimelineController } from './controller/timeline-controller';\nexport type { CuesInterface } from './utils/cues';\nexport type {\n MediaKeyFunc,\n KeySystems,\n KeySystemFormats,\n} from './utils/mediakeys-helper';\nexport type { DateRange } from './loader/date-range';\nexport type { LoadStats } from './loader/load-stats';\nexport type { LevelKey } from './loader/level-key';\nexport type { LevelDetails } from './loader/level-details';\nexport type { SourceBufferName } from './types/buffer';\nexport type {\n MetadataSample,\n MetadataSchema,\n UserdataSample,\n} from './types/demuxer';\nexport type {\n HlsSkip,\n HlsUrlParameters,\n LevelAttributes,\n LevelParsed,\n VariableMap,\n} from './types/level';\nexport type {\n PlaylistLevelType,\n HlsChunkPerformanceTiming,\n HlsPerformanceTiming,\n HlsProgressivePerformanceTiming,\n PlaylistContextType,\n PlaylistLoaderContext,\n FragmentLoaderContext,\n Loader,\n LoaderStats,\n LoaderContext,\n LoaderResponse,\n LoaderConfiguration,\n LoaderCallbacks,\n LoaderOnProgress,\n LoaderOnAbort,\n LoaderOnError,\n LoaderOnSuccess,\n LoaderOnTimeout,\n} from './types/loader';\nexport type {\n MediaAttributes,\n MediaPlaylistType,\n MainPlaylistType,\n AudioPlaylistType,\n SubtitlePlaylistType,\n} from './types/media-playlist';\nexport type { Track, TrackSet } from './types/track';\nexport type { ChunkMetadata } from './types/transmuxer';\nexport type {\n BaseSegment,\n Fragment,\n Part,\n ElementaryStreams,\n ElementaryStreamTypes,\n ElementaryStreamInfo,\n} from './loader/fragment';\nexport type {\n TrackLoadingData,\n TrackLoadedData,\n AudioTrackLoadedData,\n AudioTracksUpdatedData,\n AudioTrackSwitchedData,\n AudioTrackSwitchingData,\n BackBufferData,\n BufferAppendedData,\n BufferAppendingData,\n BufferCodecsData,\n BufferCreatedData,\n BufferEOSData,\n BufferFlushedData,\n BufferFlushingData,\n CuesParsedData,\n ErrorData,\n FPSDropData,\n FPSDropLevelCappingData,\n FragBufferedData,\n FragChangedData,\n FragDecryptedData,\n FragLoadedData,\n FragLoadEmergencyAbortedData,\n FragLoadingData,\n FragParsedData,\n FragParsingInitSegmentData,\n FragParsingMetadataData,\n FragParsingUserdataData,\n InitPTSFoundData,\n KeyLoadedData,\n KeyLoadingData,\n LevelLoadedData,\n LevelLoadingData,\n LevelPTSUpdatedData,\n LevelsUpdatedData,\n LevelSwitchedData,\n LevelSwitchingData,\n LevelUpdatedData,\n LiveBackBufferData,\n ContentSteeringOptions,\n ManifestLoadedData,\n ManifestLoadingData,\n ManifestParsedData,\n MediaAttachedData,\n MediaAttachingData,\n NonNativeTextTrack,\n NonNativeTextTracksData,\n SubtitleFragProcessedData,\n SubtitleTrackLoadedData,\n SubtitleTracksUpdatedData,\n SubtitleTrackSwitchData,\n} from './types/events';\nexport type {\n NetworkErrorAction,\n ErrorActionFlags,\n IErrorAction,\n} from './controller/error-controller';\nexport type { AttrList } from './utils/attr-list';\n","import Hls from 'hls.js';\r\nimport { PlyrDriver, PlyrDriverCreateParams, PlyrDriverDestroyParams, PlyrDriverUpdateSourceParams } from 'ngx-plyr3';\r\nimport Plyr from 'plyr';\r\n\r\nexport class HlsjsPlyrDriver implements PlyrDriver {\r\n hls = new Hls();\r\n\r\n private loaded = false;\r\n\r\n constructor(private autoload: boolean) {}\r\n\r\n create(params: PlyrDriverCreateParams) {\r\n this.hls.attachMedia(params.videoElement);\r\n\r\n return new Plyr(params.videoElement, params.options);\r\n }\r\n\r\n updateSource(params: PlyrDriverUpdateSourceParams) {\r\n if (this.autoload) {\r\n this.load(params.source.sources[0].src);\r\n } else {\r\n // poster does not work with autoload\r\n if (params.source.poster) {\r\n params.videoElement.poster = params.source.poster;\r\n }\r\n }\r\n }\r\n\r\n destroy(params: PlyrDriverDestroyParams) {\r\n params.plyr.destroy();\r\n this.hls.detachMedia();\r\n }\r\n\r\n load(src: string) {\r\n if (!this.loaded) {\r\n this.loaded = true;\r\n this.hls.loadSource(src);\r\n }\r\n }\r\n}\r\n","<div class=\"flex vertical-center space-1\">\r\n <button *ngIf=\"showSecondsControl\" (click)=\"onClickRewindSeconds()\" class=\"btn small-width rewind-seconds\">\r\n <i class=\"icon icon-24\" [inlineSVG]=\"'rewind-10-sec.svg'\"></i>\r\n </button>\r\n <div\r\n *ngIf=\"source\"\r\n class=\"plyr-container\"\r\n plyr\r\n [plyrPlaysInline]=\"true\"\r\n [plyrSources]=\"[source]\"\r\n [plyrOptions]=\"options\"\r\n plyrType=\"audio\"\r\n (plyrInit)=\"plyrInit($event)\"\r\n (plyrPlay)=\"plyrPlay($event)\"\r\n (plyrPause)=\"plyrPause($event)\"\r\n (plyrSeeked)=\"plyrSeeked($event)\"\r\n [plyrDriver]=\"useHls ? hlsDriver : undefined\"\r\n ></div>\r\n <button *ngIf=\"showSecondsControl\" (click)=\"onClickForwardSeconds()\" class=\"btn small-width forward-seconds\">\r\n <i class=\"icon icon-24\" [inlineSVG]=\"'forward-10-sec.svg'\"></i>\r\n </button>\r\n</div>\r\n","import { AfterViewInit, Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';\r\nimport { GTMEvent } from '@portal-app/enums/gtm-event.enum';\r\n\r\nimport { GoogleTagManagerService } from '@lru/felib';\r\nimport { HelperService } from '@portal-app/services/shared/helper.service';\r\nimport { LayoutAudioService } from '@portal-app/services/shared/layout-audio.service';\r\nimport { PlyrEvent } from 'plyr';\r\nimport { HlsjsPlyrDriver } from './hlsjs-plyr-driver';\r\n\r\n@Component({\r\n selector: 'portal-audio-hls-player[src]',\r\n templateUrl: './audio-hls-player.component.html',\r\n styleUrls: ['./audio-hls-player.component.scss'],\r\n})\r\nexport class AudioHlsPlayerComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {\r\n @Input() src!: string;\r\n @Input() showSecondsControl = false;\r\n @Input() autoPlay = false;\r\n\r\n player?: Plyr;\r\n source?: Plyr.Source;\r\n hlsDriver = new HlsjsPlyrDriver(true);\r\n useHls = false;\r\n options: Plyr.Options = {\r\n autoplay: this.autoPlay,\r\n invertTime: false,\r\n disableContextMenu: true,\r\n settings: ['quality', 'speed', 'loop'],\r\n controls: ['play', 'progress', 'current-time', 'duration'],\r\n captions: { active: false, update: true, language: 'en' },\r\n };\r\n\r\n constructor(\r\n public layoutAudioService: LayoutAudioService,\r\n private helperService: HelperService,\r\n private gtmService: GoogleTagManagerService\r\n ) {}\r\n\r\n ngOnInit() {\r\n if (window.device.desktop() && !this.helperService.isSafari()) {\r\n this.useHls = true;\r\n }\r\n }\r\n\r\n ngAfterViewInit() {\r\n if (this.useHls && this.hlsDriver) {\r\n this.hlsDriver.load(this.src);\r\n }\r\n }\r\n\r\n ngOnChanges() {\r\n if (this.src) {\r\n this.source = {\r\n src: this.src,\r\n type: 'application/x-mpegURL',\r\n };\r\n } else {\r\n this.source = undefined;\r\n }\r\n }\r\n\r\n async ngOnDestroy() {\r\n if (this.player) {\r\n await this.layoutAudioService.removePlayer(this.player, this.src);\r\n }\r\n }\r\n\r\n plyrInit(event: Plyr) {\r\n this.player = event;\r\n this.layoutAudioService.addPlayer(this.player, this.src);\r\n }\r\n\r\n async plyrPlay(event: PlyrEvent) {\r\n await this.layoutAudioService.pauseOtherPlayers(this.src);\r\n this.gtmService.pushTagWithUserType(GTMEvent.Play_recorded);\r\n this.layoutAudioService.handlePlyrEvents(event);\r\n }\r\n\r\n plyrPause(event: PlyrEvent) {\r\n if (event.detail.plyr.duration !== 0 && event.detail.plyr.duration !== event.detail.plyr.currentTime) {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Pause_recorded);\r\n } else {\r\n this.gtmService.pushTagWithUserType(GTMEvent.Ended_recorded);\r\n }\r\n this.layoutAudioService.handlePlyrEvents(event);\r\n }\r\n\r\n plyrSeeked(event: PlyrEvent) {\r\n this.gtmService.pushDebouncedTagWithUserType(GTMEvent.Seeked_recorded);\r\n }\r\n\r\n onClickRewindSeconds() {\r\n if (this.player) {\r\n this.player.currentTime = this.player.currentTime - 10;\r\n this.gtmService.pushTagWithUserType(GTMEvent.Backwards_recorded);\r\n }\r\n }\r\n\r\n onClickForwardSeconds() {\r\n if (this.player) {\r\n this.player.currentTime = this.player.currentTime + 10;\r\n this.gtmService.pushTagWithUserType(GTMEvent.Forward_recorded);\r\n }\r\n }\r\n}\r\n","<ng-container *ngIf=\"{ data: (data$ | async) } as sub\">\r\n <div\r\n *ngIf=\"sub.data.Recorded\"\r\n class=\"audio-element recorded\"\r\n [class.expanded]=\"sub.data.RecordedExpanded && !sub.data.Partial && !sub.data.FullExpanded\"\r\n [class.disabled]=\"sub.data.Partial || sub.data.FullExpanded\"\r\n >\r\n <div class=\"flex space-3 vertical-center grow-self\">\r\n <button\r\n class=\"btn\"\r\n (click)=\"layoutAudioService.toggleRecordedExpanded(true, true)\"\r\n [attr.aria-label]=\"'Audio.ExpandRecordedAudio' | translate\"\r\n >\r\n <i class=\"icon icon-30\" [inlineSVG]=\"'play-filled.svg'\"></i>\r\n </button>\r\n <label class=\"grow-self\">{{ 'LayoutAudioRecorded.AudioBook' | translate }}</label>\r\n </div>\r\n <div class=\"flex vertical-bottom grow-self\">\r\n <portal-audio-hls-player\r\n [src]=\"sub.data.Recorded.Src\"\r\n [showSecondsControl]=\"sub.data.Recorded.ShowSecondsControl\"\r\n [autoPlay]=\"sub.data.Recorded.AutoPlay\"\r\n >\r\n </portal-audio-hls-player>\r\n </div>\r\n </div>\r\n</ng-container>\r\n","import { Component } from '@angular/core';\r\nimport { AudioPlayerTypeEnum } from '@portal-app/enums/audio-player-type.enum';\r\nimport { LayoutAudioService } from '@portal-app/services/shared/layout-audio.service';\r\n\r\n@Component({\r\n selector: 'portal-layout-audio-recorded',\r\n templateUrl: './layout-audio-recorded.component.html',\r\n styleUrls: ['./layout-audio-recorded.component.scss'],\r\n})\r\nexport class LayoutAudioRecordedComponent {\r\n public data$ = this.layoutAudioService.data$;\r\n\r\n constructor(public layoutAudioService: LayoutAudioService) {}\r\n\r\n get AudioPlayerTypeEnum(): typeof AudioPlayerTypeEnum {\r\n return AudioPlayerTypeEnum;\r\n }\r\n}\r\n","<ng-container *ngIf=\"{ data: (data$ | async) } as sub\">\r\n <div\r\n *ngIf=\"sub.data.Partial\"\r\n class=\"audio-element partial\"\r\n [class.partial-desktop]=\"sub.data.Partial.Type === AudioPlayerTypeEnum.PartialDesktop\"\r\n [class.partial-touch]=\"sub.data.Partial.Type === AudioPlayerTypeEnum.PartialTouch\"\r\n [style.left]=\"sub.data.Partial.Selections[0].CoordinatesAndText?.X + 'px'\"\r\n [style.top]=\"sub.data.Partial.Selections[0].CoordinatesAndText?.Y + 'px'\"\r\n >\r\n <portal-audio-selection-player\r\n [src]=\"sub.data.Partial.Src\"\r\n [type]=\"sub.data.Partial.Type\"\r\n [marks]=\"sub.data.Partial.Marks\"\r\n [selections]=\"sub.data.Partial.Selections\"\r\n [autoPlay]=\"sub.data.Partial.AutoPlay\"\r\n [highlight]=\"sub.data.Partial.Highlight\"\r\n [sentenceButtons]=\"sub.data.Partial.SentenceButtons\"\r\n [autofocus]=\"true\"\r\n >\r\n </portal-audio-selection-player>\r\n </div>\r\n</ng-container>\r\n","import { Component } from '@angular/core';\r\nimport { AudioPlayerTypeEnum } from '@portal-app/enums/audio-player-type.enum';\r\nimport { LayoutAudioService } from '@portal-app/services/shared/layout-audio.service';\r\n\r\n@Component({\r\n selector: 'portal-layout-audio-partial',\r\n templateUrl: './layout-audio-partial.component.html',\r\n styleUrls: ['./layout-audio-partial.component.scss'],\r\n})\r\nexport class LayoutAudioPartialComponent {\r\n public data$ = this.layoutAudioService.data$;\r\n\r\n constructor(public layoutAudioService: LayoutAudioService) {}\r\n\r\n get AudioPlayerTypeEnum() {\r\n return AudioPlayerTypeEnum;\r\n }\r\n}\r\n","<div>\r\n <portal-breadcrumbs [isHeader]=\"true\"></portal-breadcrumbs>\r\n</div>\r\n<div>\r\n <portal-layout-audio-partial></portal-layout-audio-partial>\r\n <portal-layout-audio-recorded></portal-layout-audio-recorded>\r\n <portal-user *ngIf=\"isLoggedIn\"></portal-user>\r\n</div>\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\n\r\n@Component({\r\n selector: 'portal-header-book',\r\n templateUrl: './header-book.component.html',\r\n styleUrls: ['./header-book.component.scss'],\r\n})\r\nexport class HeaderBookComponent implements OnInit {\r\n isLoggedIn?: boolean;\r\n\r\n constructor(private userService: UserService) {}\r\n\r\n ngOnInit() {\r\n this.isLoggedIn = this.userService.isLoggedIn;\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\n\r\n@Component({\r\n selector: 'portal-header-course',\r\n templateUrl: './header-course.component.html',\r\n styleUrls: ['./header-course.component.scss'],\r\n})\r\nexport class HeaderCourseComponent implements OnInit {\r\n isLoggedIn?: boolean;\r\n\r\n constructor(private userService: UserService) {}\r\n\r\n ngOnInit() {\r\n this.isLoggedIn = this.userService.isLoggedIn;\r\n }\r\n}\r\n","<p>Course header!</p>\r\n","<div #domHeader>\r\n <portal-header-default\r\n *ngIf=\"headerType === HeaderTypeEnum.Default\"\r\n class=\"screen\"\r\n [pageType]=\"pageType\"\r\n [attr.data-project-type]=\"projectType\"\r\n [attr.data-behind]=\"behind\"\r\n [attr.data-gradient]=\"gradient\"\r\n [attr.data-scrolled]=\"scrolled\"\r\n ></portal-header-default>\r\n <portal-header-book *ngIf=\"headerType === HeaderTypeEnum.Book\" class=\"screen\"></portal-header-book>\r\n <portal-header-course *ngIf=\"headerType === HeaderTypeEnum.Course\" class=\"screen\"></portal-header-course>\r\n</div>\r\n","import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';\r\nimport { ModalService, UserService } from '@lru/felib';\r\nimport { WindowScrollService } from '@portal-app/services/shared/window-scroll.service';\r\nimport { withLatestFrom } from 'rxjs';\r\nimport { HeaderTypeEnum } from '../../../../../enums/header-type.enum';\r\nimport { PageTypeEnum } from '../../../../../enums/page-type.enum';\r\nimport { AppInitService } from '../../../../../services/shared/app-init.service';\r\nimport { HeaderService } from '../../../../../services/shared/header.service';\r\n\r\n@Component({\r\n selector: 'portal-header[headerType][pageType][behind]',\r\n templateUrl: './header.component.html',\r\n styleUrls: ['./header.component.scss'],\r\n})\r\nexport class HeaderComponent implements OnInit, AfterViewInit {\r\n @Input() headerType?: HeaderTypeEnum;\r\n @Input() pageType?: PageTypeEnum;\r\n @Input() behind?: boolean;\r\n\r\n scrolled?: boolean;\r\n projectType = this.appInitService.siteConfiguration.ProjectType;\r\n gradient = this.appInitService.isPs;\r\n @ViewChild('domHeader') domHeader!: ElementRef<HTMLDivElement>;\r\n\r\n constructor(\r\n private windowScrollService: WindowScrollService,\r\n private userService: UserService,\r\n private appInitService: AppInitService,\r\n private headerService: HeaderService,\r\n private modalService: ModalService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.headerService.resetHeader();\r\n\r\n this.windowScrollService\r\n .getScrollY()\r\n .pipe(withLatestFrom(this.modalService.displayOverlay$))\r\n .subscribe(([pos, visible]) => {\r\n if (!window.scrollLocked && !visible) {\r\n this.setScrolled(pos);\r\n }\r\n });\r\n }\r\n\r\n ngAfterViewInit() {\r\n this.appInitService.setHeaderHeight(this.domHeader.nativeElement.clientHeight);\r\n }\r\n\r\n onLogin() {\r\n this.userService.logout();\r\n }\r\n\r\n private setScrolled(verticalOffset: number) {\r\n const maxScrollVal = 1;\r\n\r\n this.scrolled = verticalOffset >= maxScrollVal;\r\n }\r\n\r\n get PageTypeEnum() {\r\n return PageTypeEnum;\r\n }\r\n\r\n get HeaderTypeEnum() {\r\n return HeaderTypeEnum;\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { IDropdown } from '@portal-app/interfaces/project/dropdown.interface';\r\nimport { DropdownService } from '@portal-app/services/shared/dropdown.service';\r\n\r\n@Component({\r\n selector: 'portal-dropdown-overlay',\r\n templateUrl: './dropdown-overlay.component.html',\r\n styleUrls: ['./dropdown-overlay.component.scss'],\r\n})\r\nexport class DropdownOverlayComponent implements OnInit {\r\n dropdownOpen?: IDropdown;\r\n\r\n constructor(private dropdownService: DropdownService) {}\r\n\r\n ngOnInit() {\r\n this.dropdownService.open$.subscribe((v) => {\r\n if (v?.ZIndex) {\r\n v.ZIndex = v.ZIndex - 1;\r\n }\r\n this.dropdownOpen = v;\r\n });\r\n }\r\n}\r\n","<div\r\n id=\"dropdown-overlay\"\r\n [hidden]=\"!dropdownOpen\"\r\n [class.dark-overlay]=\"dropdownOpen?.DarkOverlay === true\"\r\n [style.z-index]=\"dropdownOpen?.ZIndex\"\r\n></div>\r\n","<ng-container *ngIf=\"zIndex$ | async as zIndex\">\r\n <div class=\"loading-overlay\" [hidden]=\"!loading\" [style.zIndex]=\"zIndex\">\r\n <div class=\"container\">\r\n <portal-spinner></portal-spinner>\r\n </div>\r\n </div>\r\n</ng-container>\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { LoadingService, ZIndexService } from '@lru/felib';\r\nimport { LoadingKey } from '@portal-app/enums/loading-keys.enum';\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\n@Component({\r\n selector: 'portal-loader',\r\n templateUrl: './loader.component.html',\r\n})\r\nexport class LoaderComponent implements OnInit {\r\n /** unique id for this component */\r\n private uuid = uuidv4();\r\n\r\n loading = false;\r\n\r\n /** z-index for loader */\r\n public readonly zIndex$ = this.zIndexService.item$(this.uuid);\r\n\r\n constructor(private loaderService: LoadingService, private zIndexService: ZIndexService) {}\r\n\r\n ngOnInit() {\r\n this.loaderService.loading$(LoadingKey.Page).subscribe((loading) => {\r\n this.loading = loading;\r\n\r\n if (loading) {\r\n this.zIndexService.setItem(this.uuid);\r\n }\r\n });\r\n }\r\n}\r\n","<portal-header\r\n *ngIf=\"appInitService.siteConfiguration.PortalId\"\r\n [attr.data-behind]=\"behind\"\r\n [pageType]=\"pageType\"\r\n [headerType]=\"headerType\"\r\n [behind]=\"behind\"\r\n>\r\n</portal-header>\r\n<div id=\"content\">\r\n <router-outlet></router-outlet>\r\n</div>\r\n<portal-footer *ngIf=\"appInitService.siteConfiguration.PortalId\" class=\"screen\"></portal-footer>\r\n<portal-loader class=\"screen\"></portal-loader>\r\n<portal-dropdown-overlay class=\"screen\"></portal-dropdown-overlay>\r\n<lru-modal-outlet></lru-modal-outlet>\r\n<lru-dropdown-outlet></lru-dropdown-outlet>\r\n<lru-toast-message-list></lru-toast-message-list>\r\n","import { Component, ElementRef, HostListener, OnInit, Renderer2 } from '@angular/core';\r\nimport {\r\n NavigationCancel,\r\n NavigationEnd,\r\n NavigationError,\r\n NavigationStart,\r\n Router,\r\n RoutesRecognized,\r\n} from '@angular/router';\r\nimport { LoadingService } from '@lru/felib';\r\nimport { AppInitService } from '@portal-app/services/shared/app-init.service';\r\nimport { MouseAndKeyboardService } from '@portal-app/services/shared/mouse-and-keyboard.service';\r\nimport { HeaderTypeEnum } from './enums/header-type.enum';\r\nimport { LoadingKey } from './enums/loading-keys.enum';\r\nimport { PageTypeEnum } from './enums/page-type.enum';\r\nimport { DropdownService as DropdownServiceOld } from './services/shared/dropdown.service';\r\nimport { HeaderService } from './services/shared/header.service';\r\nimport { LayoutAudioService } from './services/shared/layout-audio.service';\r\nimport { PageService } from './services/shared/page/page.service';\r\n\r\n@Component({\r\n selector: 'portal-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.scss'],\r\n})\r\nexport class AppComponent implements OnInit {\r\n behind?: boolean;\r\n pageType?: PageTypeEnum;\r\n headerType?: HeaderTypeEnum;\r\n\r\n constructor(\r\n public appInitService: AppInitService,\r\n private router: Router,\r\n private mouseAndKeyboardService: MouseAndKeyboardService,\r\n private layoutAudioService: LayoutAudioService,\r\n private dropdownServiceOld: DropdownServiceOld,\r\n private renderer: Renderer2,\r\n private loadingService: LoadingService,\r\n private elementRef: ElementRef,\r\n private pageService: PageService,\r\n private headerService: HeaderService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.headerService.behind$.subscribe((behind) => {\r\n this.behind = behind;\r\n });\r\n\r\n const interval = setInterval(() => {\r\n if (getComputedStyle(this.elementRef.nativeElement).display === 'flex') {\r\n clearInterval(interval);\r\n this.renderer.setAttribute(this.elementRef.nativeElement, 'class', 'loaded');\r\n }\r\n }, 50);\r\n\r\n document.body.style.paddingRight = `${window.scrollbarWidth}px`;\r\n this.router.events.subscribe((event) => {\r\n if (event instanceof NavigationStart) {\r\n this.loadingService.start(LoadingKey.Page);\r\n this.layoutAudioService.removeAll();\r\n this.dropdownServiceOld.closeDropdown();\r\n }\r\n if (event instanceof NavigationEnd) {\r\n this.mouseAndKeyboardService.init();\r\n this.loadingService.stop(LoadingKey.Page);\r\n }\r\n\r\n // Set loading state to false in both of the below events to hide the spinner in case a request fails\r\n if (event instanceof NavigationCancel) {\r\n this.loadingService.stop(LoadingKey.Page);\r\n }\r\n if (event instanceof NavigationError) {\r\n this.loadingService.stop(LoadingKey.Page);\r\n }\r\n\r\n if (event instanceof RoutesRecognized) {\r\n this.pageType = event.state.root.firstChild?.data.pageType as PageTypeEnum;\r\n if (!this.pageType) {\r\n return;\r\n }\r\n this.headerService.setBehind(this.pageType);\r\n switch (event.state.root.firstChild?.data.pageType) {\r\n case PageTypeEnum.Book:\r\n this.headerType = HeaderTypeEnum.Book;\r\n break;\r\n case PageTypeEnum.CourseFrontpage:\r\n this.headerType = HeaderTypeEnum.Course;\r\n break;\r\n default:\r\n this.headerType = HeaderTypeEnum.Default;\r\n }\r\n this.pageService.contentPage$.subscribe((page) => {\r\n if (this.pageType) {\r\n this.headerService.setBehind(this.pageType, page?.hero ? true : false);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n @HostListener('document:keyup', ['$event'])\r\n handleKeyup(e: KeyboardEvent) {\r\n this.mouseAndKeyboardService.handleKeyup(e);\r\n }\r\n\r\n @HostListener('document:keydown', ['$event'])\r\n handleKeydown(e: KeyboardEvent) {\r\n this.mouseAndKeyboardService.handleKeydown(e);\r\n }\r\n\r\n @HostListener('document:touchstart', ['$event.target'])\r\n @HostListener('document:click', ['$event.target'])\r\n documentClick(target: HTMLElement) {\r\n this.mouseAndKeyboardService.documentClick(target);\r\n }\r\n}\r\n","import { HttpErrorResponse } from '@angular/common/http';\r\nimport { ErrorHandler, Injectable } from '@angular/core';\r\nimport { TranslateService } from '@ngx-translate/core';\r\n// import { ToastrService } from 'ngx-toastr';\r\n\r\n@Injectable()\r\nexport class GlobalErrorHandler extends ErrorHandler {\r\n constructor(private translateService: TranslateService) {\r\n // @Inject(Injector) private readonly injector: Injector\r\n super();\r\n }\r\n\r\n handleError(error: Error | HttpErrorResponse) {\r\n if (error instanceof HttpErrorResponse) {\r\n if (this.shouldHandleError(error.url || undefined)) {\r\n const _errorMessage: IErrorHttpErrorInterceptor = {\r\n title: `${error.status.toString()}: `,\r\n text: '',\r\n status: error.status,\r\n };\r\n switch (error.status) {\r\n case 400:\r\n _errorMessage.title += this.translateService.instant('GlobalError.400.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.400.Text');\r\n break;\r\n case 401:\r\n _errorMessage.title += this.translateService.instant('GlobalError.401.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.401.Text');\r\n break;\r\n case 403:\r\n _errorMessage.title += this.translateService.instant('GlobalError.403.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.403.Text');\r\n break;\r\n case 404:\r\n _errorMessage.title += this.translateService.instant('GlobalError.404.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.404.Text');\r\n break;\r\n case 500:\r\n _errorMessage.title += this.translateService.instant('GlobalError.500.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.500.Text');\r\n break;\r\n default:\r\n //// WE NEED MORE CASES ABOVE??\r\n _errorMessage.title += this.translateService.instant('GlobalError.Default.Title');\r\n _errorMessage.text = this.translateService.instant('GlobalError.Default.Text');\r\n break;\r\n }\r\n this.showToastr(_errorMessage, error.message);\r\n }\r\n } else {\r\n this.showToastr({ text: error.message }, error.message);\r\n }\r\n }\r\n\r\n /**\r\n * Need to get ToastrService from injector rather than constructor injection to avoid cyclic dependency error\r\n */\r\n // private get toastr(): ToastrService {\r\n // return this.injector.get(ToastrService);\r\n // }\r\n\r\n // private showToastr(message: string, title?: string, status?: number) {\r\n private showToastr(args: IErrorHttpErrorInterceptor, error: string) {\r\n switch (args.status) {\r\n case 400:\r\n // this.toastr.error(args.text, args.title);\r\n console.error(`${args.title}: ${args.text} - ${error}`);\r\n break;\r\n case 401:\r\n case 403:\r\n // this.toastr.warning(args.text, args.title);\r\n console.warn(`${args.title}: ${args.text} - ${error}`);\r\n break;\r\n case 404:\r\n case 500:\r\n // this.toastr.info(args.text, args.title);\r\n console.log(`${args.title}: ${args.text} - ${error}`);\r\n break;\r\n default:\r\n // this.toastr.show(args.text, args.title);\r\n console.log(`${args.title}: ${args.text} - ${error}`);\r\n break;\r\n }\r\n }\r\n\r\n private shouldHandleError(url?: string) {\r\n if (!url) {\r\n return true;\r\n }\r\n const ignore = [\r\n 'https://localhost:44375/Home/GetUserModel',\r\n 'http://localhost:55489/Home/GetUserModel',\r\n 'https://localhost:44375/Home/UpdateSiteManifest',\r\n 'http://localhost:55489/Home/UpdateSiteManifest',\r\n ];\r\n // return ignore.indexOf(url) === -1;\r\n return ignore.indexOf(url) === -1 && url.indexOf('/log/warn/message') === -1;\r\n }\r\n}\r\n\r\ninterface IErrorHttpErrorInterceptor {\r\n text: string;\r\n title?: string;\r\n status?: number;\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { BaseModule } from '@portal-app/modules/shared/base/base.module';\r\nimport { LibrarySearchModule } from '../../shared/library-search/library-search.module';\r\nimport { LayoutAudioModule } from '../layout-audio/layout-audio.module';\r\nimport { HeaderBookComponent } from './components/header-book/header-book.component';\r\nimport { HeaderCourseComponent } from './components/header-course/header-course.component';\r\nimport { HeaderDefaultComponent } from './components/header-default/header-default.component';\r\nimport { HeaderComponent } from './components/header/header.component';\r\nimport { MegaMenuComponent } from './components/mega-menu/mega-menu.component';\r\nimport { NavbarComponent } from './components/navbar/navbar.component';\r\nimport { UserComponent } from './components/user/user.component';\r\n\r\n@NgModule({\r\n declarations: [\r\n HeaderComponent,\r\n HeaderDefaultComponent,\r\n HeaderBookComponent,\r\n HeaderCourseComponent,\r\n NavbarComponent,\r\n MegaMenuComponent,\r\n UserComponent,\r\n ],\r\n imports: [CommonModule, BaseModule, LibrarySearchModule, LayoutAudioModule],\r\n exports: [HeaderComponent],\r\n})\r\nexport class HeaderModule {}\r\n","import { InjectionToken } from \"@angular/core\";\nimport { CustomFormatter } from \"@messageformat/core\";\n\nexport const MESSAGE_FORMAT_CONFIG = new InjectionToken<MessageFormatConfig>(\n \"MESSAGE_FORMAT_CONFIG\"\n);\n\nexport interface MessageFormatConfig {\n biDiSupport?: boolean;\n formatters?: {\n [key: string]: CustomFormatter;\n };\n strictNumberSign?: boolean;\n currency?: string;\n}\n\nexport const defaultConfig: MessageFormatConfig = {\n biDiSupport: false,\n formatters: {},\n strictNumberSign: false,\n currency: \"USD\",\n};\n","import { Inject, Injectable, Optional } from \"@angular/core\";\nimport { TranslateCompiler } from \"@ngx-translate/core\";\nimport MessageFormat, { MessageFormatOptions } from \"@messageformat/core\";\nimport {\n defaultConfig,\n MessageFormatConfig,\n MESSAGE_FORMAT_CONFIG,\n} from \"./message-format-config\";\n\n/**\n * This compiler expects ICU syntax and compiles the expressions with messageformat.js\n */\n@Injectable()\nexport class TranslateMessageFormatCompiler extends TranslateCompiler {\n private mfCache = new Map<string, MessageFormat>();\n private config: MessageFormatOptions<\"string\">;\n\n constructor(\n @Optional()\n @Inject(MESSAGE_FORMAT_CONFIG)\n config?: MessageFormatConfig\n ) {\n super();\n\n const {\n formatters: customFormatters,\n biDiSupport,\n strictNumberSign: strict,\n currency,\n } = {\n ...defaultConfig,\n ...config,\n };\n\n this.config = { customFormatters, biDiSupport, strict, currency };\n }\n\n public compile(value: string, lang: string): (params: any) => string {\n return this.getMessageFormatInstance(lang).compile(value);\n }\n\n public compileTranslations(translations: any, lang: string): any {\n if (typeof translations === \"string\") {\n return this.compile(translations, lang);\n }\n\n return Object.keys(translations).reduce<{ [key: string]: any }>(\n (acc, key) => {\n const value = translations[key];\n return { ...acc, [key]: this.compileTranslations(value, lang) };\n },\n {}\n );\n }\n\n private getMessageFormatInstance(locale: string): MessageFormat {\n if (!this.mfCache.has(locale)) {\n this.mfCache.set(\n locale,\n new MessageFormat<\"string\">(locale, this.config)\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.mfCache.get(locale)!;\n }\n}\n","import { HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\r\nimport { Injectable } from '@angular/core';\r\nimport { UserService } from '@lru/felib';\r\nimport { INextToken } from '@lru/felib/lib/services/core/user/interfaces/next-token.interface';\r\nimport { ReplaySubject } from 'rxjs';\r\nimport { first, mergeMap } from 'rxjs/operators';\r\nimport { environment } from '../../environments/environment';\r\n\r\n@Injectable()\r\nexport class RefreshTokenInterceptor implements HttpInterceptor {\r\n constructor(private userService: UserService) {}\r\n\r\n startRefresh(url: string) {\r\n const subject = new ReplaySubject<boolean>(1);\r\n if (this.userService.isLoggedIn && !this.userService.doNotTrack) {\r\n let expired = false;\r\n const expiresAt = this.userService.expiresAt;\r\n if (!expiresAt) {\r\n expired = true;\r\n } else {\r\n const expiresAtDate = new Date(expiresAt);\r\n const now = new Date();\r\n const expiresIn = expiresAtDate.getTime() - now.getTime();\r\n if (expiresIn < 0) {\r\n expired = true;\r\n }\r\n }\r\n if (expired) {\r\n // we only call api if it has expired\r\n try {\r\n fetch(\r\n `${environment.internalBackendUrl()}Login/RefreshToken?userid=${this.userService.userId}&contextid=${\r\n this.userService.contextIdentifier\r\n }`,\r\n {\r\n method: 'GET',\r\n credentials: 'include',\r\n }\r\n )\r\n .then((response) => {\r\n if (response.status === 503) {\r\n return;\r\n } else if (response.status === 200) {\r\n return response.json();\r\n } else {\r\n throw response;\r\n }\r\n })\r\n .then(\r\n (token: INextToken) => {\r\n if (token) {\r\n this.userService.setToken(token);\r\n }\r\n subject.next(true);\r\n },\r\n (error: HttpErrorResponse) => {\r\n this.userService.logout();\r\n }\r\n );\r\n } catch (e) {\r\n subject.next(true);\r\n }\r\n } else {\r\n subject.next(true);\r\n }\r\n } else {\r\n subject.next(true);\r\n }\r\n return subject;\r\n }\r\n\r\n intercept(req: HttpRequest<any>, next: HttpHandler) {\r\n return this.startRefresh(req.url).pipe(\r\n first(),\r\n mergeMap((success) => {\r\n return next.handle(req);\r\n })\r\n );\r\n }\r\n}\r\n","import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';\r\nimport { APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';\r\nimport { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog';\r\nimport { BrowserModule } from '@angular/platform-browser';\r\nimport { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';\r\nimport {\r\n ApiService,\r\n AuthInterceptor,\r\n CoreModule,\r\n DropdownModule,\r\n InitService,\r\n ModalModule,\r\n ToastModule,\r\n ZIndexModule,\r\n} from '@lru/felib';\r\nimport { NgbModule } from '@ng-bootstrap/ng-bootstrap';\r\nimport { EffectsModule } from '@ngrx/effects';\r\nimport { StoreModule } from '@ngrx/store';\r\nimport { StoreDevtoolsModule } from '@ngrx/store-devtools';\r\nimport { MissingTranslationHandler, TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core';\r\nimport { TranslateHttpLoader } from '@ngx-translate/http-loader';\r\n\r\nimport { AppRoutingModule } from '@portal-app/app-routing.module';\r\nimport { AppComponent } from '@portal-app/app.component';\r\nimport { DropdownOverlayComponent } from '@portal-app/components/dropdown-overlay/dropdown-overlay.component';\r\nimport { FooterComponent } from '@portal-app/components/footer/footer.component';\r\nimport { GlobalErrorHandler } from '@portal-app/modules/app/core/errors/global-error-handler';\r\nimport { HeaderModule } from '@portal-app/modules/app/header/header.module';\r\nimport { BaseModule } from '@portal-app/modules/shared/base/base.module';\r\nimport { WindowScrollService } from '@portal-app/services/shared/window-scroll.service';\r\nimport { environment } from '@portal-env/environment';\r\nimport { NgResizeObserverPonyfillModule } from 'ng-resize-observer';\r\nimport { ToastrModule } from 'ngx-toastr';\r\nimport { TranslateMessageFormatCompiler } from 'ngx-translate-messageformat-compiler';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { LoaderComponent } from './components/loader/loader.component';\r\nimport { SpinnerComponent } from './components/spinner/spinner.component';\r\nimport { ProjectTypeEnum } from './enums/project-type.enum';\r\nimport { MissingTranslationHelper } from './helpers/missing-translation.helper';\r\nimport { RefreshTokenInterceptor } from './interceptors/refreshToken.interceptor';\r\nimport { IError } from './interfaces/project/error.interface';\r\nimport { UmbLanguageType } from './interfaces/umbraco/umb-language.type';\r\nimport { TeacherDashboardStoreEffects } from './modules/routes/book-teacher-dashboard/store/teacher-dashboard.effects';\r\nimport { NextImagePipe } from './pipes/next-image.pipe';\r\nimport { AppInitService } from './services/shared/app-init.service';\r\nimport { PageService } from './services/shared/page/page.service';\r\nimport { ScriptService } from './services/shared/script.service';\r\n\r\nexport function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {\r\n return new TranslateHttpLoader(http);\r\n}\r\n\r\n@NgModule({\r\n declarations: [AppComponent, DropdownOverlayComponent, FooterComponent, LoaderComponent],\r\n imports: [\r\n SpinnerComponent,\r\n TranslateModule.forRoot({\r\n compiler: {\r\n provide: TranslateCompiler,\r\n useClass: TranslateMessageFormatCompiler,\r\n },\r\n loader: {\r\n provide: TranslateLoader,\r\n useFactory: HttpLoaderFactory,\r\n deps: [HttpClient],\r\n },\r\n }),\r\n ModalModule.forRoot({\r\n width: '630px',\r\n // maxWidth: 'calc(100vw - 40px)',\r\n // maxHeight: 'calc(100vh - 40px)',\r\n useTransition: true,\r\n }),\r\n DropdownModule.forRoot({}),\r\n NgResizeObserverPonyfillModule,\r\n HeaderModule,\r\n BrowserModule,\r\n AppRoutingModule,\r\n HttpClientModule,\r\n MatDialogModule,\r\n BrowserAnimationsModule,\r\n ToastrModule.forRoot({\r\n positionClass: 'toast-top-center',\r\n onActivateTick: true,\r\n enableHtml: true,\r\n progressBar: false,\r\n timeOut: 2000,\r\n extendedTimeOut: 2000,\r\n }),\r\n StoreModule.forRoot({}),\r\n EffectsModule.forRoot([TeacherDashboardStoreEffects]),\r\n !environment.production ? StoreDevtoolsModule.instrument() : [],\r\n BaseModule,\r\n NgbModule,\r\n NoopAnimationsModule,\r\n CoreModule.forRoot({\r\n apiConfig: {\r\n apiLoungeBaseUrl: environment.apiLoungeBaseUrl,\r\n apiNextBaseUrl: environment.apiNextBaseUrl,\r\n apiNextSearchBaseUrl: environment.apiNextSearchBaseUrl,\r\n apiUmbracoBaseUrl: environment.apIUmbBaseUrl,\r\n internalBackendUrl: environment.internalBackendUrl(),\r\n loginUsingMvcDotNet: environment.loginUsingMvcDotNet,\r\n localHostname: environment.localHostName,\r\n },\r\n }),\r\n ToastModule.forRoot({}),\r\n ZIndexModule.forRoot({\r\n zIndex: 600,\r\n }),\r\n ],\r\n providers: [\r\n {\r\n provide: MissingTranslationHandler,\r\n useClass: MissingTranslationHelper,\r\n },\r\n { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },\r\n {\r\n provide: APP_INITIALIZER,\r\n useFactory: initializeApp,\r\n deps: [InitService, AppInitService, PageService],\r\n multi: true,\r\n },\r\n { provide: ErrorHandler, useClass: GlobalErrorHandler },\r\n {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: RefreshTokenInterceptor,\r\n multi: true,\r\n },\r\n ApiService,\r\n WindowScrollService,\r\n NextImagePipe,\r\n ScriptService,\r\n ],\r\n bootstrap: [AppComponent],\r\n})\r\nexport class AppModule {}\r\n\r\nexport function initializeApp(initService: InitService, appInitService: AppInitService, pageService: PageService) {\r\n return async () => {\r\n await initService.initializeLogin();\r\n return await appInitService.Init().catch(async (error: IError) => {\r\n await firstValueFrom(\r\n appInitService.setLang(environment.fallbackLanguage as UmbLanguageType, ProjectTypeEnum.Fagportal)\r\n );\r\n if (error?.StatusCode) {\r\n console.warn(`C# error: ${error}`);\r\n await pageService.showError(window.location.pathname, error.StatusCode);\r\n } else if (error?.Message) {\r\n console.warn(`C# error: ${error}`);\r\n await pageService.showError(window.location.pathname, 500);\r\n } else {\r\n await pageService.showError(window.location.pathname, 503);\r\n }\r\n });\r\n };\r\n}\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from '@portal-env/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic()\r\n .bootstrapModule(AppModule)\r\n .then(\r\n (a) => {\r\n // App is bootstrapped\r\n },\r\n (error) => {\r\n // There's a bootstrapping error\r\n console.error('Bootstrapping Error', error);\r\n }\r\n );\r\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MessageFormat = factory());\n})(this, (function () { 'use strict';\n\n /******************************************************************************\r\n Copyright (c) Microsoft Corporation.\r\n\r\n Permission to use, copy, modify, and/or distribute this software for any\r\n purpose with or without fee is hereby granted.\r\n\r\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\n REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\n AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\n INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\n LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\n OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\n PERFORMANCE OF THIS SOFTWARE.\r\n ***************************************************************************** */\n var __assign = function () {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };\n function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator,\n m = s && o[s],\n i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return {\n value: o && o[i++],\n done: !o\n };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n }\n function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o),\n r,\n ar = [],\n e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n } catch (error) {\n e = {\n error: error\n };\n } finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n } finally {\n if (e) throw e.error;\n }\n }\n return ar;\n }\n function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n }\n\n /**\n * Parent class for errors.\n *\n * @remarks\n * Errors with `type: \"warning\"` do not necessarily indicate that the parser\n * encountered an error. In addition to a human-friendly `message`, may also\n * includes the `token` at which the error was encountered.\n *\n * @public\n */\n class DateFormatError extends Error {\n /** @internal */\n constructor(msg, token, type) {\n super(msg);\n this.token = token;\n this.type = type || 'error';\n }\n }\n const alpha = width => width < 4 ? 'short' : width === 4 ? 'long' : 'narrow';\n const numeric = width => width % 2 === 0 ? '2-digit' : 'numeric';\n function yearOptions(token, onError) {\n switch (token.char) {\n case 'y':\n return {\n year: numeric(token.width)\n };\n case 'r':\n return {\n calendar: 'gregory',\n year: 'numeric'\n };\n case 'u':\n case 'U':\n case 'Y':\n default:\n onError(`${token.desc} is not supported; falling back to year:numeric`, DateFormatError.WARNING);\n return {\n year: 'numeric'\n };\n }\n }\n function monthStyle(token, onError) {\n switch (token.width) {\n case 1:\n return 'numeric';\n case 2:\n return '2-digit';\n case 3:\n return 'short';\n case 4:\n return 'long';\n case 5:\n return 'narrow';\n default:\n onError(`${token.desc} is not supported with width ${token.width}`);\n return undefined;\n }\n }\n function dayStyle(token, onError) {\n const {\n char,\n desc,\n width\n } = token;\n if (char === 'd') return numeric(width);else {\n onError(`${desc} is not supported`);\n return undefined;\n }\n }\n function weekdayStyle(token, onError) {\n const {\n char,\n desc,\n width\n } = token;\n if ((char === 'c' || char === 'e') && width < 3) {\n // ignoring stand-alone-ness\n const msg = `Numeric value is not supported for ${desc}; falling back to weekday:short`;\n onError(msg, DateFormatError.WARNING);\n }\n // merging narrow styles\n return alpha(width);\n }\n function hourOptions(token) {\n const hour = numeric(token.width);\n let hourCycle;\n switch (token.char) {\n case 'h':\n hourCycle = 'h12';\n break;\n case 'H':\n hourCycle = 'h23';\n break;\n case 'k':\n hourCycle = 'h24';\n break;\n case 'K':\n hourCycle = 'h11';\n break;\n }\n return hourCycle ? {\n hour,\n hourCycle\n } : {\n hour\n };\n }\n function timeZoneNameStyle(token, onError) {\n // so much fallback behaviour here\n const {\n char,\n desc,\n width\n } = token;\n switch (char) {\n case 'v':\n case 'z':\n return width === 4 ? 'long' : 'short';\n case 'V':\n if (width === 4) return 'long';\n onError(`${desc} is not supported with width ${width}`);\n return undefined;\n case 'X':\n onError(`${desc} is not supported`);\n return undefined;\n }\n return 'short';\n }\n function compileOptions(token, onError) {\n switch (token.field) {\n case 'era':\n return {\n era: alpha(token.width)\n };\n case 'year':\n return yearOptions(token, onError);\n case 'month':\n return {\n month: monthStyle(token, onError)\n };\n case 'day':\n return {\n day: dayStyle(token, onError)\n };\n case 'weekday':\n return {\n weekday: weekdayStyle(token, onError)\n };\n case 'period':\n return undefined;\n case 'hour':\n return hourOptions(token);\n case 'min':\n return {\n minute: numeric(token.width)\n };\n case 'sec':\n return {\n second: numeric(token.width)\n };\n case 'tz':\n return {\n timeZoneName: timeZoneNameStyle(token, onError)\n };\n case 'quarter':\n case 'week':\n case 'sec-frac':\n case 'ms':\n onError(`${token.desc} is not supported`);\n }\n return undefined;\n }\n function getDateFormatOptions(tokens) {\n let onError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : error => {\n throw error;\n };\n const options = {};\n const fields = [];\n for (const token of tokens) {\n const {\n error,\n field,\n str\n } = token;\n if (error) {\n const dte = new DateFormatError(error.message, token);\n dte.stack = error.stack;\n onError(dte);\n }\n if (str) {\n const msg = `Ignoring string part: ${str}`;\n onError(new DateFormatError(msg, token, DateFormatError.WARNING));\n }\n if (field) {\n if (fields.indexOf(field) === -1) fields.push(field);else onError(new DateFormatError(`Duplicate ${field} token`, token));\n }\n const opt = compileOptions(token, (msg, isWarning) => onError(new DateFormatError(msg, token, isWarning)));\n if (opt) Object.assign(options, opt);\n }\n return options;\n }\n\n const fields = {\n G: {\n field: 'era',\n desc: 'Era'\n },\n y: {\n field: 'year',\n desc: 'Year'\n },\n Y: {\n field: 'year',\n desc: 'Year of \"Week of Year\"'\n },\n u: {\n field: 'year',\n desc: 'Extended year'\n },\n U: {\n field: 'year',\n desc: 'Cyclic year name'\n },\n r: {\n field: 'year',\n desc: 'Related Gregorian year'\n },\n Q: {\n field: 'quarter',\n desc: 'Quarter'\n },\n q: {\n field: 'quarter',\n desc: 'Stand-alone quarter'\n },\n M: {\n field: 'month',\n desc: 'Month in year'\n },\n L: {\n field: 'month',\n desc: 'Stand-alone month in year'\n },\n w: {\n field: 'week',\n desc: 'Week of year'\n },\n W: {\n field: 'week',\n desc: 'Week of month'\n },\n d: {\n field: 'day',\n desc: 'Day in month'\n },\n D: {\n field: 'day',\n desc: 'Day of year'\n },\n F: {\n field: 'day',\n desc: 'Day of week in month'\n },\n g: {\n field: 'day',\n desc: 'Modified julian day'\n },\n E: {\n field: 'weekday',\n desc: 'Day of week'\n },\n e: {\n field: 'weekday',\n desc: 'Local day of week'\n },\n c: {\n field: 'weekday',\n desc: 'Stand-alone local day of week'\n },\n a: {\n field: 'period',\n desc: 'AM/PM marker'\n },\n b: {\n field: 'period',\n desc: 'AM/PM/noon/midnight marker'\n },\n B: {\n field: 'period',\n desc: 'Flexible day period'\n },\n h: {\n field: 'hour',\n desc: 'Hour in AM/PM (1~12)'\n },\n H: {\n field: 'hour',\n desc: 'Hour in day (0~23)'\n },\n k: {\n field: 'hour',\n desc: 'Hour in day (1~24)'\n },\n K: {\n field: 'hour',\n desc: 'Hour in AM/PM (0~11)'\n },\n j: {\n field: 'hour',\n desc: 'Hour in preferred cycle'\n },\n J: {\n field: 'hour',\n desc: 'Hour in preferred cycle without marker'\n },\n C: {\n field: 'hour',\n desc: 'Hour in preferred cycle with flexible marker'\n },\n m: {\n field: 'min',\n desc: 'Minute in hour'\n },\n s: {\n field: 'sec',\n desc: 'Second in minute'\n },\n S: {\n field: 'sec-frac',\n desc: 'Fractional second'\n },\n A: {\n field: 'ms',\n desc: 'Milliseconds in day'\n },\n z: {\n field: 'tz',\n desc: 'Time Zone: specific non-location'\n },\n Z: {\n field: 'tz',\n desc: 'Time Zone'\n },\n O: {\n field: 'tz',\n desc: 'Time Zone: localized'\n },\n v: {\n field: 'tz',\n desc: 'Time Zone: generic non-location'\n },\n V: {\n field: 'tz',\n desc: 'Time Zone: ID'\n },\n X: {\n field: 'tz',\n desc: 'Time Zone: ISO8601 with Z'\n },\n x: {\n field: 'tz',\n desc: 'Time Zone: ISO8601'\n }\n };\n const isLetter = char => char >= 'A' && char <= 'Z' || char >= 'a' && char <= 'z';\n function readFieldToken(src, pos) {\n const char = src[pos];\n let width = 1;\n while (src[++pos] === char) ++width;\n const field = fields[char];\n if (!field) {\n const msg = `The letter ${char} is not a valid field identifier`;\n return {\n char,\n error: new Error(msg),\n width\n };\n }\n return {\n char,\n field: field.field,\n desc: field.desc,\n width\n };\n }\n function readQuotedToken(src, pos) {\n let str = src[++pos];\n let width = 2;\n if (str === \"'\") return {\n char: \"'\",\n str,\n width\n };\n while (true) {\n const next = src[++pos];\n ++width;\n if (next === undefined) {\n const msg = `Unterminated quoted literal in pattern: ${str || src}`;\n return {\n char: \"'\",\n error: new Error(msg),\n str,\n width\n };\n } else if (next === \"'\") {\n if (src[++pos] !== \"'\") return {\n char: \"'\",\n str,\n width\n };else ++width;\n }\n str += next;\n }\n }\n function readToken(src, pos) {\n const char = src[pos];\n if (!char) return null;\n if (isLetter(char)) return readFieldToken(src, pos);\n if (char === \"'\") return readQuotedToken(src, pos);\n let str = char;\n let width = 1;\n while (true) {\n const next = src[++pos];\n if (!next || isLetter(next) || next === \"'\") return {\n char,\n str,\n width\n };\n str += next;\n width += 1;\n }\n }\n /**\n * Parse an {@link http://userguide.icu-project.org/formatparse/datetime | ICU\n * DateFormat skeleton} string into a {@link DateToken} array.\n *\n * @remarks\n * Errors will not be thrown, but if encountered are included as the relevant\n * token's `error` value.\n *\n * @public\n * @param src - The skeleton string\n *\n * @example\n * ```js\n * import { parseDateTokens } from '@messageformat/date-skeleton'\n *\n * parseDateTokens('GrMMMdd', console.error)\n * // [\n * // { char: 'G', field: 'era', desc: 'Era', width: 1 },\n * // { char: 'r', field: 'year', desc: 'Related Gregorian year', width: 1 },\n * // { char: 'M', field: 'month', desc: 'Month in year', width: 3 },\n * // { char: 'd', field: 'day', desc: 'Day in month', width: 2 }\n * // ]\n * ```\n */\n function parseDateTokens(src) {\n const tokens = [];\n let pos = 0;\n while (true) {\n const token = readToken(src, pos);\n if (!token) return tokens;\n tokens.push(token);\n pos += token.width;\n }\n }\n\n /**\n * Returns a date formatter function for the given locales and date skeleton\n *\n * @remarks\n * Uses `Intl.DateTimeFormat` internally.\n *\n * @public\n * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`\n * @param tokens - An ICU DateFormat skeleton string, or an array or parsed\n * `DateToken` tokens\n * @param onError - If defined, will be called separately for each encountered\n * parsing error and unsupported feature.\n * @example\n * ```js\n * import { getDateFormatter } from '@messageformat/date-skeleton'\n *\n * // 2006 Jan 2, 15:04:05.789 in local time\n * const date = new Date(2006, 0, 2, 15, 4, 5, 789)\n *\n * let fmt = getDateFormatter('en-CA', 'GrMMMdd', console.error)\n * fmt(date) // 'Jan. 02, 2006 AD'\n *\n * fmt = getDateFormatter('en-CA', 'hamszzzz', console.error)\n * fmt(date) // '3:04:05 p.m. Newfoundland Daylight Time'\n * ```\n */\n function getDateFormatter(locales, tokens, onError) {\n if (typeof tokens === 'string') tokens = parseDateTokens(tokens);\n const opt = getDateFormatOptions(tokens, onError);\n const dtf = new Intl.DateTimeFormat(locales, opt);\n return date => dtf.format(date);\n }\n /**\n * Returns a string of JavaScript source that evaluates to a date formatter\n * function with the same `(date: Date | number) => string` signature as the\n * function returned by {@link getDateFormatter}.\n *\n * @remarks\n * The returned function will memoize an `Intl.DateTimeFormat` instance.\n *\n * @public\n * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`\n * @param tokens - An ICU DateFormat skeleton string, or an array or parsed\n * `DateToken` tokens\n * @param onError - If defined, will be called separately for each encountered\n * parsing error and unsupported feature.\n * @example\n * ```js\n * import { getDateFormatterSource } from '@messageformat/date-skeleton'\n *\n * getDateFormatterSource('en-CA', 'GrMMMdd', console.error)\n * // '(function() {\\n' +\n * // ' var opt = {\"era\":\"short\",\"calendar\":\"gregory\",\"year\":\"numeric\",' +\n * // '\"month\":\"short\",\"day\":\"2-digit\"};\\n' +\n * // ' var dtf = new Intl.DateTimeFormat(\"en-CA\", opt);\\n' +\n * // ' return function(value) { return dtf.format(value); }\\n' +\n * // '})()'\n *\n * const src = getDateFormatterSource('en-CA', 'hamszzzz', console.error)\n * // '(function() {\\n' +\n * // ' var opt = {\"hour\":\"numeric\",\"hourCycle\":\"h12\",\"minute\":\"numeric\",' +\n * // '\"second\":\"numeric\",\"timeZoneName\":\"long\"};\\n' +\n * // ' var dtf = new Intl.DateTimeFormat(\"en-CA\", opt);\\n' +\n * // ' return function(value) { return dtf.format(value); }\\n' +\n * // '})()'\n *\n * const fmt = new Function(`return ${src}`)()\n * const date = new Date(2006, 0, 2, 15, 4, 5, 789)\n * fmt(date) // '3:04:05 p.m. Newfoundland Daylight Time'\n * ```\n */\n function getDateFormatterSource(locales, tokens, onError) {\n if (typeof tokens === 'string') tokens = parseDateTokens(tokens);\n const opt = getDateFormatOptions(tokens, onError);\n const lines = [`(function() {`, `var opt = ${JSON.stringify(opt)};`, `var dtf = new Intl.DateTimeFormat(${JSON.stringify(locales)}, opt);`, `return function(value) { return dtf.format(value); }`];\n return lines.join('\\n ') + '\\n})()';\n }\n\n /**\n * Base class for errors. In addition to a `code` and a human-friendly\n * `message`, may also includes the token `stem` as well as other fields.\n *\n * @public\n */\n class NumberFormatError extends Error {\n /** @internal */\n constructor(code, msg) {\n super(msg);\n this.code = code;\n }\n }\n /** @internal */\n class BadOptionError extends NumberFormatError {\n constructor(stem, opt) {\n super('BAD_OPTION', `Unknown ${stem} option: ${opt}`);\n this.stem = stem;\n this.option = opt;\n }\n }\n /** @internal */\n class BadStemError extends NumberFormatError {\n constructor(stem) {\n super('BAD_STEM', `Unknown stem: ${stem}`);\n this.stem = stem;\n }\n }\n /** @internal */\n class MaskedValueError extends NumberFormatError {\n constructor(type, prev) {\n super('MASKED_VALUE', `Value for ${type} is set multiple times`);\n this.type = type;\n this.prev = prev;\n }\n }\n /** @internal */\n class MissingOptionError extends NumberFormatError {\n constructor(stem) {\n super('MISSING_OPTION', `Required option missing for ${stem}`);\n this.stem = stem;\n }\n }\n /** @internal */\n class PatternError extends NumberFormatError {\n constructor(char, msg) {\n super('BAD_PATTERN', msg);\n this.char = char;\n }\n }\n /** @internal */\n class TooManyOptionsError extends NumberFormatError {\n constructor(stem, options, maxOpt) {\n const maxOptStr = maxOpt > 1 ? `${maxOpt} options` : 'one option';\n super('TOO_MANY_OPTIONS', `Token ${stem} only supports ${maxOptStr} (got ${options.length})`);\n this.stem = stem;\n this.options = options;\n }\n }\n /** @internal */\n class UnsupportedError extends NumberFormatError {\n constructor(stem, source) {\n super('UNSUPPORTED', `The stem ${stem} is not supported`);\n this.stem = stem;\n if (source) {\n this.message += ` with value ${source}`;\n this.source = source;\n }\n }\n }\n\n /**\n * Add\n * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation | numbering-system tags}\n * to locale identifiers\n *\n * @internal\n */\n function getNumberFormatLocales(locales, _ref) {\n let {\n numberingSystem\n } = _ref;\n if (!Array.isArray(locales)) locales = [locales];\n return numberingSystem ? locales.map(lc => {\n const ext = lc.indexOf('-u-') === -1 ? 'u-nu' : 'nu';\n return `${lc}-${ext}-${numberingSystem}`;\n }).concat(locales) : locales;\n }\n\n // from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n function round(x, precision) {\n const y = +x + precision / 2;\n return y - y % +precision;\n }\n function getNumberFormatMultiplier(_ref) {\n let {\n scale,\n unit\n } = _ref;\n let mult = typeof scale === 'number' && scale >= 0 ? scale : 1;\n if (unit && unit.style === 'percent') mult *= 0.01;\n return mult;\n }\n /**\n * Determine a modifier for the input value to account for any `scale`,\n * `percent`, and `precision-increment` tokens in the skeleton.\n *\n * @internal\n * @remarks\n * With ICU NumberFormatter, the `percent` skeleton would style `25` as \"25%\".\n * To achieve the same with `Intl.NumberFormat`, the input value must be `0.25`.\n */\n function getNumberFormatModifier(skeleton) {\n const mult = getNumberFormatMultiplier(skeleton);\n const {\n precision\n } = skeleton;\n if (precision && precision.style === 'precision-increment') {\n return n => round(n, precision.increment) * mult;\n } else {\n return n => n * mult;\n }\n }\n /**\n * Returns a string of JavaScript source that evaluates to a modifier for the\n * input value to account for any `scale`, `percent`, and `precision-increment`\n * tokens in the skeleton.\n *\n * @internal\n * @remarks\n * With ICU NumberFormatter, the `percent` skeleton would style `25` as \"25%\".\n * To achieve the same with `Intl.NumberFormat`, the input value must be `0.25`.\n */\n function getNumberFormatModifierSource(skeleton) {\n const mult = getNumberFormatMultiplier(skeleton);\n const {\n precision\n } = skeleton;\n if (precision && precision.style === 'precision-increment') {\n // see round() above for source\n const setX = `+n + ${precision.increment / 2}`;\n let res = `x - (x % +${precision.increment})`;\n if (mult !== 1) res = `(${res}) * ${mult}`;\n return `function(n) { var x = ${setX}; return ${res}; }`;\n }\n return mult !== 1 ? `function(n) { return n * ${mult}; }` : null;\n }\n\n /**\n * Given an input ICU NumberFormatter skeleton, does its best to construct a\n * corresponding `Intl.NumberFormat` options structure.\n *\n * @remarks\n * Some features depend on `Intl.NumberFormat` features defined in ES2020.\n *\n * @internal\n * @param onUnsupported - If defined, called when encountering unsupported (but\n * valid) tokens, such as `decimal-always` or `permille`. The error `source`\n * may specify the source of an unsupported option.\n *\n * @example\n * ```js\n * import {\n * getNumberFormatOptions,\n * parseNumberSkeleton\n * } from '@messageformat/number-skeleton'\n *\n * const src = 'currency/CAD unit-width-narrow'\n * const skeleton = parseNumberSkeleton(src, console.error)\n * // {\n * // unit: { style: 'currency', currency: 'CAD' },\n * // unitWidth: 'unit-width-narrow'\n * // }\n *\n * getNumberFormatOptions(skeleton, console.error)\n * // {\n * // style: 'currency',\n * // currency: 'CAD',\n * // currencyDisplay: 'narrowSymbol',\n * // unitDisplay: 'narrow'\n * // }\n *\n * const sk2 = parseNumberSkeleton('group-min2')\n * // { group: 'group-min2' }\n *\n * getNumberFormatOptions(sk2, console.error)\n * // Error: The stem group-min2 is not supported\n * // at UnsupportedError.NumberFormatError ... {\n * // code: 'UNSUPPORTED',\n * // stem: 'group-min2'\n * // }\n * // {}\n * ```\n */\n function getNumberFormatOptions(skeleton, onUnsupported) {\n const {\n decimal,\n group,\n integerWidth,\n notation,\n precision,\n roundingMode,\n sign,\n unit,\n unitPer,\n unitWidth\n } = skeleton;\n const fail = (stem, source) => {\n if (onUnsupported) onUnsupported(new UnsupportedError(stem, source));\n };\n const opt = {};\n if (unit) {\n switch (unit.style) {\n case 'base-unit':\n opt.style = 'decimal';\n break;\n case 'currency':\n opt.style = 'currency';\n opt.currency = unit.currency;\n break;\n case 'measure-unit':\n opt.style = 'unit';\n opt.unit = unit.unit.replace(/.*-/, '');\n if (unitPer) opt.unit += '-per-' + unitPer.replace(/.*-/, '');\n break;\n case 'percent':\n opt.style = 'percent';\n break;\n case 'permille':\n fail('permille');\n break;\n }\n }\n switch (unitWidth) {\n case 'unit-width-full-name':\n opt.currencyDisplay = 'name';\n opt.unitDisplay = 'long';\n break;\n case 'unit-width-hidden':\n fail(unitWidth);\n break;\n case 'unit-width-iso-code':\n opt.currencyDisplay = 'code';\n break;\n case 'unit-width-narrow':\n opt.currencyDisplay = 'narrowSymbol';\n opt.unitDisplay = 'narrow';\n break;\n case 'unit-width-short':\n opt.currencyDisplay = 'symbol';\n opt.unitDisplay = 'short';\n break;\n }\n switch (group) {\n case 'group-off':\n opt.useGrouping = false;\n break;\n case 'group-auto':\n opt.useGrouping = true;\n break;\n case 'group-min2':\n case 'group-on-aligned':\n case 'group-thousands':\n fail(group);\n opt.useGrouping = true;\n break;\n }\n if (precision) {\n switch (precision.style) {\n case 'precision-fraction':\n {\n const {\n minFraction: minF,\n maxFraction: maxF,\n minSignificant: minS,\n maxSignificant: maxS,\n source\n } = precision;\n if (typeof minF === 'number') {\n opt.minimumFractionDigits = minF;\n if (typeof minS === 'number') fail('precision-fraction', source);\n }\n if (typeof maxF === 'number') opt.maximumFractionDigits = maxF;\n if (typeof minS === 'number') opt.minimumSignificantDigits = minS;\n if (typeof maxS === 'number') opt.maximumSignificantDigits = maxS;\n break;\n }\n case 'precision-integer':\n opt.maximumFractionDigits = 0;\n break;\n case 'precision-unlimited':\n opt.maximumFractionDigits = 20;\n break;\n case 'precision-increment':\n case 'precision-currency-standard':\n break;\n case 'precision-currency-cash':\n fail(precision.style);\n break;\n }\n }\n if (notation) {\n switch (notation.style) {\n case 'compact-short':\n opt.notation = 'compact';\n opt.compactDisplay = 'short';\n break;\n case 'compact-long':\n opt.notation = 'compact';\n opt.compactDisplay = 'long';\n break;\n case 'notation-simple':\n opt.notation = 'standard';\n break;\n case 'scientific':\n case 'engineering':\n {\n const {\n expDigits,\n expSign,\n source,\n style\n } = notation;\n opt.notation = style;\n if (expDigits && expDigits > 1 || expSign && expSign !== 'sign-auto') fail(style, source);\n break;\n }\n }\n }\n if (integerWidth) {\n const {\n min,\n max,\n source\n } = integerWidth;\n if (min > 0) opt.minimumIntegerDigits = min;\n if (Number(max) > 0) {\n const hasExp = opt.notation === 'engineering' || opt.notation === 'scientific';\n if (max === 3 && hasExp) opt.notation = 'engineering';else fail('integer-width', source);\n }\n }\n switch (sign) {\n case 'sign-auto':\n opt.signDisplay = 'auto';\n break;\n case 'sign-always':\n opt.signDisplay = 'always';\n break;\n case 'sign-except-zero':\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore https://github.com/microsoft/TypeScript/issues/46712\n opt.signDisplay = 'exceptZero';\n break;\n case 'sign-never':\n opt.signDisplay = 'never';\n break;\n case 'sign-accounting':\n opt.currencySign = 'accounting';\n break;\n case 'sign-accounting-always':\n opt.currencySign = 'accounting';\n opt.signDisplay = 'always';\n break;\n case 'sign-accounting-except-zero':\n opt.currencySign = 'accounting';\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore https://github.com/microsoft/TypeScript/issues/46712\n opt.signDisplay = 'exceptZero';\n break;\n }\n if (decimal === 'decimal-always') fail(decimal);\n if (roundingMode) fail(roundingMode);\n return opt;\n }\n\n function parseAffixToken(src, pos, onError) {\n const char = src[pos];\n switch (char) {\n case '%':\n return {\n char: '%',\n style: 'percent',\n width: 1\n };\n case '‰':\n return {\n char: '%',\n style: 'permille',\n width: 1\n };\n case '¤':\n {\n let width = 1;\n while (src[++pos] === '¤') ++width;\n switch (width) {\n case 1:\n return {\n char,\n currency: 'default',\n width\n };\n case 2:\n return {\n char,\n currency: 'iso-code',\n width\n };\n case 3:\n return {\n char,\n currency: 'full-name',\n width\n };\n case 5:\n return {\n char,\n currency: 'narrow',\n width\n };\n default:\n {\n const msg = `Invalid number (${width}) of ¤ chars in pattern`;\n onError(new PatternError('¤', msg));\n return null;\n }\n }\n }\n case '*':\n {\n const pad = src[pos + 1];\n if (pad) return {\n char,\n pad,\n width: 2\n };\n break;\n }\n case '+':\n case '-':\n return {\n char,\n width: 1\n };\n case \"'\":\n {\n let str = src[++pos];\n let width = 2;\n if (str === \"'\") return {\n char,\n str,\n width\n };\n while (true) {\n const next = src[++pos];\n ++width;\n if (next === undefined) {\n const msg = `Unterminated quoted literal in pattern: ${str}`;\n onError(new PatternError(\"'\", msg));\n return {\n char,\n str,\n width\n };\n } else if (next === \"'\") {\n if (src[++pos] !== \"'\") return {\n char,\n str,\n width\n };else ++width;\n }\n str += next;\n }\n }\n }\n return null;\n }\n\n const isDigit = char => char >= '0' && char <= '9';\n function parseNumberToken(src, pos) {\n const char = src[pos];\n if (isDigit(char)) {\n let digits = char;\n while (true) {\n const next = src[++pos];\n if (isDigit(next)) digits += next;else return {\n char: '0',\n digits,\n width: digits.length\n };\n }\n }\n switch (char) {\n case '#':\n {\n let width = 1;\n while (src[++pos] === '#') ++width;\n return {\n char,\n width\n };\n }\n case '@':\n {\n let min = 1;\n while (src[++pos] === '@') ++min;\n let width = min;\n pos -= 1;\n while (src[++pos] === '#') ++width;\n return {\n char,\n min,\n width\n };\n }\n case 'E':\n {\n const plus = src[pos + 1] === '+';\n if (plus) ++pos;\n let expDigits = 0;\n while (src[++pos] === '0') ++expDigits;\n const width = (plus ? 2 : 1) + expDigits;\n if (expDigits) return {\n char,\n expDigits,\n plus,\n width\n };else break;\n }\n case '.':\n case ',':\n return {\n char,\n width: 1\n };\n }\n return null;\n }\n\n function parseSubpattern(src, pos, onError) {\n let State;\n (function (State) {\n State[State[\"Prefix\"] = 0] = \"Prefix\";\n State[State[\"Number\"] = 1] = \"Number\";\n State[State[\"Suffix\"] = 2] = \"Suffix\";\n })(State || (State = {}));\n const prefix = [];\n const number = [];\n const suffix = [];\n let state = State.Prefix;\n let str = '';\n while (pos < src.length) {\n const char = src[pos];\n if (char === ';') {\n pos += 1;\n break;\n }\n switch (state) {\n case State.Prefix:\n {\n const token = parseAffixToken(src, pos, onError);\n if (token) {\n if (str) {\n prefix.push({\n char: \"'\",\n str,\n width: str.length\n });\n str = '';\n }\n prefix.push(token);\n pos += token.width;\n } else {\n const token = parseNumberToken(src, pos);\n if (token) {\n if (str) {\n prefix.push({\n char: \"'\",\n str,\n width: str.length\n });\n str = '';\n }\n state = State.Number;\n number.push(token);\n pos += token.width;\n } else {\n str += char;\n pos += 1;\n }\n }\n break;\n }\n case State.Number:\n {\n const token = parseNumberToken(src, pos);\n if (token) {\n number.push(token);\n pos += token.width;\n } else {\n state = State.Suffix;\n }\n break;\n }\n case State.Suffix:\n {\n const token = parseAffixToken(src, pos, onError);\n if (token) {\n if (str) {\n suffix.push({\n char: \"'\",\n str,\n width: str.length\n });\n str = '';\n }\n suffix.push(token);\n pos += token.width;\n } else {\n str += char;\n pos += 1;\n }\n break;\n }\n }\n }\n if (str) suffix.push({\n char: \"'\",\n str,\n width: str.length\n });\n return {\n pattern: {\n prefix,\n number,\n suffix\n },\n pos\n };\n }\n function parseTokens(src, onError) {\n const {\n pattern,\n pos\n } = parseSubpattern(src, 0, onError);\n if (pos < src.length) {\n const {\n pattern: negative\n } = parseSubpattern(src, pos, onError);\n return {\n tokens: pattern,\n negative\n };\n }\n return {\n tokens: pattern\n };\n }\n\n function parseNumberAsSkeleton(tokens, onError) {\n const res = {};\n let hasGroups = false;\n let hasExponent = false;\n let intOptional = 0;\n let intDigits = '';\n let decimalPos = -1;\n let fracDigits = '';\n let fracOptional = 0;\n for (let pos = 0; pos < tokens.length; ++pos) {\n const token = tokens[pos];\n switch (token.char) {\n case '#':\n {\n if (decimalPos === -1) {\n if (intDigits) {\n const msg = 'Pattern has # after integer digits';\n onError(new PatternError('#', msg));\n }\n intOptional += token.width;\n } else {\n fracOptional += token.width;\n }\n break;\n }\n case '0':\n {\n if (decimalPos === -1) {\n intDigits += token.digits;\n } else {\n if (fracOptional) {\n const msg = 'Pattern has digits after # in fraction';\n onError(new PatternError('0', msg));\n }\n fracDigits += token.digits;\n }\n break;\n }\n case '@':\n {\n if (res.precision) onError(new MaskedValueError('precision', res.precision));\n res.precision = {\n style: 'precision-fraction',\n minSignificant: token.min,\n maxSignificant: token.width\n };\n break;\n }\n case ',':\n hasGroups = true;\n break;\n case '.':\n if (decimalPos === 1) {\n const msg = 'Pattern has more than one decimal separator';\n onError(new PatternError('.', msg));\n }\n decimalPos = pos;\n break;\n case 'E':\n {\n if (hasExponent) onError(new MaskedValueError('exponent', res.notation));\n if (hasGroups) {\n const msg = 'Exponential patterns may not contain grouping separators';\n onError(new PatternError('E', msg));\n }\n res.notation = {\n style: 'scientific'\n };\n if (token.expDigits > 1) res.notation.expDigits = token.expDigits;\n if (token.plus) res.notation.expSign = 'sign-always';\n hasExponent = true;\n }\n }\n }\n // imprecise mapping due to paradigm differences\n if (hasGroups) res.group = 'group-auto';else if (intOptional + intDigits.length > 3) res.group = 'group-off';\n const increment = Number(`${intDigits || '0'}.${fracDigits}`);\n if (increment) res.precision = {\n style: 'precision-increment',\n increment\n };\n if (!hasExponent) {\n if (intDigits.length > 1) res.integerWidth = {\n min: intDigits.length\n };\n if (!res.precision && (fracDigits.length || fracOptional)) {\n res.precision = {\n style: 'precision-fraction',\n minFraction: fracDigits.length,\n maxFraction: fracDigits.length + fracOptional\n };\n }\n } else {\n if (!res.precision || increment) {\n res.integerWidth = intOptional ? {\n min: 1,\n max: intOptional + intDigits.length\n } : {\n min: Math.max(1, intDigits.length)\n };\n }\n if (res.precision) {\n if (!increment) res.integerWidth = {\n min: 1,\n max: 1\n };\n } else {\n const dc = intDigits.length + fracDigits.length;\n if (decimalPos === -1) {\n if (dc > 0) res.precision = {\n style: 'precision-fraction',\n maxSignificant: dc\n };\n } else {\n res.precision = {\n style: 'precision-fraction',\n maxSignificant: Math.max(1, dc) + fracOptional\n };\n if (dc > 1) res.precision.minSignificant = dc;\n }\n }\n }\n return res;\n }\n\n function handleAffix(affixTokens, res, currency, onError, isPrefix) {\n let inFmt = false;\n let str = '';\n for (const token of affixTokens) {\n switch (token.char) {\n case '%':\n res.unit = {\n style: token.style\n };\n if (isPrefix) inFmt = true;else str = '';\n break;\n case '¤':\n if (!currency) {\n const msg = `The ¤ pattern requires a currency`;\n onError(new PatternError('¤', msg));\n break;\n }\n res.unit = {\n style: 'currency',\n currency\n };\n switch (token.currency) {\n case 'iso-code':\n res.unitWidth = 'unit-width-iso-code';\n break;\n case 'full-name':\n res.unitWidth = 'unit-width-full-name';\n break;\n case 'narrow':\n res.unitWidth = 'unit-width-narrow';\n break;\n }\n if (isPrefix) inFmt = true;else str = '';\n break;\n case '*':\n // TODO\n break;\n case '+':\n if (!inFmt) str += '+';\n break;\n case \"'\":\n if (!inFmt) str += token.str;\n break;\n }\n }\n return str;\n }\n function getNegativeAffix(affixTokens, isPrefix) {\n let inFmt = false;\n let str = '';\n for (const token of affixTokens) {\n switch (token.char) {\n case '%':\n case '¤':\n if (isPrefix) inFmt = true;else str = '';\n break;\n case '-':\n if (!inFmt) str += '-';\n break;\n case \"'\":\n if (!inFmt) str += token.str;\n break;\n }\n }\n return str;\n }\n /**\n * Parse an {@link\n * http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns |\n * ICU NumberFormatter pattern} string into a {@link Skeleton} structure.\n *\n * @public\n * @param src - The pattern string\n * @param currency - If the pattern includes ¤ tokens, their skeleton\n * representation requires a three-letter currency code.\n * @param onError - Called when the parser encounters a syntax error. The\n * function will still return a {@link Skeleton}, but it will be incomplete\n * and/or inaccurate. If not defined, the error will be thrown instead.\n *\n * @remarks\n * Unlike the skeleton parser, the pattern parser is not able to return partial\n * results on error, and will instead throw. Output padding is not supported.\n *\n * @example\n * ```js\n * import { parseNumberPattern } from '@messageformat/number-skeleton'\n *\n * parseNumberPattern('#,##0.00 ¤', 'EUR', console.error)\n * // {\n * // group: 'group-auto',\n * // precision: {\n * // style: 'precision-fraction',\n * // minFraction: 2,\n * // maxFraction: 2\n * // },\n * // unit: { style: 'currency', currency: 'EUR' }\n * // }\n * ```\n */\n function parseNumberPattern(src, currency) {\n let onError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : error => {\n throw error;\n };\n const {\n tokens,\n negative\n } = parseTokens(src, onError);\n const res = parseNumberAsSkeleton(tokens.number, onError);\n const prefix = handleAffix(tokens.prefix, res, currency, onError, true);\n const suffix = handleAffix(tokens.suffix, res, currency, onError, false);\n if (negative) {\n const negPrefix = getNegativeAffix(negative.prefix, true);\n const negSuffix = getNegativeAffix(negative.suffix, false);\n res.affix = {\n pos: [prefix, suffix],\n neg: [negPrefix, negSuffix]\n };\n res.sign = 'sign-never';\n } else if (prefix || suffix) {\n res.affix = {\n pos: [prefix, suffix]\n };\n }\n return res;\n }\n\n /** @internal */\n function isNumberingSystem(ns) {\n const systems = ['arab', 'arabext', 'bali', 'beng', 'deva', 'fullwide', 'gujr', 'guru', 'hanidec', 'khmr', 'knda', 'laoo', 'latn', 'limb', 'mlym', 'mong', 'mymr', 'orya', 'tamldec', 'telu', 'thai', 'tibt'];\n return systems.indexOf(ns) !== -1;\n }\n\n // FIXME: subtype is not checked\n /** @internal */\n function isUnit(unit) {\n const types = ['acceleration', 'angle', 'area', 'concentr', 'consumption', 'digital', 'duration', 'electric', 'energy', 'force', 'frequency', 'graphics', 'length', 'light', 'mass', 'power', 'pressure', 'speed', 'temperature', 'torque', 'volume'];\n const [type] = unit.split('-', 1);\n return types.indexOf(type) !== -1;\n }\n\n const maxOptions = {\n 'compact-short': 0,\n 'compact-long': 0,\n 'notation-simple': 0,\n scientific: 2,\n engineering: 2,\n percent: 0,\n permille: 0,\n 'base-unit': 0,\n currency: 1,\n 'measure-unit': 1,\n 'per-measure-unit': 1,\n 'unit-width-narrow': 0,\n 'unit-width-short': 0,\n 'unit-width-full-name': 0,\n 'unit-width-iso-code': 0,\n 'unit-width-hidden': 0,\n 'precision-integer': 0,\n 'precision-unlimited': 0,\n 'precision-currency-standard': 0,\n 'precision-currency-cash': 0,\n 'precision-increment': 1,\n 'rounding-mode-ceiling': 0,\n 'rounding-mode-floor': 0,\n 'rounding-mode-down': 0,\n 'rounding-mode-up': 0,\n 'rounding-mode-half-even': 0,\n 'rounding-mode-half-down': 0,\n 'rounding-mode-half-up': 0,\n 'rounding-mode-unnecessary': 0,\n 'integer-width': 1,\n scale: 1,\n 'group-off': 0,\n 'group-min2': 0,\n 'group-auto': 0,\n 'group-on-aligned': 0,\n 'group-thousands': 0,\n latin: 0,\n 'numbering-system': 1,\n 'sign-auto': 0,\n 'sign-always': 0,\n 'sign-never': 0,\n 'sign-accounting': 0,\n 'sign-accounting-always': 0,\n 'sign-except-zero': 0,\n 'sign-accounting-except-zero': 0,\n 'decimal-auto': 0,\n 'decimal-always': 0\n };\n const minOptions = {\n currency: 1,\n 'integer-width': 1,\n 'measure-unit': 1,\n 'numbering-system': 1,\n 'per-measure-unit': 1,\n 'precision-increment': 1,\n scale: 1\n };\n function hasMaxOption(stem) {\n return stem in maxOptions;\n }\n function hasMinOption(stem) {\n return stem in minOptions;\n }\n /** @internal */\n function validOptions(stem, options, onError) {\n if (hasMaxOption(stem)) {\n const maxOpt = maxOptions[stem];\n if (options.length > maxOpt) {\n if (maxOpt === 0) {\n for (const opt of options) onError(new BadOptionError(stem, opt));\n } else {\n onError(new TooManyOptionsError(stem, options, maxOpt));\n }\n return false;\n } else if (hasMinOption(stem) && options.length < minOptions[stem]) {\n onError(new MissingOptionError(stem));\n return false;\n }\n }\n return true;\n }\n\n function parseBlueprintDigits(src, style) {\n const re = style === 'fraction' ? /^\\.(0*)(\\+|#*)$/ : /^(@+)(\\+|#*)$/;\n const match = src && src.match(re);\n if (match) {\n const min = match[1].length;\n switch (match[2].charAt(0)) {\n case '':\n return {\n min,\n max: min\n };\n case '+':\n return {\n min,\n max: null\n };\n case '#':\n {\n return {\n min,\n max: min + match[2].length\n };\n }\n }\n }\n return null;\n }\n function parsePrecisionBlueprint(stem, options, onError) {\n const fd = parseBlueprintDigits(stem, 'fraction');\n if (fd) {\n if (options.length > 1) onError(new TooManyOptionsError(stem, options, 1));\n const res = {\n style: 'precision-fraction',\n source: stem,\n minFraction: fd.min\n };\n if (fd.max != null) res.maxFraction = fd.max;\n const option = options[0];\n const sd = parseBlueprintDigits(option, 'significant');\n if (sd) {\n res.source = `${stem}/${option}`;\n res.minSignificant = sd.min;\n if (sd.max != null) res.maxSignificant = sd.max;\n } else if (option) onError(new BadOptionError(stem, option));\n return res;\n }\n const sd = parseBlueprintDigits(stem, 'significant');\n if (sd) {\n for (const opt of options) onError(new BadOptionError(stem, opt));\n const res = {\n style: 'precision-fraction',\n source: stem,\n minSignificant: sd.min\n };\n if (sd.max != null) res.maxSignificant = sd.max;\n return res;\n }\n return null;\n }\n\n /** @internal */\n class TokenParser {\n constructor(onError) {\n this.skeleton = {};\n this.onError = onError;\n }\n badOption(stem, opt) {\n this.onError(new BadOptionError(stem, opt));\n }\n assertEmpty(key) {\n const prev = this.skeleton[key];\n if (prev) this.onError(new MaskedValueError(key, prev));\n }\n parseToken(stem, options) {\n if (!validOptions(stem, options, this.onError)) return;\n const option = options[0];\n const res = this.skeleton;\n switch (stem) {\n // notation\n case 'compact-short':\n case 'compact-long':\n case 'notation-simple':\n this.assertEmpty('notation');\n res.notation = {\n style: stem\n };\n break;\n case 'scientific':\n case 'engineering':\n {\n let expDigits = null;\n let expSign = undefined;\n for (const opt of options) {\n switch (opt) {\n case 'sign-auto':\n case 'sign-always':\n case 'sign-never':\n case 'sign-accounting':\n case 'sign-accounting-always':\n case 'sign-except-zero':\n case 'sign-accounting-except-zero':\n expSign = opt;\n break;\n default:\n if (/^\\+e+$/.test(opt)) expDigits = opt.length - 1;else {\n this.badOption(stem, opt);\n }\n }\n }\n this.assertEmpty('notation');\n const source = options.join('/');\n res.notation = expDigits && expSign ? {\n style: stem,\n source,\n expDigits,\n expSign\n } : expDigits ? {\n style: stem,\n source,\n expDigits\n } : expSign ? {\n style: stem,\n source,\n expSign\n } : {\n style: stem,\n source\n };\n break;\n }\n // unit\n case 'percent':\n case 'permille':\n case 'base-unit':\n this.assertEmpty('unit');\n res.unit = {\n style: stem\n };\n break;\n case 'currency':\n if (/^[A-Z]{3}$/.test(option)) {\n this.assertEmpty('unit');\n res.unit = {\n style: stem,\n currency: option\n };\n } else this.badOption(stem, option);\n break;\n case 'measure-unit':\n {\n if (isUnit(option)) {\n this.assertEmpty('unit');\n res.unit = {\n style: stem,\n unit: option\n };\n } else this.badOption(stem, option);\n break;\n }\n // unitPer\n case 'per-measure-unit':\n {\n if (isUnit(option)) {\n this.assertEmpty('unitPer');\n res.unitPer = option;\n } else this.badOption(stem, option);\n break;\n }\n // unitWidth\n case 'unit-width-narrow':\n case 'unit-width-short':\n case 'unit-width-full-name':\n case 'unit-width-iso-code':\n case 'unit-width-hidden':\n this.assertEmpty('unitWidth');\n res.unitWidth = stem;\n break;\n // precision\n case 'precision-integer':\n case 'precision-unlimited':\n case 'precision-currency-standard':\n case 'precision-currency-cash':\n this.assertEmpty('precision');\n res.precision = {\n style: stem\n };\n break;\n case 'precision-increment':\n {\n const increment = Number(option);\n if (increment > 0) {\n this.assertEmpty('precision');\n res.precision = {\n style: stem,\n increment\n };\n } else this.badOption(stem, option);\n break;\n }\n // roundingMode\n case 'rounding-mode-ceiling':\n case 'rounding-mode-floor':\n case 'rounding-mode-down':\n case 'rounding-mode-up':\n case 'rounding-mode-half-even':\n case 'rounding-mode-half-odd':\n case 'rounding-mode-half-ceiling':\n case 'rounding-mode-half-floor':\n case 'rounding-mode-half-down':\n case 'rounding-mode-half-up':\n case 'rounding-mode-unnecessary':\n this.assertEmpty('roundingMode');\n res.roundingMode = stem;\n break;\n // integerWidth\n case 'integer-width':\n {\n if (/^\\+0*$/.test(option)) {\n this.assertEmpty('integerWidth');\n res.integerWidth = {\n source: option,\n min: option.length - 1\n };\n } else {\n const m = option.match(/^#*(0*)$/);\n if (m) {\n this.assertEmpty('integerWidth');\n res.integerWidth = {\n source: option,\n min: m[1].length,\n max: m[0].length\n };\n } else this.badOption(stem, option);\n }\n break;\n }\n // scale\n case 'scale':\n {\n const scale = Number(option);\n if (scale > 0) {\n this.assertEmpty('scale');\n res.scale = scale;\n } else this.badOption(stem, option);\n break;\n }\n // group\n case 'group-off':\n case 'group-min2':\n case 'group-auto':\n case 'group-on-aligned':\n case 'group-thousands':\n this.assertEmpty('group');\n res.group = stem;\n break;\n // numberingSystem\n case 'latin':\n this.assertEmpty('numberingSystem');\n res.numberingSystem = 'latn';\n break;\n case 'numbering-system':\n {\n if (isNumberingSystem(option)) {\n this.assertEmpty('numberingSystem');\n res.numberingSystem = option;\n } else this.badOption(stem, option);\n break;\n }\n // sign\n case 'sign-auto':\n case 'sign-always':\n case 'sign-never':\n case 'sign-accounting':\n case 'sign-accounting-always':\n case 'sign-except-zero':\n case 'sign-accounting-except-zero':\n this.assertEmpty('sign');\n res.sign = stem;\n break;\n // decimal\n case 'decimal-auto':\n case 'decimal-always':\n this.assertEmpty('decimal');\n res.decimal = stem;\n break;\n // precision blueprint\n default:\n {\n const precision = parsePrecisionBlueprint(stem, options, this.onError);\n if (precision) {\n this.assertEmpty('precision');\n res.precision = precision;\n } else {\n this.onError(new BadStemError(stem));\n }\n }\n }\n }\n }\n\n /**\n * Parse an {@link\n * https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md\n * | ICU NumberFormatter skeleton} string into a {@link Skeleton} structure.\n *\n * @public\n * @param src - The skeleton string\n * @param onError - Called when the parser encounters a syntax error. The\n * function will still return a {@link Skeleton}, but it may not contain\n * information for all tokens. If not defined, the error will be thrown\n * instead.\n *\n * @example\n * ```js\n * import { parseNumberSkeleton } from '@messageformat/number-skeleton'\n *\n * parseNumberSkeleton('compact-short currency/GBP', console.error)\n * // {\n * // notation: { style: 'compact-short' },\n * // unit: { style: 'currency', currency: 'GBP' }\n * // }\n * ```\n */\n function parseNumberSkeleton(src) {\n let onError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : error => {\n throw error;\n };\n const tokens = [];\n for (const part of src.split(' ')) {\n if (part) {\n const options = part.split('/');\n const stem = options.shift() || '';\n tokens.push({\n stem,\n options\n });\n }\n }\n const parser = new TokenParser(onError);\n for (const {\n stem,\n options\n } of tokens) {\n parser.parseToken(stem, options);\n }\n return parser.skeleton;\n }\n\n /**\n * Returns a number formatter function for the given locales and number skeleton\n *\n * @remarks\n * Uses `Intl.NumberFormat` (ES2020) internally.\n *\n * @public\n * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`\n * @param skeleton - An ICU NumberFormatter pattern or `::`-prefixed skeleton\n * string, or a parsed `Skeleton` structure\n * @param currency - If `skeleton` is a pattern string that includes ¤ tokens,\n * their skeleton representation requires a three-letter currency code.\n * @param onError - If defined, will be called separately for each encountered\n * parsing error and unsupported feature.\n * @example\n * ```js\n * import { getNumberFormatter } from '@messageformat/number-skeleton'\n *\n * let src = ':: currency/CAD unit-width-narrow'\n * let fmt = getNumberFormatter('en-CA', src, console.error)\n * fmt(42) // '$42.00'\n *\n * src = '::percent scale/100'\n * fmt = getNumberFormatter('en', src, console.error)\n * fmt(0.3) // '30%'\n * ```\n */\n function getNumberFormatter(locales, skeleton, currency, onError) {\n if (typeof skeleton === 'string') {\n skeleton = skeleton.indexOf('::') === 0 ? parseNumberSkeleton(skeleton.slice(2), onError) : parseNumberPattern(skeleton, currency, onError);\n }\n const lc = getNumberFormatLocales(locales, skeleton);\n const opt = getNumberFormatOptions(skeleton, onError);\n const mod = getNumberFormatModifier(skeleton);\n const nf = new Intl.NumberFormat(lc, opt);\n if (skeleton.affix) {\n const [p0, p1] = skeleton.affix.pos;\n const [n0, n1] = skeleton.affix.neg || ['', ''];\n return value => {\n const n = nf.format(mod(value));\n return value < 0 ? `${n0}${n}${n1}` : `${p0}${n}${p1}`;\n };\n }\n return value => nf.format(mod(value));\n }\n /**\n * Returns a string of JavaScript source that evaluates to a number formatter\n * function with the same `(value: number) => string` signature as the function\n * returned by {@link getNumberFormatter}.\n *\n * @remarks\n * The returned function will memoize an `Intl.NumberFormat` instance.\n *\n * @public\n * @param locales - One or more valid BCP 47 language tags, e.g. `fr` or `en-CA`\n * @param skeleton - An ICU NumberFormatter pattern or `::`-prefixed skeleton\n * string, or a parsed `Skeleton` structure\n * @param currency - If `skeleton` is a pattern string that includes ¤ tokens,\n * their skeleton representation requires a three-letter currency code.\n * @param onError - If defined, will be called separately for each encountered\n * parsing error and unsupported feature.\n * @example\n * ```js\n * import { getNumberFormatterSource } from '@messageformat/number-skeleton'\n *\n * getNumberFormatterSource('en', '::percent', console.error)\n * // '(function() {\\n' +\n * // ' var opt = {\"style\":\"percent\"};\\n' +\n * // ' var nf = new Intl.NumberFormat([\"en\"], opt);\\n' +\n * // ' var mod = function(n) { return n * 0.01; };\\n' +\n * // ' return function(value) { return nf.format(mod(value)); }\\n' +\n * // '})()'\n *\n * const src = getNumberFormatterSource('en-CA', ':: currency/CAD unit-width-narrow', console.error)\n * // '(function() {\\n' +\n * // ' var opt = {\"style\":\"currency\",\"currency\":\"CAD\",\"currencyDisplay\":\"narrowSymbol\",\"unitDisplay\":\"narrow\"};\\n' +\n * // ' var nf = new Intl.NumberFormat([\"en-CA\"], opt);\\n'\n * // ' return function(value) { return nf.format(value); }\\n' +\n * // '})()'\n * const fmt = new Function(`return ${src}`)()\n * fmt(42) // '$42.00'\n * ```\n */\n function getNumberFormatterSource(locales, skeleton, currency, onError) {\n if (typeof skeleton === 'string') {\n skeleton = skeleton.indexOf('::') === 0 ? parseNumberSkeleton(skeleton.slice(2), onError) : parseNumberPattern(skeleton, currency, onError);\n }\n const lc = getNumberFormatLocales(locales, skeleton);\n const opt = getNumberFormatOptions(skeleton, onError);\n const modSrc = getNumberFormatModifierSource(skeleton);\n const lines = [`(function() {`, `var opt = ${JSON.stringify(opt)};`, `var nf = new Intl.NumberFormat(${JSON.stringify(lc)}, opt);`];\n let res = 'nf.format(value)';\n if (modSrc) {\n lines.push(`var mod = ${modSrc};`);\n res = 'nf.format(mod(value))';\n }\n if (skeleton.affix) {\n const [p0, p1] = skeleton.affix.pos.map(s => JSON.stringify(s));\n if (skeleton.affix.neg) {\n const [n0, n1] = skeleton.affix.neg.map(s => JSON.stringify(s));\n res = `value < 0 ? ${n0} + ${res} + ${n1} : ${p0} + ${res} + ${p1}`;\n } else {\n res = `${p0} + ${res} + ${p1}`;\n }\n }\n lines.push(`return function(value) { return ${res}; }`);\n return lines.join('\\n ') + '\\n})()';\n }\n\n var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n var parser = {};\n\n var lexer = {};\n\n var mooExports = {};\n var moo = {\n get exports(){ return mooExports; },\n set exports(v){ mooExports = v; },\n };\n\n (function (module) {\n (function (root, factory) {\n if (module.exports) {\n module.exports = factory();\n } else {\n root.moo = factory();\n }\n })(commonjsGlobal, function () {\n\n var hasOwnProperty = Object.prototype.hasOwnProperty;\n var toString = Object.prototype.toString;\n var hasSticky = typeof new RegExp().sticky === 'boolean';\n\n /***************************************************************************/\n\n function isRegExp(o) {\n return o && toString.call(o) === '[object RegExp]';\n }\n function isObject(o) {\n return o && typeof o === 'object' && !isRegExp(o) && !Array.isArray(o);\n }\n function reEscape(s) {\n return s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n function reGroups(s) {\n var re = new RegExp('|' + s);\n return re.exec('').length - 1;\n }\n function reCapture(s) {\n return '(' + s + ')';\n }\n function reUnion(regexps) {\n if (!regexps.length) return '(?!)';\n var source = regexps.map(function (s) {\n return \"(?:\" + s + \")\";\n }).join('|');\n return \"(?:\" + source + \")\";\n }\n function regexpOrLiteral(obj) {\n if (typeof obj === 'string') {\n return '(?:' + reEscape(obj) + ')';\n } else if (isRegExp(obj)) {\n // TODO: consider /u support\n if (obj.ignoreCase) throw new Error('RegExp /i flag not allowed');\n if (obj.global) throw new Error('RegExp /g flag is implied');\n if (obj.sticky) throw new Error('RegExp /y flag is implied');\n if (obj.multiline) throw new Error('RegExp /m flag is implied');\n return obj.source;\n } else {\n throw new Error('Not a pattern: ' + obj);\n }\n }\n function pad(s, length) {\n if (s.length > length) {\n return s;\n }\n return Array(length - s.length + 1).join(\" \") + s;\n }\n function lastNLines(string, numLines) {\n var position = string.length;\n var lineBreaks = 0;\n while (true) {\n var idx = string.lastIndexOf(\"\\n\", position - 1);\n if (idx === -1) {\n break;\n } else {\n lineBreaks++;\n }\n position = idx;\n if (lineBreaks === numLines) {\n break;\n }\n if (position === 0) {\n break;\n }\n }\n var startPosition = lineBreaks < numLines ? 0 : position + 1;\n return string.substring(startPosition).split(\"\\n\");\n }\n function objectToRules(object) {\n var keys = Object.getOwnPropertyNames(object);\n var result = [];\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var thing = object[key];\n var rules = [].concat(thing);\n if (key === 'include') {\n for (var j = 0; j < rules.length; j++) {\n result.push({\n include: rules[j]\n });\n }\n continue;\n }\n var match = [];\n rules.forEach(function (rule) {\n if (isObject(rule)) {\n if (match.length) result.push(ruleOptions(key, match));\n result.push(ruleOptions(key, rule));\n match = [];\n } else {\n match.push(rule);\n }\n });\n if (match.length) result.push(ruleOptions(key, match));\n }\n return result;\n }\n function arrayToRules(array) {\n var result = [];\n for (var i = 0; i < array.length; i++) {\n var obj = array[i];\n if (obj.include) {\n var include = [].concat(obj.include);\n for (var j = 0; j < include.length; j++) {\n result.push({\n include: include[j]\n });\n }\n continue;\n }\n if (!obj.type) {\n throw new Error('Rule has no type: ' + JSON.stringify(obj));\n }\n result.push(ruleOptions(obj.type, obj));\n }\n return result;\n }\n function ruleOptions(type, obj) {\n if (!isObject(obj)) {\n obj = {\n match: obj\n };\n }\n if (obj.include) {\n throw new Error('Matching rules cannot also include states');\n }\n\n // nb. error and fallback imply lineBreaks\n var options = {\n defaultType: type,\n lineBreaks: !!obj.error || !!obj.fallback,\n pop: false,\n next: null,\n push: null,\n error: false,\n fallback: false,\n value: null,\n type: null,\n shouldThrow: false\n };\n\n // Avoid Object.assign(), so we support IE9+\n for (var key in obj) {\n if (hasOwnProperty.call(obj, key)) {\n options[key] = obj[key];\n }\n }\n\n // type transform cannot be a string\n if (typeof options.type === 'string' && type !== options.type) {\n throw new Error(\"Type transform cannot be a string (type '\" + options.type + \"' for token '\" + type + \"')\");\n }\n\n // convert to array\n var match = options.match;\n options.match = Array.isArray(match) ? match : match ? [match] : [];\n options.match.sort(function (a, b) {\n return isRegExp(a) && isRegExp(b) ? 0 : isRegExp(b) ? -1 : isRegExp(a) ? +1 : b.length - a.length;\n });\n return options;\n }\n function toRules(spec) {\n return Array.isArray(spec) ? arrayToRules(spec) : objectToRules(spec);\n }\n var defaultErrorRule = ruleOptions('error', {\n lineBreaks: true,\n shouldThrow: true\n });\n function compileRules(rules, hasStates) {\n var errorRule = null;\n var fast = Object.create(null);\n var fastAllowed = true;\n var unicodeFlag = null;\n var groups = [];\n var parts = [];\n\n // If there is a fallback rule, then disable fast matching\n for (var i = 0; i < rules.length; i++) {\n if (rules[i].fallback) {\n fastAllowed = false;\n }\n }\n for (var i = 0; i < rules.length; i++) {\n var options = rules[i];\n if (options.include) {\n // all valid inclusions are removed by states() preprocessor\n throw new Error('Inheritance is not allowed in stateless lexers');\n }\n if (options.error || options.fallback) {\n // errorRule can only be set once\n if (errorRule) {\n if (!options.fallback === !errorRule.fallback) {\n throw new Error(\"Multiple \" + (options.fallback ? \"fallback\" : \"error\") + \" rules not allowed (for token '\" + options.defaultType + \"')\");\n } else {\n throw new Error(\"fallback and error are mutually exclusive (for token '\" + options.defaultType + \"')\");\n }\n }\n errorRule = options;\n }\n var match = options.match.slice();\n if (fastAllowed) {\n while (match.length && typeof match[0] === 'string' && match[0].length === 1) {\n var word = match.shift();\n fast[word.charCodeAt(0)] = options;\n }\n }\n\n // Warn about inappropriate state-switching options\n if (options.pop || options.push || options.next) {\n if (!hasStates) {\n throw new Error(\"State-switching options are not allowed in stateless lexers (for token '\" + options.defaultType + \"')\");\n }\n if (options.fallback) {\n throw new Error(\"State-switching options are not allowed on fallback tokens (for token '\" + options.defaultType + \"')\");\n }\n }\n\n // Only rules with a .match are included in the RegExp\n if (match.length === 0) {\n continue;\n }\n fastAllowed = false;\n groups.push(options);\n\n // Check unicode flag is used everywhere or nowhere\n for (var j = 0; j < match.length; j++) {\n var obj = match[j];\n if (!isRegExp(obj)) {\n continue;\n }\n if (unicodeFlag === null) {\n unicodeFlag = obj.unicode;\n } else if (unicodeFlag !== obj.unicode && options.fallback === false) {\n throw new Error('If one rule is /u then all must be');\n }\n }\n\n // convert to RegExp\n var pat = reUnion(match.map(regexpOrLiteral));\n\n // validate\n var regexp = new RegExp(pat);\n if (regexp.test(\"\")) {\n throw new Error(\"RegExp matches empty string: \" + regexp);\n }\n var groupCount = reGroups(pat);\n if (groupCount > 0) {\n throw new Error(\"RegExp has capture groups: \" + regexp + \"\\nUse (?: … ) instead\");\n }\n\n // try and detect rules matching newlines\n if (!options.lineBreaks && regexp.test('\\n')) {\n throw new Error('Rule should declare lineBreaks: ' + regexp);\n }\n\n // store regex\n parts.push(reCapture(pat));\n }\n\n // If there's no fallback rule, use the sticky flag so we only look for\n // matches at the current index.\n //\n // If we don't support the sticky flag, then fake it using an irrefutable\n // match (i.e. an empty pattern).\n var fallbackRule = errorRule && errorRule.fallback;\n var flags = hasSticky && !fallbackRule ? 'ym' : 'gm';\n var suffix = hasSticky || fallbackRule ? '' : '|';\n if (unicodeFlag === true) flags += \"u\";\n var combined = new RegExp(reUnion(parts) + suffix, flags);\n return {\n regexp: combined,\n groups: groups,\n fast: fast,\n error: errorRule || defaultErrorRule\n };\n }\n function compile(rules) {\n var result = compileRules(toRules(rules));\n return new Lexer({\n start: result\n }, 'start');\n }\n function checkStateGroup(g, name, map) {\n var state = g && (g.push || g.next);\n if (state && !map[state]) {\n throw new Error(\"Missing state '\" + state + \"' (in token '\" + g.defaultType + \"' of state '\" + name + \"')\");\n }\n if (g && g.pop && +g.pop !== 1) {\n throw new Error(\"pop must be 1 (in token '\" + g.defaultType + \"' of state '\" + name + \"')\");\n }\n }\n function compileStates(states, start) {\n var all = states.$all ? toRules(states.$all) : [];\n delete states.$all;\n var keys = Object.getOwnPropertyNames(states);\n if (!start) start = keys[0];\n var ruleMap = Object.create(null);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n ruleMap[key] = toRules(states[key]).concat(all);\n }\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var rules = ruleMap[key];\n var included = Object.create(null);\n for (var j = 0; j < rules.length; j++) {\n var rule = rules[j];\n if (!rule.include) continue;\n var splice = [j, 1];\n if (rule.include !== key && !included[rule.include]) {\n included[rule.include] = true;\n var newRules = ruleMap[rule.include];\n if (!newRules) {\n throw new Error(\"Cannot include nonexistent state '\" + rule.include + \"' (in state '\" + key + \"')\");\n }\n for (var k = 0; k < newRules.length; k++) {\n var newRule = newRules[k];\n if (rules.indexOf(newRule) !== -1) continue;\n splice.push(newRule);\n }\n }\n rules.splice.apply(rules, splice);\n j--;\n }\n }\n var map = Object.create(null);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n map[key] = compileRules(ruleMap[key], true);\n }\n for (var i = 0; i < keys.length; i++) {\n var name = keys[i];\n var state = map[name];\n var groups = state.groups;\n for (var j = 0; j < groups.length; j++) {\n checkStateGroup(groups[j], name, map);\n }\n var fastKeys = Object.getOwnPropertyNames(state.fast);\n for (var j = 0; j < fastKeys.length; j++) {\n checkStateGroup(state.fast[fastKeys[j]], name, map);\n }\n }\n return new Lexer(map, start);\n }\n function keywordTransform(map) {\n // Use a JavaScript Map to map keywords to their corresponding token type\n // unless Map is unsupported, then fall back to using an Object:\n var isMap = typeof Map !== 'undefined';\n var reverseMap = isMap ? new Map() : Object.create(null);\n var types = Object.getOwnPropertyNames(map);\n for (var i = 0; i < types.length; i++) {\n var tokenType = types[i];\n var item = map[tokenType];\n var keywordList = Array.isArray(item) ? item : [item];\n keywordList.forEach(function (keyword) {\n if (typeof keyword !== 'string') {\n throw new Error(\"keyword must be string (in keyword '\" + tokenType + \"')\");\n }\n if (isMap) {\n reverseMap.set(keyword, tokenType);\n } else {\n reverseMap[keyword] = tokenType;\n }\n });\n }\n return function (k) {\n return isMap ? reverseMap.get(k) : reverseMap[k];\n };\n }\n\n /***************************************************************************/\n\n var Lexer = function (states, state) {\n this.startState = state;\n this.states = states;\n this.buffer = '';\n this.stack = [];\n this.reset();\n };\n Lexer.prototype.reset = function (data, info) {\n this.buffer = data || '';\n this.index = 0;\n this.line = info ? info.line : 1;\n this.col = info ? info.col : 1;\n this.queuedToken = info ? info.queuedToken : null;\n this.queuedText = info ? info.queuedText : \"\";\n this.queuedThrow = info ? info.queuedThrow : null;\n this.setState(info ? info.state : this.startState);\n this.stack = info && info.stack ? info.stack.slice() : [];\n return this;\n };\n Lexer.prototype.save = function () {\n return {\n line: this.line,\n col: this.col,\n state: this.state,\n stack: this.stack.slice(),\n queuedToken: this.queuedToken,\n queuedText: this.queuedText,\n queuedThrow: this.queuedThrow\n };\n };\n Lexer.prototype.setState = function (state) {\n if (!state || this.state === state) return;\n this.state = state;\n var info = this.states[state];\n this.groups = info.groups;\n this.error = info.error;\n this.re = info.regexp;\n this.fast = info.fast;\n };\n Lexer.prototype.popState = function () {\n this.setState(this.stack.pop());\n };\n Lexer.prototype.pushState = function (state) {\n this.stack.push(this.state);\n this.setState(state);\n };\n var eat = hasSticky ? function (re, buffer) {\n // assume re is /y\n return re.exec(buffer);\n } : function (re, buffer) {\n // assume re is /g\n var match = re.exec(buffer);\n // will always match, since we used the |(?:) trick\n if (match[0].length === 0) {\n return null;\n }\n return match;\n };\n Lexer.prototype._getGroup = function (match) {\n var groupCount = this.groups.length;\n for (var i = 0; i < groupCount; i++) {\n if (match[i + 1] !== undefined) {\n return this.groups[i];\n }\n }\n throw new Error('Cannot find token type for matched text');\n };\n function tokenToString() {\n return this.value;\n }\n Lexer.prototype.next = function () {\n var index = this.index;\n\n // If a fallback token matched, we don't need to re-run the RegExp\n if (this.queuedGroup) {\n var token = this._token(this.queuedGroup, this.queuedText, index);\n this.queuedGroup = null;\n this.queuedText = \"\";\n return token;\n }\n var buffer = this.buffer;\n if (index === buffer.length) {\n return; // EOF\n }\n\n // Fast matching for single characters\n var group = this.fast[buffer.charCodeAt(index)];\n if (group) {\n return this._token(group, buffer.charAt(index), index);\n }\n\n // Execute RegExp\n var re = this.re;\n re.lastIndex = index;\n var match = eat(re, buffer);\n\n // Error tokens match the remaining buffer\n var error = this.error;\n if (match == null) {\n return this._token(error, buffer.slice(index, buffer.length), index);\n }\n var group = this._getGroup(match);\n var text = match[0];\n if (error.fallback && match.index !== index) {\n this.queuedGroup = group;\n this.queuedText = text;\n\n // Fallback tokens contain the unmatched portion of the buffer\n return this._token(error, buffer.slice(index, match.index), index);\n }\n return this._token(group, text, index);\n };\n Lexer.prototype._token = function (group, text, offset) {\n // count line breaks\n var lineBreaks = 0;\n if (group.lineBreaks) {\n var matchNL = /\\n/g;\n var nl = 1;\n if (text === '\\n') {\n lineBreaks = 1;\n } else {\n while (matchNL.exec(text)) {\n lineBreaks++;\n nl = matchNL.lastIndex;\n }\n }\n }\n var token = {\n type: typeof group.type === 'function' && group.type(text) || group.defaultType,\n value: typeof group.value === 'function' ? group.value(text) : text,\n text: text,\n toString: tokenToString,\n offset: offset,\n lineBreaks: lineBreaks,\n line: this.line,\n col: this.col\n };\n // nb. adding more props to token object will make V8 sad!\n\n var size = text.length;\n this.index += size;\n this.line += lineBreaks;\n if (lineBreaks !== 0) {\n this.col = size - nl + 1;\n } else {\n this.col += size;\n }\n\n // throw, if no rule with {error: true}\n if (group.shouldThrow) {\n var err = new Error(this.formatError(token, \"invalid syntax\"));\n throw err;\n }\n if (group.pop) this.popState();else if (group.push) this.pushState(group.push);else if (group.next) this.setState(group.next);\n return token;\n };\n if (typeof Symbol !== 'undefined' && Symbol.iterator) {\n var LexerIterator = function (lexer) {\n this.lexer = lexer;\n };\n LexerIterator.prototype.next = function () {\n var token = this.lexer.next();\n return {\n value: token,\n done: !token\n };\n };\n LexerIterator.prototype[Symbol.iterator] = function () {\n return this;\n };\n Lexer.prototype[Symbol.iterator] = function () {\n return new LexerIterator(this);\n };\n }\n Lexer.prototype.formatError = function (token, message) {\n if (token == null) {\n // An undefined token indicates EOF\n var text = this.buffer.slice(this.index);\n var token = {\n text: text,\n offset: this.index,\n lineBreaks: text.indexOf('\\n') === -1 ? 0 : 1,\n line: this.line,\n col: this.col\n };\n }\n var numLinesAround = 2;\n var firstDisplayedLine = Math.max(token.line - numLinesAround, 1);\n var lastDisplayedLine = token.line + numLinesAround;\n var lastLineDigits = String(lastDisplayedLine).length;\n var displayedLines = lastNLines(this.buffer, this.line - token.line + numLinesAround + 1).slice(0, 5);\n var errorLines = [];\n errorLines.push(message + \" at line \" + token.line + \" col \" + token.col + \":\");\n errorLines.push(\"\");\n for (var i = 0; i < displayedLines.length; i++) {\n var line = displayedLines[i];\n var lineNo = firstDisplayedLine + i;\n errorLines.push(pad(String(lineNo), lastLineDigits) + \" \" + line);\n if (lineNo === token.line) {\n errorLines.push(pad(\"\", lastLineDigits + token.col + 1) + \"^\");\n }\n }\n return errorLines.join(\"\\n\");\n };\n Lexer.prototype.clone = function () {\n return new Lexer(this.states, this.state);\n };\n Lexer.prototype.has = function (tokenType) {\n return true;\n };\n return {\n compile: compile,\n states: compileStates,\n error: Object.freeze({\n error: true\n }),\n fallback: Object.freeze({\n fallback: true\n }),\n keywords: keywordTransform\n };\n });\n })(moo);\n\n (function (exports) {\n\n var __importDefault = commonjsGlobal && commonjsGlobal.__importDefault || function (mod) {\n return mod && mod.__esModule ? mod : {\n \"default\": mod\n };\n };\n Object.defineProperty(exports, \"__esModule\", {\n value: true\n });\n exports.lexer = exports.states = void 0;\n const moo_1 = __importDefault(mooExports);\n exports.states = {\n body: {\n doubleapos: {\n match: \"''\",\n value: () => \"'\"\n },\n quoted: {\n lineBreaks: true,\n match: /'[{}#](?:[^]*?[^'])?'(?!')/u,\n value: src => src.slice(1, -1).replace(/''/g, \"'\")\n },\n argument: {\n lineBreaks: true,\n match: /\\{\\s*[^\\p{Pat_Syn}\\p{Pat_WS}]+\\s*/u,\n push: 'arg',\n value: src => src.substring(1).trim()\n },\n octothorpe: '#',\n end: {\n match: '}',\n pop: 1\n },\n content: {\n lineBreaks: true,\n match: /[^][^{}#']*/u\n }\n },\n arg: {\n select: {\n lineBreaks: true,\n match: /,\\s*(?:plural|select|selectordinal)\\s*,\\s*/u,\n next: 'select',\n value: src => src.split(',')[1].trim()\n },\n 'func-args': {\n lineBreaks: true,\n match: /,\\s*[^\\p{Pat_Syn}\\p{Pat_WS}]+\\s*,/u,\n next: 'body',\n value: src => src.split(',')[1].trim()\n },\n 'func-simple': {\n lineBreaks: true,\n match: /,\\s*[^\\p{Pat_Syn}\\p{Pat_WS}]+\\s*/u,\n value: src => src.substring(1).trim()\n },\n end: {\n match: '}',\n pop: 1\n }\n },\n select: {\n offset: {\n lineBreaks: true,\n match: /\\s*offset\\s*:\\s*\\d+\\s*/u,\n value: src => src.split(':')[1].trim()\n },\n case: {\n lineBreaks: true,\n match: /\\s*(?:=\\d+|[^\\p{Pat_Syn}\\p{Pat_WS}]+)\\s*\\{/u,\n push: 'body',\n value: src => src.substring(0, src.indexOf('{')).trim()\n },\n end: {\n match: /\\s*\\}/u,\n pop: 1\n }\n }\n };\n exports.lexer = moo_1.default.states(exports.states);\n })(lexer);\n\n /**\n * An AST parser for ICU MessageFormat strings\n *\n * @packageDocumentation\n * @example\n * ```\n * import { parse } from '@messageformat/parser\n *\n * parse('So {wow}.')\n * [ { type: 'content', value: 'So ' },\n * { type: 'argument', arg: 'wow' },\n * { type: 'content', value: '.' } ]\n *\n *\n * parse('Such { thing }. { count, selectordinal, one {First} two {Second}' +\n * ' few {Third} other {#th} } word.')\n * [ { type: 'content', value: 'Such ' },\n * { type: 'argument', arg: 'thing' },\n * { type: 'content', value: '. ' },\n * { type: 'selectordinal',\n * arg: 'count',\n * cases: [\n * { key: 'one', tokens: [ { type: 'content', value: 'First' } ] },\n * { key: 'two', tokens: [ { type: 'content', value: 'Second' } ] },\n * { key: 'few', tokens: [ { type: 'content', value: 'Third' } ] },\n * { key: 'other',\n * tokens: [ { type: 'octothorpe' }, { type: 'content', value: 'th' } ] }\n * ] },\n * { type: 'content', value: ' word.' } ]\n *\n *\n * parse('Many{type,select,plural{ numbers}selectordinal{ counting}' +\n * 'select{ choices}other{ some {type}}}.')\n * [ { type: 'content', value: 'Many' },\n * { type: 'select',\n * arg: 'type',\n * cases: [\n * { key: 'plural', tokens: [ { type: 'content', value: 'numbers' } ] },\n * { key: 'selectordinal', tokens: [ { type: 'content', value: 'counting' } ] },\n * { key: 'select', tokens: [ { type: 'content', value: 'choices' } ] },\n * { key: 'other',\n * tokens: [ { type: 'content', value: 'some ' }, { type: 'argument', arg: 'type' } ] }\n * ] },\n * { type: 'content', value: '.' } ]\n *\n *\n * parse('{Such compliance')\n * // ParseError: invalid syntax at line 1 col 7:\n * //\n * // {Such compliance\n * // ^\n *\n *\n * const msg = '{words, plural, zero{No words} one{One word} other{# words}}'\n * parse(msg)\n * [ { type: 'plural',\n * arg: 'words',\n * cases: [\n * { key: 'zero', tokens: [ { type: 'content', value: 'No words' } ] },\n * { key: 'one', tokens: [ { type: 'content', value: 'One word' } ] },\n * { key: 'other',\n * tokens: [ { type: 'octothorpe' }, { type: 'content', value: ' words' } ] }\n * ] } ]\n *\n *\n * parse(msg, { cardinal: [ 'one', 'other' ], ordinal: [ 'one', 'two', 'few', 'other' ] })\n * // ParseError: The plural case zero is not valid in this locale at line 1 col 17:\n * //\n * // {words, plural, zero{\n * // ^\n * ```\n */\n Object.defineProperty(parser, \"__esModule\", {\n value: true\n });\n var parse_1 = parser.parse = parser.ParseError = void 0;\n const lexer_js_1 = lexer;\n const getContext = lt => ({\n offset: lt.offset,\n line: lt.line,\n col: lt.col,\n text: lt.text,\n lineBreaks: lt.lineBreaks\n });\n const isSelectType = type => type === 'plural' || type === 'select' || type === 'selectordinal';\n function strictArgStyleParam(lt, param) {\n let value = '';\n let text = '';\n for (const p of param) {\n const pText = p.ctx.text;\n text += pText;\n switch (p.type) {\n case 'content':\n value += p.value;\n break;\n case 'argument':\n case 'function':\n case 'octothorpe':\n value += pText;\n break;\n default:\n throw new ParseError(lt, `Unsupported part in strict mode function arg style: ${pText}`);\n }\n }\n const c = {\n type: 'content',\n value: value.trim(),\n ctx: Object.assign({}, param[0].ctx, {\n text\n })\n };\n return [c];\n }\n const strictArgTypes = ['number', 'date', 'time', 'spellout', 'ordinal', 'duration'];\n const defaultPluralKeys = ['zero', 'one', 'two', 'few', 'many', 'other'];\n /**\n * Thrown by {@link parse} on error\n *\n * @public\n */\n class ParseError extends Error {\n /** @internal */\n constructor(lt, msg) {\n super(lexer_js_1.lexer.formatError(lt, msg));\n }\n }\n parser.ParseError = ParseError;\n class Parser {\n constructor(src, opt) {\n this.lexer = lexer_js_1.lexer.reset(src);\n this.cardinalKeys = opt && opt.cardinal || defaultPluralKeys;\n this.ordinalKeys = opt && opt.ordinal || defaultPluralKeys;\n this.strict = opt && opt.strict || false;\n }\n parse() {\n return this.parseBody(false, true);\n }\n checkSelectKey(lt, type, key) {\n if (key[0] === '=') {\n if (type === 'select') throw new ParseError(lt, `The case ${key} is not valid with select`);\n } else if (type !== 'select') {\n const keys = type === 'plural' ? this.cardinalKeys : this.ordinalKeys;\n if (keys.length > 0 && !keys.includes(key)) {\n const msg = `The ${type} case ${key} is not valid in this locale`;\n throw new ParseError(lt, msg);\n }\n }\n }\n parseSelect(_ref, inPlural, ctx, type) {\n let {\n value: arg\n } = _ref;\n const sel = {\n type,\n arg,\n cases: [],\n ctx\n };\n if (type === 'plural' || type === 'selectordinal') inPlural = true;else if (this.strict) inPlural = false;\n for (const lt of this.lexer) {\n switch (lt.type) {\n case 'offset':\n if (type === 'select') throw new ParseError(lt, 'Unexpected plural offset for select');\n if (sel.cases.length > 0) throw new ParseError(lt, 'Plural offset must be set before cases');\n sel.pluralOffset = Number(lt.value);\n ctx.text += lt.text;\n ctx.lineBreaks += lt.lineBreaks;\n break;\n case 'case':\n {\n this.checkSelectKey(lt, type, lt.value);\n sel.cases.push({\n key: lt.value,\n tokens: this.parseBody(inPlural),\n ctx: getContext(lt)\n });\n break;\n }\n case 'end':\n return sel;\n /* istanbul ignore next: never happens */\n default:\n throw new ParseError(lt, `Unexpected lexer token: ${lt.type}`);\n }\n }\n throw new ParseError(null, 'Unexpected message end');\n }\n parseArgToken(lt, inPlural) {\n const ctx = getContext(lt);\n const argType = this.lexer.next();\n if (!argType) throw new ParseError(null, 'Unexpected message end');\n ctx.text += argType.text;\n ctx.lineBreaks += argType.lineBreaks;\n if (this.strict && (argType.type === 'func-simple' || argType.type === 'func-args') && !strictArgTypes.includes(argType.value)) {\n const msg = `Invalid strict mode function arg type: ${argType.value}`;\n throw new ParseError(lt, msg);\n }\n switch (argType.type) {\n case 'end':\n return {\n type: 'argument',\n arg: lt.value,\n ctx\n };\n case 'func-simple':\n {\n const end = this.lexer.next();\n if (!end) throw new ParseError(null, 'Unexpected message end');\n /* istanbul ignore if: never happens */\n if (end.type !== 'end') throw new ParseError(end, `Unexpected lexer token: ${end.type}`);\n ctx.text += end.text;\n if (isSelectType(argType.value.toLowerCase())) throw new ParseError(argType, `Invalid type identifier: ${argType.value}`);\n return {\n type: 'function',\n arg: lt.value,\n key: argType.value,\n ctx\n };\n }\n case 'func-args':\n {\n if (isSelectType(argType.value.toLowerCase())) {\n const msg = `Invalid type identifier: ${argType.value}`;\n throw new ParseError(argType, msg);\n }\n let param = this.parseBody(this.strict ? false : inPlural);\n if (this.strict && param.length > 0) param = strictArgStyleParam(lt, param);\n return {\n type: 'function',\n arg: lt.value,\n key: argType.value,\n param,\n ctx\n };\n }\n case 'select':\n /* istanbul ignore else: never happens */\n if (isSelectType(argType.value)) return this.parseSelect(lt, inPlural, ctx, argType.value);else throw new ParseError(argType, `Unexpected select type ${argType.value}`);\n /* istanbul ignore next: never happens */\n default:\n throw new ParseError(argType, `Unexpected lexer token: ${argType.type}`);\n }\n }\n parseBody(inPlural, atRoot) {\n const tokens = [];\n let content = null;\n for (const lt of this.lexer) {\n if (lt.type === 'argument') {\n if (content) content = null;\n tokens.push(this.parseArgToken(lt, inPlural));\n } else if (lt.type === 'octothorpe' && inPlural) {\n if (content) content = null;\n tokens.push({\n type: 'octothorpe',\n ctx: getContext(lt)\n });\n } else if (lt.type === 'end' && !atRoot) {\n return tokens;\n } else {\n let value = lt.value;\n if (!inPlural && lt.type === 'quoted' && value[0] === '#') {\n if (value.includes('{')) {\n const errMsg = `Unsupported escape pattern: ${value}`;\n throw new ParseError(lt, errMsg);\n }\n value = lt.text;\n }\n if (content) {\n content.value += value;\n content.ctx.text += lt.text;\n content.ctx.lineBreaks += lt.lineBreaks;\n } else {\n content = {\n type: 'content',\n value,\n ctx: getContext(lt)\n };\n tokens.push(content);\n }\n }\n }\n if (atRoot) return tokens;\n throw new ParseError(null, 'Unexpected message end');\n }\n }\n /**\n * Parse an input string into an array of tokens\n *\n * @public\n * @remarks\n * The parser only supports the default `DOUBLE_OPTIONAL`\n * {@link http://www.icu-project.org/apiref/icu4c/messagepattern_8h.html#af6e0757e0eb81c980b01ee5d68a9978b | apostrophe mode}.\n */\n function parse(src) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n const parser = new Parser(src, options);\n return parser.parse();\n }\n parse_1 = parser.parse = parse;\n\n /**\n * A set of utility functions that are called by the compiled Javascript\n * functions, these are included locally in the output of {@link MessageFormat.compile compile()}.\n */\n /** @private */\n function _nf$1(lc) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return _nf$1[lc] || (_nf$1[lc] = new Intl.NumberFormat(lc));\n }\n /**\n * Utility function for `#` in plural rules\n *\n * @param lc The current locale\n * @param value The value to operate on\n * @param offset An offset, set by the surrounding context\n * @returns The result of applying the offset to the input value\n */\n function number(lc, value, offset) {\n return _nf$1(lc).format(value - offset);\n }\n /**\n * Strict utility function for `#` in plural rules\n *\n * Will throw an Error if `value` or `offset` are non-numeric.\n *\n * @param lc The current locale\n * @param value The value to operate on\n * @param offset An offset, set by the surrounding context\n * @param name The name of the argument, used for error reporting\n * @returns The result of applying the offset to the input value\n */\n function strictNumber(lc, value, offset, name) {\n var n = value - offset;\n if (isNaN(n)) throw new Error('`' + name + '` or its offset is not a number');\n return _nf$1(lc).format(n);\n }\n /**\n * Utility function for `{N, plural|selectordinal, ...}`\n *\n * @param value The key to use to find a pluralization rule\n * @param offset An offset to apply to `value`\n * @param lcfunc A locale function from `pluralFuncs`\n * @param data The object from which results are looked up\n * @param isOrdinal If true, use ordinal rather than cardinal rules\n * @returns The result of the pluralization\n */\n function plural(value, offset, lcfunc, data, isOrdinal) {\n if ({}.hasOwnProperty.call(data, value)) return data[value];\n if (offset) value -= offset;\n var key = lcfunc(value, isOrdinal);\n return key in data ? data[key] : data.other;\n }\n /**\n * Utility function for `{N, select, ...}`\n *\n * @param value The key to use to find a selection\n * @param data The object from which results are looked up\n * @returns The result of the select statement\n */\n function select(value, data) {\n return {}.hasOwnProperty.call(data, value) ? data[value] : data.other;\n }\n /**\n * Checks that all required arguments are set to defined values\n *\n * Throws on failure; otherwise returns undefined\n *\n * @param keys The required keys\n * @param data The data object being checked\n */\n function reqArgs(keys, data) {\n for (var i = 0; i < keys.length; ++i) if (!data || data[keys[i]] === undefined) throw new Error(\"Message requires argument '\".concat(keys[i], \"'\"));\n }\n\n var Runtime = /*#__PURE__*/Object.freeze({\n __proto__: null,\n _nf: _nf$1,\n number: number,\n plural: plural,\n reqArgs: reqArgs,\n select: select,\n strictNumber: strictNumber\n });\n\n /**\n * Represent a date as a short/default/long/full string\n *\n * @param value Either a Unix epoch time in milliseconds, or a string value\n * representing a date. Parsed with `new Date(value)`\n *\n * @example\n * ```js\n * var mf = new MessageFormat(['en', 'fi']);\n *\n * mf.compile('Today is {T, date}')({ T: Date.now() })\n * // 'Today is Feb 21, 2016'\n *\n * mf.compile('Tänään on {T, date}', 'fi')({ T: Date.now() })\n * // 'Tänään on 21. helmikuuta 2016'\n *\n * mf.compile('Unix time started on {T, date, full}')({ T: 0 })\n * // 'Unix time started on Thursday, January 1, 1970'\n *\n * var cf = mf.compile('{sys} became operational on {d0, date, short}');\n * cf({ sys: 'HAL 9000', d0: '12 January 1999' })\n * // 'HAL 9000 became operational on 1/12/1999'\n * ```\n */\n function date(value, lc, size) {\n var o = {\n day: 'numeric',\n month: 'short',\n year: 'numeric'\n };\n /* eslint-disable no-fallthrough */\n switch (size) {\n case 'full':\n o.weekday = 'long';\n case 'long':\n o.month = 'long';\n break;\n case 'short':\n o.month = 'numeric';\n }\n return new Date(value).toLocaleDateString(lc, o);\n }\n\n /**\n * Represent a duration in seconds as a string\n *\n * @param value A finite number, or its string representation\n * @return Includes one or two `:` separators, and matches the pattern\n * `hhhh:mm:ss`, possibly with a leading `-` for negative values and a\n * trailing `.sss` part for non-integer input\n *\n * @example\n * ```js\n * var mf = new MessageFormat();\n *\n * mf.compile('It has been {D, duration}')({ D: 123 })\n * // 'It has been 2:03'\n *\n * mf.compile('Countdown: {D, duration}')({ D: -151200.42 })\n * // 'Countdown: -42:00:00.420'\n * ```\n */\n function duration(value) {\n if (typeof value !== 'number') value = Number(value);\n if (!isFinite(value)) return String(value);\n var sign = '';\n if (value < 0) {\n sign = '-';\n value = Math.abs(value);\n } else {\n value = Number(value);\n }\n var sec = value % 60;\n var parts = [Math.round(sec) === sec ? sec : sec.toFixed(3)];\n if (value < 60) {\n parts.unshift(0); // at least one : is required\n } else {\n value = Math.round((value - Number(parts[0])) / 60);\n parts.unshift(value % 60); // minutes\n if (value >= 60) {\n value = Math.round((value - Number(parts[0])) / 60);\n parts.unshift(value); // hours\n }\n }\n\n var first = parts.shift();\n return sign + first + ':' + parts.map(function (n) {\n return n < 10 ? '0' + String(n) : String(n);\n }).join(':');\n }\n\n /**\n * Represent a number as an integer, percent or currency value\n *\n * Available in MessageFormat strings as `{VAR, number, integer|percent|currency}`.\n * Internally, calls Intl.NumberFormat with appropriate parameters. `currency` will\n * default to USD; to change, set `MessageFormat#currency` to the appropriate\n * three-letter currency code, or use the `currency:EUR` form of the argument.\n *\n * @example\n * ```js\n * var mf = new MessageFormat('en', { currency: 'EUR'});\n *\n * mf.compile('{N} is almost {N, number, integer}')({ N: 3.14 })\n * // '3.14 is almost 3'\n *\n * mf.compile('{P, number, percent} complete')({ P: 0.99 })\n * // '99% complete'\n *\n * mf.compile('The total is {V, number, currency}.')({ V: 5.5 })\n * // 'The total is €5.50.'\n *\n * mf.compile('The total is {V, number, currency:GBP}.')({ V: 5.5 })\n * // 'The total is £5.50.'\n * ```\n */\n var _nf = {};\n function nf(lc, opt) {\n var key = String(lc) + JSON.stringify(opt);\n if (!_nf[key]) _nf[key] = new Intl.NumberFormat(lc, opt);\n return _nf[key];\n }\n function numberFmt(value, lc, arg, defaultCurrency) {\n var _a = arg && arg.split(':') || [],\n type = _a[0],\n currency = _a[1];\n var opt = {\n integer: {\n maximumFractionDigits: 0\n },\n percent: {\n style: 'percent'\n },\n currency: {\n style: 'currency',\n currency: currency && currency.trim() || defaultCurrency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2\n }\n };\n return nf(lc, opt[type] || {}).format(value);\n }\n var numberCurrency = function (value, lc, arg) {\n return nf(lc, {\n style: 'currency',\n currency: arg,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2\n }).format(value);\n };\n var numberInteger = function (value, lc) {\n return nf(lc, {\n maximumFractionDigits: 0\n }).format(value);\n };\n var numberPercent = function (value, lc) {\n return nf(lc, {\n style: 'percent'\n }).format(value);\n };\n\n /**\n * Represent a time as a short/default/long string\n *\n * @param value Either a Unix epoch time in milliseconds, or a string value\n * representing a date. Parsed with `new Date(value)`\n *\n * @example\n * ```js\n * var mf = new MessageFormat(['en', 'fi']);\n *\n * mf.compile('The time is now {T, time}')({ T: Date.now() })\n * // 'The time is now 11:26:35 PM'\n *\n * mf.compile('Kello on nyt {T, time}', 'fi')({ T: Date.now() })\n * // 'Kello on nyt 23.26.35'\n *\n * var cf = mf.compile('The Eagle landed at {T, time, full} on {T, date, full}');\n * cf({ T: '1969-07-20 20:17:40 UTC' })\n * // 'The Eagle landed at 10:17:40 PM GMT+2 on Sunday, July 20, 1969'\n * ```\n */\n function time(value, lc, size) {\n var o = {\n second: 'numeric',\n minute: 'numeric',\n hour: 'numeric'\n };\n /* eslint-disable no-fallthrough */\n switch (size) {\n case 'full':\n case 'long':\n o.timeZoneName = 'short';\n break;\n case 'short':\n delete o.second;\n }\n return new Date(value).toLocaleTimeString(lc, o);\n }\n\n var Formatters = /*#__PURE__*/Object.freeze({\n __proto__: null,\n date: date,\n duration: duration,\n numberCurrency: numberCurrency,\n numberFmt: numberFmt,\n numberInteger: numberInteger,\n numberPercent: numberPercent,\n time: time\n });\n\n const ES3 = {\n break: true,\n continue: true,\n delete: true,\n else: true,\n for: true,\n function: true,\n if: true,\n in: true,\n new: true,\n return: true,\n this: true,\n typeof: true,\n var: true,\n void: true,\n while: true,\n with: true,\n case: true,\n catch: true,\n default: true,\n do: true,\n finally: true,\n instanceof: true,\n switch: true,\n throw: true,\n try: true\n };\n const ESnext = {\n // in addition to reservedES3\n await: true,\n debugger: true,\n class: true,\n enum: true,\n extends: true,\n super: true,\n const: true,\n export: true,\n import: true,\n null: true,\n true: true,\n false: true,\n implements: true,\n let: true,\n private: true,\n public: true,\n yield: true,\n interface: true,\n package: true,\n protected: true,\n static: true\n };\n var reserved = {\n ES3,\n ESnext\n };\n var reserved$1 = reserved;\n\n // from https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/\n function hashCode(str) {\n let hash = 0;\n for (let i = 0; i < str.length; ++i) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash |= 0; // Convert to 32bit integer\n }\n\n return hash;\n }\n function identifier(key, unique) {\n if (unique) key += ' ' + hashCode(key).toString(36);\n const id = key.trim().replace(/\\W+/g, '_');\n return reserved$1.ES3[id] || reserved$1.ESnext[id] || /^\\d/.test(id) ? '_' + id : id;\n }\n function property(obj, key) {\n if (/^[A-Z_$][0-9A-Z_$]*$/i.test(key) && !reserved$1.ES3[key]) {\n return obj ? obj + '.' + key : key;\n } else {\n const jkey = JSON.stringify(key);\n return obj ? obj + '[' + jkey + ']' : jkey;\n }\n }\n\n var rtlLanguages = [\n 'ar',\n 'ckb',\n 'fa',\n 'he',\n 'ks($|[^bfh])',\n 'lrc',\n 'mzn',\n 'pa-Arab',\n 'ps',\n 'ug',\n 'ur',\n 'uz-Arab',\n 'yi'\n ];\n var rtlRegExp = new RegExp('^' + rtlLanguages.join('|^'));\n function biDiMarkText(text, locale) {\n var isLocaleRTL = rtlRegExp.test(locale);\n var mark = JSON.stringify(isLocaleRTL ? '\\u200F' : '\\u200E');\n return \"\".concat(mark, \" + \").concat(text, \" + \").concat(mark);\n }\n\n var RUNTIME_MODULE = '@messageformat/runtime';\n var CARDINAL_MODULE = '@messageformat/runtime/lib/cardinals';\n var PLURAL_MODULE = '@messageformat/runtime/lib/plurals';\n var FORMATTER_MODULE = '@messageformat/runtime/lib/formatters';\n var Compiler = (function () {\n function Compiler(options) {\n this.arguments = [];\n this.runtime = {};\n this.options = options;\n }\n Compiler.prototype.compile = function (src, plural, plurals) {\n var e_1, _a;\n var _this = this;\n var _b = this.options, localeCodeFromKey = _b.localeCodeFromKey, requireAllArguments = _b.requireAllArguments, strict = _b.strict;\n if (typeof src === 'object') {\n var result = {};\n try {\n for (var _c = __values(Object.keys(src)), _d = _c.next(); !_d.done; _d = _c.next()) {\n var key = _d.value;\n var lc = localeCodeFromKey ? localeCodeFromKey(key) : key;\n var pl = (plurals && lc && plurals[lc]) || plural;\n result[key] = this.compile(src[key], pl, plurals);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (_d && !_d.done && (_a = _c.return)) _a.call(_c);\n }\n finally { if (e_1) throw e_1.error; }\n }\n return result;\n }\n this.plural = plural;\n var parserOptions = {\n cardinal: plural.cardinals,\n ordinal: plural.ordinals,\n strict: strict\n };\n this.arguments = [];\n var r = parse_1(src, parserOptions).map(function (token) { return _this.token(token, null); });\n var hasArgs = this.arguments.length > 0;\n var res = this.concatenate(r, true);\n if (requireAllArguments && hasArgs) {\n this.setRuntimeFn('reqArgs');\n var reqArgs = JSON.stringify(this.arguments);\n return \"(d) => { reqArgs(\".concat(reqArgs, \", d); return \").concat(res, \"; }\");\n }\n return \"(\".concat(hasArgs ? 'd' : '', \") => \").concat(res);\n };\n Compiler.prototype.cases = function (token, pluralToken) {\n var _this = this;\n var needOther = true;\n var r = token.cases.map(function (_a) {\n var key = _a.key, tokens = _a.tokens;\n if (key === 'other')\n needOther = false;\n var s = tokens.map(function (tok) { return _this.token(tok, pluralToken); });\n return \"\".concat(property(null, key.replace(/^=/, '')), \": \").concat(_this.concatenate(s, false));\n });\n if (needOther) {\n var type = token.type;\n var _a = this.plural, cardinals = _a.cardinals, ordinals = _a.ordinals;\n if (type === 'select' ||\n (type === 'plural' && cardinals.includes('other')) ||\n (type === 'selectordinal' && ordinals.includes('other')))\n throw new Error(\"No 'other' form found in \".concat(JSON.stringify(token)));\n }\n return \"{ \".concat(r.join(', '), \" }\");\n };\n Compiler.prototype.concatenate = function (tokens, root) {\n var asValues = this.options.returnType === 'values';\n return asValues && (root || tokens.length > 1)\n ? '[' + tokens.join(', ') + ']'\n : tokens.join(' + ') || '\"\"';\n };\n Compiler.prototype.token = function (token, pluralToken) {\n if (token.type === 'content')\n return JSON.stringify(token.value);\n var _a = this.plural, id = _a.id, lc = _a.lc;\n var args, fn;\n if ('arg' in token) {\n this.arguments.push(token.arg);\n args = [property('d', token.arg)];\n }\n else\n args = [];\n switch (token.type) {\n case 'argument':\n return this.options.biDiSupport\n ? biDiMarkText(String(args[0]), lc)\n : String(args[0]);\n case 'select':\n fn = 'select';\n if (pluralToken && this.options.strict)\n pluralToken = null;\n args.push(this.cases(token, pluralToken));\n this.setRuntimeFn('select');\n break;\n case 'selectordinal':\n fn = 'plural';\n args.push(token.pluralOffset || 0, id, this.cases(token, token), 1);\n this.setLocale(id, true);\n this.setRuntimeFn('plural');\n break;\n case 'plural':\n fn = 'plural';\n args.push(token.pluralOffset || 0, id, this.cases(token, token));\n this.setLocale(id, false);\n this.setRuntimeFn('plural');\n break;\n case 'function':\n if (!this.options.customFormatters[token.key]) {\n if (token.key === 'date') {\n fn = this.setDateFormatter(token, args, pluralToken);\n break;\n }\n else if (token.key === 'number') {\n fn = this.setNumberFormatter(token, args, pluralToken);\n break;\n }\n }\n args.push(JSON.stringify(this.plural.locale));\n if (token.param) {\n if (pluralToken && this.options.strict)\n pluralToken = null;\n var arg = this.getFormatterArg(token, pluralToken);\n if (arg)\n args.push(arg);\n }\n fn = token.key;\n this.setFormatter(fn);\n break;\n case 'octothorpe':\n if (!pluralToken)\n return '\"#\"';\n args = [\n JSON.stringify(this.plural.locale),\n property('d', pluralToken.arg),\n pluralToken.pluralOffset || 0\n ];\n if (this.options.strict) {\n fn = 'strictNumber';\n args.push(JSON.stringify(pluralToken.arg));\n this.setRuntimeFn('strictNumber');\n }\n else {\n fn = 'number';\n this.setRuntimeFn('number');\n }\n break;\n }\n if (!fn)\n throw new Error('Parser error for token ' + JSON.stringify(token));\n return \"\".concat(fn, \"(\").concat(args.join(', '), \")\");\n };\n Compiler.prototype.runtimeIncludes = function (key, type) {\n if (identifier(key) !== key)\n throw new SyntaxError(\"Reserved word used as \".concat(type, \" identifier: \").concat(key));\n var prev = this.runtime[key];\n if (!prev || prev.type === type)\n return prev;\n throw new TypeError(\"Cannot override \".concat(prev.type, \" runtime function as \").concat(type, \": \").concat(key));\n };\n Compiler.prototype.setLocale = function (key, ord) {\n var prev = this.runtimeIncludes(key, 'locale');\n var _a = this.plural, getCardinal = _a.getCardinal, getPlural = _a.getPlural, isDefault = _a.isDefault;\n var pf, module, toString;\n if (!ord && isDefault && getCardinal) {\n if (prev)\n return;\n pf = function (n) { return getCardinal(n); };\n module = CARDINAL_MODULE;\n toString = function () { return String(getCardinal); };\n }\n else {\n if (prev && (!isDefault || prev.module === PLURAL_MODULE))\n return;\n pf = function (n, ord) { return getPlural(n, ord); };\n module = isDefault ? PLURAL_MODULE : getPlural.module || null;\n toString = function () { return String(getPlural); };\n }\n this.runtime[key] = Object.assign(pf, {\n id: key,\n module: module,\n toString: toString,\n type: 'locale'\n });\n };\n Compiler.prototype.setRuntimeFn = function (key) {\n if (this.runtimeIncludes(key, 'runtime'))\n return;\n this.runtime[key] = Object.assign(Runtime[key], {\n id: key,\n module: RUNTIME_MODULE,\n type: 'runtime'\n });\n };\n Compiler.prototype.getFormatterArg = function (_a, pluralToken) {\n var e_2, _b, e_3, _c;\n var _this = this;\n var key = _a.key, param = _a.param;\n var fmt = this.options.customFormatters[key] ||\n (isFormatterKey(key) && Formatters[key]);\n if (!fmt || !param)\n return null;\n var argShape = ('arg' in fmt && fmt.arg) || 'string';\n if (argShape === 'options') {\n var value = '';\n try {\n for (var param_1 = __values(param), param_1_1 = param_1.next(); !param_1_1.done; param_1_1 = param_1.next()) {\n var tok = param_1_1.value;\n if (tok.type === 'content')\n value += tok.value;\n else\n throw new SyntaxError(\"Expected literal options for \".concat(key, \" formatter\"));\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (param_1_1 && !param_1_1.done && (_b = param_1.return)) _b.call(param_1);\n }\n finally { if (e_2) throw e_2.error; }\n }\n var options = {};\n try {\n for (var _d = __values(value.split(',')), _e = _d.next(); !_e.done; _e = _d.next()) {\n var pair = _e.value;\n var keyEnd = pair.indexOf(':');\n if (keyEnd === -1)\n options[pair.trim()] = null;\n else {\n var k = pair.substring(0, keyEnd).trim();\n var v = pair.substring(keyEnd + 1).trim();\n if (v === 'true')\n options[k] = true;\n else if (v === 'false')\n options[k] = false;\n else if (v === 'null')\n options[k] = null;\n else {\n var n = Number(v);\n options[k] = Number.isFinite(n) ? n : v;\n }\n }\n }\n }\n catch (e_3_1) { e_3 = { error: e_3_1 }; }\n finally {\n try {\n if (_e && !_e.done && (_c = _d.return)) _c.call(_d);\n }\n finally { if (e_3) throw e_3.error; }\n }\n return JSON.stringify(options);\n }\n else {\n var parts = param.map(function (tok) { return _this.token(tok, pluralToken); });\n if (argShape === 'raw')\n return \"[\".concat(parts.join(', '), \"]\");\n var s = parts.join(' + ');\n return s ? \"(\".concat(s, \").trim()\") : '\"\"';\n }\n };\n Compiler.prototype.setFormatter = function (key) {\n if (this.runtimeIncludes(key, 'formatter'))\n return;\n var cf = this.options.customFormatters[key];\n if (cf) {\n if (typeof cf === 'function')\n cf = { formatter: cf };\n this.runtime[key] = Object.assign(cf.formatter, { type: 'formatter' }, 'module' in cf && cf.module && cf.id\n ? { id: identifier(cf.id), module: cf.module }\n : { id: null, module: null });\n }\n else if (isFormatterKey(key)) {\n this.runtime[key] = Object.assign(Formatters[key], { type: 'formatter' }, { id: key, module: FORMATTER_MODULE });\n }\n else {\n throw new Error(\"Formatting function not found: \".concat(key));\n }\n };\n Compiler.prototype.setDateFormatter = function (_a, args, plural) {\n var _this = this;\n var param = _a.param;\n var locale = this.plural.locale;\n var argStyle = param && param.length === 1 && param[0];\n if (argStyle &&\n argStyle.type === 'content' &&\n /^\\s*::/.test(argStyle.value)) {\n var argSkeletonText_1 = argStyle.value.trim().substr(2);\n var key = identifier(\"date_\".concat(locale, \"_\").concat(argSkeletonText_1), true);\n if (!this.runtimeIncludes(key, 'formatter')) {\n var fmt = getDateFormatter(locale, argSkeletonText_1);\n this.runtime[key] = Object.assign(fmt, {\n id: key,\n module: null,\n toString: function () { return getDateFormatterSource(locale, argSkeletonText_1); },\n type: 'formatter'\n });\n }\n return key;\n }\n args.push(JSON.stringify(locale));\n if (param && param.length > 0) {\n if (plural && this.options.strict)\n plural = null;\n var s = param.map(function (tok) { return _this.token(tok, plural); });\n args.push('(' + (s.join(' + ') || '\"\"') + ').trim()');\n }\n this.setFormatter('date');\n return 'date';\n };\n Compiler.prototype.setNumberFormatter = function (_a, args, plural) {\n var _this = this;\n var param = _a.param;\n var locale = this.plural.locale;\n if (!param || param.length === 0) {\n args.unshift(JSON.stringify(locale));\n args.push('0');\n this.setRuntimeFn('number');\n return 'number';\n }\n args.push(JSON.stringify(locale));\n if (param.length === 1 && param[0].type === 'content') {\n var fmtArg_1 = param[0].value.trim();\n switch (fmtArg_1) {\n case 'currency':\n args.push(JSON.stringify(this.options.currency));\n this.setFormatter('numberCurrency');\n return 'numberCurrency';\n case 'integer':\n this.setFormatter('numberInteger');\n return 'numberInteger';\n case 'percent':\n this.setFormatter('numberPercent');\n return 'numberPercent';\n }\n var cm = fmtArg_1.match(/^currency:([A-Z]+)$/);\n if (cm) {\n args.push(JSON.stringify(cm[1]));\n this.setFormatter('numberCurrency');\n return 'numberCurrency';\n }\n var key = identifier(\"number_\".concat(locale, \"_\").concat(fmtArg_1), true);\n if (!this.runtimeIncludes(key, 'formatter')) {\n var currency_1 = this.options.currency;\n var fmt = getNumberFormatter(locale, fmtArg_1, currency_1);\n this.runtime[key] = Object.assign(fmt, {\n id: null,\n module: null,\n toString: function () { return getNumberFormatterSource(locale, fmtArg_1, currency_1); },\n type: 'formatter'\n });\n }\n return key;\n }\n if (plural && this.options.strict)\n plural = null;\n var s = param.map(function (tok) { return _this.token(tok, plural); });\n args.push('(' + (s.join(' + ') || '\"\"') + ').trim()');\n args.push(JSON.stringify(this.options.currency));\n this.setFormatter('numberFmt');\n return 'numberFmt';\n };\n return Compiler;\n }());\n function isFormatterKey(key) {\n return key in Formatters;\n }\n\n const a$2 = n => n == 1 ? 'one' : 'other';\n const b$2 = n => n == 0 || n == 1 ? 'one' : 'other';\n const c$2 = n => n >= 0 && n <= 1 ? 'one' : 'other';\n const d$2 = n => {\n const s = String(n).split('.'),\n v0 = !s[1];\n return n == 1 && v0 ? 'one' : 'other';\n };\n const e$1 = n => 'other';\n const f$2 = n => n == 1 ? 'one' : n == 2 ? 'two' : 'other';\n const af$2 = a$2;\n const ak$2 = b$2;\n const am$2 = c$2;\n const an$2 = a$2;\n const ar$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n return n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 99 ? 'many' : 'other';\n };\n const ars$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n return n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 99 ? 'many' : 'other';\n };\n const as$2 = c$2;\n const asa$2 = a$2;\n const ast$2 = d$2;\n const az$2 = a$2;\n const bal$2 = a$2;\n const be$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n return n10 == 1 && n100 != 11 ? 'one' : n10 >= 2 && n10 <= 4 && (n100 < 12 || n100 > 14) ? 'few' : t0 && n10 == 0 || n10 >= 5 && n10 <= 9 || n100 >= 11 && n100 <= 14 ? 'many' : 'other';\n };\n const bem$2 = a$2;\n const bez$2 = a$2;\n const bg$2 = a$2;\n const bho$2 = b$2;\n const bm$2 = e$1;\n const bn$2 = c$2;\n const bo$2 = e$1;\n const br$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n n1000000 = t0 && s[0].slice(-6);\n return n10 == 1 && n100 != 11 && n100 != 71 && n100 != 91 ? 'one' : n10 == 2 && n100 != 12 && n100 != 72 && n100 != 92 ? 'two' : (n10 == 3 || n10 == 4 || n10 == 9) && (n100 < 10 || n100 > 19) && (n100 < 70 || n100 > 79) && (n100 < 90 || n100 > 99) ? 'few' : n != 0 && t0 && n1000000 == 0 ? 'many' : 'other';\n };\n const brx$2 = a$2;\n const bs$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const ca$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const ce$2 = a$2;\n const ceb$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const cgg$2 = a$2;\n const chr$2 = a$2;\n const ckb$2 = a$2;\n const cs$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n return n == 1 && v0 ? 'one' : i >= 2 && i <= 4 && v0 ? 'few' : !v0 ? 'many' : 'other';\n };\n const cy$2 = n => n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n == 3 ? 'few' : n == 6 ? 'many' : 'other';\n const da$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n t0 = Number(s[0]) == n;\n return n == 1 || !t0 && (i == 0 || i == 1) ? 'one' : 'other';\n };\n const de$2 = d$2;\n const doi$2 = c$2;\n const dsb$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i100 = i.slice(-2),\n f100 = f.slice(-2);\n return v0 && i100 == 1 || f100 == 1 ? 'one' : v0 && i100 == 2 || f100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || f100 == 3 || f100 == 4 ? 'few' : 'other';\n };\n const dv$2 = a$2;\n const dz$2 = e$1;\n const ee$2 = a$2;\n const el$2 = a$2;\n const en$2 = d$2;\n const eo$2 = a$2;\n const es$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n == 1 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const et$2 = d$2;\n const eu$2 = a$2;\n const fa$2 = c$2;\n const ff$2 = n => n >= 0 && n < 2 ? 'one' : 'other';\n const fi$2 = d$2;\n const fil$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const fo$2 = a$2;\n const fr$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n >= 0 && n < 2 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const fur$2 = a$2;\n const fy$2 = d$2;\n const ga$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n return n == 1 ? 'one' : n == 2 ? 'two' : t0 && n >= 3 && n <= 6 ? 'few' : t0 && n >= 7 && n <= 10 ? 'many' : 'other';\n };\n const gd$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n return n == 1 || n == 11 ? 'one' : n == 2 || n == 12 ? 'two' : t0 && n >= 3 && n <= 10 || t0 && n >= 13 && n <= 19 ? 'few' : 'other';\n };\n const gl$2 = d$2;\n const gsw$2 = a$2;\n const gu$2 = c$2;\n const guw$2 = b$2;\n const gv$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n return v0 && i10 == 1 ? 'one' : v0 && i10 == 2 ? 'two' : v0 && (i100 == 0 || i100 == 20 || i100 == 40 || i100 == 60 || i100 == 80) ? 'few' : !v0 ? 'many' : 'other';\n };\n const ha$2 = a$2;\n const haw$2 = a$2;\n const he$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n return i == 1 && v0 || i == 0 && !v0 ? 'one' : i == 2 && v0 ? 'two' : 'other';\n };\n const hi$2 = c$2;\n const hnj$2 = e$1;\n const hr$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const hsb$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i100 = i.slice(-2),\n f100 = f.slice(-2);\n return v0 && i100 == 1 || f100 == 1 ? 'one' : v0 && i100 == 2 || f100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || f100 == 3 || f100 == 4 ? 'few' : 'other';\n };\n const hu$2 = a$2;\n const hy$2 = n => n >= 0 && n < 2 ? 'one' : 'other';\n const ia$2 = d$2;\n const id$2 = e$1;\n const ig$2 = e$1;\n const ii$2 = e$1;\n const io$2 = d$2;\n const is$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n t = (s[1] || '').replace(/0+$/, ''),\n t0 = Number(s[0]) == n,\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n return t0 && i10 == 1 && i100 != 11 || t % 10 == 1 && t % 100 != 11 ? 'one' : 'other';\n };\n const it$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const iu$2 = f$2;\n const ja$2 = e$1;\n const jbo$2 = e$1;\n const jgo$2 = a$2;\n const jmc$2 = a$2;\n const jv$2 = e$1;\n const jw$2 = e$1;\n const ka$2 = a$2;\n const kab$2 = n => n >= 0 && n < 2 ? 'one' : 'other';\n const kaj$2 = a$2;\n const kcg$2 = a$2;\n const kde$2 = e$1;\n const kea$2 = e$1;\n const kk$2 = a$2;\n const kkj$2 = a$2;\n const kl$2 = a$2;\n const km$2 = e$1;\n const kn$2 = c$2;\n const ko$2 = e$1;\n const ks$2 = a$2;\n const ksb$2 = a$2;\n const ksh$2 = n => n == 0 ? 'zero' : n == 1 ? 'one' : 'other';\n const ku$2 = a$2;\n const kw$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2),\n n1000 = t0 && s[0].slice(-3),\n n100000 = t0 && s[0].slice(-5),\n n1000000 = t0 && s[0].slice(-6);\n return n == 0 ? 'zero' : n == 1 ? 'one' : n100 == 2 || n100 == 22 || n100 == 42 || n100 == 62 || n100 == 82 || t0 && n1000 == 0 && (n100000 >= 1000 && n100000 <= 20000 || n100000 == 40000 || n100000 == 60000 || n100000 == 80000) || n != 0 && n1000000 == 100000 ? 'two' : n100 == 3 || n100 == 23 || n100 == 43 || n100 == 63 || n100 == 83 ? 'few' : n != 1 && (n100 == 1 || n100 == 21 || n100 == 41 || n100 == 61 || n100 == 81) ? 'many' : 'other';\n };\n const ky$2 = a$2;\n const lag$2 = n => {\n const s = String(n).split('.'),\n i = s[0];\n return n == 0 ? 'zero' : (i == 0 || i == 1) && n != 0 ? 'one' : 'other';\n };\n const lb$2 = a$2;\n const lg$2 = a$2;\n const lij$2 = d$2;\n const lkt$2 = e$1;\n const ln$2 = b$2;\n const lo$2 = e$1;\n const lt$2 = n => {\n const s = String(n).split('.'),\n f = s[1] || '',\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n return n10 == 1 && (n100 < 11 || n100 > 19) ? 'one' : n10 >= 2 && n10 <= 9 && (n100 < 11 || n100 > 19) ? 'few' : f != 0 ? 'many' : 'other';\n };\n const lv$2 = n => {\n const s = String(n).split('.'),\n f = s[1] || '',\n v = f.length,\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n f100 = f.slice(-2),\n f10 = f.slice(-1);\n return t0 && n10 == 0 || n100 >= 11 && n100 <= 19 || v == 2 && f100 >= 11 && f100 <= 19 ? 'zero' : n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 || v != 2 && f10 == 1 ? 'one' : 'other';\n };\n const mas$2 = a$2;\n const mg$2 = b$2;\n const mgo$2 = a$2;\n const mk$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : 'other';\n };\n const ml$2 = a$2;\n const mn$2 = a$2;\n const mo$2 = n => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n return n == 1 && v0 ? 'one' : !v0 || n == 0 || n != 1 && n100 >= 1 && n100 <= 19 ? 'few' : 'other';\n };\n const mr$2 = a$2;\n const ms$2 = e$1;\n const mt$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n return n == 1 ? 'one' : n == 2 ? 'two' : n == 0 || n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 19 ? 'many' : 'other';\n };\n const my$2 = e$1;\n const nah$2 = a$2;\n const naq$2 = f$2;\n const nb$2 = a$2;\n const nd$2 = a$2;\n const ne$2 = a$2;\n const nl$2 = d$2;\n const nn$2 = a$2;\n const nnh$2 = a$2;\n const no$2 = a$2;\n const nqo$2 = e$1;\n const nr$2 = a$2;\n const nso$2 = b$2;\n const ny$2 = a$2;\n const nyn$2 = a$2;\n const om$2 = a$2;\n const or$2 = a$2;\n const os$2 = a$2;\n const osa$2 = e$1;\n const pa$2 = b$2;\n const pap$2 = a$2;\n const pcm$2 = c$2;\n const pl$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n return n == 1 && v0 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i != 1 && (i10 == 0 || i10 == 1) || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 12 && i100 <= 14 ? 'many' : 'other';\n };\n const prg$2 = n => {\n const s = String(n).split('.'),\n f = s[1] || '',\n v = f.length,\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n f100 = f.slice(-2),\n f10 = f.slice(-1);\n return t0 && n10 == 0 || n100 >= 11 && n100 <= 19 || v == 2 && f100 >= 11 && f100 <= 19 ? 'zero' : n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 || v != 2 && f10 == 1 ? 'one' : 'other';\n };\n const ps$2 = a$2;\n const pt$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return i == 0 || i == 1 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const pt_PT$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const rm$2 = a$2;\n const ro$2 = n => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n return n == 1 && v0 ? 'one' : !v0 || n == 0 || n != 1 && n100 >= 1 && n100 <= 19 ? 'few' : 'other';\n };\n const rof$2 = a$2;\n const ru$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n return v0 && i10 == 1 && i100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i10 == 0 || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 11 && i100 <= 14 ? 'many' : 'other';\n };\n const rwk$2 = a$2;\n const sah$2 = e$1;\n const saq$2 = a$2;\n const sat$2 = f$2;\n const sc$2 = d$2;\n const scn$2 = d$2;\n const sd$2 = a$2;\n const sdh$2 = a$2;\n const se$2 = f$2;\n const seh$2 = a$2;\n const ses$2 = e$1;\n const sg$2 = e$1;\n const sh$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const shi$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n return n >= 0 && n <= 1 ? 'one' : t0 && n >= 2 && n <= 10 ? 'few' : 'other';\n };\n const si$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '';\n return n == 0 || n == 1 || i == 0 && f == 1 ? 'one' : 'other';\n };\n const sk$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n return n == 1 && v0 ? 'one' : i >= 2 && i <= 4 && v0 ? 'few' : !v0 ? 'many' : 'other';\n };\n const sl$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i100 = i.slice(-2);\n return v0 && i100 == 1 ? 'one' : v0 && i100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || !v0 ? 'few' : 'other';\n };\n const sma$2 = f$2;\n const smi$2 = f$2;\n const smj$2 = f$2;\n const smn$2 = f$2;\n const sms$2 = f$2;\n const sn$2 = a$2;\n const so$2 = a$2;\n const sq$2 = a$2;\n const sr$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const ss$2 = a$2;\n const ssy$2 = a$2;\n const st$2 = a$2;\n const su$2 = e$1;\n const sv$2 = d$2;\n const sw$2 = d$2;\n const syr$2 = a$2;\n const ta$2 = a$2;\n const te$2 = a$2;\n const teo$2 = a$2;\n const th$2 = e$1;\n const ti$2 = b$2;\n const tig$2 = a$2;\n const tk$2 = a$2;\n const tl$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const tn$2 = a$2;\n const to$2 = e$1;\n const tpi$2 = e$1;\n const tr$2 = a$2;\n const ts$2 = a$2;\n const tzm$2 = n => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n return n == 0 || n == 1 || t0 && n >= 11 && n <= 99 ? 'one' : 'other';\n };\n const ug$2 = a$2;\n const uk$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n return v0 && i10 == 1 && i100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i10 == 0 || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 11 && i100 <= 14 ? 'many' : 'other';\n };\n const und$2 = e$1;\n const ur$2 = d$2;\n const uz$2 = a$2;\n const ve$2 = a$2;\n const vec$2 = n => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const vi$2 = e$1;\n const vo$2 = a$2;\n const vun$2 = a$2;\n const wa$2 = b$2;\n const wae$2 = a$2;\n const wo$2 = e$1;\n const xh$2 = a$2;\n const xog$2 = a$2;\n const yi$2 = d$2;\n const yo$2 = e$1;\n const yue$2 = e$1;\n const zh$2 = e$1;\n const zu$2 = c$2;\n\n var Cardinals = /*#__PURE__*/Object.freeze({\n __proto__: null,\n af: af$2,\n ak: ak$2,\n am: am$2,\n an: an$2,\n ar: ar$2,\n ars: ars$2,\n as: as$2,\n asa: asa$2,\n ast: ast$2,\n az: az$2,\n bal: bal$2,\n be: be$2,\n bem: bem$2,\n bez: bez$2,\n bg: bg$2,\n bho: bho$2,\n bm: bm$2,\n bn: bn$2,\n bo: bo$2,\n br: br$2,\n brx: brx$2,\n bs: bs$2,\n ca: ca$2,\n ce: ce$2,\n ceb: ceb$2,\n cgg: cgg$2,\n chr: chr$2,\n ckb: ckb$2,\n cs: cs$2,\n cy: cy$2,\n da: da$2,\n de: de$2,\n doi: doi$2,\n dsb: dsb$2,\n dv: dv$2,\n dz: dz$2,\n ee: ee$2,\n el: el$2,\n en: en$2,\n eo: eo$2,\n es: es$2,\n et: et$2,\n eu: eu$2,\n fa: fa$2,\n ff: ff$2,\n fi: fi$2,\n fil: fil$2,\n fo: fo$2,\n fr: fr$2,\n fur: fur$2,\n fy: fy$2,\n ga: ga$2,\n gd: gd$2,\n gl: gl$2,\n gsw: gsw$2,\n gu: gu$2,\n guw: guw$2,\n gv: gv$2,\n ha: ha$2,\n haw: haw$2,\n he: he$2,\n hi: hi$2,\n hnj: hnj$2,\n hr: hr$2,\n hsb: hsb$2,\n hu: hu$2,\n hy: hy$2,\n ia: ia$2,\n id: id$2,\n ig: ig$2,\n ii: ii$2,\n io: io$2,\n is: is$2,\n it: it$2,\n iu: iu$2,\n ja: ja$2,\n jbo: jbo$2,\n jgo: jgo$2,\n jmc: jmc$2,\n jv: jv$2,\n jw: jw$2,\n ka: ka$2,\n kab: kab$2,\n kaj: kaj$2,\n kcg: kcg$2,\n kde: kde$2,\n kea: kea$2,\n kk: kk$2,\n kkj: kkj$2,\n kl: kl$2,\n km: km$2,\n kn: kn$2,\n ko: ko$2,\n ks: ks$2,\n ksb: ksb$2,\n ksh: ksh$2,\n ku: ku$2,\n kw: kw$2,\n ky: ky$2,\n lag: lag$2,\n lb: lb$2,\n lg: lg$2,\n lij: lij$2,\n lkt: lkt$2,\n ln: ln$2,\n lo: lo$2,\n lt: lt$2,\n lv: lv$2,\n mas: mas$2,\n mg: mg$2,\n mgo: mgo$2,\n mk: mk$2,\n ml: ml$2,\n mn: mn$2,\n mo: mo$2,\n mr: mr$2,\n ms: ms$2,\n mt: mt$2,\n my: my$2,\n nah: nah$2,\n naq: naq$2,\n nb: nb$2,\n nd: nd$2,\n ne: ne$2,\n nl: nl$2,\n nn: nn$2,\n nnh: nnh$2,\n no: no$2,\n nqo: nqo$2,\n nr: nr$2,\n nso: nso$2,\n ny: ny$2,\n nyn: nyn$2,\n om: om$2,\n or: or$2,\n os: os$2,\n osa: osa$2,\n pa: pa$2,\n pap: pap$2,\n pcm: pcm$2,\n pl: pl$2,\n prg: prg$2,\n ps: ps$2,\n pt: pt$2,\n pt_PT: pt_PT$2,\n rm: rm$2,\n ro: ro$2,\n rof: rof$2,\n ru: ru$2,\n rwk: rwk$2,\n sah: sah$2,\n saq: saq$2,\n sat: sat$2,\n sc: sc$2,\n scn: scn$2,\n sd: sd$2,\n sdh: sdh$2,\n se: se$2,\n seh: seh$2,\n ses: ses$2,\n sg: sg$2,\n sh: sh$2,\n shi: shi$2,\n si: si$2,\n sk: sk$2,\n sl: sl$2,\n sma: sma$2,\n smi: smi$2,\n smj: smj$2,\n smn: smn$2,\n sms: sms$2,\n sn: sn$2,\n so: so$2,\n sq: sq$2,\n sr: sr$2,\n ss: ss$2,\n ssy: ssy$2,\n st: st$2,\n su: su$2,\n sv: sv$2,\n sw: sw$2,\n syr: syr$2,\n ta: ta$2,\n te: te$2,\n teo: teo$2,\n th: th$2,\n ti: ti$2,\n tig: tig$2,\n tk: tk$2,\n tl: tl$2,\n tn: tn$2,\n to: to$2,\n tpi: tpi$2,\n tr: tr$2,\n ts: ts$2,\n tzm: tzm$2,\n ug: ug$2,\n uk: uk$2,\n und: und$2,\n ur: ur$2,\n uz: uz$2,\n ve: ve$2,\n vec: vec$2,\n vi: vi$2,\n vo: vo$2,\n vun: vun$2,\n wa: wa$2,\n wae: wae$2,\n wo: wo$2,\n xh: xh$2,\n xog: xog$2,\n yi: yi$2,\n yo: yo$2,\n yue: yue$2,\n zh: zh$2,\n zu: zu$2\n });\n\n const z = \"zero\",\n o = \"one\",\n t = \"two\",\n f$1 = \"few\",\n m = \"many\",\n x = \"other\";\n const a$1 = {\n cardinal: [o, x],\n ordinal: [x]\n };\n const b$1 = {\n cardinal: [o, x],\n ordinal: [o, x]\n };\n const c$1 = {\n cardinal: [x],\n ordinal: [x]\n };\n const d$1 = {\n cardinal: [o, t, x],\n ordinal: [x]\n };\n const af$1 = a$1;\n const ak$1 = a$1;\n const am$1 = a$1;\n const an$1 = a$1;\n const ar$1 = {\n cardinal: [z, o, t, f$1, m, x],\n ordinal: [x]\n };\n const ars$1 = {\n cardinal: [z, o, t, f$1, m, x],\n ordinal: [x]\n };\n const as$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, m, x]\n };\n const asa$1 = a$1;\n const ast$1 = a$1;\n const az$1 = {\n cardinal: [o, x],\n ordinal: [o, f$1, m, x]\n };\n const bal$1 = b$1;\n const be$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [f$1, x]\n };\n const bem$1 = a$1;\n const bez$1 = a$1;\n const bg$1 = a$1;\n const bho$1 = a$1;\n const bm$1 = c$1;\n const bn$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, m, x]\n };\n const bo$1 = c$1;\n const br$1 = {\n cardinal: [o, t, f$1, m, x],\n ordinal: [x]\n };\n const brx$1 = a$1;\n const bs$1 = {\n cardinal: [o, f$1, x],\n ordinal: [x]\n };\n const ca$1 = {\n cardinal: [o, m, x],\n ordinal: [o, t, f$1, x]\n };\n const ce$1 = a$1;\n const ceb$1 = a$1;\n const cgg$1 = a$1;\n const chr$1 = a$1;\n const ckb$1 = a$1;\n const cs$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [x]\n };\n const cy$1 = {\n cardinal: [z, o, t, f$1, m, x],\n ordinal: [z, o, t, f$1, m, x]\n };\n const da$1 = a$1;\n const de$1 = a$1;\n const doi$1 = a$1;\n const dsb$1 = {\n cardinal: [o, t, f$1, x],\n ordinal: [x]\n };\n const dv$1 = a$1;\n const dz$1 = c$1;\n const ee$1 = a$1;\n const el$1 = a$1;\n const en$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, x]\n };\n const eo$1 = a$1;\n const es$1 = {\n cardinal: [o, m, x],\n ordinal: [x]\n };\n const et$1 = a$1;\n const eu$1 = a$1;\n const fa$1 = a$1;\n const ff$1 = a$1;\n const fi$1 = a$1;\n const fil$1 = b$1;\n const fo$1 = a$1;\n const fr$1 = {\n cardinal: [o, m, x],\n ordinal: [o, x]\n };\n const fur$1 = a$1;\n const fy$1 = a$1;\n const ga$1 = {\n cardinal: [o, t, f$1, m, x],\n ordinal: [o, x]\n };\n const gd$1 = {\n cardinal: [o, t, f$1, x],\n ordinal: [o, t, f$1, x]\n };\n const gl$1 = a$1;\n const gsw$1 = a$1;\n const gu$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, m, x]\n };\n const guw$1 = a$1;\n const gv$1 = {\n cardinal: [o, t, f$1, m, x],\n ordinal: [x]\n };\n const ha$1 = a$1;\n const haw$1 = a$1;\n const he$1 = d$1;\n const hi$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, m, x]\n };\n const hnj$1 = c$1;\n const hr$1 = {\n cardinal: [o, f$1, x],\n ordinal: [x]\n };\n const hsb$1 = {\n cardinal: [o, t, f$1, x],\n ordinal: [x]\n };\n const hu$1 = b$1;\n const hy$1 = b$1;\n const ia$1 = a$1;\n const id$1 = c$1;\n const ig$1 = c$1;\n const ii$1 = c$1;\n const io$1 = a$1;\n const is$1 = a$1;\n const it$1 = {\n cardinal: [o, m, x],\n ordinal: [m, x]\n };\n const iu$1 = d$1;\n const ja$1 = c$1;\n const jbo$1 = c$1;\n const jgo$1 = a$1;\n const jmc$1 = a$1;\n const jv$1 = c$1;\n const jw$1 = c$1;\n const ka$1 = {\n cardinal: [o, x],\n ordinal: [o, m, x]\n };\n const kab$1 = a$1;\n const kaj$1 = a$1;\n const kcg$1 = a$1;\n const kde$1 = c$1;\n const kea$1 = c$1;\n const kk$1 = {\n cardinal: [o, x],\n ordinal: [m, x]\n };\n const kkj$1 = a$1;\n const kl$1 = a$1;\n const km$1 = c$1;\n const kn$1 = a$1;\n const ko$1 = c$1;\n const ks$1 = a$1;\n const ksb$1 = a$1;\n const ksh$1 = {\n cardinal: [z, o, x],\n ordinal: [x]\n };\n const ku$1 = a$1;\n const kw$1 = {\n cardinal: [z, o, t, f$1, m, x],\n ordinal: [o, m, x]\n };\n const ky$1 = a$1;\n const lag$1 = {\n cardinal: [z, o, x],\n ordinal: [x]\n };\n const lb$1 = a$1;\n const lg$1 = a$1;\n const lij$1 = {\n cardinal: [o, x],\n ordinal: [m, x]\n };\n const lkt$1 = c$1;\n const ln$1 = a$1;\n const lo$1 = {\n cardinal: [x],\n ordinal: [o, x]\n };\n const lt$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [x]\n };\n const lv$1 = {\n cardinal: [z, o, x],\n ordinal: [x]\n };\n const mas$1 = a$1;\n const mg$1 = a$1;\n const mgo$1 = a$1;\n const mk$1 = {\n cardinal: [o, x],\n ordinal: [o, t, m, x]\n };\n const ml$1 = a$1;\n const mn$1 = a$1;\n const mo$1 = {\n cardinal: [o, f$1, x],\n ordinal: [o, x]\n };\n const mr$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, x]\n };\n const ms$1 = {\n cardinal: [x],\n ordinal: [o, x]\n };\n const mt$1 = {\n cardinal: [o, t, f$1, m, x],\n ordinal: [x]\n };\n const my$1 = c$1;\n const nah$1 = a$1;\n const naq$1 = d$1;\n const nb$1 = a$1;\n const nd$1 = a$1;\n const ne$1 = b$1;\n const nl$1 = a$1;\n const nn$1 = a$1;\n const nnh$1 = a$1;\n const no$1 = a$1;\n const nqo$1 = c$1;\n const nr$1 = a$1;\n const nso$1 = a$1;\n const ny$1 = a$1;\n const nyn$1 = a$1;\n const om$1 = a$1;\n const or$1 = {\n cardinal: [o, x],\n ordinal: [o, t, f$1, m, x]\n };\n const os$1 = a$1;\n const osa$1 = c$1;\n const pa$1 = a$1;\n const pap$1 = a$1;\n const pcm$1 = a$1;\n const pl$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [x]\n };\n const prg$1 = {\n cardinal: [z, o, x],\n ordinal: [x]\n };\n const ps$1 = a$1;\n const pt$1 = {\n cardinal: [o, m, x],\n ordinal: [x]\n };\n const pt_PT$1 = {\n cardinal: [o, m, x],\n ordinal: [x]\n };\n const rm$1 = a$1;\n const ro$1 = {\n cardinal: [o, f$1, x],\n ordinal: [o, x]\n };\n const rof$1 = a$1;\n const ru$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [x]\n };\n const rwk$1 = a$1;\n const sah$1 = c$1;\n const saq$1 = a$1;\n const sat$1 = d$1;\n const sc$1 = {\n cardinal: [o, x],\n ordinal: [m, x]\n };\n const scn$1 = {\n cardinal: [o, x],\n ordinal: [m, x]\n };\n const sd$1 = a$1;\n const sdh$1 = a$1;\n const se$1 = d$1;\n const seh$1 = a$1;\n const ses$1 = c$1;\n const sg$1 = c$1;\n const sh$1 = {\n cardinal: [o, f$1, x],\n ordinal: [x]\n };\n const shi$1 = {\n cardinal: [o, f$1, x],\n ordinal: [x]\n };\n const si$1 = a$1;\n const sk$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [x]\n };\n const sl$1 = {\n cardinal: [o, t, f$1, x],\n ordinal: [x]\n };\n const sma$1 = d$1;\n const smi$1 = d$1;\n const smj$1 = d$1;\n const smn$1 = d$1;\n const sms$1 = d$1;\n const sn$1 = a$1;\n const so$1 = a$1;\n const sq$1 = {\n cardinal: [o, x],\n ordinal: [o, m, x]\n };\n const sr$1 = {\n cardinal: [o, f$1, x],\n ordinal: [x]\n };\n const ss$1 = a$1;\n const ssy$1 = a$1;\n const st$1 = a$1;\n const su$1 = c$1;\n const sv$1 = b$1;\n const sw$1 = a$1;\n const syr$1 = a$1;\n const ta$1 = a$1;\n const te$1 = a$1;\n const teo$1 = a$1;\n const th$1 = c$1;\n const ti$1 = a$1;\n const tig$1 = a$1;\n const tk$1 = {\n cardinal: [o, x],\n ordinal: [f$1, x]\n };\n const tl$1 = b$1;\n const tn$1 = a$1;\n const to$1 = c$1;\n const tpi$1 = c$1;\n const tr$1 = a$1;\n const ts$1 = a$1;\n const tzm$1 = a$1;\n const ug$1 = a$1;\n const uk$1 = {\n cardinal: [o, f$1, m, x],\n ordinal: [f$1, x]\n };\n const und$1 = c$1;\n const ur$1 = a$1;\n const uz$1 = a$1;\n const ve$1 = a$1;\n const vec$1 = {\n cardinal: [o, m, x],\n ordinal: [m, x]\n };\n const vi$1 = {\n cardinal: [x],\n ordinal: [o, x]\n };\n const vo$1 = a$1;\n const vun$1 = a$1;\n const wa$1 = a$1;\n const wae$1 = a$1;\n const wo$1 = c$1;\n const xh$1 = a$1;\n const xog$1 = a$1;\n const yi$1 = a$1;\n const yo$1 = c$1;\n const yue$1 = c$1;\n const zh$1 = c$1;\n const zu$1 = a$1;\n\n var PluralCategories = /*#__PURE__*/Object.freeze({\n __proto__: null,\n af: af$1,\n ak: ak$1,\n am: am$1,\n an: an$1,\n ar: ar$1,\n ars: ars$1,\n as: as$1,\n asa: asa$1,\n ast: ast$1,\n az: az$1,\n bal: bal$1,\n be: be$1,\n bem: bem$1,\n bez: bez$1,\n bg: bg$1,\n bho: bho$1,\n bm: bm$1,\n bn: bn$1,\n bo: bo$1,\n br: br$1,\n brx: brx$1,\n bs: bs$1,\n ca: ca$1,\n ce: ce$1,\n ceb: ceb$1,\n cgg: cgg$1,\n chr: chr$1,\n ckb: ckb$1,\n cs: cs$1,\n cy: cy$1,\n da: da$1,\n de: de$1,\n doi: doi$1,\n dsb: dsb$1,\n dv: dv$1,\n dz: dz$1,\n ee: ee$1,\n el: el$1,\n en: en$1,\n eo: eo$1,\n es: es$1,\n et: et$1,\n eu: eu$1,\n fa: fa$1,\n ff: ff$1,\n fi: fi$1,\n fil: fil$1,\n fo: fo$1,\n fr: fr$1,\n fur: fur$1,\n fy: fy$1,\n ga: ga$1,\n gd: gd$1,\n gl: gl$1,\n gsw: gsw$1,\n gu: gu$1,\n guw: guw$1,\n gv: gv$1,\n ha: ha$1,\n haw: haw$1,\n he: he$1,\n hi: hi$1,\n hnj: hnj$1,\n hr: hr$1,\n hsb: hsb$1,\n hu: hu$1,\n hy: hy$1,\n ia: ia$1,\n id: id$1,\n ig: ig$1,\n ii: ii$1,\n io: io$1,\n is: is$1,\n it: it$1,\n iu: iu$1,\n ja: ja$1,\n jbo: jbo$1,\n jgo: jgo$1,\n jmc: jmc$1,\n jv: jv$1,\n jw: jw$1,\n ka: ka$1,\n kab: kab$1,\n kaj: kaj$1,\n kcg: kcg$1,\n kde: kde$1,\n kea: kea$1,\n kk: kk$1,\n kkj: kkj$1,\n kl: kl$1,\n km: km$1,\n kn: kn$1,\n ko: ko$1,\n ks: ks$1,\n ksb: ksb$1,\n ksh: ksh$1,\n ku: ku$1,\n kw: kw$1,\n ky: ky$1,\n lag: lag$1,\n lb: lb$1,\n lg: lg$1,\n lij: lij$1,\n lkt: lkt$1,\n ln: ln$1,\n lo: lo$1,\n lt: lt$1,\n lv: lv$1,\n mas: mas$1,\n mg: mg$1,\n mgo: mgo$1,\n mk: mk$1,\n ml: ml$1,\n mn: mn$1,\n mo: mo$1,\n mr: mr$1,\n ms: ms$1,\n mt: mt$1,\n my: my$1,\n nah: nah$1,\n naq: naq$1,\n nb: nb$1,\n nd: nd$1,\n ne: ne$1,\n nl: nl$1,\n nn: nn$1,\n nnh: nnh$1,\n no: no$1,\n nqo: nqo$1,\n nr: nr$1,\n nso: nso$1,\n ny: ny$1,\n nyn: nyn$1,\n om: om$1,\n or: or$1,\n os: os$1,\n osa: osa$1,\n pa: pa$1,\n pap: pap$1,\n pcm: pcm$1,\n pl: pl$1,\n prg: prg$1,\n ps: ps$1,\n pt: pt$1,\n pt_PT: pt_PT$1,\n rm: rm$1,\n ro: ro$1,\n rof: rof$1,\n ru: ru$1,\n rwk: rwk$1,\n sah: sah$1,\n saq: saq$1,\n sat: sat$1,\n sc: sc$1,\n scn: scn$1,\n sd: sd$1,\n sdh: sdh$1,\n se: se$1,\n seh: seh$1,\n ses: ses$1,\n sg: sg$1,\n sh: sh$1,\n shi: shi$1,\n si: si$1,\n sk: sk$1,\n sl: sl$1,\n sma: sma$1,\n smi: smi$1,\n smj: smj$1,\n smn: smn$1,\n sms: sms$1,\n sn: sn$1,\n so: so$1,\n sq: sq$1,\n sr: sr$1,\n ss: ss$1,\n ssy: ssy$1,\n st: st$1,\n su: su$1,\n sv: sv$1,\n sw: sw$1,\n syr: syr$1,\n ta: ta$1,\n te: te$1,\n teo: teo$1,\n th: th$1,\n ti: ti$1,\n tig: tig$1,\n tk: tk$1,\n tl: tl$1,\n tn: tn$1,\n to: to$1,\n tpi: tpi$1,\n tr: tr$1,\n ts: ts$1,\n tzm: tzm$1,\n ug: ug$1,\n uk: uk$1,\n und: und$1,\n ur: ur$1,\n uz: uz$1,\n ve: ve$1,\n vec: vec$1,\n vi: vi$1,\n vo: vo$1,\n vun: vun$1,\n wa: wa$1,\n wae: wae$1,\n wo: wo$1,\n xh: xh$1,\n xog: xog$1,\n yi: yi$1,\n yo: yo$1,\n yue: yue$1,\n zh: zh$1,\n zu: zu$1\n });\n\n const a = (n, ord) => {\n if (ord) return 'other';\n return n == 1 ? 'one' : 'other';\n };\n const b = (n, ord) => {\n if (ord) return 'other';\n return n == 0 || n == 1 ? 'one' : 'other';\n };\n const c = (n, ord) => {\n if (ord) return 'other';\n return n >= 0 && n <= 1 ? 'one' : 'other';\n };\n const d = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1];\n if (ord) return 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const e = (n, ord) => 'other';\n const f = (n, ord) => {\n if (ord) return 'other';\n return n == 1 ? 'one' : n == 2 ? 'two' : 'other';\n };\n const af = a;\n const ak = b;\n const am = c;\n const an = a;\n const ar = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n if (ord) return 'other';\n return n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 99 ? 'many' : 'other';\n };\n const ars = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n if (ord) return 'other';\n return n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 99 ? 'many' : 'other';\n };\n const as = (n, ord) => {\n if (ord) return n == 1 || n == 5 || n == 7 || n == 8 || n == 9 || n == 10 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : n == 6 ? 'many' : 'other';\n return n >= 0 && n <= 1 ? 'one' : 'other';\n };\n const asa = a;\n const ast = d;\n const az = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n i1000 = i.slice(-3);\n if (ord) return i10 == 1 || i10 == 2 || i10 == 5 || i10 == 7 || i10 == 8 || i100 == 20 || i100 == 50 || i100 == 70 || i100 == 80 ? 'one' : i10 == 3 || i10 == 4 || i1000 == 100 || i1000 == 200 || i1000 == 300 || i1000 == 400 || i1000 == 500 || i1000 == 600 || i1000 == 700 || i1000 == 800 || i1000 == 900 ? 'few' : i == 0 || i10 == 6 || i100 == 40 || i100 == 60 || i100 == 90 ? 'many' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const bal = (n, ord) => n == 1 ? 'one' : 'other';\n const be = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n if (ord) return (n10 == 2 || n10 == 3) && n100 != 12 && n100 != 13 ? 'few' : 'other';\n return n10 == 1 && n100 != 11 ? 'one' : n10 >= 2 && n10 <= 4 && (n100 < 12 || n100 > 14) ? 'few' : t0 && n10 == 0 || n10 >= 5 && n10 <= 9 || n100 >= 11 && n100 <= 14 ? 'many' : 'other';\n };\n const bem = a;\n const bez = a;\n const bg = a;\n const bho = b;\n const bm = e;\n const bn = (n, ord) => {\n if (ord) return n == 1 || n == 5 || n == 7 || n == 8 || n == 9 || n == 10 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : n == 6 ? 'many' : 'other';\n return n >= 0 && n <= 1 ? 'one' : 'other';\n };\n const bo = e;\n const br = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n n1000000 = t0 && s[0].slice(-6);\n if (ord) return 'other';\n return n10 == 1 && n100 != 11 && n100 != 71 && n100 != 91 ? 'one' : n10 == 2 && n100 != 12 && n100 != 72 && n100 != 92 ? 'two' : (n10 == 3 || n10 == 4 || n10 == 9) && (n100 < 10 || n100 > 19) && (n100 < 70 || n100 > 79) && (n100 < 90 || n100 > 99) ? 'few' : n != 0 && t0 && n1000000 == 0 ? 'many' : 'other';\n };\n const brx = a;\n const bs = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const ca = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return n == 1 || n == 3 ? 'one' : n == 2 ? 'two' : n == 4 ? 'few' : 'other';\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const ce = a;\n const ceb = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n if (ord) return 'other';\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const cgg = a;\n const chr = a;\n const ckb = a;\n const cs = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n if (ord) return 'other';\n return n == 1 && v0 ? 'one' : i >= 2 && i <= 4 && v0 ? 'few' : !v0 ? 'many' : 'other';\n };\n const cy = (n, ord) => {\n if (ord) return n == 0 || n == 7 || n == 8 || n == 9 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n == 3 || n == 4 ? 'few' : n == 5 || n == 6 ? 'many' : 'other';\n return n == 0 ? 'zero' : n == 1 ? 'one' : n == 2 ? 'two' : n == 3 ? 'few' : n == 6 ? 'many' : 'other';\n };\n const da = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n t0 = Number(s[0]) == n;\n if (ord) return 'other';\n return n == 1 || !t0 && (i == 0 || i == 1) ? 'one' : 'other';\n };\n const de = d;\n const doi = c;\n const dsb = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i100 = i.slice(-2),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i100 == 1 || f100 == 1 ? 'one' : v0 && i100 == 2 || f100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || f100 == 3 || f100 == 4 ? 'few' : 'other';\n };\n const dv = a;\n const dz = e;\n const ee = a;\n const el = a;\n const en = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n if (ord) return n10 == 1 && n100 != 11 ? 'one' : n10 == 2 && n100 != 12 ? 'two' : n10 == 3 && n100 != 13 ? 'few' : 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const eo = a;\n const es = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return 'other';\n return n == 1 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const et = d;\n const eu = a;\n const fa = c;\n const ff = (n, ord) => {\n if (ord) return 'other';\n return n >= 0 && n < 2 ? 'one' : 'other';\n };\n const fi = d;\n const fil = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n if (ord) return n == 1 ? 'one' : 'other';\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const fo = a;\n const fr = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return n == 1 ? 'one' : 'other';\n return n >= 0 && n < 2 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const fur = a;\n const fy = d;\n const ga = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return n == 1 ? 'one' : 'other';\n return n == 1 ? 'one' : n == 2 ? 'two' : t0 && n >= 3 && n <= 6 ? 'few' : t0 && n >= 7 && n <= 10 ? 'many' : 'other';\n };\n const gd = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return n == 1 || n == 11 ? 'one' : n == 2 || n == 12 ? 'two' : n == 3 || n == 13 ? 'few' : 'other';\n return n == 1 || n == 11 ? 'one' : n == 2 || n == 12 ? 'two' : t0 && n >= 3 && n <= 10 || t0 && n >= 13 && n <= 19 ? 'few' : 'other';\n };\n const gl = d;\n const gsw = a;\n const gu = (n, ord) => {\n if (ord) return n == 1 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : n == 6 ? 'many' : 'other';\n return n >= 0 && n <= 1 ? 'one' : 'other';\n };\n const guw = b;\n const gv = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 ? 'one' : v0 && i10 == 2 ? 'two' : v0 && (i100 == 0 || i100 == 20 || i100 == 40 || i100 == 60 || i100 == 80) ? 'few' : !v0 ? 'many' : 'other';\n };\n const ha = a;\n const haw = a;\n const he = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n if (ord) return 'other';\n return i == 1 && v0 || i == 0 && !v0 ? 'one' : i == 2 && v0 ? 'two' : 'other';\n };\n const hi = (n, ord) => {\n if (ord) return n == 1 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : n == 6 ? 'many' : 'other';\n return n >= 0 && n <= 1 ? 'one' : 'other';\n };\n const hnj = e;\n const hr = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const hsb = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i100 = i.slice(-2),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i100 == 1 || f100 == 1 ? 'one' : v0 && i100 == 2 || f100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || f100 == 3 || f100 == 4 ? 'few' : 'other';\n };\n const hu = (n, ord) => {\n if (ord) return n == 1 || n == 5 ? 'one' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const hy = (n, ord) => {\n if (ord) return n == 1 ? 'one' : 'other';\n return n >= 0 && n < 2 ? 'one' : 'other';\n };\n const ia = d;\n const id = e;\n const ig = e;\n const ii = e;\n const io = d;\n const is = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n t = (s[1] || '').replace(/0+$/, ''),\n t0 = Number(s[0]) == n,\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n if (ord) return 'other';\n return t0 && i10 == 1 && i100 != 11 || t % 10 == 1 && t % 100 != 11 ? 'one' : 'other';\n };\n const it = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return n == 11 || n == 8 || n == 80 || n == 800 ? 'many' : 'other';\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const iu = f;\n const ja = e;\n const jbo = e;\n const jgo = a;\n const jmc = a;\n const jv = e;\n const jw = e;\n const ka = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n i100 = i.slice(-2);\n if (ord) return i == 1 ? 'one' : i == 0 || i100 >= 2 && i100 <= 20 || i100 == 40 || i100 == 60 || i100 == 80 ? 'many' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const kab = (n, ord) => {\n if (ord) return 'other';\n return n >= 0 && n < 2 ? 'one' : 'other';\n };\n const kaj = a;\n const kcg = a;\n const kde = e;\n const kea = e;\n const kk = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1);\n if (ord) return n10 == 6 || n10 == 9 || t0 && n10 == 0 && n != 0 ? 'many' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const kkj = a;\n const kl = a;\n const km = e;\n const kn = c;\n const ko = e;\n const ks = a;\n const ksb = a;\n const ksh = (n, ord) => {\n if (ord) return 'other';\n return n == 0 ? 'zero' : n == 1 ? 'one' : 'other';\n };\n const ku = a;\n const kw = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2),\n n1000 = t0 && s[0].slice(-3),\n n100000 = t0 && s[0].slice(-5),\n n1000000 = t0 && s[0].slice(-6);\n if (ord) return t0 && n >= 1 && n <= 4 || n100 >= 1 && n100 <= 4 || n100 >= 21 && n100 <= 24 || n100 >= 41 && n100 <= 44 || n100 >= 61 && n100 <= 64 || n100 >= 81 && n100 <= 84 ? 'one' : n == 5 || n100 == 5 ? 'many' : 'other';\n return n == 0 ? 'zero' : n == 1 ? 'one' : n100 == 2 || n100 == 22 || n100 == 42 || n100 == 62 || n100 == 82 || t0 && n1000 == 0 && (n100000 >= 1000 && n100000 <= 20000 || n100000 == 40000 || n100000 == 60000 || n100000 == 80000) || n != 0 && n1000000 == 100000 ? 'two' : n100 == 3 || n100 == 23 || n100 == 43 || n100 == 63 || n100 == 83 ? 'few' : n != 1 && (n100 == 1 || n100 == 21 || n100 == 41 || n100 == 61 || n100 == 81) ? 'many' : 'other';\n };\n const ky = a;\n const lag = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0];\n if (ord) return 'other';\n return n == 0 ? 'zero' : (i == 0 || i == 1) && n != 0 ? 'one' : 'other';\n };\n const lb = a;\n const lg = a;\n const lij = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n;\n if (ord) return n == 11 || n == 8 || t0 && n >= 80 && n <= 89 || t0 && n >= 800 && n <= 899 ? 'many' : 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const lkt = e;\n const ln = b;\n const lo = (n, ord) => {\n if (ord) return n == 1 ? 'one' : 'other';\n return 'other';\n };\n const lt = (n, ord) => {\n const s = String(n).split('.'),\n f = s[1] || '',\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n if (ord) return 'other';\n return n10 == 1 && (n100 < 11 || n100 > 19) ? 'one' : n10 >= 2 && n10 <= 9 && (n100 < 11 || n100 > 19) ? 'few' : f != 0 ? 'many' : 'other';\n };\n const lv = (n, ord) => {\n const s = String(n).split('.'),\n f = s[1] || '',\n v = f.length,\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n f100 = f.slice(-2),\n f10 = f.slice(-1);\n if (ord) return 'other';\n return t0 && n10 == 0 || n100 >= 11 && n100 <= 19 || v == 2 && f100 >= 11 && f100 <= 19 ? 'zero' : n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 || v != 2 && f10 == 1 ? 'one' : 'other';\n };\n const mas = a;\n const mg = b;\n const mgo = a;\n const mk = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n if (ord) return i10 == 1 && i100 != 11 ? 'one' : i10 == 2 && i100 != 12 ? 'two' : (i10 == 7 || i10 == 8) && i100 != 17 && i100 != 18 ? 'many' : 'other';\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : 'other';\n };\n const ml = a;\n const mn = a;\n const mo = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n if (ord) return n == 1 ? 'one' : 'other';\n return n == 1 && v0 ? 'one' : !v0 || n == 0 || n != 1 && n100 >= 1 && n100 <= 19 ? 'few' : 'other';\n };\n const mr = (n, ord) => {\n if (ord) return n == 1 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const ms = (n, ord) => {\n if (ord) return n == 1 ? 'one' : 'other';\n return 'other';\n };\n const mt = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n if (ord) return 'other';\n return n == 1 ? 'one' : n == 2 ? 'two' : n == 0 || n100 >= 3 && n100 <= 10 ? 'few' : n100 >= 11 && n100 <= 19 ? 'many' : 'other';\n };\n const my = e;\n const nah = a;\n const naq = f;\n const nb = a;\n const nd = a;\n const ne = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return t0 && n >= 1 && n <= 4 ? 'one' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const nl = d;\n const nn = a;\n const nnh = a;\n const no = a;\n const nqo = e;\n const nr = a;\n const nso = b;\n const ny = a;\n const nyn = a;\n const om = a;\n const or = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return n == 1 || n == 5 || t0 && n >= 7 && n <= 9 ? 'one' : n == 2 || n == 3 ? 'two' : n == 4 ? 'few' : n == 6 ? 'many' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const os = a;\n const osa = e;\n const pa = b;\n const pap = a;\n const pcm = c;\n const pl = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n if (ord) return 'other';\n return n == 1 && v0 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i != 1 && (i10 == 0 || i10 == 1) || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 12 && i100 <= 14 ? 'many' : 'other';\n };\n const prg = (n, ord) => {\n const s = String(n).split('.'),\n f = s[1] || '',\n v = f.length,\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n f100 = f.slice(-2),\n f10 = f.slice(-1);\n if (ord) return 'other';\n return t0 && n10 == 0 || n100 >= 11 && n100 <= 19 || v == 2 && f100 >= 11 && f100 <= 19 ? 'zero' : n10 == 1 && n100 != 11 || v == 2 && f10 == 1 && f100 != 11 || v != 2 && f10 == 1 ? 'one' : 'other';\n };\n const ps = a;\n const pt = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return 'other';\n return i == 0 || i == 1 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const pt_PT = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return 'other';\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const rm = a;\n const ro = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n100 = t0 && s[0].slice(-2);\n if (ord) return n == 1 ? 'one' : 'other';\n return n == 1 && v0 ? 'one' : !v0 || n == 0 || n != 1 && n100 >= 1 && n100 <= 19 ? 'few' : 'other';\n };\n const rof = a;\n const ru = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 && i100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i10 == 0 || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 11 && i100 <= 14 ? 'many' : 'other';\n };\n const rwk = a;\n const sah = e;\n const saq = a;\n const sat = f;\n const sc = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1];\n if (ord) return n == 11 || n == 8 || n == 80 || n == 800 ? 'many' : 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const scn = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1];\n if (ord) return n == 11 || n == 8 || n == 80 || n == 800 ? 'many' : 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const sd = a;\n const sdh = a;\n const se = f;\n const seh = a;\n const ses = e;\n const sg = e;\n const sh = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const shi = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return 'other';\n return n >= 0 && n <= 1 ? 'one' : t0 && n >= 2 && n <= 10 ? 'few' : 'other';\n };\n const si = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '';\n if (ord) return 'other';\n return n == 0 || n == 1 || i == 0 && f == 1 ? 'one' : 'other';\n };\n const sk = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1];\n if (ord) return 'other';\n return n == 1 && v0 ? 'one' : i >= 2 && i <= 4 && v0 ? 'few' : !v0 ? 'many' : 'other';\n };\n const sl = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i100 = i.slice(-2);\n if (ord) return 'other';\n return v0 && i100 == 1 ? 'one' : v0 && i100 == 2 ? 'two' : v0 && (i100 == 3 || i100 == 4) || !v0 ? 'few' : 'other';\n };\n const sma = f;\n const smi = f;\n const smj = f;\n const smn = f;\n const sms = f;\n const sn = a;\n const so = a;\n const sq = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n if (ord) return n == 1 ? 'one' : n10 == 4 && n100 != 14 ? 'many' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const sr = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n i100 = i.slice(-2),\n f10 = f.slice(-1),\n f100 = f.slice(-2);\n if (ord) return 'other';\n return v0 && i10 == 1 && i100 != 11 || f10 == 1 && f100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) || f10 >= 2 && f10 <= 4 && (f100 < 12 || f100 > 14) ? 'few' : 'other';\n };\n const ss = a;\n const ssy = a;\n const st = a;\n const su = e;\n const sv = (n, ord) => {\n const s = String(n).split('.'),\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2);\n if (ord) return (n10 == 1 || n10 == 2) && n100 != 11 && n100 != 12 ? 'one' : 'other';\n return n == 1 && v0 ? 'one' : 'other';\n };\n const sw = d;\n const syr = a;\n const ta = a;\n const te = a;\n const teo = a;\n const th = e;\n const ti = b;\n const tig = a;\n const tk = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1);\n if (ord) return n10 == 6 || n10 == 9 || n == 10 ? 'few' : 'other';\n return n == 1 ? 'one' : 'other';\n };\n const tl = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n f = s[1] || '',\n v0 = !s[1],\n i10 = i.slice(-1),\n f10 = f.slice(-1);\n if (ord) return n == 1 ? 'one' : 'other';\n return v0 && (i == 1 || i == 2 || i == 3) || v0 && i10 != 4 && i10 != 6 && i10 != 9 || !v0 && f10 != 4 && f10 != 6 && f10 != 9 ? 'one' : 'other';\n };\n const tn = a;\n const to = e;\n const tpi = e;\n const tr = a;\n const ts = a;\n const tzm = (n, ord) => {\n const s = String(n).split('.'),\n t0 = Number(s[0]) == n;\n if (ord) return 'other';\n return n == 0 || n == 1 || t0 && n >= 11 && n <= 99 ? 'one' : 'other';\n };\n const ug = a;\n const uk = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n t0 = Number(s[0]) == n,\n n10 = t0 && s[0].slice(-1),\n n100 = t0 && s[0].slice(-2),\n i10 = i.slice(-1),\n i100 = i.slice(-2);\n if (ord) return n10 == 3 && n100 != 13 ? 'few' : 'other';\n return v0 && i10 == 1 && i100 != 11 ? 'one' : v0 && i10 >= 2 && i10 <= 4 && (i100 < 12 || i100 > 14) ? 'few' : v0 && i10 == 0 || v0 && i10 >= 5 && i10 <= 9 || v0 && i100 >= 11 && i100 <= 14 ? 'many' : 'other';\n };\n const und = e;\n const ur = d;\n const uz = a;\n const ve = a;\n const vec = (n, ord) => {\n const s = String(n).split('.'),\n i = s[0],\n v0 = !s[1],\n i1000000 = i.slice(-6);\n if (ord) return n == 11 || n == 8 || n == 80 || n == 800 ? 'many' : 'other';\n return n == 1 && v0 ? 'one' : i != 0 && i1000000 == 0 && v0 ? 'many' : 'other';\n };\n const vi = (n, ord) => {\n if (ord) return n == 1 ? 'one' : 'other';\n return 'other';\n };\n const vo = a;\n const vun = a;\n const wa = b;\n const wae = a;\n const wo = e;\n const xh = a;\n const xog = a;\n const yi = d;\n const yo = e;\n const yue = e;\n const zh = e;\n const zu = c;\n\n var Plurals = /*#__PURE__*/Object.freeze({\n __proto__: null,\n af: af,\n ak: ak,\n am: am,\n an: an,\n ar: ar,\n ars: ars,\n as: as,\n asa: asa,\n ast: ast,\n az: az,\n bal: bal,\n be: be,\n bem: bem,\n bez: bez,\n bg: bg,\n bho: bho,\n bm: bm,\n bn: bn,\n bo: bo,\n br: br,\n brx: brx,\n bs: bs,\n ca: ca,\n ce: ce,\n ceb: ceb,\n cgg: cgg,\n chr: chr,\n ckb: ckb,\n cs: cs,\n cy: cy,\n da: da,\n de: de,\n doi: doi,\n dsb: dsb,\n dv: dv,\n dz: dz,\n ee: ee,\n el: el,\n en: en,\n eo: eo,\n es: es,\n et: et,\n eu: eu,\n fa: fa,\n ff: ff,\n fi: fi,\n fil: fil,\n fo: fo,\n fr: fr,\n fur: fur,\n fy: fy,\n ga: ga,\n gd: gd,\n gl: gl,\n gsw: gsw,\n gu: gu,\n guw: guw,\n gv: gv,\n ha: ha,\n haw: haw,\n he: he,\n hi: hi,\n hnj: hnj,\n hr: hr,\n hsb: hsb,\n hu: hu,\n hy: hy,\n ia: ia,\n id: id,\n ig: ig,\n ii: ii,\n io: io,\n is: is,\n it: it,\n iu: iu,\n ja: ja,\n jbo: jbo,\n jgo: jgo,\n jmc: jmc,\n jv: jv,\n jw: jw,\n ka: ka,\n kab: kab,\n kaj: kaj,\n kcg: kcg,\n kde: kde,\n kea: kea,\n kk: kk,\n kkj: kkj,\n kl: kl,\n km: km,\n kn: kn,\n ko: ko,\n ks: ks,\n ksb: ksb,\n ksh: ksh,\n ku: ku,\n kw: kw,\n ky: ky,\n lag: lag,\n lb: lb,\n lg: lg,\n lij: lij,\n lkt: lkt,\n ln: ln,\n lo: lo,\n lt: lt,\n lv: lv,\n mas: mas,\n mg: mg,\n mgo: mgo,\n mk: mk,\n ml: ml,\n mn: mn,\n mo: mo,\n mr: mr,\n ms: ms,\n mt: mt,\n my: my,\n nah: nah,\n naq: naq,\n nb: nb,\n nd: nd,\n ne: ne,\n nl: nl,\n nn: nn,\n nnh: nnh,\n no: no,\n nqo: nqo,\n nr: nr,\n nso: nso,\n ny: ny,\n nyn: nyn,\n om: om,\n or: or,\n os: os,\n osa: osa,\n pa: pa,\n pap: pap,\n pcm: pcm,\n pl: pl,\n prg: prg,\n ps: ps,\n pt: pt,\n pt_PT: pt_PT,\n rm: rm,\n ro: ro,\n rof: rof,\n ru: ru,\n rwk: rwk,\n sah: sah,\n saq: saq,\n sat: sat,\n sc: sc,\n scn: scn,\n sd: sd,\n sdh: sdh,\n se: se,\n seh: seh,\n ses: ses,\n sg: sg,\n sh: sh,\n shi: shi,\n si: si,\n sk: sk,\n sl: sl,\n sma: sma,\n smi: smi,\n smj: smj,\n smn: smn,\n sms: sms,\n sn: sn,\n so: so,\n sq: sq,\n sr: sr,\n ss: ss,\n ssy: ssy,\n st: st,\n su: su,\n sv: sv,\n sw: sw,\n syr: syr,\n ta: ta,\n te: te,\n teo: teo,\n th: th,\n ti: ti,\n tig: tig,\n tk: tk,\n tl: tl,\n tn: tn,\n to: to,\n tpi: tpi,\n tr: tr,\n ts: ts,\n tzm: tzm,\n ug: ug,\n uk: uk,\n und: und,\n ur: ur,\n uz: uz,\n ve: ve,\n vec: vec,\n vi: vi,\n vo: vo,\n vun: vun,\n wa: wa,\n wae: wae,\n wo: wo,\n xh: xh,\n xog: xog,\n yi: yi,\n yo: yo,\n yue: yue,\n zh: zh,\n zu: zu\n });\n\n function normalize(locale) {\n if (typeof locale !== 'string' || locale.length < 2)\n throw new RangeError(\"Invalid language tag: \".concat(locale));\n if (locale.startsWith('pt-PT'))\n return 'pt-PT';\n var m = locale.match(/.+?(?=[-_])/);\n return m ? m[0] : locale;\n }\n function getPlural(locale) {\n if (typeof locale === 'function') {\n var lc_1 = normalize(locale.name);\n return {\n isDefault: false,\n id: identifier(lc_1),\n lc: lc_1,\n locale: locale.name,\n getPlural: locale,\n cardinals: locale.cardinals || [],\n ordinals: locale.ordinals || []\n };\n }\n var lc = normalize(locale);\n var id = identifier(lc);\n if (isPluralId(id)) {\n return {\n isDefault: true,\n id: id,\n lc: lc,\n locale: locale,\n getCardinal: Cardinals[id],\n getPlural: Plurals[id],\n cardinals: PluralCategories[id].cardinal,\n ordinals: PluralCategories[id].ordinal\n };\n }\n return null;\n }\n function getAllPlurals(firstLocale) {\n var keys = Object.keys(Plurals).filter(function (key) { return key !== firstLocale; });\n keys.unshift(firstLocale);\n return keys.map(getPlural);\n }\n function hasPlural(locale) {\n var lc = normalize(locale);\n return identifier(lc) in Plurals;\n }\n function isPluralId(id) {\n return id in Plurals;\n }\n\n var MessageFormat = (function () {\n function MessageFormat(locale, options) {\n this.plurals = [];\n this.options = Object.assign({\n biDiSupport: false,\n currency: 'USD',\n customFormatters: {},\n localeCodeFromKey: null,\n requireAllArguments: false,\n returnType: 'string',\n strict: (options && options.strictNumberSign) || false\n }, options);\n if (locale === '*') {\n this.plurals = getAllPlurals(MessageFormat.defaultLocale);\n }\n else if (Array.isArray(locale)) {\n this.plurals = locale.map(getPlural).filter(Boolean);\n }\n else if (locale) {\n var pl = getPlural(locale);\n if (pl)\n this.plurals = [pl];\n }\n if (this.plurals.length === 0) {\n var pl = getPlural(MessageFormat.defaultLocale);\n this.plurals = [pl];\n }\n }\n MessageFormat.escape = function (str, octothorpe) {\n var esc = octothorpe ? /[#{}]/g : /[{}]/g;\n return String(str).replace(esc, \"'$&'\");\n };\n MessageFormat.supportedLocalesOf = function (locales) {\n var la = Array.isArray(locales) ? locales : [locales];\n return la.filter(hasPlural);\n };\n MessageFormat.prototype.resolvedOptions = function () {\n return __assign(__assign({}, this.options), { locale: this.plurals[0].locale, plurals: this.plurals });\n };\n MessageFormat.prototype.compile = function (message) {\n var e_1, _a;\n var compiler = new Compiler(this.options);\n var fnBody = 'return ' + compiler.compile(message, this.plurals[0]);\n var nfArgs = [];\n var fnArgs = [];\n try {\n for (var _b = __values(Object.entries(compiler.runtime)), _c = _b.next(); !_c.done; _c = _b.next()) {\n var _d = __read(_c.value, 2), key = _d[0], fmt = _d[1];\n nfArgs.push(key);\n fnArgs.push(fmt);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (_c && !_c.done && (_a = _b.return)) _a.call(_b);\n }\n finally { if (e_1) throw e_1.error; }\n }\n var fn = new (Function.bind.apply(Function, __spreadArray(__spreadArray([void 0], __read(nfArgs), false), [fnBody], false)))();\n return fn.apply(void 0, __spreadArray([], __read(fnArgs), false));\n };\n MessageFormat.defaultLocale = 'en';\n return MessageFormat;\n }());\n\n return MessageFormat;\n\n}));\n","var InlineSVGConfig = (function () {\n function InlineSVGConfig() {\n }\n return InlineSVGConfig;\n}());\nexport { InlineSVGConfig };\n","import { Injectable, RendererFactory2 } from '@angular/core';\nimport * as i0 from \"@angular/core\";\nvar InlineSVGService = (function () {\n function InlineSVGService(rendererFactory) {\n this._ranScripts = {};\n this._renderer = rendererFactory.createRenderer(null, null);\n }\n InlineSVGService.prototype.insertEl = function (dir, parentEl, content, replaceContents, prepend) {\n if (replaceContents && !prepend) {\n var parentNode = dir._prevSVG && dir._prevSVG.parentNode;\n if (parentNode) {\n this._renderer.removeChild(parentNode, dir._prevSVG);\n }\n parentEl.innerHTML = '';\n }\n if (prepend) {\n this._renderer.insertBefore(parentEl, content, parentEl.firstChild);\n }\n else {\n this._renderer.appendChild(parentEl, content);\n }\n if (content.nodeName === 'svg') {\n dir._prevSVG = content;\n }\n };\n InlineSVGService.prototype.evalScripts = function (svg, url, evalMode) {\n var scripts = svg.querySelectorAll('script');\n var scriptsToEval = [];\n for (var i = 0; i < scripts.length; i++) {\n var scriptType = scripts[i].getAttribute('type');\n if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {\n var script = scripts[i].innerText || scripts[i].textContent;\n scriptsToEval.push(script);\n this._renderer.removeChild(scripts[i].parentNode, scripts[i]);\n }\n }\n if (scriptsToEval.length > 0 && (evalMode === \"always\" ||\n (evalMode === \"once\" && !this._ranScripts[url]))) {\n for (var i = 0; i < scriptsToEval.length; i++) {\n new Function(scriptsToEval[i])(window);\n }\n this._ranScripts[url] = true;\n }\n };\n InlineSVGService.ɵfac = function InlineSVGService_Factory(t) { return new (t || InlineSVGService)(i0.ɵɵinject(i0.RendererFactory2)); };\n InlineSVGService.ɵprov = i0.ɵɵdefineInjectable({ token: InlineSVGService, factory: InlineSVGService.ɵfac, providedIn: 'root' });\n return InlineSVGService;\n}());\nexport { InlineSVGService };\n(function () { (typeof ngDevMode === \"undefined\" || ngDevMode) && i0.ɵsetClassMetadata(InlineSVGService, [{\n type: Injectable,\n args: [{\n providedIn: 'root'\n }]\n }], function () { return [{ type: i0.RendererFactory2 }]; }, null); })();\n","import { ChangeDetectionStrategy, Component, ElementRef, Input } from '@angular/core';\nimport { InlineSVGDirective } from './inline-svg.directive';\nimport { InlineSVGService } from './inline-svg.service';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"./inline-svg.service\";\nvar InlineSVGComponent = (function () {\n function InlineSVGComponent(_inlineSVGService, el) {\n this._inlineSVGService = _inlineSVGService;\n this._el = el;\n }\n InlineSVGComponent.prototype.ngAfterViewInit = function () {\n this._updateContent();\n };\n InlineSVGComponent.prototype.ngOnChanges = function (changes) {\n if (changes['content']) {\n this._updateContent();\n }\n };\n InlineSVGComponent.prototype._updateContent = function () {\n this._inlineSVGService.insertEl(this.context, this._el.nativeElement, this.content, this.replaceContents, this.prepend);\n };\n InlineSVGComponent.ɵfac = function InlineSVGComponent_Factory(t) { return new (t || InlineSVGComponent)(i0.ɵɵdirectiveInject(i1.InlineSVGService), i0.ɵɵdirectiveInject(i0.ElementRef)); };\n InlineSVGComponent.ɵcmp = i0.ɵɵdefineComponent({ type: InlineSVGComponent, selectors: [[\"inline-svg\"]], inputs: { context: \"context\", content: \"content\", replaceContents: \"replaceContents\", prepend: \"prepend\" }, features: [i0.ɵɵNgOnChangesFeature], decls: 0, vars: 0, template: function InlineSVGComponent_Template(rf, ctx) { }, encapsulation: 2, changeDetection: 0 });\n return InlineSVGComponent;\n}());\nexport { InlineSVGComponent };\n(function () { (typeof ngDevMode === \"undefined\" || ngDevMode) && i0.ɵsetClassMetadata(InlineSVGComponent, [{\n type: Component,\n args: [{\n selector: 'inline-svg',\n template: '',\n changeDetection: ChangeDetectionStrategy.OnPush\n }]\n }], function () { return [{ type: i1.InlineSVGService }, { type: i0.ElementRef }]; }, { context: [{\n type: Input\n }], content: [{\n type: Input\n }], replaceContents: [{\n type: Input\n }], prepend: [{\n type: Input\n }] }); })();\n","import { APP_BASE_HREF, PlatformLocation } from '@angular/common';\nimport { HttpBackend, HttpClient } from '@angular/common/http';\nimport { Inject, Injectable, Optional, RendererFactory2 } from '@angular/core';\nimport { of, throwError } from 'rxjs';\nimport { catchError, map, share, tap } from 'rxjs/operators';\nimport { InlineSVGConfig } from './inline-svg.config';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"@angular/common\";\nimport * as i2 from \"./inline-svg.config\";\nimport * as i3 from \"@angular/common/http\";\nvar SVGCacheService = (function () {\n function SVGCacheService(_appBase, _location, _config, httpClient, httpBackend, rendererFactory) {\n this._appBase = _appBase;\n this._location = _location;\n this._config = _config;\n this._http = _config && !_config.bypassHttpClientInterceptorChain\n ? httpClient\n : new HttpClient(httpBackend);\n this._renderer = rendererFactory.createRenderer(null, null);\n this.setBaseUrl();\n if (!SVGCacheService._cache) {\n SVGCacheService._cache = new Map();\n }\n if (!SVGCacheService._inProgressReqs) {\n SVGCacheService._inProgressReqs = new Map();\n }\n }\n SVGCacheService.prototype.getSVG = function (url, resolveSVGUrl, cache) {\n var _this = this;\n if (cache === void 0) { cache = true; }\n var svgUrl = (resolveSVGUrl\n ? this.getAbsoluteUrl(url)\n : url).replace(/#.+$/, '');\n if (cache && SVGCacheService._cache.has(svgUrl)) {\n return of(this._cloneSVG(SVGCacheService._cache.get(svgUrl)));\n }\n if (SVGCacheService._inProgressReqs.has(svgUrl)) {\n return SVGCacheService._inProgressReqs.get(svgUrl);\n }\n var req = this._http.get(svgUrl, { responseType: 'text' })\n .pipe(tap(function () {\n SVGCacheService._inProgressReqs.delete(svgUrl);\n }), catchError(function (error) {\n SVGCacheService._inProgressReqs.delete(svgUrl);\n return throwError(error.message);\n }), share(), map(function (svgText) {\n var svgEl = _this._svgElementFromString(svgText);\n SVGCacheService._cache.set(svgUrl, svgEl);\n return _this._cloneSVG(svgEl);\n }));\n SVGCacheService._inProgressReqs.set(svgUrl, req);\n return req;\n };\n SVGCacheService.prototype.setBaseUrl = function () {\n if (this._config) {\n this._baseUrl = this._config.baseUrl;\n }\n else if (this._appBase !== null) {\n this._baseUrl = this._appBase;\n }\n else if (this._location !== null) {\n this._baseUrl = this._location.getBaseHrefFromDOM();\n }\n };\n SVGCacheService.prototype.getAbsoluteUrl = function (url) {\n if (this._baseUrl && !/^https?:\\/\\//i.test(url)) {\n url = this._baseUrl + url;\n if (url.indexOf('//') === 0) {\n url = url.substring(1);\n }\n }\n var base = this._renderer.createElement('BASE');\n base.href = url;\n return base.href;\n };\n SVGCacheService.prototype._svgElementFromString = function (str) {\n var div = this._renderer.createElement('DIV');\n div.innerHTML = str;\n var svg = div.querySelector('svg');\n if (!svg) {\n throw new Error('No SVG found in loaded contents');\n }\n return svg;\n };\n SVGCacheService.prototype._cloneSVG = function (svg) {\n return svg.cloneNode(true);\n };\n SVGCacheService.ɵfac = function SVGCacheService_Factory(t) { return new (t || SVGCacheService)(i0.ɵɵinject(APP_BASE_HREF, 8), i0.ɵɵinject(i1.PlatformLocation, 8), i0.ɵɵinject(i2.InlineSVGConfig, 8), i0.ɵɵinject(i3.HttpClient), i0.ɵɵinject(i3.HttpBackend), i0.ɵɵinject(i0.RendererFactory2)); };\n SVGCacheService.ɵprov = i0.ɵɵdefineInjectable({ token: SVGCacheService, factory: SVGCacheService.ɵfac, providedIn: 'root' });\n return SVGCacheService;\n}());\nexport { SVGCacheService };\n(function () { (typeof ngDevMode === \"undefined\" || ngDevMode) && i0.ɵsetClassMetadata(SVGCacheService, [{\n type: Injectable,\n args: [{\n providedIn: 'root'\n }]\n }], function () { return [{ type: undefined, decorators: [{\n type: Optional\n }, {\n type: Inject,\n args: [APP_BASE_HREF]\n }] }, { type: i1.PlatformLocation, decorators: [{\n type: Optional\n }] }, { type: i2.InlineSVGConfig, decorators: [{\n type: Optional\n }] }, { type: i3.HttpClient }, { type: i3.HttpBackend }, { type: i0.RendererFactory2 }]; }, null); })();\n","export function isUrlSymbol(url) {\n return url.charAt(0) === '#' || url.indexOf('.svg#') > -1;\n}\nexport function isSvgSupported() {\n return typeof SVGRect !== 'undefined';\n}\nexport function createSymbolSvg(renderer, svg, symbolId) {\n var symbol = svg.querySelector(\"[id=\\\"\".concat(symbolId, \"\\\"]\"));\n if (!symbol) {\n throw new Error(\"Symbol \\\"\".concat(symbolId, \"\\\" not found\"));\n }\n var elSvg = renderer.createElement('svg', 'svg');\n renderer.appendChild(elSvg, symbol);\n var elSvgUse = renderer.createElement('use', 'svg');\n renderer.setAttribute(elSvgUse, 'href', \"#\".concat(symbolId), 'xlink');\n renderer.appendChild(elSvg, elSvgUse);\n return elSvg;\n}\nexport function removeAttributes(element, attrs) {\n for (var i = 0; i < attrs.length; i++) {\n var elAttr = element.getAttribute(attrs[i]);\n if (elAttr) {\n element.removeAttribute(attrs[i]);\n }\n }\n var innerEls = element.getElementsByTagName('*');\n for (var i = 0; i < innerEls.length; i++) {\n removeAttributes(innerEls[i], attrs);\n }\n}\nexport function setAttributes(element, attrs) {\n for (var attr in attrs) {\n element.setAttribute(attr, attrs[attr]);\n }\n}\n","import { ComponentFactoryResolver, Directive, ElementRef, EventEmitter, Inject, Input, Optional, Output, PLATFORM_ID, Renderer2, ViewContainerRef, } from '@angular/core';\nimport { isPlatformBrowser, isPlatformServer } from '@angular/common';\nimport { InlineSVGComponent } from './inline-svg.component';\nimport { SVGCacheService } from './svg-cache.service';\nimport { InlineSVGService } from './inline-svg.service';\nimport { InlineSVGConfig } from './inline-svg.config';\nimport * as SvgUtil from './svg-util';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"./svg-cache.service\";\nimport * as i2 from \"./inline-svg.service\";\nimport * as i3 from \"./inline-svg.config\";\nvar InlineSVGDirective = (function () {\n function InlineSVGDirective(_el, _viewContainerRef, _resolver, _svgCache, _renderer, _inlineSVGService, _config, platformId) {\n this._el = _el;\n this._viewContainerRef = _viewContainerRef;\n this._resolver = _resolver;\n this._svgCache = _svgCache;\n this._renderer = _renderer;\n this._inlineSVGService = _inlineSVGService;\n this._config = _config;\n this.platformId = platformId;\n this.resolveSVGUrl = true;\n this.replaceContents = true;\n this.prepend = false;\n this.injectComponent = false;\n this.cacheSVG = true;\n this.forceEvalStyles = false;\n this.evalScripts = \"always\";\n this.onSVGInserted = new EventEmitter();\n this.onSVGFailed = new EventEmitter();\n this._supportsSVG = SvgUtil.isSvgSupported();\n if (!isPlatformServer(this.platformId) && !this._supportsSVG) {\n this._fail('Embed SVG are not supported by this browser');\n }\n }\n InlineSVGDirective.prototype.ngOnInit = function () {\n if (!this._isValidPlatform() || this._isSSRDisabled()) {\n return;\n }\n this._insertSVG();\n };\n InlineSVGDirective.prototype.ngOnChanges = function (changes) {\n if (!this._isValidPlatform() || this._isSSRDisabled()) {\n return;\n }\n var setSVGAttributesChanged = Boolean(changes['setSVGAttributes']);\n if (changes['inlineSVG'] || setSVGAttributesChanged) {\n this._insertSVG(setSVGAttributesChanged);\n }\n };\n InlineSVGDirective.prototype.ngOnDestroy = function () {\n if (this._subscription) {\n this._subscription.unsubscribe();\n }\n };\n InlineSVGDirective.prototype._insertSVG = function (force) {\n var _this = this;\n if (force === void 0) { force = false; }\n if (!isPlatformServer(this.platformId) && !this._supportsSVG) {\n return;\n }\n if (!this.inlineSVG) {\n this._fail('No URL passed to [inlineSVG]');\n return;\n }\n if (!force && this.inlineSVG === this._prevUrl) {\n return;\n }\n this._prevUrl = this.inlineSVG;\n this._subscription = this._svgCache.getSVG(this.inlineSVG, this.resolveSVGUrl, this.cacheSVG)\n .subscribe(function (svg) {\n if (SvgUtil.isUrlSymbol(_this.inlineSVG)) {\n var symbolId = _this.inlineSVG.split('#')[1];\n svg = SvgUtil.createSymbolSvg(_this._renderer, svg, symbolId);\n }\n _this._processSvg(svg);\n }, function (err) {\n _this._fail(err);\n });\n };\n InlineSVGDirective.prototype._processSvg = function (svg) {\n if (!svg) {\n return;\n }\n if (this.removeSVGAttributes && isPlatformBrowser(this.platformId)) {\n SvgUtil.removeAttributes(svg, this.removeSVGAttributes);\n }\n if (this.setSVGAttributes) {\n SvgUtil.setAttributes(svg, this.setSVGAttributes);\n }\n if (this.onSVGLoaded) {\n svg = this.onSVGLoaded(svg, this._el.nativeElement);\n }\n this._insertEl(svg);\n if (isPlatformBrowser(this.platformId)) {\n this._inlineSVGService.evalScripts(svg, this.inlineSVG, this.evalScripts);\n }\n if (this.forceEvalStyles) {\n var styleTags = svg.querySelectorAll('style');\n Array.from(styleTags).forEach(function (tag) { return tag.textContent += ''; });\n }\n this.onSVGInserted.emit(svg);\n };\n InlineSVGDirective.prototype._insertEl = function (el) {\n if (this.injectComponent) {\n if (!this._svgComp) {\n var factory = this._resolver.resolveComponentFactory(InlineSVGComponent);\n this._svgComp = this._viewContainerRef.createComponent(factory);\n }\n this._svgComp.instance.context = this;\n this._svgComp.instance.replaceContents = this.replaceContents;\n this._svgComp.instance.prepend = this.prepend;\n this._svgComp.instance.content = el;\n this._renderer.appendChild(this._el.nativeElement, this._svgComp.injector.get(InlineSVGComponent)._el.nativeElement);\n }\n else {\n this._inlineSVGService.insertEl(this, this._el.nativeElement, el, this.replaceContents, this.prepend);\n }\n };\n InlineSVGDirective.prototype._fail = function (msg) {\n this.onSVGFailed.emit(msg);\n if (this.fallbackImgUrl) {\n var elImg = this._renderer.createElement('IMG');\n this._renderer.setAttribute(elImg, 'src', this.fallbackImgUrl);\n this._insertEl(elImg);\n }\n else if (this.fallbackSVG && this.fallbackSVG !== this.inlineSVG) {\n this.inlineSVG = this.fallbackSVG;\n this._insertSVG();\n }\n };\n InlineSVGDirective.prototype._isValidPlatform = function () {\n return isPlatformServer(this.platformId) || isPlatformBrowser(this.platformId);\n };\n InlineSVGDirective.prototype._isSSRDisabled = function () {\n return isPlatformServer(this.platformId) && this._config && this._config.clientOnly;\n };\n InlineSVGDirective.ɵfac = function InlineSVGDirective_Factory(t) { return new (t || InlineSVGDirective)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i0.ComponentFactoryResolver), i0.ɵɵdirectiveInject(i1.SVGCacheService), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i2.InlineSVGService), i0.ɵɵdirectiveInject(i3.InlineSVGConfig, 8), i0.ɵɵdirectiveInject(PLATFORM_ID)); };\n InlineSVGDirective.ɵdir = i0.ɵɵdefineDirective({ type: InlineSVGDirective, selectors: [[\"\", \"inlineSVG\", \"\"]], inputs: { inlineSVG: \"inlineSVG\", resolveSVGUrl: \"resolveSVGUrl\", replaceContents: \"replaceContents\", prepend: \"prepend\", injectComponent: \"injectComponent\", cacheSVG: \"cacheSVG\", setSVGAttributes: \"setSVGAttributes\", removeSVGAttributes: \"removeSVGAttributes\", forceEvalStyles: \"forceEvalStyles\", evalScripts: \"evalScripts\", fallbackImgUrl: \"fallbackImgUrl\", fallbackSVG: \"fallbackSVG\", onSVGLoaded: \"onSVGLoaded\" }, outputs: { onSVGInserted: \"onSVGInserted\", onSVGFailed: \"onSVGFailed\" }, features: [i0.ɵɵProvidersFeature([SVGCacheService]), i0.ɵɵNgOnChangesFeature] });\n return InlineSVGDirective;\n}());\nexport { InlineSVGDirective };\n(function () { (typeof ngDevMode === \"undefined\" || ngDevMode) && i0.ɵsetClassMetadata(InlineSVGDirective, [{\n type: Directive,\n args: [{\n selector: '[inlineSVG]',\n providers: [SVGCacheService]\n }]\n }], function () { return [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: i1.SVGCacheService }, { type: i0.Renderer2 }, { type: i2.InlineSVGService }, { type: i3.InlineSVGConfig, decorators: [{\n type: Optional\n }] }, { type: Object, decorators: [{\n type: Inject,\n args: [PLATFORM_ID]\n }] }]; }, { inlineSVG: [{\n type: Input\n }], resolveSVGUrl: [{\n type: Input\n }], replaceContents: [{\n type: Input\n }], prepend: [{\n type: Input\n }], injectComponent: [{\n type: Input\n }], cacheSVG: [{\n type: Input\n }], setSVGAttributes: [{\n type: Input\n }], removeSVGAttributes: [{\n type: Input\n }], forceEvalStyles: [{\n type: Input\n }], evalScripts: [{\n type: Input\n }], fallbackImgUrl: [{\n type: Input\n }], fallbackSVG: [{\n type: Input\n }], onSVGLoaded: [{\n type: Input\n }], onSVGInserted: [{\n type: Output\n }], onSVGFailed: [{\n type: Output\n }] }); })();\n","import { NgModule } from '@angular/core';\nimport { InlineSVGComponent } from './inline-svg.component';\nimport { InlineSVGConfig } from './inline-svg.config';\nimport { InlineSVGDirective } from './inline-svg.directive';\nimport * as i0 from \"@angular/core\";\nvar InlineSVGModule = (function () {\n function InlineSVGModule() {\n }\n InlineSVGModule.forRoot = function (config) {\n return {\n ngModule: InlineSVGModule,\n providers: [\n { provide: InlineSVGConfig, useValue: config }\n ]\n };\n };\n InlineSVGModule.ɵfac = function InlineSVGModule_Factory(t) { return new (t || InlineSVGModule)(); };\n InlineSVGModule.ɵmod = i0.ɵɵdefineNgModule({ type: InlineSVGModule });\n InlineSVGModule.ɵinj = i0.ɵɵdefineInjector({});\n return InlineSVGModule;\n}());\nexport { InlineSVGModule };\n(function () { (typeof ngDevMode === \"undefined\" || ngDevMode) && i0.ɵsetClassMetadata(InlineSVGModule, [{\n type: NgModule,\n args: [{\n declarations: [InlineSVGDirective, InlineSVGComponent],\n exports: [InlineSVGDirective],\n entryComponents: [InlineSVGComponent]\n }]\n }], null, null); })();\n(function () { (typeof ngJitMode === \"undefined\" || ngJitMode) && i0.ɵɵsetNgModuleScope(InlineSVGModule, { declarations: [InlineSVGDirective, InlineSVGComponent], exports: [InlineSVGDirective] }); })();\n","typeof navigator === \"object\" && (function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define('Plyr', factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Plyr = factory());\n})(this, (function () { 'use strict';\n\n function _defineProperty$1(obj, key, value) {\n key = _toPropertyKey(key);\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n return obj;\n }\n function _toPrimitive(input, hint) {\n if (typeof input !== \"object\" || input === null) return input;\n var prim = input[Symbol.toPrimitive];\n if (prim !== undefined) {\n var res = prim.call(input, hint || \"default\");\n if (typeof res !== \"object\") return res;\n throw new TypeError(\"@@toPrimitive must return a primitive value.\");\n }\n return (hint === \"string\" ? String : Number)(input);\n }\n function _toPropertyKey(arg) {\n var key = _toPrimitive(arg, \"string\");\n return typeof key === \"symbol\" ? key : String(key);\n }\n\n function _classCallCheck(e, t) {\n if (!(e instanceof t)) throw new TypeError(\"Cannot call a class as a function\");\n }\n function _defineProperties(e, t) {\n for (var n = 0; n < t.length; n++) {\n var r = t[n];\n r.enumerable = r.enumerable || !1, r.configurable = !0, \"value\" in r && (r.writable = !0), Object.defineProperty(e, r.key, r);\n }\n }\n function _createClass(e, t, n) {\n return t && _defineProperties(e.prototype, t), n && _defineProperties(e, n), e;\n }\n function _defineProperty(e, t, n) {\n return t in e ? Object.defineProperty(e, t, {\n value: n,\n enumerable: !0,\n configurable: !0,\n writable: !0\n }) : e[t] = n, e;\n }\n function ownKeys(e, t) {\n var n = Object.keys(e);\n if (Object.getOwnPropertySymbols) {\n var r = Object.getOwnPropertySymbols(e);\n t && (r = r.filter(function (t) {\n return Object.getOwnPropertyDescriptor(e, t).enumerable;\n })), n.push.apply(n, r);\n }\n return n;\n }\n function _objectSpread2(e) {\n for (var t = 1; t < arguments.length; t++) {\n var n = null != arguments[t] ? arguments[t] : {};\n t % 2 ? ownKeys(Object(n), !0).forEach(function (t) {\n _defineProperty(e, t, n[t]);\n }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : ownKeys(Object(n)).forEach(function (t) {\n Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));\n });\n }\n return e;\n }\n var defaults$1 = {\n addCSS: !0,\n thumbWidth: 15,\n watch: !0\n };\n function matches$1(e, t) {\n return function () {\n return Array.from(document.querySelectorAll(t)).includes(this);\n }.call(e, t);\n }\n function trigger(e, t) {\n if (e && t) {\n var n = new Event(t, {\n bubbles: !0\n });\n e.dispatchEvent(n);\n }\n }\n var getConstructor$1 = function (e) {\n return null != e ? e.constructor : null;\n },\n instanceOf$1 = function (e, t) {\n return !!(e && t && e instanceof t);\n },\n isNullOrUndefined$1 = function (e) {\n return null == e;\n },\n isObject$1 = function (e) {\n return getConstructor$1(e) === Object;\n },\n isNumber$1 = function (e) {\n return getConstructor$1(e) === Number && !Number.isNaN(e);\n },\n isString$1 = function (e) {\n return getConstructor$1(e) === String;\n },\n isBoolean$1 = function (e) {\n return getConstructor$1(e) === Boolean;\n },\n isFunction$1 = function (e) {\n return getConstructor$1(e) === Function;\n },\n isArray$1 = function (e) {\n return Array.isArray(e);\n },\n isNodeList$1 = function (e) {\n return instanceOf$1(e, NodeList);\n },\n isElement$1 = function (e) {\n return instanceOf$1(e, Element);\n },\n isEvent$1 = function (e) {\n return instanceOf$1(e, Event);\n },\n isEmpty$1 = function (e) {\n return isNullOrUndefined$1(e) || (isString$1(e) || isArray$1(e) || isNodeList$1(e)) && !e.length || isObject$1(e) && !Object.keys(e).length;\n },\n is$1 = {\n nullOrUndefined: isNullOrUndefined$1,\n object: isObject$1,\n number: isNumber$1,\n string: isString$1,\n boolean: isBoolean$1,\n function: isFunction$1,\n array: isArray$1,\n nodeList: isNodeList$1,\n element: isElement$1,\n event: isEvent$1,\n empty: isEmpty$1\n };\n function getDecimalPlaces(e) {\n var t = \"\".concat(e).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n return t ? Math.max(0, (t[1] ? t[1].length : 0) - (t[2] ? +t[2] : 0)) : 0;\n }\n function round(e, t) {\n if (1 > t) {\n var n = getDecimalPlaces(t);\n return parseFloat(e.toFixed(n));\n }\n return Math.round(e / t) * t;\n }\n var RangeTouch = function () {\n function e(t, n) {\n _classCallCheck(this, e), is$1.element(t) ? this.element = t : is$1.string(t) && (this.element = document.querySelector(t)), is$1.element(this.element) && is$1.empty(this.element.rangeTouch) && (this.config = _objectSpread2({}, defaults$1, {}, n), this.init());\n }\n return _createClass(e, [{\n key: \"init\",\n value: function () {\n e.enabled && (this.config.addCSS && (this.element.style.userSelect = \"none\", this.element.style.webKitUserSelect = \"none\", this.element.style.touchAction = \"manipulation\"), this.listeners(!0), this.element.rangeTouch = this);\n }\n }, {\n key: \"destroy\",\n value: function () {\n e.enabled && (this.config.addCSS && (this.element.style.userSelect = \"\", this.element.style.webKitUserSelect = \"\", this.element.style.touchAction = \"\"), this.listeners(!1), this.element.rangeTouch = null);\n }\n }, {\n key: \"listeners\",\n value: function (e) {\n var t = this,\n n = e ? \"addEventListener\" : \"removeEventListener\";\n [\"touchstart\", \"touchmove\", \"touchend\"].forEach(function (e) {\n t.element[n](e, function (e) {\n return t.set(e);\n }, !1);\n });\n }\n }, {\n key: \"get\",\n value: function (t) {\n if (!e.enabled || !is$1.event(t)) return null;\n var n,\n r = t.target,\n i = t.changedTouches[0],\n o = parseFloat(r.getAttribute(\"min\")) || 0,\n s = parseFloat(r.getAttribute(\"max\")) || 100,\n u = parseFloat(r.getAttribute(\"step\")) || 1,\n c = r.getBoundingClientRect(),\n a = 100 / c.width * (this.config.thumbWidth / 2) / 100;\n return 0 > (n = 100 / c.width * (i.clientX - c.left)) ? n = 0 : 100 < n && (n = 100), 50 > n ? n -= (100 - 2 * n) * a : 50 < n && (n += 2 * (n - 50) * a), o + round(n / 100 * (s - o), u);\n }\n }, {\n key: \"set\",\n value: function (t) {\n e.enabled && is$1.event(t) && !t.target.disabled && (t.preventDefault(), t.target.value = this.get(t), trigger(t.target, \"touchend\" === t.type ? \"change\" : \"input\"));\n }\n }], [{\n key: \"setup\",\n value: function (t) {\n var n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {},\n r = null;\n if (is$1.empty(t) || is$1.string(t) ? r = Array.from(document.querySelectorAll(is$1.string(t) ? t : 'input[type=\"range\"]')) : is$1.element(t) ? r = [t] : is$1.nodeList(t) ? r = Array.from(t) : is$1.array(t) && (r = t.filter(is$1.element)), is$1.empty(r)) return null;\n var i = _objectSpread2({}, defaults$1, {}, n);\n if (is$1.string(t) && i.watch) {\n var o = new MutationObserver(function (n) {\n Array.from(n).forEach(function (n) {\n Array.from(n.addedNodes).forEach(function (n) {\n is$1.element(n) && matches$1(n, t) && new e(n, i);\n });\n });\n });\n o.observe(document.body, {\n childList: !0,\n subtree: !0\n });\n }\n return r.map(function (t) {\n return new e(t, n);\n });\n }\n }, {\n key: \"enabled\",\n get: function () {\n return \"ontouchstart\" in document.documentElement;\n }\n }]), e;\n }();\n\n // ==========================================================================\n // Type checking utils\n // ==========================================================================\n\n const getConstructor = input => input !== null && typeof input !== 'undefined' ? input.constructor : null;\n const instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\n const isNullOrUndefined = input => input === null || typeof input === 'undefined';\n const isObject = input => getConstructor(input) === Object;\n const isNumber = input => getConstructor(input) === Number && !Number.isNaN(input);\n const isString = input => getConstructor(input) === String;\n const isBoolean = input => getConstructor(input) === Boolean;\n const isFunction = input => typeof input === 'function';\n const isArray = input => Array.isArray(input);\n const isWeakMap = input => instanceOf(input, WeakMap);\n const isNodeList = input => instanceOf(input, NodeList);\n const isTextNode = input => getConstructor(input) === Text;\n const isEvent = input => instanceOf(input, Event);\n const isKeyboardEvent = input => instanceOf(input, KeyboardEvent);\n const isCue = input => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\n const isTrack = input => instanceOf(input, TextTrack) || !isNullOrUndefined(input) && isString(input.kind);\n const isPromise = input => instanceOf(input, Promise) && isFunction(input.then);\n const isElement = input => input !== null && typeof input === 'object' && input.nodeType === 1 && typeof input.style === 'object' && typeof input.ownerDocument === 'object';\n const isEmpty = input => isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;\n const isUrl = input => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (_) {\n return false;\n }\n };\n var is = {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n promise: isPromise,\n url: isUrl,\n empty: isEmpty\n };\n\n // ==========================================================================\n const transitionEndEvent = (() => {\n const element = document.createElement('span');\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend'\n };\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n return is.string(type) ? events[type] : false;\n })();\n\n // Force repaint of element\n function repaint(element, delay) {\n setTimeout(() => {\n try {\n // eslint-disable-next-line no-param-reassign\n element.hidden = true;\n\n // eslint-disable-next-line no-unused-expressions\n element.offsetHeight;\n\n // eslint-disable-next-line no-param-reassign\n element.hidden = false;\n } catch (_) {\n // Do nothing\n }\n }, delay);\n }\n\n // ==========================================================================\n // Browser sniffing\n // Unfortunately, due to mixed support, UA sniffing is required\n // ==========================================================================\n\n const isIE = Boolean(window.document.documentMode);\n const isEdge = /Edge/g.test(navigator.userAgent);\n const isWebKit = 'WebkitAppearance' in document.documentElement.style && !/Edge/g.test(navigator.userAgent);\n const isIPhone = /iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;\n // navigator.platform may be deprecated but this check is still required\n const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;\n const isIos = /iPad|iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;\n var browser = {\n isIE,\n isEdge,\n isWebKit,\n isIPhone,\n isIPadOS,\n isIos\n };\n\n // ==========================================================================\n\n // Clone nested objects\n function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n }\n\n // Get a nested value in an object\n function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n }\n\n // Deep extend destination object with N more objects\n function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n const source = sources.shift();\n if (!is.object(source)) {\n return target;\n }\n Object.keys(source).forEach(key => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, {\n [key]: {}\n });\n }\n extend(target[key], source[key]);\n } else {\n Object.assign(target, {\n [key]: source[key]\n });\n }\n });\n return extend(target, ...sources);\n }\n\n // ==========================================================================\n\n // Wrap an element\n function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets).reverse().forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n }\n\n // Set attributes\n function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) return;\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes).filter(([, value]) => !is.nullOrUndefined(value)).forEach(([key, value]) => element.setAttribute(key, value));\n }\n\n // Create a DocumentFragment\n function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n }\n\n // Insert an element after another\n function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) return;\n target.parentNode.insertBefore(element, target.nextSibling);\n }\n\n // Insert a DocumentFragment\n function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) return;\n parent.appendChild(createElement(type, attributes, text));\n }\n\n // Remove element(s)\n function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n element.parentNode.removeChild(element);\n }\n\n // Remove all child elements\n function emptyElement(element) {\n if (!is.element(element)) return;\n let {\n length\n } = element.childNodes;\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n }\n\n // Replace element\n function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) return null;\n oldChild.parentNode.replaceChild(newChild, oldChild);\n return newChild;\n }\n\n // Get an attribute object from a string selector\n function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) return {};\n const attributes = {};\n const existing = extend({}, existingAttributes);\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n // Get the parts and value\n const parts = stripped.split('=');\n const [key] = parts;\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n // Get the first character\n const start = selector.charAt(0);\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.string(existing.class)) {\n attributes.class = `${existing.class} ${className}`;\n } else {\n attributes.class = className;\n }\n break;\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n case '[':\n // Attribute selector\n attributes[key] = value;\n break;\n }\n });\n return extend(existing, attributes);\n }\n\n // Toggle hidden\n function toggleHidden(element, hidden) {\n if (!is.element(element)) return;\n let hide = hidden;\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n // eslint-disable-next-line no-param-reassign\n element.hidden = hide;\n }\n\n // Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\n function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map(e => toggleClass(e, className, force));\n }\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n element.classList[method](className);\n return element.classList.contains(className);\n }\n return false;\n }\n\n // Has class name\n function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n }\n\n // Element matches selector\n function matches(element, selector) {\n const {\n prototype\n } = Element;\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n const method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;\n return method.call(element, selector);\n }\n\n // Closest ancestor element matching selector (also tests element itself)\n function closest$1(element, selector) {\n const {\n prototype\n } = Element;\n\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill\n function closestElement() {\n let el = this;\n do {\n if (matches.matches(el, selector)) return el;\n el = el.parentElement || el.parentNode;\n } while (el !== null && el.nodeType === 1);\n return null;\n }\n const method = prototype.closest || closestElement;\n return method.call(element, selector);\n }\n\n // Find all elements\n function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n }\n\n // Find a single element\n function getElement(selector) {\n return this.elements.container.querySelector(selector);\n }\n\n // Set focus and tab focus class\n function setFocus(element = null, focusVisible = false) {\n if (!is.element(element)) return;\n\n // Set regular focus\n element.focus({\n preventScroll: true,\n focusVisible\n });\n }\n\n // ==========================================================================\n\n // Default codecs for checking mimetype support\n const defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora'\n };\n\n // Check for feature support\n const support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n // Check for support\n // Basic functionality vs full UI\n check(type, provider) {\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput;\n return {\n api,\n ui\n };\n },\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n // While iPhone's support picture-in-picture for some apps, seemingly Safari isn't one of them\n // It will throw the following error when trying to enter picture-in-picture\n // `NotSupportedError: The Picture-in-Picture mode is not supported.`\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n return false;\n })(),\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (_) {\n return false;\n }\n },\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches\n };\n\n // ==========================================================================\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n const supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n }\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (_) {\n // Do nothing\n }\n return supported;\n })();\n\n // Toggle event listener\n function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({\n element,\n type,\n callback,\n options\n });\n }\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n }\n\n // Bind event handler\n function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n }\n\n // Unbind event handler\n function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n }\n\n // Bind once-only event handler\n function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n }\n\n // Trigger event\n function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: {\n ...detail,\n plyr: this\n }\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n }\n\n // Unbind all cached event listeners\n function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach(item => {\n const {\n element,\n type,\n callback,\n options\n } = item;\n element.removeEventListener(type, callback, options);\n });\n this.eventListeners = [];\n }\n }\n\n // Run method when / if player is ready\n function ready() {\n return new Promise(resolve => this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve)).then(() => {});\n }\n\n /**\n * Silence a Promise-like object.\n * This is useful for avoiding non-harmful, but potentially confusing \"uncaught\n * play promise\" rejection error messages.\n * @param {Object} value An object that may or may not be `Promise`-like.\n */\n function silencePromise(value) {\n if (is.promise(value)) {\n value.then(null, () => {});\n }\n }\n\n // ==========================================================================\n\n // Remove duplicates in an array\n function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n return array.filter((item, index) => array.indexOf(item) === index);\n }\n\n // Get the closest value in an array\n function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n return array.reduce((prev, curr) => Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev);\n }\n\n // ==========================================================================\n\n // Check support for a CSS declaration\n function supportsCSS(declaration) {\n if (!window || !window.CSS) {\n return false;\n }\n return window.CSS.supports(declaration);\n }\n\n // Standard/common aspect ratios\n const standardRatios = [[1, 1], [4, 3], [3, 4], [5, 4], [4, 5], [3, 2], [2, 3], [16, 10], [10, 16], [16, 9], [9, 16], [21, 9], [9, 21], [32, 9], [9, 32]].reduce((out, [x, y]) => ({\n ...out,\n [x / y]: [x, y]\n }), {});\n\n // Validate an aspect ratio\n function validateAspectRatio(input) {\n if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {\n return false;\n }\n const ratio = is.array(input) ? input : input.split(':');\n return ratio.map(Number).every(is.number);\n }\n\n // Reduce an aspect ratio to it's lowest form\n function reduceAspectRatio(ratio) {\n if (!is.array(ratio) || !ratio.every(is.number)) {\n return null;\n }\n const [width, height] = ratio;\n const getDivider = (w, h) => h === 0 ? w : getDivider(h, w % h);\n const divider = getDivider(width, height);\n return [width / divider, height / divider];\n }\n\n // Calculate an aspect ratio\n function getAspectRatio(input) {\n const parse = ratio => validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null;\n // Try provided ratio\n let ratio = parse(input);\n\n // Get from config\n if (ratio === null) {\n ratio = parse(this.config.ratio);\n }\n\n // Get from embed\n if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {\n ({\n ratio\n } = this.embed);\n }\n\n // Get from HTML5 video\n if (ratio === null && this.isHTML5) {\n const {\n videoWidth,\n videoHeight\n } = this.media;\n ratio = [videoWidth, videoHeight];\n }\n return reduceAspectRatio(ratio);\n }\n\n // Set aspect ratio for responsive container\n function setAspectRatio(input) {\n if (!this.isVideo) {\n return {};\n }\n const {\n wrapper\n } = this.elements;\n const ratio = getAspectRatio.call(this, input);\n if (!is.array(ratio)) {\n return {};\n }\n const [x, y] = reduceAspectRatio(ratio);\n const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);\n const padding = 100 / x * y;\n if (useNative) {\n wrapper.style.aspectRatio = `${x}/${y}`;\n } else {\n wrapper.style.paddingBottom = `${padding}%`;\n }\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {\n const height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);\n const offset = (height - padding) / (height / 50);\n if (this.fullscreen.active) {\n wrapper.style.paddingBottom = null;\n } else {\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n } else if (this.isHTML5) {\n wrapper.classList.add(this.config.classNames.videoFixedRatio);\n }\n return {\n padding,\n ratio\n };\n }\n\n // Round an aspect ratio to closest standard ratio\n function roundAspectRatio(x, y, tolerance = 0.05) {\n const ratio = x / y;\n const closestRatio = closest(Object.keys(standardRatios), ratio);\n\n // Check match is within tolerance\n if (Math.abs(closestRatio - ratio) <= tolerance) {\n return standardRatios[closestRatio];\n }\n\n // No match\n return [x, y];\n }\n\n // Get the size of the viewport\n // https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions\n function getViewportSize() {\n const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);\n const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);\n return [width, height];\n }\n\n // ==========================================================================\n const html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter(source => {\n const type = source.getAttribute('type');\n if (is.empty(type)) {\n return true;\n }\n return support.mime.call(this, type);\n });\n },\n // Get quality levels\n getQualityOptions() {\n // Whether we're forcing all options (e.g. for streaming)\n if (this.config.quality.forced) {\n return this.config.quality.options;\n }\n\n // Get sizes from <source> elements\n return html5.getSources.call(this).map(source => Number(source.getAttribute('size'))).filter(Boolean);\n },\n setup() {\n if (!this.isHTML5) {\n return;\n }\n const player = this;\n\n // Set speed options from config\n player.options.speed = player.config.speed.options;\n\n // Set aspect ratio if fixed\n if (!is.empty(this.config.ratio)) {\n setAspectRatio.call(player);\n }\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find(s => s.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n if (player.quality === input) {\n return;\n }\n\n // If we're using an external handler...\n if (player.config.quality.forced && is.function(player.config.quality.onChange)) {\n player.config.quality.onChange(input);\n } else {\n // Get sources\n const sources = html5.getSources.call(player);\n // Get first match for requested size\n const source = sources.find(s => Number(s.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const {\n currentTime,\n paused,\n preload,\n readyState,\n playbackRate\n } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.speed = playbackRate;\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n silencePromise(player.play());\n }\n });\n\n // Load new source\n player.media.load();\n }\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input\n });\n }\n });\n },\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n }\n };\n\n // ==========================================================================\n\n // Generate a random ID\n function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n }\n\n // Format string\n function format(input, ...args) {\n if (is.empty(input)) return input;\n return input.toString().replace(/{(\\d+)}/g, (_, i) => args[i].toString());\n }\n\n // Get percentage\n function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n }\n\n // Replace all occurrences of a string in a string\n const replaceAll = (input = '', find = '', replace = '') => input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n\n // Convert to title case\n const toTitleCase = (input = '') => input.toString().replace(/\\w\\S*/g, text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase());\n\n // Convert string to pascalCase\n function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n }\n\n // Convert string to pascalCase\n function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n }\n\n // Remove HTML from a string\n function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n }\n\n // Like outerHTML, but also works for DocumentFragment\n function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n }\n\n // ==========================================================================\n\n // Skip i18n for abbreviations and brand names\n const resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube'\n };\n const i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n let string = getDeep(config.i18n, key);\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n return '';\n }\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title\n };\n Object.entries(replace).forEach(([k, v]) => {\n string = replaceAll(string, k, v);\n });\n return string;\n }\n };\n\n class Storage {\n constructor(player) {\n _defineProperty$1(this, \"get\", key => {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n const store = window.localStorage.getItem(this.key);\n if (is.empty(store)) {\n return null;\n }\n const json = JSON.parse(store);\n return is.string(key) && key.length ? json[key] : json;\n });\n _defineProperty$1(this, \"set\", object => {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n try {\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n } catch (_) {\n // Do nothing\n }\n });\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (_) {\n return false;\n }\n }\n }\n\n // ==========================================================================\n // Fetch wrapper\n // Using XHR to avoid issues with older browsers\n // ==========================================================================\n\n function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (_) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n request.send();\n } catch (error) {\n reject(error);\n }\n });\n }\n\n // ==========================================================================\n\n // Load an external SVG sprite\n function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n const exists = () => document.getElementById(id) !== null;\n const update = (container, data) => {\n // eslint-disable-next-line no-param-reassign\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url).then(result => {\n if (is.empty(result)) {\n return;\n }\n if (useStorage) {\n try {\n window.localStorage.setItem(`${prefix}-${id}`, JSON.stringify({\n content: result\n }));\n } catch (_) {\n // Do nothing\n }\n }\n update(container, result);\n }).catch(() => {});\n }\n }\n\n // ==========================================================================\n\n // Time helpers\n const getHours = value => Math.trunc(value / 60 / 60 % 60, 10);\n const getMinutes = value => Math.trunc(value / 60 % 60, 10);\n const getSeconds = value => Math.trunc(value % 60, 10);\n\n // Format time to UI friendly string\n function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(undefined, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = value => `0${value}`.slice(-2);\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n }\n\n // ==========================================================================\n\n // TODO: Don't export a massive object - break down and create class\n const controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const host = window.location.host ? window.location.host : window.top.location.host;\n const cors = url.host !== host || browser.isIE && !window.svg4everybody;\n return {\n url: this.config.iconUrl,\n cors\n };\n },\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen)\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume)\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration)\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n return false;\n }\n },\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(icon, extend(attributes, {\n 'aria-hidden': 'true',\n focusable: 'false'\n }));\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n return icon;\n },\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n const attributes = {\n ...attr,\n class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')\n };\n return createElement('span', attributes, text);\n },\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n const badge = createElement('span', {\n class: this.config.classNames.menu.value\n });\n badge.appendChild(createElement('span', {\n class: this.config.classNames.menu.badge\n }, text));\n return badge;\n },\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = extend({}, attr);\n let type = toCamelCase(buttonType);\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null\n };\n ['element', 'icon', 'label'].forEach(key => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.split(' ').some(c => c === this.config.classNames.control)) {\n extend(attributes, {\n class: `${attributes.class} ${this.config.classNames.control}`\n });\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed'\n }));\n button.appendChild(controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed'\n }));\n\n // Label/Tooltip\n button.appendChild(controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed'\n }));\n button.appendChild(controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed'\n }));\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n return button;\n },\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement('input', extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0\n }, attributes));\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n // Improve support on touch devices\n RangeTouch.setup(input);\n return input;\n },\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement('progress', extend(getAttributesFromSelector(this.config.selectors.display[type]), {\n min: 0,\n max: 100,\n value: 0,\n role: 'progressbar',\n 'aria-hidden': true\n }, attributes));\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n const suffixKey = {\n played: 'played',\n buffer: 'buffered'\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n this.elements.display[type] = progress;\n return progress;\n },\n // Create time display\n createTime(type, attrs) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);\n const container = createElement('div', extend(attributes, {\n class: `${attributes.class ? attributes.class : ''} ${this.config.classNames.display.time} `.trim(),\n 'aria-label': i18n.get(type, this.config),\n role: 'timer'\n }), '00:00');\n\n // Reference for updates\n this.elements.display[type] = container;\n return container;\n },\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on.call(this, menuItem, 'keydown keyup', event => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![' ', 'ArrowUp', 'ArrowDown', 'ArrowRight'].includes(event.key)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [' ', 'ArrowRight'].includes(event.key)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n if (event.key !== ' ') {\n if (event.key === 'ArrowDown' || isRadioButton && event.key === 'ArrowRight') {\n target = menuItem.nextElementSibling;\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n setFocus.call(this, target, true);\n }\n }\n }, false);\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on.call(this, menuItem, 'keyup', event => {\n if (event.key !== 'Return') return;\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n // Create a settings menu item\n createMenuItem({\n value,\n list,\n type,\n title,\n badge = null,\n checked = false\n }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n const menuItem = createElement('button', extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value\n }));\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n menuItem.appendChild(flex);\n\n // Replicate radio button behavior\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(check) {\n // Ensure exclusivity\n if (check) {\n Array.from(menuItem.parentNode.children).filter(node => matches(node, '[role=\"menuitemradio\"]')).forEach(node => node.setAttribute('aria-checked', 'false'));\n }\n menuItem.setAttribute('aria-checked', check ? 'true' : 'false');\n }\n });\n this.listeners.bind(menuItem, 'click keyup', event => {\n if (is.keyboardEvent(event) && event.key !== ' ') {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n menuItem.checked = true;\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n case 'quality':\n this.quality = value;\n break;\n case 'speed':\n this.speed = parseFloat(value);\n break;\n }\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n }, type, false);\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n list.appendChild(menuItem);\n },\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n return formatTime(time, forceHours, inverted);\n },\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n let value = 0;\n const setProgress = (target, input) => {\n const val = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = val;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = val;\n }\n }\n };\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n break;\n }\n }\n },\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute('aria-valuetext', format.replace('{currentTime}', currentTime).replace('{duration}', duration));\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebKit && !browser.isIPadOS) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${range.value / range.max * 100}%`);\n },\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n var _this$config$markers, _this$config$markers$;\n // Bail if setting not true\n if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) {\n return;\n }\n const tipElement = this.elements.display.seekTooltip;\n const visible = `${this.config.classNames.tooltip}--visible`;\n const toggle = show => toggleClass(tipElement, visible, show);\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n if (is.event(event)) {\n percent = 100 / clientRect.width * (event.pageX - clientRect.left);\n } else if (hasClass(tipElement, visible)) {\n percent = parseFloat(tipElement.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n const time = this.duration / 100 * percent;\n\n // Display the time a click would seek to\n tipElement.innerText = controls.formatTime(time);\n\n // Get marker point for time\n const point = (_this$config$markers = this.config.markers) === null || _this$config$markers === void 0 ? void 0 : (_this$config$markers$ = _this$config$markers.points) === null || _this$config$markers$ === void 0 ? void 0 : _this$config$markers$.find(({\n time: t\n }) => t === Math.round(time));\n\n // Append the point label to the tooltip\n if (point) {\n tipElement.insertAdjacentHTML('afterbegin', `${point.label}<br>`);\n }\n\n // Set position\n tipElement.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || !this.config.invertTime && this.currentTime) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n if (this.config.markers.enabled) {\n controls.setMarkers.call(this);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n if (is.element(target)) {\n target.checked = true;\n }\n },\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n if (!label.length) {\n return `${value}p`;\n }\n return label;\n }\n return toTitleCase(value);\n case 'captions':\n return captions.getLabel.call(this);\n default:\n return null;\n }\n },\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter(quality => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = quality => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n if (!label.length) {\n return null;\n }\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality.sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n }).forEach(quality => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality)\n });\n });\n controls.updateSetting.call(this, type, list);\n },\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n // Empty the menu\n emptyElement(list);\n options.forEach(option => {\n const item = createElement('li');\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language'\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language'\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n controls.updateSetting.call(this, type, list);\n },\n // Set a list of available captions languages\n setSpeedMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Filter out invalid speeds\n this.options.speed = this.options.speed.filter(o => o >= this.minimumSpeed && o <= this.maximumSpeed);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach(speed => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed)\n });\n });\n controls.updateSetting.call(this, type, list);\n },\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const {\n buttons\n } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some(button => !button.hidden);\n toggleHidden(this.elements.settings.menu, !visible);\n },\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, focusVisible = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n let target = pane;\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find(p => !p.hidden);\n }\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n setFocus.call(this, firstItem, focusVisible);\n },\n // Show/hide menu\n toggleMenu(input) {\n const {\n popup\n } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const {\n hidden\n } = popup;\n let show = hidden;\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.key === 'Escape') {\n show = false;\n } else if (is.event(input)) {\n // If Plyr is in a shadowDOM, the event target is set to the component, instead of the\n // Element in the shadowDOM. The path, if available, is complete.\n const target = is.function(input.composedPath) ? input.composedPath()[0] : input.target;\n const isMenuItem = popup.contains(target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || !isMenuItem && input.target !== button && show) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n return {\n width,\n height\n };\n },\n // Show a panel in the menu\n showMenuPanel(type = '', focusVisible = false) {\n const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find(node => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = event => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, focusVisible);\n },\n // Set the download URL\n setDownloadUrl() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set attribute\n button.setAttribute('href', this.download);\n },\n // Build the default HTML\n create(data) {\n const {\n bindMenuItemShortcuts,\n createButton,\n createProgress,\n createRange,\n createTime,\n setQualityMenu,\n setSpeedMenu,\n showMenuPanel\n } = controls;\n this.elements.controls = null;\n\n // Larger overlaid play button\n if (is.array(this.config.controls) && this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(createButton.call(this, 'play-large'));\n }\n\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n this.elements.controls = container;\n\n // Default item attributes\n const defaultAttributes = {\n class: 'plyr__controls__item'\n };\n\n // Loop through controls in order\n dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach(control => {\n // Restart button\n if (control === 'restart') {\n container.appendChild(createButton.call(this, 'restart', defaultAttributes));\n }\n\n // Rewind button\n if (control === 'rewind') {\n container.appendChild(createButton.call(this, 'rewind', defaultAttributes));\n }\n\n // Play/Pause button\n if (control === 'play') {\n container.appendChild(createButton.call(this, 'play', defaultAttributes));\n }\n\n // Fast forward button\n if (control === 'fast-forward') {\n container.appendChild(createButton.call(this, 'fast-forward', defaultAttributes));\n }\n\n // Progress\n if (control === 'progress') {\n const progressContainer = createElement('div', {\n class: `${defaultAttributes.class} plyr__progress__container`\n });\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`\n }));\n\n // Buffer progress\n progress.appendChild(createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement('span', {\n class: this.config.classNames.tooltip\n }, '00:00');\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n this.elements.progress = progress;\n progressContainer.appendChild(this.elements.progress);\n container.appendChild(progressContainer);\n }\n\n // Media current time display\n if (control === 'current-time') {\n container.appendChild(createTime.call(this, 'currentTime', defaultAttributes));\n }\n\n // Media duration display\n if (control === 'duration') {\n container.appendChild(createTime.call(this, 'duration', defaultAttributes));\n }\n\n // Volume controls\n if (control === 'mute' || control === 'volume') {\n let {\n volume\n } = this.elements;\n\n // Create the volume container if needed\n if (!is.element(volume) || !container.contains(volume)) {\n volume = createElement('div', extend({}, defaultAttributes, {\n class: `${defaultAttributes.class} plyr__volume`.trim()\n }));\n this.elements.volume = volume;\n container.appendChild(volume);\n }\n\n // Toggle mute button\n if (control === 'mute') {\n volume.appendChild(createButton.call(this, 'mute'));\n }\n\n // Volume range control\n // Ignored on iOS as it's handled globally\n // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html\n if (control === 'volume' && !browser.isIos && !browser.isIPadOS) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume\n };\n\n // Create the volume range slider\n volume.appendChild(createRange.call(this, 'volume', extend(attributes, {\n id: `plyr-volume-${data.id}`\n })));\n }\n }\n\n // Toggle captions button\n if (control === 'captions') {\n container.appendChild(createButton.call(this, 'captions', defaultAttributes));\n }\n\n // Settings button / menu\n if (control === 'settings' && !is.empty(this.config.settings)) {\n const wrapper = createElement('div', extend({}, defaultAttributes, {\n class: `${defaultAttributes.class} plyr__menu`.trim(),\n hidden: ''\n }));\n wrapper.appendChild(createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false\n }));\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: ''\n });\n const inner = createElement('div');\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu'\n });\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach(type => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement('button', extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: ''\n }));\n\n // Bind menu shortcuts for keyboard users\n bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on.call(this, menuItem, 'click', () => {\n showMenuPanel.call(this, type, false);\n });\n const flex = createElement('span', null, i18n.get(type, this.config));\n const value = createElement('span', {\n class: this.config.classNames.menu.value\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: ''\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`\n });\n\n // Visible label\n backButton.appendChild(createElement('span', {\n 'aria-hidden': true\n }, i18n.get(type, this.config)));\n\n // Screen reader label\n backButton.appendChild(createElement('span', {\n class: this.config.classNames.hidden\n }, i18n.get('menuBack', this.config)));\n\n // Go back via keyboard\n on.call(this, pane, 'keydown', event => {\n if (event.key !== 'ArrowLeft') return;\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n showMenuPanel.call(this, 'home', true);\n }, false);\n\n // Go back via button click\n on.call(this, backButton, 'click', () => {\n showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(createElement('div', {\n role: 'menu'\n }));\n inner.appendChild(pane);\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n popup.appendChild(inner);\n wrapper.appendChild(popup);\n container.appendChild(wrapper);\n this.elements.settings.popup = popup;\n this.elements.settings.menu = wrapper;\n }\n\n // Picture in picture button\n if (control === 'pip' && support.pip) {\n container.appendChild(createButton.call(this, 'pip', defaultAttributes));\n }\n\n // Airplay button\n if (control === 'airplay' && support.airplay) {\n container.appendChild(createButton.call(this, 'airplay', defaultAttributes));\n }\n\n // Download button\n if (control === 'download') {\n const attributes = extend({}, defaultAttributes, {\n element: 'a',\n href: this.download,\n target: '_blank'\n });\n\n // Set download attribute for HTML5 only\n if (this.isHTML5) {\n attributes.download = '';\n }\n const {\n download\n } = this.config.urls;\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider\n });\n }\n container.appendChild(createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (control === 'fullscreen') {\n container.appendChild(createButton.call(this, 'fullscreen', defaultAttributes));\n }\n });\n\n // Set available quality levels\n if (this.isHTML5) {\n setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n setSpeedMenu.call(this);\n return container;\n },\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this)\n // TODO: Looping\n // loop: 'None',\n });\n\n update = false;\n }\n\n // Replace props with their value\n const replace = input => {\n let result = input;\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = button => {\n const className = this.config.classNames.controlPressed;\n button.setAttribute('aria-pressed', 'false');\n Object.defineProperty(button, 'pressed', {\n configurable: true,\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n button.setAttribute('aria-pressed', pressed ? 'true' : 'false');\n }\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons).filter(Boolean).forEach(button => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button).filter(Boolean).forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const {\n classNames,\n selectors\n } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n Array.from(labels).forEach(label => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n // Set media metadata\n setMediaMetadata() {\n try {\n if ('mediaSession' in navigator) {\n navigator.mediaSession.metadata = new window.MediaMetadata({\n title: this.config.mediaMetadata.title,\n artist: this.config.mediaMetadata.artist,\n album: this.config.mediaMetadata.album,\n artwork: this.config.mediaMetadata.artwork\n });\n }\n } catch (_) {\n // Do nothing\n }\n },\n // Add markers\n setMarkers() {\n var _this$config$markers2, _this$config$markers3;\n if (!this.duration || this.elements.markers) return;\n\n // Get valid points\n const points = (_this$config$markers2 = this.config.markers) === null || _this$config$markers2 === void 0 ? void 0 : (_this$config$markers3 = _this$config$markers2.points) === null || _this$config$markers3 === void 0 ? void 0 : _this$config$markers3.filter(({\n time\n }) => time > 0 && time < this.duration);\n if (!(points !== null && points !== void 0 && points.length)) return;\n const containerFragment = document.createDocumentFragment();\n const pointsFragment = document.createDocumentFragment();\n let tipElement = null;\n const tipVisible = `${this.config.classNames.tooltip}--visible`;\n const toggleTip = show => toggleClass(tipElement, tipVisible, show);\n\n // Inject markers to progress container\n points.forEach(point => {\n const markerElement = createElement('span', {\n class: this.config.classNames.marker\n }, '');\n const left = `${point.time / this.duration * 100}%`;\n if (tipElement) {\n // Show on hover\n markerElement.addEventListener('mouseenter', () => {\n if (point.label) return;\n tipElement.style.left = left;\n tipElement.innerHTML = point.label;\n toggleTip(true);\n });\n\n // Hide on leave\n markerElement.addEventListener('mouseleave', () => {\n toggleTip(false);\n });\n }\n markerElement.addEventListener('click', () => {\n this.currentTime = point.time;\n });\n markerElement.style.left = left;\n pointsFragment.appendChild(markerElement);\n });\n containerFragment.appendChild(pointsFragment);\n\n // Inject a tooltip if needed\n if (!this.config.tooltips.seek) {\n tipElement = createElement('span', {\n class: this.config.classNames.tooltip\n }, '');\n containerFragment.appendChild(tipElement);\n }\n this.elements.markers = {\n points: pointsFragment,\n tip: tipElement\n };\n this.elements.progress.appendChild(containerFragment);\n }\n };\n\n // ==========================================================================\n\n /**\n * Parse a string to a URL object\n * @param {String} input - the URL to be parsed\n * @param {Boolean} safe - failsafe parsing\n */\n function parseUrl(input, safe = true) {\n let url = input;\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n try {\n return new URL(url);\n } catch (_) {\n return null;\n }\n }\n\n // Convert object to URLSearchParams\n function buildUrlParams(input) {\n const params = new URLSearchParams();\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n return params;\n }\n\n // ==========================================================================\n const captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) {\n // Clear menu and hide\n if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n this.elements.captions.setAttribute('dir', 'auto');\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n Array.from(elements).forEach(track => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n if (url !== null && url.hostname !== window.location.href.hostname && ['http:', 'https:'].includes(url.protocol)) {\n fetch(src, 'blob').then(blob => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n }).catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map(language => language.split('-')[0]));\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({\n active\n } = this.config.captions);\n }\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const {\n active,\n language,\n meta,\n currentTrackNode\n } = this.captions;\n const languageExists = Boolean(tracks.find(track => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks.filter(track => !meta.get(track)).forEach(track => {\n this.debug.log('Track added', track);\n\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing'\n });\n\n // Turn off native caption rendering to avoid double captions\n // Note: mode='hidden' forces a track to download. To ensure every track\n // isn't downloaded at once, only 'showing' tracks should be reassigned\n // eslint-disable-next-line no-param-reassign\n if (track.mode === 'showing') {\n // eslint-disable-next-line no-param-reassign\n track.mode = 'hidden';\n }\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if (languageExists && this.language !== language || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n if (this.elements) {\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n }\n\n // Update available languages in list\n if (is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {\n controls.setCaptionsMenu.call(this);\n }\n },\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n const {\n toggled\n } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({\n captions: active\n });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n // Wait for the call stack to clear before setting mode='hidden'\n // on the active track - forcing the browser to download it\n setTimeout(() => {\n if (active && this.captions.toggled) {\n this.captions.currentTrackNode.mode = 'hidden';\n }\n });\n },\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const {\n language\n } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({\n language\n });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks.filter(track => !this.isHTML5 || update || this.captions.meta.has(track)).filter(track => ['captions', 'subtitles'].includes(track.kind));\n },\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = track => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n languages.every(language => {\n track = sorted.find(t => t.language === language);\n return !track; // Break iteration if there is a match\n });\n\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n return i18n.get('enabled', this.config);\n }\n return i18n.get('disabled', this.config);\n },\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n cues = Array.from((track || {}).activeCues || []).map(cue => cue.getCueAsHTML()).map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map(cueText => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n }\n };\n\n // ==========================================================================\n // Plyr default config\n // ==========================================================================\n\n const defaults = {\n // Disable\n enabled: true,\n // Custom media title\n title: '',\n // Logging to console\n debug: false,\n // Auto play (if supported)\n autoplay: false,\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n // Allow inline playback on iOS\n playsinline: true,\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n // Default volume\n volume: 1,\n muted: false,\n // Pass a custom duration\n duration: null,\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n // Invert the current time to be a countdown\n invertTime: true,\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n // Force an aspect ratio\n // The format must be `'w:h'` (e.g. `'16:9'`)\n ratio: null,\n // Click video container to play/pause\n clickToPlay: true,\n // Auto hide the controls\n hideControls: true,\n // Reset to start when playback ended\n resetOnEnd: false,\n // Disable the standard context menu\n disableContextMenu: true,\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.7.8/plyr.svg',\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n // Quality default\n quality: {\n default: 576,\n // The options to display in the UI, if available for the source media\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n forced: false,\n onChange: null\n },\n // Set loops\n loop: {\n active: false\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4]\n },\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false\n },\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true\n },\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false\n },\n // Fullscreen settings\n fullscreen: {\n enabled: true,\n // Allow fullscreen?\n fallback: true,\n // Fallback using full viewport/window\n iosNative: false // Use the native fullscreen in iOS (disables custom controls)\n // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode\n // Non-ancestors of the player element will be ignored\n // container: null, // defaults to the player element\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr'\n },\n // Default controls\n controls: ['play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress', 'current-time',\n // 'duration',\n 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay',\n // 'download',\n 'fullscreen'],\n settings: ['captions', 'quality', 'speed'],\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n pip: 'PIP',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD'\n }\n },\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/oembed.json?url={0}'\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}'\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'\n }\n },\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null\n },\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied', 'ratechange', 'cuechange',\n // Custom events\n 'download', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled', 'languagechange', 'controlshidden', 'controlsshown', 'ready',\n // YouTube\n 'statechange',\n // Quality\n 'qualitychange',\n // Ads\n 'adsloaded', 'adscontentpause', 'adscontentresume', 'adstarted', 'adsmidpoint', 'adscomplete', 'adsallcomplete', 'adsimpression', 'adsclick'],\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls'\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]'\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]'\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop',\n // Used later\n volume: '.plyr__volume--display'\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption'\n },\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n marker: 'plyr__progress__marker',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time'\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open'\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active'\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback'\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active'\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active'\n },\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown'\n }\n },\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n hash: 'data-plyr-embed-hash'\n }\n },\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: ''\n },\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: ''\n },\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n // Custom settings from Plyr\n customControls: true,\n referrerPolicy: null,\n // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy\n // Whether the owner of the video has a Pro or Business account\n // (which allows us to properly hide controls without CSS hacks, etc)\n premium: false\n },\n // YouTube plugin\n youtube: {\n rel: 0,\n // No related vids\n showinfo: 0,\n // Hide info\n iv_load_policy: 3,\n // Hide annotations\n modestbranding: 1,\n // Hide logos as much as possible (they still show one in the corner when paused)\n // Custom settings from Plyr\n customControls: true,\n noCookie: false // Whether to use an alternative version of YouTube without cookies\n },\n\n // Media Metadata\n mediaMetadata: {\n title: '',\n artist: '',\n album: '',\n artwork: []\n },\n // Markers\n markers: {\n enabled: false,\n points: []\n }\n };\n\n // ==========================================================================\n // Plyr states\n // ==========================================================================\n\n const pip = {\n active: 'picture-in-picture',\n inactive: 'inline'\n };\n\n // ==========================================================================\n // Plyr supported types and providers\n // ==========================================================================\n\n const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo'\n };\n const types = {\n audio: 'audio',\n video: 'video'\n };\n\n /**\n * Get provider by URL\n * @param {String} url\n */\n function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n return null;\n }\n\n // ==========================================================================\n // Console wrapper\n // ==========================================================================\n\n const noop = () => {};\n class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n }\n\n class Fullscreen {\n constructor(player) {\n _defineProperty$1(this, \"onChange\", () => {\n if (!this.supported) return;\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up\n const target = this.target === this.player.media ? this.target : this.player.elements.container;\n // Trigger an event\n triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n });\n _defineProperty$1(this, \"toggleFallback\", (toggle = false) => {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX ?? 0,\n y: window.scrollY ?? 0\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n if (!hasProperty) viewport.content += `,${property}`;\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content.split(',').filter(part => part.trim() !== property).join(',');\n }\n }\n\n // Toggle button and fire events\n this.onChange();\n });\n // Trap focus inside container\n _defineProperty$1(this, \"trapFocus\", event => {\n // Bail if iOS/iPadOS, not active, not the tab key\n if (browser.isIos || browser.isIPadOS || !this.active || event.key !== 'Tab') return;\n\n // Get the current focused element\n const focused = document.activeElement;\n const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');\n const [first] = focusable;\n const last = focusable[focusable.length - 1];\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n });\n // Update UI\n _defineProperty$1(this, \"update\", () => {\n if (this.supported) {\n let mode;\n if (this.forceFallback) mode = 'Fallback (forced)';else if (Fullscreen.nativeSupported) mode = 'Native';else mode = 'Fallback';\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.supported);\n });\n // Make an element fullscreen\n _defineProperty$1(this, \"enter\", () => {\n if (!this.supported) return;\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.isVimeo) {\n this.player.embed.requestFullscreen();\n } else {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.nativeSupported || this.forceFallback) {\n this.toggleFallback(true);\n } else if (!this.prefix) {\n this.target.requestFullscreen({\n navigationUI: 'hide'\n });\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n });\n // Bail from fullscreen\n _defineProperty$1(this, \"exit\", () => {\n if (!this.supported) return;\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.isVimeo) {\n this.player.embed.exitFullscreen();\n } else {\n this.target.webkitEnterFullscreen();\n }\n silencePromise(this.player.play());\n } else if (!Fullscreen.nativeSupported || this.forceFallback) {\n this.toggleFallback(false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n });\n // Toggle state\n _defineProperty$1(this, \"toggle\", () => {\n if (!this.active) this.enter();else this.exit();\n });\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = {\n x: 0,\n y: 0\n };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Get the fullscreen element\n // Checks container is an ancestor, defaults to null\n this.player.elements.fullscreen = player.config.fullscreen.container && closest$1(this.player.elements.container, player.config.fullscreen.container);\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`, () => {\n // TODO: Filter for target??\n this.onChange();\n });\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', event => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n this.player.listeners.proxy(event, this.toggle, 'fullscreen');\n });\n\n // Tap focus when in fullscreen\n on.call(this, this.player.elements.container, 'keydown', event => this.trapFocus(event));\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get nativeSupported() {\n return !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled);\n }\n\n // If we're actually using native\n get useNative() {\n return Fullscreen.nativeSupported && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) return '';\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n prefixes.some(pre => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n return false;\n });\n return value;\n }\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is supported\n get supported() {\n return [\n // Fullscreen is enabled in config\n this.player.config.fullscreen.enabled,\n // Must be a video\n this.player.isVideo,\n // Either native is supported or fallback enabled\n Fullscreen.nativeSupported || this.player.config.fullscreen.fallback,\n // YouTube has no way to trigger fullscreen, so on devices with no native support, playsinline\n // must be enabled and iosNative fullscreen must be disabled to offer the fullscreen fallback\n !this.player.isYouTube || Fullscreen.nativeSupported || !browser.isIos || this.player.config.playsinline && !this.player.config.fullscreen.iosNative].every(Boolean);\n }\n\n // Get active state\n get active() {\n if (!this.supported) return false;\n\n // Fallback using classname\n if (!Fullscreen.nativeSupported || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n const element = !this.prefix ? this.target.getRootNode().fullscreenElement : this.target.getRootNode()[`${this.prefix}${this.property}Element`];\n return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen ?? this.player.elements.container;\n }\n }\n\n // ==========================================================================\n // Load image avoiding xhr/fetch CORS issues\n // Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n // By default it checks if it is at least 1px, but you can add a second argument to change this\n // ==========================================================================\n\n function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n Object.assign(image, {\n onload: handler,\n onerror: handler,\n src\n });\n });\n }\n\n // ==========================================================================\n const ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Reset duration display\n controls.durationUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(this.elements.container, this.config.classNames.pip.supported, support.pip && this.isHTML5 && this.isVideo);\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n\n // Media metadata\n if (this.config.mediaMetadata) {\n controls.setMediaMetadata.call(this);\n }\n },\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach(button => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('data-poster', poster);\n\n // Show the poster\n this.elements.poster.removeAttribute('hidden');\n\n // Wait until ui is ready\n return ready.call(this)\n // Load image\n .then(() => loadImage(poster)).catch(error => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw error;\n }).then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n }).then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: ''\n });\n ui.togglePoster.call(this, true);\n return poster;\n });\n },\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach(target => {\n Object.assign(target, {\n pressed: this.playing\n });\n target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n }, this.loading ? 250 : 0);\n },\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const {\n controls: controlsElement\n } = this.elements;\n if (controlsElement && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));\n }\n },\n // Migrate any custom properties from the media to the parent\n migrateStyles() {\n // Loop through values (as they are the keys when the object is spread 🤔)\n Object.values({\n ...this.media.style\n })\n // We're only fussed about Plyr specific properties\n .filter(key => !is.empty(key) && is.string(key) && key.startsWith('--plyr')).forEach(key => {\n // Set on the container\n this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key));\n\n // Clean up from media element\n this.media.style.removeProperty(key);\n });\n\n // Remove attribute if empty\n if (is.empty(this.media.style)) {\n this.media.removeAttribute('style');\n }\n }\n };\n\n class Listeners {\n constructor(_player) {\n // Device is touch enabled\n _defineProperty$1(this, \"firstTouch\", () => {\n const {\n player\n } = this;\n const {\n elements\n } = player;\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n });\n // Global window & document listeners\n _defineProperty$1(this, \"global\", (toggle = true) => {\n const {\n player\n } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n });\n // Container listeners\n _defineProperty$1(this, \"container\", () => {\n const {\n player\n } = this;\n const {\n config,\n elements,\n timers\n } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', event => {\n const {\n controls: controlsElement\n } = elements;\n\n // Remove button states for fullscreen\n if (controlsElement && event.type === 'enterfullscreen') {\n controlsElement.pressed = false;\n controlsElement.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n let delay = 0;\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Set a gutter for Vimeo\n const setGutter = () => {\n if (!player.isVimeo || player.config.vimeo.premium) {\n return;\n }\n const target = elements.wrapper;\n const {\n active\n } = player.fullscreen;\n const [videoWidth, videoHeight] = getAspectRatio.call(player);\n const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`);\n\n // If not active, remove styles\n if (!active) {\n if (useNativeAspectRatio) {\n target.style.width = null;\n target.style.height = null;\n } else {\n target.style.maxWidth = null;\n target.style.margin = null;\n }\n return;\n }\n\n // Determine which dimension will overflow and constrain view\n const [viewportWidth, viewportHeight] = getViewportSize();\n const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;\n if (useNativeAspectRatio) {\n target.style.width = overflow ? 'auto' : '100%';\n target.style.height = overflow ? '100%' : 'auto';\n } else {\n target.style.maxWidth = overflow ? `${viewportHeight / videoHeight * videoWidth}px` : null;\n target.style.margin = overflow ? '0 auto' : null;\n }\n };\n\n // Handle resizing\n const resized = () => {\n clearTimeout(timers.resized);\n timers.resized = setTimeout(setGutter, 50);\n };\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', event => {\n const {\n target\n } = player.fullscreen;\n\n // Ignore events not from target\n if (target !== elements.container) {\n return;\n }\n\n // If it's not an embed and no ratio specified\n if (!player.isEmbed && is.empty(player.config.ratio)) {\n return;\n }\n\n // Set Vimeo gutter\n setGutter();\n\n // Watch for resizes\n const method = event.type === 'enterfullscreen' ? on : off;\n method.call(player, window, 'resize', resized);\n });\n });\n // Listen for media events\n _defineProperty$1(this, \"media\", () => {\n const {\n player\n } = this;\n const {\n elements\n } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', event => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', event => controls.durationUpdate.call(player, event));\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n\n // Call pause otherwise IE11 will start playing the video again\n player.pause();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', event => controls.updateProgress.call(player, event));\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', event => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', event => ui.checkPlaying.call(player, event));\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', event => ui.checkLoading.call(player, event));\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', event => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(event, () => {\n silencePromise(player.play());\n }, 'play');\n } else {\n this.proxy(event, () => {\n silencePromise(player.togglePlay());\n }, 'play');\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(player, elements.wrapper, 'contextmenu', event => {\n event.preventDefault();\n }, false);\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({\n speed: player.speed\n });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', event => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadUrl.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n on.call(player, player.media, proxyEvents, event => {\n let {\n detail = {}\n } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n });\n // Run default and custom handlers\n _defineProperty$1(this, \"proxy\", (event, defaultHandler, customHandlerKey) => {\n const {\n player\n } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned !== false && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n });\n // Trigger custom and default handlers\n _defineProperty$1(this, \"bind\", (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const {\n player\n } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n on.call(player, element, type, event => this.proxy(event, defaultHandler, customHandlerKey), passive && !hasCustomHandler);\n });\n // Listen for control events\n _defineProperty$1(this, \"controls\", () => {\n const {\n player\n } = this;\n const {\n elements\n } = player;\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach(button => {\n this.bind(button, 'click', () => {\n silencePromise(player.togglePlay());\n }, 'play');\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(elements.buttons.rewind, 'click', () => {\n // Record seek time so we can prevent hiding controls for a few seconds after rewind\n player.lastSeekTime = Date.now();\n player.rewind();\n }, 'rewind');\n\n // Rewind\n this.bind(elements.buttons.fastForward, 'click', () => {\n // Record seek time so we can prevent hiding controls for a few seconds after fast forward\n player.lastSeekTime = Date.now();\n player.forward();\n }, 'fastForward');\n\n // Mute toggle\n this.bind(elements.buttons.mute, 'click', () => {\n player.muted = !player.muted;\n }, 'mute');\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(elements.buttons.download, 'click', () => {\n triggerEvent.call(player, player.media, 'download');\n }, 'download');\n\n // Fullscreen toggle\n this.bind(elements.buttons.fullscreen, 'click', () => {\n player.fullscreen.toggle();\n }, 'fullscreen');\n\n // Picture-in-Picture\n this.bind(elements.buttons.pip, 'click', () => {\n player.pip = 'toggle';\n }, 'pip');\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(elements.buttons.settings, 'click', event => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n event.preventDefault();\n controls.toggleMenu.call(player, event);\n }, null, false); // Can't be passive as we're preventing default\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(elements.buttons.settings, 'keyup', event => {\n if (![' ', 'Enter'].includes(event.key)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (event.key === 'Enter') {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n }, null, false // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', event => {\n if (event.key === 'Escape') {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', event => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = 100 / rect.width * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', event => {\n const seek = event.currentTarget;\n const attribute = 'play-on-seeked';\n if (is.keyboardEvent(event) && !['ArrowLeft', 'ArrowRight'].includes(event.key)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n silencePromise(player.play());\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach(input => this.bind(input, inputEvent, event => repaint(event.target)));\n }\n\n // Seek\n this.bind(elements.inputs.seek, inputEvent, event => {\n const seek = event.currentTarget;\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n seek.removeAttribute('seek-value');\n player.currentTime = seekTo / seek.max * player.duration;\n }, 'seek');\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', event => controls.updateSeekTooltip.call(player, event));\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', event => {\n const {\n previewThumbnails\n } = player;\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave touchend click', () => {\n const {\n previewThumbnails\n } = player;\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', event => {\n const {\n previewThumbnails\n } = player;\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n this.bind(elements.progress, 'mouseup touchend', event => {\n const {\n previewThumbnails\n } = player;\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebKit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach(element => {\n this.bind(element, 'input', event => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n player.config.invertTime = !player.config.invertTime;\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(elements.inputs.volume, inputEvent, event => {\n player.volume = event.target.value;\n }, 'volume');\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', event => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Also update controls.hover state for any non-player children of fullscreen element (as above)\n if (elements.fullscreen) {\n Array.from(elements.fullscreen.children).filter(c => !c.contains(elements.container)).forEach(child => {\n this.bind(child, 'mouseenter mouseleave', event => {\n if (elements.controls) {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n }\n });\n });\n }\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const {\n config,\n timers\n } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(elements.inputs.volume, 'wheel', event => {\n // Detect \"natural\" scroll - supported on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map(value => inverted ? -value : value);\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const {\n volume\n } = player.media;\n if (direction === 1 && volume < 1 || direction === -1 && volume > 0) {\n event.preventDefault();\n }\n }, 'volume', false);\n });\n this.player = _player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const {\n player\n } = this;\n const {\n elements\n } = player;\n const {\n key,\n type,\n altKey,\n ctrlKey,\n metaKey,\n shiftKey\n } = event;\n const pressed = type === 'keydown';\n const repeat = pressed && key === this.lastKey;\n\n // Bail if a modifier key is set\n if (altKey || ctrlKey || metaKey || shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the key for whatever reason\n if (!key) {\n return;\n }\n\n // Seek by increment\n const seekByIncrement = increment => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = player.duration / 10 * increment;\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const {\n editable\n } = player.config.selectors;\n const {\n seek\n } = elements.inputs;\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n if (event.key === ' ' && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keys should we prevent default\n const preventDefault = [' ', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'c', 'f', 'k', 'l', 'm'];\n\n // If the key is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n }\n switch (key) {\n case '0':\n case '1':\n case '2':\n case '3':\n case '4':\n case '5':\n case '6':\n case '7':\n case '8':\n case '9':\n if (!repeat) {\n seekByIncrement(parseInt(key, 10));\n }\n break;\n case ' ':\n case 'k':\n if (!repeat) {\n silencePromise(player.togglePlay());\n }\n break;\n case 'ArrowUp':\n player.increaseVolume(0.1);\n break;\n case 'ArrowDown':\n player.decreaseVolume(0.1);\n break;\n case 'm':\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n case 'ArrowRight':\n player.forward();\n break;\n case 'ArrowLeft':\n player.rewind();\n break;\n case 'f':\n player.fullscreen.toggle();\n break;\n case 'c':\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n case 'l':\n player.loop = !player.loop;\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (key === 'Escape' && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last key for next cycle\n this.lastKey = key;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n }\n\n var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};\n\n function createCommonjsModule(fn, module) {\n \treturn module = { exports: {} }, fn(module, module.exports), module.exports;\n }\n\n var loadjs_umd = createCommonjsModule(function (module, exports) {\n (function (root, factory) {\n {\n module.exports = factory();\n }\n })(commonjsGlobal, function () {\n /**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\n var devnull = function () {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n /**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\n function subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n }\n\n /**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\n function publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n }\n\n /**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\n function executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {\n success: args\n };\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);else (args.success || devnull)(args);\n }\n\n /**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\n function loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathname = path.replace(/[\\?|#].*$/, ''),\n pathStripped = path.replace(/^(css|img)!/, ''),\n isLegacyIECss,\n e;\n numTries = numTries || 0;\n if (/(^css!|\\.css$)/.test(pathname)) {\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped;\n\n // tag IE9+\n isLegacyIECss = 'hideFocus' in e;\n\n // use preload in IE Edge (to detect load errors)\n if (isLegacyIECss && e.relList) {\n isLegacyIECss = 0;\n e.rel = 'preload';\n e.as = 'style';\n }\n } else if (/(^img!|\\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped;\n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // treat empty stylesheets as failures to get around lack of onerror\n // support in IE9-11\n if (isLegacyIECss) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n } else if (e.rel == 'preload' && e.as == 'style') {\n // activate preloaded stylesheets\n return e.rel = 'stylesheet'; // jshint ignore:line\n }\n\n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n }\n\n /**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\n function loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function (path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);else return;\n }\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i = 0; i < x; i++) loadFile(paths[i], fn, args);\n }\n\n /**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function|Object)} [arg1] - The (1) bundleId or (2) success\n * callback or (3) object literal with success/error arguments, numRetries,\n * etc.\n * @param {(Function|Object)} [arg2] - The (1) success callback or (2) object\n * literal with success/error arguments, numRetries, etc.\n */\n function loadjs(paths, arg1, arg2) {\n var bundleId, args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n function loadFn(resolve, reject) {\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n\n // resolve Promise\n if (resolve) {\n executeCallbacks({\n success: resolve,\n error: reject\n }, pathsNotFound);\n }\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n }\n if (args.returnPromise) return new Promise(loadFn);else loadFn();\n }\n\n /**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\n loadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n return loadjs;\n };\n\n /**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\n loadjs.done = function done(bundleId) {\n publish(bundleId, []);\n };\n\n /**\n * Reset loadjs dependencies statuses\n */\n loadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n };\n\n /**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\n loadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n };\n\n // export\n return loadjs;\n });\n });\n\n // ==========================================================================\n function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs_umd(url, {\n success: resolve,\n error: reject\n });\n });\n }\n\n // ==========================================================================\n\n // Parse Vimeo ID from URL\n function parseId$1(url) {\n if (is.empty(url)) {\n return null;\n }\n if (is.number(Number(url))) {\n return url;\n }\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n }\n\n // Try to extract a hash for private videos from the URL\n function parseHash(url) {\n /* This regex matches a hexadecimal hash if given in any of these forms:\n * - [https://player.]vimeo.com/video/{id}/{hash}[?params]\n * - [https://player.]vimeo.com/video/{id}?h={hash}[¶ms]\n * - [https://player.]vimeo.com/video/{id}?[params]&h={hash}\n * - video/{id}/{hash}\n * If matched, the hash is available in capture group 4\n */\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+)(\\?.*&*h=|\\/)+([\\d,a-f]+)/;\n const found = url.match(regex);\n return found && found.length === 5 ? found[4] : null;\n }\n\n // Set playback state and trigger change (only on actual change)\n function assurePlaybackState$1(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n }\n const vimeo = {\n setup() {\n const player = this;\n\n // Add embed class for responsive\n toggleClass(player.elements.wrapper, player.config.classNames.embed, true);\n\n // Set speed options from config\n player.options.speed = player.config.speed.options;\n\n // Set intial ratio\n setAspectRatio.call(player);\n\n // Load the SDK if not already\n if (!is.object(window.Vimeo)) {\n loadScript(player.config.urls.vimeo.sdk).then(() => {\n vimeo.ready.call(player);\n }).catch(error => {\n player.debug.warn('Vimeo SDK (player.js) failed to load', error);\n });\n } else {\n vimeo.ready.call(player);\n }\n },\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n const {\n premium,\n referrerPolicy,\n ...frameParams\n } = config;\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n let hash = '';\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n // hash can also be set as attribute on the <div>\n hash = player.media.getAttribute(player.config.attributes.embed.hash);\n } else {\n hash = parseHash(source);\n }\n const hashParam = hash ? {\n h: hash\n } : {};\n\n // If the owner has a pro or premium account then we can hide controls etc\n if (premium) {\n Object.assign(frameParams, {\n controls: false,\n sidedock: false\n });\n }\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams({\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: player.config.playsinline,\n // hash has to be added to iframe-URL\n ...hashParam,\n ...frameParams\n });\n const id = parseId$1(source);\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allow', ['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '));\n\n // Set the referrer policy if required\n if (!is.empty(referrerPolicy)) {\n iframe.setAttribute('referrerPolicy', referrerPolicy);\n }\n\n // Inject the package\n if (premium || !config.customControls) {\n iframe.setAttribute('data-poster', player.poster);\n player.media = replaceElement(iframe, player.media);\n } else {\n const wrapper = createElement('div', {\n class: player.config.classNames.embedContainer,\n 'data-poster': player.poster\n });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n }\n\n // Get poster image\n if (!config.customControls) {\n fetch(format(player.config.urls.vimeo.api, src)).then(response => {\n if (is.empty(response) || !response.thumbnail_url) {\n return;\n }\n\n // Set and show poster\n ui.setPoster.call(player, response.thumbnail_url).catch(() => {});\n });\n }\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted\n });\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState$1.call(player, true);\n return player.embed.play();\n };\n player.media.pause = () => {\n assurePlaybackState$1.call(player, false);\n return player.embed.pause();\n };\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let {\n currentTime\n } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const {\n embed,\n media,\n paused,\n volume\n } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume)).catch(() => {\n // Do nothing\n });\n }\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed.setPlaybackRate(input).then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n }).catch(() => {\n // Cannot set Playback Rate, Video is probably not on Pro account\n player.options.speed = [1];\n });\n }\n });\n\n // Volume\n let {\n volume\n } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n }\n });\n\n // Muted\n let {\n muted\n } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n player.embed.setMuted(toggle ? true : player.config.muted).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n }\n });\n\n // Loop\n let {\n loop\n } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n }\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n controls.setDownloadUrl.call(player);\n }).catch(error => {\n this.debug.warn(error);\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n }\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n }\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const [width, height] = dimensions;\n player.embed.ratio = roundAspectRatio(width, height);\n setAspectRatio.call(this);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then(state => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n player.embed.on('cuechange', ({\n cues = []\n }) => {\n const strippedCues = cues.map(cue => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then(paused => {\n assurePlaybackState$1.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n player.embed.on('bufferstart', () => {\n triggerEvent.call(player, player.media, 'waiting');\n });\n player.embed.on('bufferend', () => {\n triggerEvent.call(player, player.media, 'playing');\n });\n player.embed.on('play', () => {\n assurePlaybackState$1.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n player.embed.on('pause', () => {\n assurePlaybackState$1.call(player, false);\n });\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then(value => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n player.embed.on('error', detail => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n if (config.customControls) {\n setTimeout(() => ui.build.call(player), 0);\n }\n }\n };\n\n // ==========================================================================\n\n // Parse YouTube ID from URL\n function parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n }\n\n // Set playback state and trigger change (only on actual change)\n function assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n }\n function getHost(config) {\n if (config.noCookie) {\n return 'https://www.youtube-nocookie.com';\n }\n if (window.location.protocol === 'http:') {\n return 'http://www.youtube.com';\n }\n\n // Use YouTube's default\n return undefined;\n }\n const youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Reference current global callback\n const callback = window.onYouTubeIframeAPIReady;\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n // Call global callback if set\n if (is.function(callback)) {\n callback();\n }\n youtube.ready.call(this);\n };\n\n // Load the SDK\n loadScript(this.config.urls.youtube.sdk).catch(error => {\n this.debug.warn('YouTube API failed to load', error);\n });\n }\n },\n // Get the media title\n getTitle(videoId) {\n const url = format(this.config.urls.youtube.api, videoId);\n fetch(url).then(data => {\n if (is.object(data)) {\n const {\n title,\n height,\n width\n } = data;\n\n // Set title\n this.config.title = title;\n ui.setTitle.call(this);\n\n // Set aspect ratio\n this.embed.ratio = roundAspectRatio(width, height);\n }\n setAspectRatio.call(this);\n }).catch(() => {\n // Set aspect ratio\n setAspectRatio.call(this);\n });\n },\n // API ready\n ready() {\n const player = this;\n const config = player.config.youtube;\n // Ignore already setup (race condition)\n const currentId = player.media && player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n // Replace media element\n const container = createElement('div', {\n id,\n 'data-poster': config.customControls ? player.poster : undefined\n });\n player.media = replaceElement(container, player.media);\n\n // Only load the poster when using custom controls\n if (config.customControls) {\n const posterSrc = s => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Highest quality and un-padded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then(image => ui.setPoster.call(player, image.src)).then(src => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!src.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n }).catch(() => {});\n }\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(player.media, {\n videoId,\n host: getHost(config),\n playerVars: extend({}, {\n // Autoplay\n autoplay: player.config.autoplay ? 1 : 0,\n // iframe interface language\n hl: player.config.hl,\n // Only show controls if not fully supported or opted out\n controls: player.supported.ui && config.customControls ? 0 : 1,\n // Disable keyboard as we handle it\n disablekb: 1,\n // Allow iOS inline playback\n playsinline: player.config.playsinline && !player.config.fullscreen.iosNative ? 1 : 0,\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null\n }, config),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message = {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.'\n }[code] || 'An unknown error occurred';\n player.media.error = {\n code,\n message\n };\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n player.media.stop = () => {\n instance.stopVideo();\n };\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n }\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n }\n });\n\n // Volume\n let {\n volume\n } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n }\n });\n\n // Muted\n let {\n muted\n } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n }\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n }\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n }\n });\n\n // Get available speeds\n const speeds = instance.getAvailablePlaybackRates();\n // Filter based on config\n player.options.speed = speeds.filter(s => player.config.speed.options.includes(s));\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui && config.customControls) {\n player.media.setAttribute('tabindex', -1);\n }\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n if (config.customControls) {\n setTimeout(() => ui.build.call(player), 50);\n }\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n break;\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n break;\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n break;\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n break;\n case 3:\n // Trigger waiting event to add loading classes to container as the video buffers.\n triggerEvent.call(player, player.media, 'waiting');\n break;\n }\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data\n });\n }\n }\n });\n }\n };\n\n // ==========================================================================\n const media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Poster image container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster\n });\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n if (this.isHTML5) {\n html5.setup.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n }\n };\n\n const destroy = instance => {\n // Destroy our adsManager\n if (instance.manager) {\n instance.manager.destroy();\n }\n\n // Destroy our adsManager\n if (instance.elements.displayContainer) {\n instance.elements.displayContainer.destroy();\n }\n instance.elements.container.remove();\n };\n class Ads {\n /**\n * Ads constructor.\n * @param {Object} player\n * @return {Ads}\n */\n constructor(player) {\n /**\n * Load the IMA SDK\n */\n _defineProperty$1(this, \"load\", () => {\n if (!this.enabled) {\n return;\n }\n\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk).then(() => {\n this.ready();\n }).catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n });\n /**\n * Get the ads instance ready\n */\n _defineProperty$1(this, \"ready\", () => {\n // Double check we're enabled\n if (!this.enabled) {\n destroy(this);\n }\n\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n });\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n _defineProperty$1(this, \"setupIMA\", () => {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads\n });\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // Set playback for iOS10+\n google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline);\n\n // We assume the adContainer is the video container of the plyr element that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media);\n\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, event => this.onAdsManagerLoaded(event), false);\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error), false);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n });\n /**\n * Request advertisements\n */\n _defineProperty$1(this, \"requestAds\", () => {\n const {\n container\n } = this.player.elements;\n try {\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n this.loader.requestAds(request);\n } catch (error) {\n this.onAdError(error);\n }\n });\n /**\n * Update the ad countdown\n * @param {Boolean} start\n */\n _defineProperty$1(this, \"pollCountdown\", (start = false) => {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n this.countdownTimer = setInterval(update, 100);\n });\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} event - adsManagerLoadedEvent\n */\n _defineProperty$1(this, \"onAdsManagerLoaded\", event => {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, error => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach(type => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], e => this.onAdEvent(e));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n });\n _defineProperty$1(this, \"addCuePoints\", () => {\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach(cuePoint => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n if (is.element(seekElement)) {\n const cuePercentage = 100 / this.player.duration * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues\n });\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n });\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n _defineProperty$1(this, \"onAdEvent\", event => {\n const {\n container\n } = this.player.elements;\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = type => {\n triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);\n };\n\n // Bubble the event\n dispatchEvent(event.type);\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Start countdown\n this.pollCountdown(true);\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n\n break;\n case google.ima.AdEvent.Type.STARTED:\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n break;\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n if (this.player.ended) {\n this.loadAds();\n } else {\n // The SDK won't allow new ads to be called without receiving a contentComplete()\n this.loader.contentComplete();\n }\n break;\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n this.pauseContent();\n break;\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n this.pollCountdown();\n this.resumeContent();\n break;\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n break;\n }\n });\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n _defineProperty$1(this, \"onAdError\", event => {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n });\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n _defineProperty$1(this, \"listeners\", () => {\n const {\n container\n } = this.player.elements;\n let time;\n this.player.on('canplay', () => {\n this.addCuePoints();\n });\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n if (is.empty(this.cuePoints)) {\n return;\n }\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n });\n /**\n * Initialize the adsManager and start playing advertisements\n */\n _defineProperty$1(this, \"play\", () => {\n const {\n container\n } = this.player.elements;\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise.then(() => {\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n }).catch(() => {});\n });\n /**\n * Resume our video\n */\n _defineProperty$1(this, \"resumeContent\", () => {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play video\n silencePromise(this.player.media.play());\n });\n /**\n * Pause our video\n */\n _defineProperty$1(this, \"pauseContent\", () => {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing\n this.playing = true;\n\n // Pause our video.\n this.player.media.pause();\n });\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n _defineProperty$1(this, \"cancel\", () => {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n });\n /**\n * Re-create our adsManager\n */\n _defineProperty$1(this, \"loadAds\", () => {\n // Tell our adsManager to go bye bye\n this.managerPromise.then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise(resolve => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n // Now that the manager has been destroyed set it to also be un-initialized\n this.initialized = false;\n\n // Now request some new advertisements\n this.requestAds();\n }).catch(() => {});\n });\n /**\n * Handles callbacks after an ad event was invoked\n * @param {String} event - Event type\n * @param args\n */\n _defineProperty$1(this, \"trigger\", (event, ...args) => {\n const handlers = this.events[event];\n if (is.array(handlers)) {\n handlers.forEach(handler => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n });\n /**\n * Add event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n * @return {Ads}\n */\n _defineProperty$1(this, \"on\", (event, callback) => {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n this.events[event].push(callback);\n return this;\n });\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {Number} time\n * @param {String} from\n */\n _defineProperty$1(this, \"startSafetyTimer\", (time, from) => {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n });\n /**\n * Clear our safety timer(s)\n * @param {String} from\n */\n _defineProperty$1(this, \"clearSafetyTimer\", from => {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n });\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n this.load();\n }\n get enabled() {\n const {\n config\n } = this;\n return this.player.isHTML5 && this.player.isVideo && config.enabled && (!is.empty(config.publisherId) || is.url(config.tagUrl));\n }\n // Build the tag URL\n get tagUrl() {\n const {\n config\n } = this;\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: config.publisherId\n };\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n return `${base}?${buildUrlParams(params)}`;\n }\n }\n\n /**\n * Returns a number whose value is limited to the given range.\n *\n * Example: limit the output of this computation to between 0 and 255\n * (x * 255).clamp(0, 255)\n *\n * @param {Number} input\n * @param {Number} min The lower boundary of the output range\n * @param {Number} max The upper boundary of the output range\n * @returns A number within the bounds of min and max\n * @type Number\n */\n function clamp(input = 0, min = 0, max = 255) {\n return Math.min(Math.max(input, min), max);\n }\n\n // Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\n const parseVtt = vttDataString => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n frames.forEach(frame => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n lines.forEach(line => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(/([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime = Number(matchTimes[1] || 0) * 60 * 60 + Number(matchTimes[2]) * 60 + Number(matchTimes[3]) + Number(`0.${matchTimes[4]}`);\n result.endTime = Number(matchTimes[6] || 0) * 60 * 60 + Number(matchTimes[7]) * 60 + Number(matchTimes[8]) + Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n if (result.text) {\n processedList.push(result);\n }\n });\n return processedList;\n };\n\n /**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\n const fitRatio = (ratio, outer) => {\n const targetRatio = outer.width / outer.height;\n const result = {};\n if (ratio > targetRatio) {\n result.width = outer.width;\n result.height = 1 / ratio * outer.width;\n } else {\n result.height = outer.height;\n result.width = ratio * outer.height;\n }\n return result;\n };\n class PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n _defineProperty$1(this, \"load\", () => {\n // Toggle the regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n if (!this.enabled) return;\n this.getThumbnails().then(() => {\n if (!this.enabled) {\n return;\n }\n\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n // Set up listeners\n this.listeners();\n this.loaded = true;\n });\n });\n // Download VTT files and parse them\n _defineProperty$1(this, \"getThumbnails\", () => {\n return new Promise(resolve => {\n const {\n src\n } = this.player.config.previewThumbnails;\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // Resolve promise\n const sortAndResolve = () => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n resolve();\n };\n\n // Via callback()\n if (is.function(src)) {\n src(thumbnails => {\n this.thumbnails = thumbnails;\n sortAndResolve();\n });\n }\n // VTT urls\n else {\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map(u => this.getThumbnail(u));\n // Resolve\n Promise.all(promises).then(sortAndResolve);\n }\n });\n });\n // Process individual VTT file\n _defineProperty$1(this, \"getThumbnail\", url => {\n return new Promise(resolve => {\n fetch(url).then(response => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: ''\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n // If the thumbnail URLs start with with none of '/', 'http://' or 'https://', then we need to set their relative path to be the location of the VTT file\n if (!thumbnail.frames[0].text.startsWith('/') && !thumbnail.frames[0].text.startsWith('http://') && !thumbnail.frames[0].text.startsWith('https://')) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n this.thumbnails.push(thumbnail);\n resolve();\n };\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n });\n _defineProperty$1(this, \"startMove\", event => {\n if (!this.loaded) return;\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) return;\n\n // Wait until media has a duration\n if (!this.player.media.duration) return;\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n var _this$player$config$m, _this$player$config$m2;\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = 100 / clientRect.width * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n\n // Get marker point for time\n const point = (_this$player$config$m = this.player.config.markers) === null || _this$player$config$m === void 0 ? void 0 : (_this$player$config$m2 = _this$player$config$m.points) === null || _this$player$config$m2 === void 0 ? void 0 : _this$player$config$m2.find(({\n time: t\n }) => t === Math.round(this.seekTime));\n\n // Append the point label to the tooltip\n if (point) {\n // this.elements.thumb.time.innerText.concat('\\n');\n this.elements.thumb.time.insertAdjacentHTML('afterbegin', `${point.label}<br>`);\n }\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n });\n _defineProperty$1(this, \"endMove\", () => {\n this.toggleThumbContainer(false, true);\n });\n _defineProperty$1(this, \"startScrubbing\", event => {\n // Only act on left mouse button (0), or touch device (event.button does not exist or is false)\n if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {\n this.mouseDown = true;\n\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n });\n _defineProperty$1(this, \"endScrubbing\", () => {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n });\n /**\n * Setup hooks for Plyr and window events\n */\n _defineProperty$1(this, \"listeners\", () => {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n });\n /**\n * Create HTML elements for image containers\n */\n _defineProperty$1(this, \"render\", () => {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer\n });\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n this.elements.thumb.imageContainer.appendChild(timeContainer);\n\n // Inject the whole thumb\n if (is.element(this.player.elements.progress)) {\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n }\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer\n });\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n });\n _defineProperty$1(this, \"destroy\", () => {\n if (this.elements.thumb.container) {\n this.elements.thumb.container.remove();\n }\n if (this.elements.scrubbing.container) {\n this.elements.scrubbing.container.remove();\n }\n });\n _defineProperty$1(this, \"showImageAtCurrentTime\", () => {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(frame => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime);\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n // Show the thumb container if we're not scrubbing\n if (!this.mouseDown) {\n this.toggleThumbContainer(hasThumb);\n }\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumb num or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n });\n // Show the image that's currently specified in this.showingThumb\n _defineProperty$1(this, \"loadImage\", (qualityIndex = 0) => {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const {\n urlPrefix\n } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () => this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n });\n _defineProperty$1(this, \"showImage\", (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {\n this.player.debug.log(`Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`);\n this.setImageSizeAndOffset(previewImage, frame);\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true).then(this.preloadNearby(thumbNum, false)).then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n });\n // Remove all preview images that aren't the designated current image\n _defineProperty$1(this, \"removeOldImages\", currentImage => {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach(image => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n const removeDelay = this.usingSprites ? 500 : 1000;\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n // eslint-disable-next-line no-param-reassign\n image.dataset.deleting = true;\n\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const {\n currentImageContainer\n } = this;\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n });\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n _defineProperty$1(this, \"preloadNearby\", (thumbNum, forward = true) => {\n return new Promise(resolve => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n let foundOne = false;\n thumbnailsClone.forEach(frame => {\n const newThumbFilename = frame.text;\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n const {\n urlPrefix\n } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename)) this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n });\n // If user has been hovering current image for half a second, look for a higher quality one\n _defineProperty$1(this, \"getHigherQuality\", (currentQualityIndex, previewImage, frame, thumbFilename) => {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n });\n _defineProperty$1(this, \"toggleThumbContainer\", (toggle = false, clearShowing = false) => {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n });\n _defineProperty$1(this, \"toggleScrubbingContainer\", (toggle = false) => {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n });\n _defineProperty$1(this, \"determineContainerAutoSizing\", () => {\n if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n });\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n _defineProperty$1(this, \"setThumbContainerSizeAndPos\", () => {\n const {\n imageContainer\n } = this.elements.thumb;\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n imageContainer.style.height = `${this.thumbContainerHeight}px`;\n imageContainer.style.width = `${thumbWidth}px`;\n } else if (imageContainer.clientHeight > 20 && imageContainer.clientWidth < 20) {\n const thumbWidth = Math.floor(imageContainer.clientHeight * this.thumbAspectRatio);\n imageContainer.style.width = `${thumbWidth}px`;\n } else if (imageContainer.clientHeight < 20 && imageContainer.clientWidth > 20) {\n const thumbHeight = Math.floor(imageContainer.clientWidth / this.thumbAspectRatio);\n imageContainer.style.height = `${thumbHeight}px`;\n }\n this.setThumbContainerPos();\n });\n _defineProperty$1(this, \"setThumbContainerPos\", () => {\n const scrubberRect = this.player.elements.progress.getBoundingClientRect();\n const containerRect = this.player.elements.container.getBoundingClientRect();\n const {\n container\n } = this.elements.thumb;\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const min = containerRect.left - scrubberRect.left + 10;\n const max = containerRect.right - scrubberRect.left - container.clientWidth - 10;\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n const position = this.mousePosX - scrubberRect.left - container.clientWidth / 2;\n const clamped = clamp(position, min, max);\n\n // Move the popover position\n container.style.left = `${clamped}px`;\n\n // The arrow can follow the cursor\n container.style.setProperty('--preview-arrow-offset', `${position - clamped}px`);\n });\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n _defineProperty$1(this, \"setScrubbingContainerSize\", () => {\n const {\n width,\n height\n } = fitRatio(this.thumbAspectRatio, {\n width: this.player.media.clientWidth,\n height: this.player.media.clientHeight\n });\n this.elements.scrubbing.container.style.width = `${width}px`;\n this.elements.scrubbing.container.style.height = `${height}px`;\n });\n // Sprites need to be offset to the correct location\n _defineProperty$1(this, \"setImageSizeAndOffset\", (previewImage, frame) => {\n if (!this.usingSprites) return;\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n // eslint-disable-next-line no-param-reassign\n previewImage.style.height = `${previewImage.naturalHeight * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.width = `${previewImage.naturalWidth * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.left = `-${frame.x * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.top = `-${frame.y * multiplier}px`;\n });\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n this.elements = {\n thumb: {},\n scrubbing: {}\n };\n this.load();\n }\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n get currentImageContainer() {\n return this.mouseDown ? this.elements.scrubbing.container : this.elements.thumb.imageContainer;\n }\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n get thumbContainerHeight() {\n if (this.mouseDown) {\n const {\n height\n } = fitRatio(this.thumbAspectRatio, {\n width: this.player.media.clientWidth,\n height: this.player.media.clientHeight\n });\n return height;\n }\n\n // If css is used this needs to return the css height for sprites to work (see setImageSizeAndOffset)\n if (this.sizeSpecifiedInCSS) {\n return this.elements.thumb.imageContainer.clientHeight;\n }\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n get currentImageElement() {\n return this.mouseDown ? this.currentScrubbingImageElement : this.currentThumbnailImageElement;\n }\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n }\n\n // ==========================================================================\n const source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes\n });\n } else if (is.array(attributes)) {\n attributes.forEach(attribute => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(this, () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const {\n sources,\n type\n } = input;\n const [{\n provider = providers.html5,\n src\n }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : {\n src\n };\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes)\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || this.isEmbed && !this.supported.ui) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Update previewThumbnails config & reload plugin\n if (!is.empty(input.previewThumbnails)) {\n Object.assign(this.config.previewThumbnails, input.previewThumbnails);\n\n // Cleanup previewThumbnails plugin if it was loaded\n if (this.previewThumbnails && this.previewThumbnails.loaded) {\n this.previewThumbnails.destroy();\n this.previewThumbnails = null;\n }\n\n // Create new instance if it is still enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n }, true);\n }\n };\n\n // Private properties\n // TODO: Use a WeakMap for private globals\n // const globals = new WeakMap();\n\n // Plyr instance\n class Plyr {\n constructor(target, options) {\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n _defineProperty$1(this, \"play\", () => {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Intecept play with ads\n if (this.ads && this.ads.enabled) {\n this.ads.managerPromise.then(() => this.ads.play()).catch(() => silencePromise(this.media.play()));\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n });\n /**\n * Pause the media\n */\n _defineProperty$1(this, \"pause\", () => {\n if (!this.playing || !is.function(this.media.pause)) {\n return null;\n }\n return this.media.pause();\n });\n /**\n * Toggle playback based on current status\n * @param {Boolean} input\n */\n _defineProperty$1(this, \"togglePlay\", input => {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n if (toggle) {\n return this.play();\n }\n return this.pause();\n });\n /**\n * Stop playback\n */\n _defineProperty$1(this, \"stop\", () => {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n });\n /**\n * Restart playback\n */\n _defineProperty$1(this, \"restart\", () => {\n this.currentTime = 0;\n });\n /**\n * Rewind\n * @param {Number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n _defineProperty$1(this, \"rewind\", seekTime => {\n this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;\n });\n /**\n * Fast forward\n * @param {Number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n _defineProperty$1(this, \"forward\", seekTime => {\n this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;\n });\n /**\n * Increase volume\n * @param {Boolean} step - How much to decrease by (between 0 and 1)\n */\n _defineProperty$1(this, \"increaseVolume\", step => {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n });\n /**\n * Decrease volume\n * @param {Boolean} step - How much to decrease by (between 0 and 1)\n */\n _defineProperty$1(this, \"decreaseVolume\", step => {\n this.increaseVolume(-step);\n });\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n _defineProperty$1(this, \"airplay\", () => {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n });\n /**\n * Toggle the player controls\n * @param {Boolean} [toggle] - Whether to show the controls\n */\n _defineProperty$1(this, \"toggleControls\", toggle => {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (hiding && is.array(this.config.controls) && this.config.controls.includes('settings') && !is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n return !hiding;\n }\n return false;\n });\n /**\n * Add event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n _defineProperty$1(this, \"on\", (event, callback) => {\n on.call(this, this.elements.container, event, callback);\n });\n /**\n * Add event listeners once\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n _defineProperty$1(this, \"once\", (event, callback) => {\n once.call(this, this.elements.container, event, callback);\n });\n /**\n * Remove event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n _defineProperty$1(this, \"off\", (event, callback) => {\n off(this.elements.container, event, callback);\n });\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {Function} callback - Callback for when destroy is complete\n * @param {Boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n _defineProperty$1(this, \"destroy\", (callback, soft = false) => {\n if (!this.ready) {\n return;\n }\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Clear timeouts\n clearTimeout(this.timers.loading);\n clearTimeout(this.timers.controls);\n clearTimeout(this.timers.resized);\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n });\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {String} type - Mime type\n */\n _defineProperty$1(this, \"supports\", type => support.mime.call(this, type));\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if (window.jQuery && this.media instanceof jQuery || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend({}, defaults, Plyr.defaults, options || {}, (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (_) {\n return {};\n }\n })());\n\n // Elements cache\n this.elements = {\n container: null,\n fullscreen: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {}\n }\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap()\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false\n };\n\n // Options\n this.options = {\n speed: [],\n quality: []\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const _type = this.media.tagName.toLowerCase();\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (_type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n break;\n case 'video':\n case 'audio':\n this.type = _type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n break;\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div');\n wrap(this.media, this.elements.container);\n }\n\n // Migrate custom properties from media to container (so they work 😉)\n ui.migrateStyles.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), event => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || this.isEmbed && !this.supported.ui) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.isHTML5 && this.config.autoplay) {\n this.once('canplay', () => silencePromise(this.play()));\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return this.provider === providers.html5;\n }\n get isEmbed() {\n return this.isYouTube || this.isVimeo;\n }\n get isYouTube() {\n return this.provider === providers.youtube;\n }\n get isVimeo() {\n return this.provider === providers.vimeo;\n }\n get isVideo() {\n return this.type === types.video;\n }\n get isAudio() {\n return this.type === types.audio;\n }\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n /**\n * Seek to a time\n * @param {Number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const {\n buffered\n } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {Number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({\n volume\n } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n /**\n * Set muted state\n * @param {Boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return Boolean(this.media.mozHasAudio) || Boolean(this.media.webkitAudioDecodedByteCount) || Boolean(this.media.audioTracks && this.media.audioTracks.length);\n }\n\n /**\n * Set playback speed\n * @param {Number} input - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n if (is.number(input)) {\n speed = input;\n }\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Clamp to min/max\n const {\n minimumSpeed: min,\n maximumSpeed: max\n } = this;\n speed = clamp(speed, min, max);\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n setTimeout(() => {\n if (this.media) {\n this.media.playbackRate = speed;\n }\n }, 0);\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Get the minimum allowed speed\n */\n get minimumSpeed() {\n if (this.isYouTube) {\n // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n return Math.min(...this.options.speed);\n }\n if (this.isVimeo) {\n // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n return 0.5;\n }\n\n // https://stackoverflow.com/a/32320020/1191319\n return 0.0625;\n }\n\n /**\n * Get the maximum allowed speed\n */\n get maximumSpeed() {\n if (this.isYouTube) {\n // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n return Math.max(...this.options.speed);\n }\n if (this.isVimeo) {\n // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n return 2;\n }\n\n // https://stackoverflow.com/a/32320020/1191319\n return 16;\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {Number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n if (!options.length) {\n return;\n }\n let quality = [!is.empty(input) && Number(input), this.storage.get('quality'), config.selected, config.default].find(is.number);\n let updateStorage = true;\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({\n quality\n });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {Boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {Object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const {\n download\n } = this.config.urls;\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the download URL\n */\n set download(input) {\n if (!is.url(input)) {\n return;\n }\n this.config.urls.download = input;\n controls.setDownloadUrl.call(this);\n }\n\n /**\n * Set the poster image for a video\n * @param {String} input - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');\n }\n\n /**\n * Get the current aspect ratio in use\n */\n get ratio() {\n if (!this.isVideo) {\n return null;\n }\n const ratio = reduceAspectRatio(getAspectRatio.call(this));\n return is.array(ratio) ? ratio.join(':') : ratio;\n }\n\n /**\n * Set video aspect ratio\n */\n set ratio(input) {\n if (!this.isVideo) {\n this.debug.warn('Aspect ratio can only be set for video');\n return;\n }\n if (!is.string(input) || !validateAspectRatio(input)) {\n this.debug.error(`Invalid aspect ratio specified (${input})`);\n return;\n }\n this.config.ratio = reduceAspectRatio(input);\n setAspectRatio.call(this);\n }\n\n /**\n * Set the autoplay state\n * @param {Boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n this.config.autoplay = is.boolean(input) ? input : this.config.autoplay;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {Boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {Number} input - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n captions.setup.call(this);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const {\n toggled,\n currentTrack\n } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {String} input - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Sets the preview thumbnails for the current source\n */\n setPreviewThumbnails(thumbnailSource) {\n if (this.previewThumbnails && this.previewThumbnails.loaded) {\n this.previewThumbnails.destroy();\n this.previewThumbnails = null;\n }\n Object.assign(this.config.previewThumbnails, thumbnailSource);\n\n // Create new instance if it is still enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n /**\n * Check for support\n * @param {String} type - Player type (audio/video)\n * @param {String} provider - Provider (html5/youtube/vimeo)\n */\n static supported(type, provider) {\n return support.check(type, provider);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {String} url - URL for the SVG sprite\n * @param {String} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {Object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n if (is.empty(targets)) {\n return null;\n }\n return targets.map(t => new Plyr(t, options));\n }\n }\n Plyr.defaults = cloneDeep(defaults);\n\n return Plyr;\n\n}));\n//# sourceMappingURL=plyr.js.map\n","function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}function _defineProperties(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,\"value\"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _createClass(e,t,n){return t&&_defineProperties(e.prototype,t),n&&_defineProperties(e,n),e}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function _objectSpread2(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?ownKeys(Object(n),!0).forEach((function(t){_defineProperty(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ownKeys(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}var defaults={addCSS:!0,thumbWidth:15,watch:!0};function matches(e,t){return function(){return Array.from(document.querySelectorAll(t)).includes(this)}.call(e,t)}function trigger(e,t){if(e&&t){var n=new Event(t,{bubbles:!0});e.dispatchEvent(n)}}var getConstructor=function(e){return null!=e?e.constructor:null},instanceOf=function(e,t){return!!(e&&t&&e instanceof t)},isNullOrUndefined=function(e){return null==e},isObject=function(e){return getConstructor(e)===Object},isNumber=function(e){return getConstructor(e)===Number&&!Number.isNaN(e)},isString=function(e){return getConstructor(e)===String},isBoolean=function(e){return getConstructor(e)===Boolean},isFunction=function(e){return getConstructor(e)===Function},isArray=function(e){return Array.isArray(e)},isNodeList=function(e){return instanceOf(e,NodeList)},isElement=function(e){return instanceOf(e,Element)},isEvent=function(e){return instanceOf(e,Event)},isEmpty=function(e){return isNullOrUndefined(e)||(isString(e)||isArray(e)||isNodeList(e))&&!e.length||isObject(e)&&!Object.keys(e).length},is={nullOrUndefined:isNullOrUndefined,object:isObject,number:isNumber,string:isString,boolean:isBoolean,function:isFunction,array:isArray,nodeList:isNodeList,element:isElement,event:isEvent,empty:isEmpty};function getDecimalPlaces(e){var t=\"\".concat(e).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0}function round(e,t){if(1>t){var n=getDecimalPlaces(t);return parseFloat(e.toFixed(n))}return Math.round(e/t)*t}var RangeTouch=function(){function e(t,n){_classCallCheck(this,e),is.element(t)?this.element=t:is.string(t)&&(this.element=document.querySelector(t)),is.element(this.element)&&is.empty(this.element.rangeTouch)&&(this.config=_objectSpread2({},defaults,{},n),this.init())}return _createClass(e,[{key:\"init\",value:function(){e.enabled&&(this.config.addCSS&&(this.element.style.userSelect=\"none\",this.element.style.webKitUserSelect=\"none\",this.element.style.touchAction=\"manipulation\"),this.listeners(!0),this.element.rangeTouch=this)}},{key:\"destroy\",value:function(){e.enabled&&(this.config.addCSS&&(this.element.style.userSelect=\"\",this.element.style.webKitUserSelect=\"\",this.element.style.touchAction=\"\"),this.listeners(!1),this.element.rangeTouch=null)}},{key:\"listeners\",value:function(e){var t=this,n=e?\"addEventListener\":\"removeEventListener\";[\"touchstart\",\"touchmove\",\"touchend\"].forEach((function(e){t.element[n](e,(function(e){return t.set(e)}),!1)}))}},{key:\"get\",value:function(t){if(!e.enabled||!is.event(t))return null;var n,r=t.target,i=t.changedTouches[0],o=parseFloat(r.getAttribute(\"min\"))||0,s=parseFloat(r.getAttribute(\"max\"))||100,u=parseFloat(r.getAttribute(\"step\"))||1,c=r.getBoundingClientRect(),a=100/c.width*(this.config.thumbWidth/2)/100;return 0>(n=100/c.width*(i.clientX-c.left))?n=0:100<n&&(n=100),50>n?n-=(100-2*n)*a:50<n&&(n+=2*(n-50)*a),o+round(n/100*(s-o),u)}},{key:\"set\",value:function(t){e.enabled&&is.event(t)&&!t.target.disabled&&(t.preventDefault(),t.target.value=this.get(t),trigger(t.target,\"touchend\"===t.type?\"change\":\"input\"))}}],[{key:\"setup\",value:function(t){var n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},r=null;if(is.empty(t)||is.string(t)?r=Array.from(document.querySelectorAll(is.string(t)?t:'input[type=\"range\"]')):is.element(t)?r=[t]:is.nodeList(t)?r=Array.from(t):is.array(t)&&(r=t.filter(is.element)),is.empty(r))return null;var i=_objectSpread2({},defaults,{},n);if(is.string(t)&&i.watch){var o=new MutationObserver((function(n){Array.from(n).forEach((function(n){Array.from(n.addedNodes).forEach((function(n){is.element(n)&&matches(n,t)&&new e(n,i)}))}))}));o.observe(document.body,{childList:!0,subtree:!0})}return r.map((function(t){return new e(t,n)}))}},{key:\"enabled\",get:function(){return\"ontouchstart\"in document.documentElement}}]),e}();export default RangeTouch;","// ==========================================================================\n// Type checking utils\n// ==========================================================================\n\nconst getConstructor = (input) => (input !== null && typeof input !== 'undefined' ? input.constructor : null);\nconst instanceOf = (input, constructor) => Boolean(input && constructor && input instanceof constructor);\nconst isNullOrUndefined = (input) => input === null || typeof input === 'undefined';\nconst isObject = (input) => getConstructor(input) === Object;\nconst isNumber = (input) => getConstructor(input) === Number && !Number.isNaN(input);\nconst isString = (input) => getConstructor(input) === String;\nconst isBoolean = (input) => getConstructor(input) === Boolean;\nconst isFunction = (input) => typeof input === 'function';\nconst isArray = (input) => Array.isArray(input);\nconst isWeakMap = (input) => instanceOf(input, WeakMap);\nconst isNodeList = (input) => instanceOf(input, NodeList);\nconst isTextNode = (input) => getConstructor(input) === Text;\nconst isEvent = (input) => instanceOf(input, Event);\nconst isKeyboardEvent = (input) => instanceOf(input, KeyboardEvent);\nconst isCue = (input) => instanceOf(input, window.TextTrackCue) || instanceOf(input, window.VTTCue);\nconst isTrack = (input) => instanceOf(input, TextTrack) || (!isNullOrUndefined(input) && isString(input.kind));\nconst isPromise = (input) => instanceOf(input, Promise) && isFunction(input.then);\n\nconst isElement = (input) =>\n input !== null &&\n typeof input === 'object' &&\n input.nodeType === 1 &&\n typeof input.style === 'object' &&\n typeof input.ownerDocument === 'object';\n\nconst isEmpty = (input) =>\n isNullOrUndefined(input) ||\n ((isString(input) || isArray(input) || isNodeList(input)) && !input.length) ||\n (isObject(input) && !Object.keys(input).length);\n\nconst isUrl = (input) => {\n // Accept a URL object\n if (instanceOf(input, window.URL)) {\n return true;\n }\n\n // Must be string from here\n if (!isString(input)) {\n return false;\n }\n\n // Add the protocol if required\n let string = input;\n if (!input.startsWith('http://') || !input.startsWith('https://')) {\n string = `http://${input}`;\n }\n\n try {\n return !isEmpty(new URL(string).hostname);\n } catch (_) {\n return false;\n }\n};\n\nexport default {\n nullOrUndefined: isNullOrUndefined,\n object: isObject,\n number: isNumber,\n string: isString,\n boolean: isBoolean,\n function: isFunction,\n array: isArray,\n weakMap: isWeakMap,\n nodeList: isNodeList,\n element: isElement,\n textNode: isTextNode,\n event: isEvent,\n keyboardEvent: isKeyboardEvent,\n cue: isCue,\n track: isTrack,\n promise: isPromise,\n url: isUrl,\n empty: isEmpty,\n};\n","// ==========================================================================\n// Animation utils\n// ==========================================================================\n\nimport is from './is';\n\nexport const transitionEndEvent = (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find((event) => element.style[event] !== undefined);\n\n return is.string(type) ? events[type] : false;\n})();\n\n// Force repaint of element\nexport function repaint(element, delay) {\n setTimeout(() => {\n try {\n // eslint-disable-next-line no-param-reassign\n element.hidden = true;\n\n // eslint-disable-next-line no-unused-expressions\n element.offsetHeight;\n\n // eslint-disable-next-line no-param-reassign\n element.hidden = false;\n } catch (_) {\n // Do nothing\n }\n }, delay);\n}\n","// ==========================================================================\n// Browser sniffing\n// Unfortunately, due to mixed support, UA sniffing is required\n// ==========================================================================\n\nconst isIE = Boolean(window.document.documentMode);\nconst isEdge = /Edge/g.test(navigator.userAgent);\nconst isWebKit = 'WebkitAppearance' in document.documentElement.style && !/Edge/g.test(navigator.userAgent);\nconst isIPhone = /iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;\n// navigator.platform may be deprecated but this check is still required\nconst isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;\nconst isIos = /iPad|iPhone|iPod/gi.test(navigator.userAgent) && navigator.maxTouchPoints > 1;\n\nexport default {\n isIE,\n isEdge,\n isWebKit,\n isIPhone,\n isIPadOS,\n isIos,\n};\n","// ==========================================================================\n// Object utils\n// ==========================================================================\n\nimport is from './is';\n\n// Clone nested objects\nexport function cloneDeep(object) {\n return JSON.parse(JSON.stringify(object));\n}\n\n// Get a nested value in an object\nexport function getDeep(object, path) {\n return path.split('.').reduce((obj, key) => obj && obj[key], object);\n}\n\n// Deep extend destination object with N more objects\nexport function extend(target = {}, ...sources) {\n if (!sources.length) {\n return target;\n }\n\n const source = sources.shift();\n\n if (!is.object(source)) {\n return target;\n }\n\n Object.keys(source).forEach((key) => {\n if (is.object(source[key])) {\n if (!Object.keys(target).includes(key)) {\n Object.assign(target, { [key]: {} });\n }\n\n extend(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n });\n\n return extend(target, ...sources);\n}\n","// ==========================================================================\n// Element utils\n// ==========================================================================\n\nimport is from './is';\nimport { extend } from './objects';\n\n// Wrap an element\nexport function wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n}\n\n// Set attributes\nexport function setAttributes(element, attributes) {\n if (!is.element(element) || is.empty(attributes)) return;\n\n // Assume null and undefined attributes should be left out,\n // Setting them would otherwise convert them to \"null\" and \"undefined\"\n Object.entries(attributes)\n .filter(([, value]) => !is.nullOrUndefined(value))\n .forEach(([key, value]) => element.setAttribute(key, value));\n}\n\n// Create a DocumentFragment\nexport function createElement(type, attributes, text) {\n // Create a new <element>\n const element = document.createElement(type);\n\n // Set all passed attributes\n if (is.object(attributes)) {\n setAttributes(element, attributes);\n }\n\n // Add text node\n if (is.string(text)) {\n element.innerText = text;\n }\n\n // Return built element\n return element;\n}\n\n// Insert an element after another\nexport function insertAfter(element, target) {\n if (!is.element(element) || !is.element(target)) return;\n\n target.parentNode.insertBefore(element, target.nextSibling);\n}\n\n// Insert a DocumentFragment\nexport function insertElement(type, parent, attributes, text) {\n if (!is.element(parent)) return;\n\n parent.appendChild(createElement(type, attributes, text));\n}\n\n// Remove element(s)\nexport function removeElement(element) {\n if (is.nodeList(element) || is.array(element)) {\n Array.from(element).forEach(removeElement);\n return;\n }\n\n if (!is.element(element) || !is.element(element.parentNode)) {\n return;\n }\n\n element.parentNode.removeChild(element);\n}\n\n// Remove all child elements\nexport function emptyElement(element) {\n if (!is.element(element)) return;\n\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n}\n\n// Replace element\nexport function replaceElement(newChild, oldChild) {\n if (!is.element(oldChild) || !is.element(oldChild.parentNode) || !is.element(newChild)) return null;\n\n oldChild.parentNode.replaceChild(newChild, oldChild);\n\n return newChild;\n}\n\n// Get an attribute object from a string selector\nexport function getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!is.string(sel) || is.empty(sel)) return {};\n\n const attributes = {};\n const existing = extend({}, existingAttributes);\n\n sel.split(',').forEach((s) => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n // Get the parts and value\n const parts = stripped.split('=');\n const [key] = parts;\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (is.string(existing.class)) {\n attributes.class = `${existing.class} ${className}`;\n } else {\n attributes.class = className;\n }\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return extend(existing, attributes);\n}\n\n// Toggle hidden\nexport function toggleHidden(element, hidden) {\n if (!is.element(element)) return;\n\n let hide = hidden;\n\n if (!is.boolean(hide)) {\n hide = !element.hidden;\n }\n\n // eslint-disable-next-line no-param-reassign\n element.hidden = hide;\n}\n\n// Mirror Element.classList.toggle, with IE compatibility for \"force\" argument\nexport function toggleClass(element, className, force) {\n if (is.nodeList(element)) {\n return Array.from(element).map((e) => toggleClass(e, className, force));\n }\n\n if (is.element(element)) {\n let method = 'toggle';\n if (typeof force !== 'undefined') {\n method = force ? 'add' : 'remove';\n }\n\n element.classList[method](className);\n return element.classList.contains(className);\n }\n\n return false;\n}\n\n// Has class name\nexport function hasClass(element, className) {\n return is.element(element) && element.classList.contains(className);\n}\n\n// Element matches selector\nexport function matches(element, selector) {\n const { prototype } = Element;\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const method =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return method.call(element, selector);\n}\n\n// Closest ancestor element matching selector (also tests element itself)\nexport function closest(element, selector) {\n const { prototype } = Element;\n\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill\n function closestElement() {\n let el = this;\n\n do {\n if (matches.matches(el, selector)) return el;\n el = el.parentElement || el.parentNode;\n } while (el !== null && el.nodeType === 1);\n return null;\n }\n\n const method = prototype.closest || closestElement;\n\n return method.call(element, selector);\n}\n\n// Find all elements\nexport function getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n}\n\n// Find a single element\nexport function getElement(selector) {\n return this.elements.container.querySelector(selector);\n}\n\n// Set focus and tab focus class\nexport function setFocus(element = null, focusVisible = false) {\n if (!is.element(element)) return;\n\n // Set regular focus\n element.focus({ preventScroll: true, focusVisible });\n}\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport { transitionEndEvent } from './utils/animation';\nimport browser from './utils/browser';\nimport { createElement } from './utils/elements';\nimport is from './utils/is';\n\n// Default codecs for checking mimetype support\nconst defaultCodecs = {\n 'audio/ogg': 'vorbis',\n 'audio/wav': '1',\n 'video/webm': 'vp8, vorbis',\n 'video/mp4': 'avc1.42E01E, mp4a.40.2',\n 'video/ogg': 'theora',\n};\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, provider) {\n const api = support[type] || provider !== 'html5';\n const ui = api && support.rangeInput;\n\n return {\n api,\n ui,\n };\n },\n\n // Picture-in-picture support\n // Safari & Chrome only currently\n pip: (() => {\n // While iPhone's support picture-in-picture for some apps, seemingly Safari isn't one of them\n // It will throw the following error when trying to enter picture-in-picture\n // `NotSupportedError: The Picture-in-Picture mode is not supported.`\n if (browser.isIPhone) {\n return false;\n }\n\n // Safari\n // https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls\n if (is.function(createElement('video').webkitSetPresentationMode)) {\n return true;\n }\n\n // Chrome\n // https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture\n if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {\n return true;\n }\n\n return false;\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n playsinline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(input) {\n if (is.empty(input)) {\n return false;\n }\n\n const [mediaType] = input.split('/');\n let type = input;\n\n // Verify we're using HTML5 and there's no media type mismatch\n if (!this.isHTML5 || mediaType !== this.type) {\n return false;\n }\n\n // Add codec if required\n if (Object.keys(defaultCodecs).includes(type)) {\n type += `; codecs=\"${defaultCodecs[input]}\"`;\n }\n\n try {\n return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));\n } catch (_) {\n return false;\n }\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // <input type=\"range\"> Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // NOTE: Remember a device can be mouse + touch enabled so we check on first touch event\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: transitionEndEvent !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Event utils\n// ==========================================================================\n\nimport is from './is';\n\n// Check for passive event listener support\n// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n// https://www.youtube.com/watch?v=NPM6172J22g\nconst supportsPassiveListeners = (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n window.removeEventListener('test', null, options);\n } catch (_) {\n // Do nothing\n }\n\n return supported;\n})();\n\n// Toggle event listener\nexport function toggleListener(element, event, callback, toggle = false, passive = true, capture = false) {\n // Bail if no element, event, or callback\n if (!element || !('addEventListener' in element) || is.empty(event) || !is.function(callback)) {\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n // Build options\n // Default to just the capture boolean for browsers with no passive listener support\n let options = capture;\n\n // If passive events listeners are supported\n if (supportsPassiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive,\n // Whether the listener is a capturing listener or not\n capture,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach((type) => {\n if (this && this.eventListeners && toggle) {\n // Cache event listener\n this.eventListeners.push({ element, type, callback, options });\n }\n\n element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n}\n\n// Bind event handler\nexport function on(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, true, passive, capture);\n}\n\n// Unbind event handler\nexport function off(element, events = '', callback, passive = true, capture = false) {\n toggleListener.call(this, element, events, callback, false, passive, capture);\n}\n\n// Bind once-only event handler\nexport function once(element, events = '', callback, passive = true, capture = false) {\n const onceCallback = (...args) => {\n off(element, events, onceCallback, passive, capture);\n callback.apply(this, args);\n };\n\n toggleListener.call(this, element, events, onceCallback, true, passive, capture);\n}\n\n// Trigger event\nexport function triggerEvent(element, type = '', bubbles = false, detail = {}) {\n // Bail if no element\n if (!is.element(element) || is.empty(type)) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles,\n detail: { ...detail, plyr: this },\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n}\n\n// Unbind all cached event listeners\nexport function unbindListeners() {\n if (this && this.eventListeners) {\n this.eventListeners.forEach((item) => {\n const { element, type, callback, options } = item;\n element.removeEventListener(type, callback, options);\n });\n\n this.eventListeners = [];\n }\n}\n\n// Run method when / if player is ready\nexport function ready() {\n return new Promise((resolve) =>\n this.ready ? setTimeout(resolve, 0) : on.call(this, this.elements.container, 'ready', resolve),\n ).then(() => {});\n}\n","import is from './is';\n/**\n * Silence a Promise-like object.\n * This is useful for avoiding non-harmful, but potentially confusing \"uncaught\n * play promise\" rejection error messages.\n * @param {Object} value An object that may or may not be `Promise`-like.\n */\nexport function silencePromise(value) {\n if (is.promise(value)) {\n value.then(null, () => {});\n }\n}\n\nexport default { silencePromise };\n","// ==========================================================================\n// Array utils\n// ==========================================================================\n\nimport is from './is';\n\n// Remove duplicates in an array\nexport function dedupe(array) {\n if (!is.array(array)) {\n return array;\n }\n\n return array.filter((item, index) => array.indexOf(item) === index);\n}\n\n// Get the closest value in an array\nexport function closest(array, value) {\n if (!is.array(array) || !array.length) {\n return null;\n }\n\n return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));\n}\n","// ==========================================================================\n// Style utils\n// ==========================================================================\n\nimport { closest } from './arrays';\nimport is from './is';\n\n// Check support for a CSS declaration\nexport function supportsCSS(declaration) {\n if (!window || !window.CSS) {\n return false;\n }\n\n return window.CSS.supports(declaration);\n}\n\n// Standard/common aspect ratios\nconst standardRatios = [\n [1, 1],\n [4, 3],\n [3, 4],\n [5, 4],\n [4, 5],\n [3, 2],\n [2, 3],\n [16, 10],\n [10, 16],\n [16, 9],\n [9, 16],\n [21, 9],\n [9, 21],\n [32, 9],\n [9, 32],\n].reduce((out, [x, y]) => ({ ...out, [x / y]: [x, y] }), {});\n\n// Validate an aspect ratio\nexport function validateAspectRatio(input) {\n if (!is.array(input) && (!is.string(input) || !input.includes(':'))) {\n return false;\n }\n\n const ratio = is.array(input) ? input : input.split(':');\n\n return ratio.map(Number).every(is.number);\n}\n\n// Reduce an aspect ratio to it's lowest form\nexport function reduceAspectRatio(ratio) {\n if (!is.array(ratio) || !ratio.every(is.number)) {\n return null;\n }\n\n const [width, height] = ratio;\n const getDivider = (w, h) => (h === 0 ? w : getDivider(h, w % h));\n const divider = getDivider(width, height);\n\n return [width / divider, height / divider];\n}\n\n// Calculate an aspect ratio\nexport function getAspectRatio(input) {\n const parse = (ratio) => (validateAspectRatio(ratio) ? ratio.split(':').map(Number) : null);\n // Try provided ratio\n let ratio = parse(input);\n\n // Get from config\n if (ratio === null) {\n ratio = parse(this.config.ratio);\n }\n\n // Get from embed\n if (ratio === null && !is.empty(this.embed) && is.array(this.embed.ratio)) {\n ({ ratio } = this.embed);\n }\n\n // Get from HTML5 video\n if (ratio === null && this.isHTML5) {\n const { videoWidth, videoHeight } = this.media;\n ratio = [videoWidth, videoHeight];\n }\n\n return reduceAspectRatio(ratio);\n}\n\n// Set aspect ratio for responsive container\nexport function setAspectRatio(input) {\n if (!this.isVideo) {\n return {};\n }\n\n const { wrapper } = this.elements;\n const ratio = getAspectRatio.call(this, input);\n\n if (!is.array(ratio)) {\n return {};\n }\n\n const [x, y] = reduceAspectRatio(ratio);\n const useNative = supportsCSS(`aspect-ratio: ${x}/${y}`);\n const padding = (100 / x) * y;\n\n if (useNative) {\n wrapper.style.aspectRatio = `${x}/${y}`;\n } else {\n wrapper.style.paddingBottom = `${padding}%`;\n }\n\n // For Vimeo we have an extra <div> to hide the standard controls and UI\n if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {\n const height = (100 / this.media.offsetWidth) * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);\n const offset = (height - padding) / (height / 50);\n\n if (this.fullscreen.active) {\n wrapper.style.paddingBottom = null;\n } else {\n this.media.style.transform = `translateY(-${offset}%)`;\n }\n } else if (this.isHTML5) {\n wrapper.classList.add(this.config.classNames.videoFixedRatio);\n }\n\n return { padding, ratio };\n}\n\n// Round an aspect ratio to closest standard ratio\nexport function roundAspectRatio(x, y, tolerance = 0.05) {\n const ratio = x / y;\n const closestRatio = closest(Object.keys(standardRatios), ratio);\n\n // Check match is within tolerance\n if (Math.abs(closestRatio - ratio) <= tolerance) {\n return standardRatios[closestRatio];\n }\n\n // No match\n return [x, y];\n}\n\n// Get the size of the viewport\n// https://stackoverflow.com/questions/1248081/how-to-get-the-browser-viewport-dimensions\nexport function getViewportSize() {\n const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);\n const height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);\n return [width, height];\n}\n","// ==========================================================================\n// Plyr HTML5 helpers\n// ==========================================================================\n\nimport support from './support';\nimport { removeElement } from './utils/elements';\nimport { triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\nimport { setAspectRatio } from './utils/style';\n\nconst html5 = {\n getSources() {\n if (!this.isHTML5) {\n return [];\n }\n\n const sources = Array.from(this.media.querySelectorAll('source'));\n\n // Filter out unsupported sources (if type is specified)\n return sources.filter((source) => {\n const type = source.getAttribute('type');\n\n if (is.empty(type)) {\n return true;\n }\n\n return support.mime.call(this, type);\n });\n },\n\n // Get quality levels\n getQualityOptions() {\n // Whether we're forcing all options (e.g. for streaming)\n if (this.config.quality.forced) {\n return this.config.quality.options;\n }\n\n // Get sizes from <source> elements\n return html5.getSources\n .call(this)\n .map((source) => Number(source.getAttribute('size')))\n .filter(Boolean);\n },\n\n setup() {\n if (!this.isHTML5) {\n return;\n }\n\n const player = this;\n\n // Set speed options from config\n player.options.speed = player.config.speed.options;\n\n // Set aspect ratio if fixed\n if (!is.empty(this.config.ratio)) {\n setAspectRatio.call(player);\n }\n\n // Quality\n Object.defineProperty(player.media, 'quality', {\n get() {\n // Get sources\n const sources = html5.getSources.call(player);\n const source = sources.find((s) => s.getAttribute('src') === player.source);\n\n // Return size, if match is found\n return source && Number(source.getAttribute('size'));\n },\n set(input) {\n if (player.quality === input) {\n return;\n }\n\n // If we're using an external handler...\n if (player.config.quality.forced && is.function(player.config.quality.onChange)) {\n player.config.quality.onChange(input);\n } else {\n // Get sources\n const sources = html5.getSources.call(player);\n // Get first match for requested size\n const source = sources.find((s) => Number(s.getAttribute('size')) === input);\n\n // No matching source found\n if (!source) {\n return;\n }\n\n // Get current state\n const { currentTime, paused, preload, readyState, playbackRate } = player.media;\n\n // Set new source\n player.media.src = source.getAttribute('src');\n\n // Prevent loading if preload=\"none\" and the current source isn't loaded (#1044)\n if (preload !== 'none' || readyState) {\n // Restore time\n player.once('loadedmetadata', () => {\n player.speed = playbackRate;\n player.currentTime = currentTime;\n\n // Resume playing\n if (!paused) {\n silencePromise(player.play());\n }\n });\n\n // Load new source\n player.media.load();\n }\n }\n\n // Trigger change event\n triggerEvent.call(player, player.media, 'qualitychange', false, {\n quality: input,\n });\n },\n });\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n removeElement(html5.getSources.call(this));\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.debug.log('Cancelled network requests');\n },\n};\n\nexport default html5;\n","// ==========================================================================\n// String utils\n// ==========================================================================\n\nimport is from './is';\n\n// Generate a random ID\nexport function generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n}\n\n// Format string\nexport function format(input, ...args) {\n if (is.empty(input)) return input;\n\n return input.toString().replace(/{(\\d+)}/g, (_, i) => args[i].toString());\n}\n\n// Get percentage\nexport function getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n\n return ((current / max) * 100).toFixed(2);\n}\n\n// Replace all occurrences of a string in a string\nexport const replaceAll = (input = '', find = '', replace = '') =>\n input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\\]/\\\\])/g, '\\\\$1'), 'g'), replace.toString());\n\n// Convert to title case\nexport const toTitleCase = (input = '') =>\n input.toString().replace(/\\w\\S*/g, (text) => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase());\n\n// Convert string to pascalCase\nexport function toPascalCase(input = '') {\n let string = input.toString();\n\n // Convert kebab case\n string = replaceAll(string, '-', ' ');\n\n // Convert snake case\n string = replaceAll(string, '_', ' ');\n\n // Convert to title case\n string = toTitleCase(string);\n\n // Convert to pascal case\n return replaceAll(string, ' ', '');\n}\n\n// Convert string to pascalCase\nexport function toCamelCase(input = '') {\n let string = input.toString();\n\n // Convert to pascal case\n string = toPascalCase(string);\n\n // Convert first character to lowercase\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\n// Remove HTML from a string\nexport function stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n}\n\n// Like outerHTML, but also works for DocumentFragment\nexport function getHTML(element) {\n const wrapper = document.createElement('div');\n wrapper.appendChild(element);\n return wrapper.innerHTML;\n}\n","// ==========================================================================\n// Plyr internationalization\n// ==========================================================================\n\nimport is from './is';\nimport { getDeep } from './objects';\nimport { replaceAll } from './strings';\n\n// Skip i18n for abbreviations and brand names\nconst resources = {\n pip: 'PIP',\n airplay: 'AirPlay',\n html5: 'HTML5',\n vimeo: 'Vimeo',\n youtube: 'YouTube',\n};\n\nconst i18n = {\n get(key = '', config = {}) {\n if (is.empty(key) || is.empty(config)) {\n return '';\n }\n\n let string = getDeep(config.i18n, key);\n\n if (is.empty(string)) {\n if (Object.keys(resources).includes(key)) {\n return resources[key];\n }\n\n return '';\n }\n\n const replace = {\n '{seektime}': config.seekTime,\n '{title}': config.title,\n };\n\n Object.entries(replace).forEach(([k, v]) => {\n string = replaceAll(string, k, v);\n });\n\n return string;\n },\n};\n\nexport default i18n;\n","// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport is from './utils/is';\nimport { extend } from './utils/objects';\n\nclass Storage {\n constructor(player) {\n this.enabled = player.config.storage.enabled;\n this.key = player.config.storage.key;\n }\n\n // Check for actual support (see if we can use it)\n static get supported() {\n try {\n if (!('localStorage' in window)) {\n return false;\n }\n\n const test = '___test';\n\n // Try to use it (it might be disabled, e.g. user is in private mode)\n // see: https://github.com/sampotts/plyr/issues/131\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n\n return true;\n } catch (_) {\n return false;\n }\n }\n\n get = (key) => {\n if (!Storage.supported || !this.enabled) {\n return null;\n }\n\n const store = window.localStorage.getItem(this.key);\n\n if (is.empty(store)) {\n return null;\n }\n\n const json = JSON.parse(store);\n\n return is.string(key) && key.length ? json[key] : json;\n };\n\n set = (object) => {\n // Bail if we don't have localStorage support or it's disabled\n if (!Storage.supported || !this.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!is.object(object)) {\n return;\n }\n\n // Get current storage\n let storage = this.get();\n\n // Default to empty object\n if (is.empty(storage)) {\n storage = {};\n }\n\n // Update the working copy of the values\n extend(storage, object);\n\n // Update storage\n try {\n window.localStorage.setItem(this.key, JSON.stringify(storage));\n } catch (_) {\n // Do nothing\n }\n };\n}\n\nexport default Storage;\n","// ==========================================================================\n// Fetch wrapper\n// Using XHR to avoid issues with older browsers\n// ==========================================================================\n\nexport default function fetch(url, responseType = 'text') {\n return new Promise((resolve, reject) => {\n try {\n const request = new XMLHttpRequest();\n\n // Check for CORS support\n if (!('withCredentials' in request)) {\n return;\n }\n\n request.addEventListener('load', () => {\n if (responseType === 'text') {\n try {\n resolve(JSON.parse(request.responseText));\n } catch (_) {\n resolve(request.responseText);\n }\n } else {\n resolve(request.response);\n }\n });\n\n request.addEventListener('error', () => {\n throw new Error(request.status);\n });\n\n request.open('GET', url, true);\n\n // Set the required response type\n request.responseType = responseType;\n\n request.send();\n } catch (error) {\n reject(error);\n }\n });\n}\n","// ==========================================================================\n// Sprite loader\n// ==========================================================================\n\nimport Storage from '../storage';\nimport fetch from './fetch';\nimport is from './is';\n\n// Load an external SVG sprite\nexport default function loadSprite(url, id) {\n if (!is.string(url)) {\n return;\n }\n\n const prefix = 'cache';\n const hasId = is.string(id);\n let isCached = false;\n const exists = () => document.getElementById(id) !== null;\n\n const update = (container, data) => {\n // eslint-disable-next-line no-param-reassign\n container.innerHTML = data;\n\n // Check again incase of race condition\n if (hasId && exists()) {\n return;\n }\n\n // Inject the SVG to the body\n document.body.insertAdjacentElement('afterbegin', container);\n };\n\n // Only load once if ID set\n if (!hasId || !exists()) {\n const useStorage = Storage.supported;\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (useStorage) {\n const cached = window.localStorage.getItem(`${prefix}-${id}`);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n update(container, data.content);\n }\n }\n\n // Get the sprite\n fetch(url)\n .then((result) => {\n if (is.empty(result)) {\n return;\n }\n\n if (useStorage) {\n try {\n window.localStorage.setItem(\n `${prefix}-${id}`,\n JSON.stringify({\n content: result,\n }),\n );\n } catch (_) {\n // Do nothing\n }\n }\n\n update(container, result);\n })\n .catch(() => {});\n }\n}\n","// ==========================================================================\n// Time utils\n// ==========================================================================\n\nimport is from './is';\n\n// Time helpers\nexport const getHours = (value) => Math.trunc((value / 60 / 60) % 60, 10);\nexport const getMinutes = (value) => Math.trunc((value / 60) % 60, 10);\nexport const getSeconds = (value) => Math.trunc(value % 60, 10);\n\n// Format time to UI friendly string\nexport function formatTime(time = 0, displayHours = false, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return formatTime(undefined, displayHours, inverted);\n }\n\n // Format time component to add leading zero\n const format = (value) => `0${value}`.slice(-2);\n // Breakdown to hours, mins, secs\n let hours = getHours(time);\n const mins = getMinutes(time);\n const secs = getSeconds(time);\n\n // Do we need to display hours?\n if (displayHours || hours > 0) {\n hours = `${hours}:`;\n } else {\n hours = '';\n }\n\n // Render\n return `${inverted && time > 0 ? '-' : ''}${hours}${format(mins)}:${format(secs)}`;\n}\n","// ==========================================================================\n// Plyr controls\n// TODO: This needs to be split into smaller files and cleaned up\n// ==========================================================================\n\nimport RangeTouch from 'rangetouch';\n\nimport captions from './captions';\nimport html5 from './html5';\nimport support from './support';\nimport { repaint, transitionEndEvent } from './utils/animation';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n getElement,\n getElements,\n hasClass,\n matches,\n removeElement,\n setAttributes,\n setFocus,\n toggleClass,\n toggleHidden,\n} from './utils/elements';\nimport { off, on } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadSprite from './utils/load-sprite';\nimport { extend } from './utils/objects';\nimport { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';\nimport { formatTime, getHours } from './utils/time';\n\n// TODO: Don't export a massive object - break down and create class\nconst controls = {\n // Get icon URL\n getIconUrl() {\n const url = new URL(this.config.iconUrl, window.location);\n const host = window.location.host ? window.location.host : window.top.location.host;\n const cors = url.host !== host || (browser.isIE && !window.svg4everybody);\n\n return {\n url: this.config.iconUrl,\n cors,\n };\n },\n\n // Find the UI controls\n findElements() {\n try {\n this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: getElements.call(this, this.config.selectors.buttons.play),\n pause: getElement.call(this, this.config.selectors.buttons.pause),\n restart: getElement.call(this, this.config.selectors.buttons.restart),\n rewind: getElement.call(this, this.config.selectors.buttons.rewind),\n fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),\n mute: getElement.call(this, this.config.selectors.buttons.mute),\n pip: getElement.call(this, this.config.selectors.buttons.pip),\n airplay: getElement.call(this, this.config.selectors.buttons.airplay),\n settings: getElement.call(this, this.config.selectors.buttons.settings),\n captions: getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: getElement.call(this, this.config.selectors.inputs.seek),\n volume: getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: getElement.call(this, this.config.selectors.display.buffer),\n currentTime: getElement.call(this, this.config.selectors.display.currentTime),\n duration: getElement.call(this, this.config.selectors.display.duration),\n };\n\n // Seek tooltip\n if (is.element(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);\n }\n\n return true;\n } catch (error) {\n // Log it\n this.debug.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Create <svg> icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.cors ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n // Create <svg>\n const icon = document.createElementNS(namespace, 'svg');\n setAttributes(\n icon,\n extend(attributes, {\n 'aria-hidden': 'true',\n focusable: 'false',\n }),\n );\n\n // Create the <use> to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // Set `href` attributes\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', path);\n }\n\n // Always set the older attribute even though it's \"deprecated\" (it'll be around for ages)\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n\n // Add <use> to <svg>\n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(key, attr = {}) {\n const text = i18n.get(key, this.config);\n const attributes = { ...attr, class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') };\n\n return createElement('span', attributes, text);\n },\n\n // Create a badge\n createBadge(text) {\n if (is.empty(text)) {\n return null;\n }\n\n const badge = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text,\n ),\n );\n\n return badge;\n },\n\n // Create a <button>\n createButton(buttonType, attr) {\n const attributes = extend({}, attr);\n let type = toCamelCase(buttonType);\n\n const props = {\n element: 'button',\n toggle: false,\n label: null,\n icon: null,\n labelPressed: null,\n iconPressed: null,\n };\n\n ['element', 'icon', 'label'].forEach((key) => {\n if (Object.keys(attributes).includes(key)) {\n props[key] = attributes[key];\n delete attributes[key];\n }\n });\n\n // Default to 'button' type to prevent form submission\n if (props.element === 'button' && !Object.keys(attributes).includes('type')) {\n attributes.type = 'button';\n }\n\n // Set class name\n if (Object.keys(attributes).includes('class')) {\n if (!attributes.class.split(' ').some((c) => c === this.config.classNames.control)) {\n extend(attributes, {\n class: `${attributes.class} ${this.config.classNames.control}`,\n });\n }\n } else {\n attributes.class = this.config.classNames.control;\n }\n\n // Large play button\n switch (buttonType) {\n case 'play':\n props.toggle = true;\n props.label = 'play';\n props.labelPressed = 'pause';\n props.icon = 'play';\n props.iconPressed = 'pause';\n break;\n\n case 'mute':\n props.toggle = true;\n props.label = 'mute';\n props.labelPressed = 'unmute';\n props.icon = 'volume';\n props.iconPressed = 'muted';\n break;\n\n case 'captions':\n props.toggle = true;\n props.label = 'enableCaptions';\n props.labelPressed = 'disableCaptions';\n props.icon = 'captions-off';\n props.iconPressed = 'captions-on';\n break;\n\n case 'fullscreen':\n props.toggle = true;\n props.label = 'enterFullscreen';\n props.labelPressed = 'exitFullscreen';\n props.icon = 'enter-fullscreen';\n props.iconPressed = 'exit-fullscreen';\n break;\n\n case 'play-large':\n attributes.class += ` ${this.config.classNames.control}--overlaid`;\n type = 'play';\n props.label = 'play';\n props.icon = 'play';\n break;\n\n default:\n if (is.empty(props.label)) {\n props.label = type;\n }\n if (is.empty(props.icon)) {\n props.icon = buttonType;\n }\n }\n\n const button = createElement(props.element);\n\n // Setup toggle icon and labels\n if (props.toggle) {\n // Icon\n button.appendChild(\n controls.createIcon.call(this, props.iconPressed, {\n class: 'icon--pressed',\n }),\n );\n button.appendChild(\n controls.createIcon.call(this, props.icon, {\n class: 'icon--not-pressed',\n }),\n );\n\n // Label/Tooltip\n button.appendChild(\n controls.createLabel.call(this, props.labelPressed, {\n class: 'label--pressed',\n }),\n );\n button.appendChild(\n controls.createLabel.call(this, props.label, {\n class: 'label--not-pressed',\n }),\n );\n } else {\n button.appendChild(controls.createIcon.call(this, props.icon));\n button.appendChild(controls.createLabel.call(this, props.label));\n }\n\n // Merge and set attributes\n extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));\n setAttributes(button, attributes);\n\n // We have multiple play buttons\n if (type === 'play') {\n if (!is.array(this.elements.buttons[type])) {\n this.elements.buttons[type] = [];\n }\n\n this.elements.buttons[type].push(button);\n } else {\n this.elements.buttons[type] = button;\n }\n\n return button;\n },\n\n // Create an <input type='range'>\n createRange(type, attributes) {\n // Seek input\n const input = createElement(\n 'input',\n extend(\n getAttributesFromSelector(this.config.selectors.inputs[type]),\n {\n type: 'range',\n min: 0,\n max: 100,\n step: 0.01,\n value: 0,\n autocomplete: 'off',\n // A11y fixes for https://github.com/sampotts/plyr/issues/905\n role: 'slider',\n 'aria-label': i18n.get(type, this.config),\n 'aria-valuemin': 0,\n 'aria-valuemax': 100,\n 'aria-valuenow': 0,\n },\n attributes,\n ),\n );\n\n this.elements.inputs[type] = input;\n\n // Set the fill for webkit now\n controls.updateRangeFill.call(this, input);\n\n // Improve support on touch devices\n RangeTouch.setup(input);\n\n return input;\n },\n\n // Create a <progress>\n createProgress(type, attributes) {\n const progress = createElement(\n 'progress',\n extend(\n getAttributesFromSelector(this.config.selectors.display[type]),\n {\n min: 0,\n max: 100,\n value: 0,\n role: 'progressbar',\n 'aria-hidden': true,\n },\n attributes,\n ),\n );\n\n // Create the label inside\n if (type !== 'volume') {\n progress.appendChild(createElement('span', null, '0'));\n\n const suffixKey = {\n played: 'played',\n buffer: 'buffered',\n }[type];\n const suffix = suffixKey ? i18n.get(suffixKey, this.config) : '';\n\n progress.innerText = `% ${suffix.toLowerCase()}`;\n }\n\n this.elements.display[type] = progress;\n\n return progress;\n },\n\n // Create time display\n createTime(type, attrs) {\n const attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);\n\n const container = createElement(\n 'div',\n extend(attributes, {\n class: `${attributes.class ? attributes.class : ''} ${this.config.classNames.display.time} `.trim(),\n 'aria-label': i18n.get(type, this.config),\n role: 'timer',\n }),\n '00:00',\n );\n\n // Reference for updates\n this.elements.display[type] = container;\n\n return container;\n },\n\n // Bind keyboard shortcuts for a menu item\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n bindMenuItemShortcuts(menuItem, type) {\n // Navigate through menus via arrow keys and space\n on.call(\n this,\n menuItem,\n 'keydown keyup',\n (event) => {\n // We only care about space and ⬆️ ⬇️️ ➡️\n if (![' ', 'ArrowUp', 'ArrowDown', 'ArrowRight'].includes(event.key)) {\n return;\n }\n\n // Prevent play / seek\n event.preventDefault();\n event.stopPropagation();\n\n // We're just here to prevent the keydown bubbling\n if (event.type === 'keydown') {\n return;\n }\n\n const isRadioButton = matches(menuItem, '[role=\"menuitemradio\"]');\n\n // Show the respective menu\n if (!isRadioButton && [' ', 'ArrowRight'].includes(event.key)) {\n controls.showMenuPanel.call(this, type, true);\n } else {\n let target;\n\n if (event.key !== ' ') {\n if (event.key === 'ArrowDown' || (isRadioButton && event.key === 'ArrowRight')) {\n target = menuItem.nextElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.firstElementChild;\n }\n } else {\n target = menuItem.previousElementSibling;\n\n if (!is.element(target)) {\n target = menuItem.parentNode.lastElementChild;\n }\n }\n\n setFocus.call(this, target, true);\n }\n }\n },\n false,\n );\n\n // Enter will fire a `click` event but we still need to manage focus\n // So we bind to keyup which fires after and set focus here\n on.call(this, menuItem, 'keyup', (event) => {\n if (event.key !== 'Return') return;\n\n controls.focusFirstMenuItem.call(this, null, true);\n });\n },\n\n // Create a settings menu item\n createMenuItem({ value, list, type, title, badge = null, checked = false }) {\n const attributes = getAttributesFromSelector(this.config.selectors.inputs[type]);\n\n const menuItem = createElement(\n 'button',\n extend(attributes, {\n type: 'button',\n role: 'menuitemradio',\n class: `${this.config.classNames.control} ${attributes.class ? attributes.class : ''}`.trim(),\n 'aria-checked': checked,\n value,\n }),\n );\n\n const flex = createElement('span');\n\n // We have to set as HTML incase of special characters\n flex.innerHTML = title;\n\n if (is.element(badge)) {\n flex.appendChild(badge);\n }\n\n menuItem.appendChild(flex);\n\n // Replicate radio button behavior\n Object.defineProperty(menuItem, 'checked', {\n enumerable: true,\n get() {\n return menuItem.getAttribute('aria-checked') === 'true';\n },\n set(check) {\n // Ensure exclusivity\n if (check) {\n Array.from(menuItem.parentNode.children)\n .filter((node) => matches(node, '[role=\"menuitemradio\"]'))\n .forEach((node) => node.setAttribute('aria-checked', 'false'));\n }\n\n menuItem.setAttribute('aria-checked', check ? 'true' : 'false');\n },\n });\n\n this.listeners.bind(\n menuItem,\n 'click keyup',\n (event) => {\n if (is.keyboardEvent(event) && event.key !== ' ') {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n menuItem.checked = true;\n\n switch (type) {\n case 'language':\n this.currentTrack = Number(value);\n break;\n\n case 'quality':\n this.quality = value;\n break;\n\n case 'speed':\n this.speed = parseFloat(value);\n break;\n\n default:\n break;\n }\n\n controls.showMenuPanel.call(this, 'home', is.keyboardEvent(event));\n },\n type,\n false,\n );\n\n controls.bindMenuItemShortcuts.call(this, menuItem, type);\n\n list.appendChild(menuItem);\n },\n\n // Format a time for display\n formatTime(time = 0, inverted = false) {\n // Bail if the value isn't a number\n if (!is.number(time)) {\n return time;\n }\n\n // Always display hours if duration is over an hour\n const forceHours = getHours(this.duration) > 0;\n\n return formatTime(time, forceHours, inverted);\n },\n\n // Update the displayed time\n updateTimeDisplay(target = null, time = 0, inverted = false) {\n // Bail if there's no element to display or the value isn't a number\n if (!is.element(target) || !is.number(time)) {\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n target.innerText = controls.formatTime(time, inverted);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (is.element(this.elements.inputs.volume)) {\n controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update mute state\n if (is.element(this.elements.buttons.mute)) {\n this.elements.buttons.mute.pressed = this.muted || this.volume === 0;\n }\n },\n\n // Update seek value and lower fill\n setRange(target, value = 0) {\n if (!is.element(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Update <progress> elements\n updateProgress(event) {\n if (!this.supported.ui || !is.event(event)) {\n return;\n }\n\n let value = 0;\n\n const setProgress = (target, input) => {\n const val = is.number(input) ? input : 0;\n const progress = is.element(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (is.element(progress)) {\n progress.value = val;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (is.element(label)) {\n label.childNodes[0].nodeValue = val;\n }\n }\n };\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n case 'seeked':\n value = getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n controls.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n setProgress(this.elements.display.buffer, this.buffered * 100);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // Get range from event if event passed\n const range = is.event(target) ? target.target : target;\n\n // Needs to be a valid <input type='range'>\n if (!is.element(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Set aria values for https://github.com/sampotts/plyr/issues/905\n if (matches(range, this.config.selectors.inputs.seek)) {\n range.setAttribute('aria-valuenow', this.currentTime);\n const currentTime = controls.formatTime(this.currentTime);\n const duration = controls.formatTime(this.duration);\n const format = i18n.get('seekLabel', this.config);\n range.setAttribute(\n 'aria-valuetext',\n format.replace('{currentTime}', currentTime).replace('{duration}', duration),\n );\n } else if (matches(range, this.config.selectors.inputs.volume)) {\n const percent = range.value * 100;\n range.setAttribute('aria-valuenow', percent);\n range.setAttribute('aria-valuetext', `${percent.toFixed(1)}%`);\n } else {\n range.setAttribute('aria-valuenow', range.value);\n }\n\n // WebKit only\n if (!browser.isWebKit && !browser.isIPadOS) {\n return;\n }\n\n // Set CSS custom property\n range.style.setProperty('--value', `${(range.value / range.max) * 100}%`);\n },\n\n // Update hover tooltip for seeking\n updateSeekTooltip(event) {\n // Bail if setting not true\n if (\n !this.config.tooltips.seek ||\n !is.element(this.elements.inputs.seek) ||\n !is.element(this.elements.display.seekTooltip) ||\n this.duration === 0\n ) {\n return;\n }\n\n const tipElement = this.elements.display.seekTooltip;\n const visible = `${this.config.classNames.tooltip}--visible`;\n const toggle = (show) => toggleClass(tipElement, visible, show);\n\n // Hide on touch\n if (this.touch) {\n toggle(false);\n return;\n }\n\n // Determine percentage, if already visible\n let percent = 0;\n const clientRect = this.elements.progress.getBoundingClientRect();\n\n if (is.event(event)) {\n percent = (100 / clientRect.width) * (event.pageX - clientRect.left);\n } else if (hasClass(tipElement, visible)) {\n percent = parseFloat(tipElement.style.left, 10);\n } else {\n return;\n }\n\n // Set bounds\n if (percent < 0) {\n percent = 0;\n } else if (percent > 100) {\n percent = 100;\n }\n\n const time = (this.duration / 100) * percent;\n\n // Display the time a click would seek to\n tipElement.innerText = controls.formatTime(time);\n\n // Get marker point for time\n const point = this.config.markers?.points?.find(({ time: t }) => t === Math.round(time));\n\n // Append the point label to the tooltip\n if (point) {\n tipElement.insertAdjacentHTML('afterbegin', `${point.label}<br>`);\n }\n\n // Set position\n tipElement.style.left = `${percent}%`;\n\n // Show/hide the tooltip\n // If the event is a moues in/out and percentage is inside bounds\n if (is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {\n toggle(event.type === 'mouseenter');\n }\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Only invert if only one time element is displayed and used for both duration and currentTime\n const invert = !is.element(this.elements.display.duration) && this.config.invertTime;\n\n // Duration\n controls.updateTimeDisplay.call(\n this,\n this.elements.display.currentTime,\n invert ? this.duration - this.currentTime : this.currentTime,\n invert,\n );\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n controls.updateProgress.call(this, event);\n },\n\n // Show the duration on metadataloaded or durationchange events\n durationUpdate() {\n // Bail if no UI or durationchange event triggered after playing/seek when invertTime is false\n if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {\n return;\n }\n\n // If duration is the 2**32 (shaka), Infinity (HLS), DASH-IF (Number.MAX_SAFE_INTEGER || Number.MAX_VALUE) indicating live we hide the currentTime and progressbar.\n // https://github.com/video-dev/hls.js/blob/5820d29d3c4c8a46e8b75f1e3afa3e68c1a9a2db/src/controller/buffer-controller.js#L415\n // https://github.com/google/shaka-player/blob/4d889054631f4e1cf0fbd80ddd2b71887c02e232/lib/media/streaming_engine.js#L1062\n // https://github.com/Dash-Industry-Forum/dash.js/blob/69859f51b969645b234666800d4cb596d89c602d/src/dash/models/DashManifestModel.js#L338\n if (this.duration >= 2 ** 32) {\n toggleHidden(this.elements.display.currentTime, true);\n toggleHidden(this.elements.progress, true);\n return;\n }\n\n // Update ARIA values\n if (is.element(this.elements.inputs.seek)) {\n this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);\n }\n\n // If there's a spot to display duration\n const hasDuration = is.element(this.elements.display.duration);\n\n // If there's only one time display, display duration there\n if (!hasDuration && this.config.displayDuration && this.paused) {\n controls.updateTimeDisplay.call(this, this.elements.display.currentTime, this.duration);\n }\n\n // If there's a duration element, update content\n if (hasDuration) {\n controls.updateTimeDisplay.call(this, this.elements.display.duration, this.duration);\n }\n\n if (this.config.markers.enabled) {\n controls.setMarkers.call(this);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Hide/show a tab\n toggleMenuButton(setting, toggle) {\n toggleHidden(this.elements.settings.buttons[setting], !toggle);\n },\n\n // Update the selected setting\n updateSetting(setting, container, input) {\n const pane = this.elements.settings.panels[setting];\n let value = null;\n let list = container;\n\n if (setting === 'captions') {\n value = this.currentTrack;\n } else {\n value = !is.empty(input) ? input : this[setting];\n\n // Get default\n if (is.empty(value)) {\n value = this.config[setting].default;\n }\n\n // Unsupported value\n if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {\n this.debug.warn(`Unsupported value of '${value}' for ${setting}`);\n return;\n }\n\n // Disabled value\n if (!this.config[setting].options.includes(value)) {\n this.debug.warn(`Disabled value of '${value}' for ${setting}`);\n return;\n }\n }\n\n // Get the list if we need to\n if (!is.element(list)) {\n list = pane && pane.querySelector('[role=\"menu\"]');\n }\n\n // If there's no list it means it's not been rendered...\n if (!is.element(list)) {\n return;\n }\n\n // Update the label\n const label = this.elements.settings.buttons[setting].querySelector(`.${this.config.classNames.menu.value}`);\n label.innerHTML = controls.getLabel.call(this, setting, value);\n\n // Find the radio option and check it\n const target = list && list.querySelector(`[value=\"${value}\"]`);\n\n if (is.element(target)) {\n target.checked = true;\n }\n },\n\n // Translate a value into a nice label\n getLabel(setting, value) {\n switch (setting) {\n case 'speed':\n return value === 1 ? i18n.get('normal', this.config) : `${value}×`;\n\n case 'quality':\n if (is.number(value)) {\n const label = i18n.get(`qualityLabel.${value}`, this.config);\n\n if (!label.length) {\n return `${value}p`;\n }\n\n return label;\n }\n\n return toTitleCase(value);\n\n case 'captions':\n return captions.getLabel.call(this);\n\n default:\n return null;\n }\n },\n\n // Set the quality menu\n setQualityMenu(options) {\n // Menu required\n if (!is.element(this.elements.settings.panels.quality)) {\n return;\n }\n\n const type = 'quality';\n const list = this.elements.settings.panels.quality.querySelector('[role=\"menu\"]');\n\n // Set options if passed and filter based on uniqueness and config\n if (is.array(options)) {\n this.options.quality = dedupe(options).filter((quality) => this.config.quality.options.includes(quality));\n }\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Get the badge HTML for HD, 4K etc\n const getBadge = (quality) => {\n const label = i18n.get(`qualityBadge.${quality}`, this.config);\n\n if (!label.length) {\n return null;\n }\n\n return controls.createBadge.call(this, label);\n };\n\n // Sort options by the config and then render options\n this.options.quality\n .sort((a, b) => {\n const sorting = this.config.quality.options;\n return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;\n })\n .forEach((quality) => {\n controls.createMenuItem.call(this, {\n value: quality,\n list,\n type,\n title: controls.getLabel.call(this, 'quality', quality),\n badge: getBadge(quality),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set the looping options\n /* setLoopMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.loop)) {\n return;\n }\n\n const options = ['start', 'end', 'all', 'reset'];\n const list = this.elements.settings.panels.loop.querySelector('[role=\"menu\"]');\n\n // Show the pane and tab\n toggleHidden(this.elements.settings.buttons.loop, false);\n toggleHidden(this.elements.settings.panels.loop, false);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.loop.options);\n controls.toggleMenuButton.call(this, 'loop', toggle);\n\n // Empty the menu\n emptyElement(list);\n\n options.forEach(option => {\n const item = createElement('li');\n\n const button = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {\n type: 'button',\n class: this.config.classNames.control,\n 'data-plyr-loop-action': option,\n }),\n i18n.get(option, this.config)\n );\n\n if (['start', 'end'].includes(option)) {\n const badge = controls.createBadge.call(this, '00:00');\n button.appendChild(badge);\n }\n\n item.appendChild(button);\n list.appendChild(item);\n });\n }, */\n\n // Get current selected caption language\n // TODO: rework this to user the getter in the API?\n\n // Set a list of available captions languages\n setCaptionsMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.captions)) {\n return;\n }\n\n // TODO: Captions or language? Currently it's mixed\n const type = 'captions';\n const list = this.elements.settings.panels.captions.querySelector('[role=\"menu\"]');\n const tracks = captions.getTracks.call(this);\n const toggle = Boolean(tracks.length);\n\n // Toggle the pane and tab\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If there's no captions, bail\n if (!toggle) {\n return;\n }\n\n // Generate options data\n const options = tracks.map((track, value) => ({\n value,\n checked: this.captions.toggled && this.currentTrack === value,\n title: captions.getLabel.call(this, track),\n badge: track.language && controls.createBadge.call(this, track.language.toUpperCase()),\n list,\n type: 'language',\n }));\n\n // Add the \"Disabled\" option to turn off captions\n options.unshift({\n value: -1,\n checked: !this.captions.toggled,\n title: i18n.get('disabled', this.config),\n list,\n type: 'language',\n });\n\n // Generate options\n options.forEach(controls.createMenuItem.bind(this));\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Set a list of available captions languages\n setSpeedMenu() {\n // Menu required\n if (!is.element(this.elements.settings.panels.speed)) {\n return;\n }\n\n const type = 'speed';\n const list = this.elements.settings.panels.speed.querySelector('[role=\"menu\"]');\n\n // Filter out invalid speeds\n this.options.speed = this.options.speed.filter((o) => o >= this.minimumSpeed && o <= this.maximumSpeed);\n\n // Toggle the pane and tab\n const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;\n controls.toggleMenuButton.call(this, type, toggle);\n\n // Empty the menu\n emptyElement(list);\n\n // Check if we need to toggle the parent\n controls.checkMenu.call(this);\n\n // If we're hiding, nothing more to do\n if (!toggle) {\n return;\n }\n\n // Create items\n this.options.speed.forEach((speed) => {\n controls.createMenuItem.call(this, {\n value: speed,\n list,\n type,\n title: controls.getLabel.call(this, 'speed', speed),\n });\n });\n\n controls.updateSetting.call(this, type, list);\n },\n\n // Check if we need to hide/show the settings menu\n checkMenu() {\n const { buttons } = this.elements.settings;\n const visible = !is.empty(buttons) && Object.values(buttons).some((button) => !button.hidden);\n\n toggleHidden(this.elements.settings.menu, !visible);\n },\n\n // Focus the first menu item in a given (or visible) menu\n focusFirstMenuItem(pane, focusVisible = false) {\n if (this.elements.settings.popup.hidden) {\n return;\n }\n\n let target = pane;\n\n if (!is.element(target)) {\n target = Object.values(this.elements.settings.panels).find((p) => !p.hidden);\n }\n\n const firstItem = target.querySelector('[role^=\"menuitem\"]');\n\n setFocus.call(this, firstItem, focusVisible);\n },\n\n // Show/hide menu\n toggleMenu(input) {\n const { popup } = this.elements.settings;\n const button = this.elements.buttons.settings;\n\n // Menu and button are required\n if (!is.element(popup) || !is.element(button)) {\n return;\n }\n\n // True toggle by default\n const { hidden } = popup;\n let show = hidden;\n\n if (is.boolean(input)) {\n show = input;\n } else if (is.keyboardEvent(input) && input.key === 'Escape') {\n show = false;\n } else if (is.event(input)) {\n // If Plyr is in a shadowDOM, the event target is set to the component, instead of the\n // Element in the shadowDOM. The path, if available, is complete.\n const target = is.function(input.composedPath) ? input.composedPath()[0] : input.target;\n const isMenuItem = popup.contains(target);\n\n // If the click was inside the menu or if the click\n // wasn't the button or menu item and we're trying to\n // show the menu (a doc click shouldn't show the menu)\n if (isMenuItem || (!isMenuItem && input.target !== button && show)) {\n return;\n }\n }\n\n // Set button attributes\n button.setAttribute('aria-expanded', show);\n\n // Show the actual popup\n toggleHidden(popup, !show);\n\n // Add class hook\n toggleClass(this.elements.container, this.config.classNames.menu.open, show);\n\n // Focus the first item if key interaction\n if (show && is.keyboardEvent(input)) {\n controls.focusFirstMenuItem.call(this, null, true);\n } else if (!show && !hidden) {\n // If closing, re-focus the button\n setFocus.call(this, button, is.keyboardEvent(input));\n }\n },\n\n // Get the natural size of a menu panel\n getMenuSize(tab) {\n const clone = tab.cloneNode(true);\n clone.style.position = 'absolute';\n clone.style.opacity = 0;\n clone.removeAttribute('hidden');\n\n // Append to parent so we get the \"real\" size\n tab.parentNode.appendChild(clone);\n\n // Get the sizes before we remove\n const width = clone.scrollWidth;\n const height = clone.scrollHeight;\n\n // Remove from the DOM\n removeElement(clone);\n\n return {\n width,\n height,\n };\n },\n\n // Show a panel in the menu\n showMenuPanel(type = '', focusVisible = false) {\n const target = this.elements.container.querySelector(`#plyr-settings-${this.id}-${type}`);\n\n // Nothing to show, bail\n if (!is.element(target)) {\n return;\n }\n\n // Hide all other panels\n const container = target.parentNode;\n const current = Array.from(container.children).find((node) => !node.hidden);\n\n // If we can do fancy animations, we'll animate the height/width\n if (support.transitions && !support.reducedMotion) {\n // Set the current width as a base\n container.style.width = `${current.scrollWidth}px`;\n container.style.height = `${current.scrollHeight}px`;\n\n // Get potential sizes\n const size = controls.getMenuSize.call(this, target);\n\n // Restore auto height/width\n const restore = (event) => {\n // We're only bothered about height and width on the container\n if (event.target !== container || !['width', 'height'].includes(event.propertyName)) {\n return;\n }\n\n // Revert back to auto\n container.style.width = '';\n container.style.height = '';\n\n // Only listen once\n off.call(this, container, transitionEndEvent, restore);\n };\n\n // Listen for the transition finishing and restore auto height/width\n on.call(this, container, transitionEndEvent, restore);\n\n // Set dimensions to target\n container.style.width = `${size.width}px`;\n container.style.height = `${size.height}px`;\n }\n\n // Set attributes on current tab\n toggleHidden(current, true);\n\n // Set attributes on target\n toggleHidden(target, false);\n\n // Focus the first item\n controls.focusFirstMenuItem.call(this, target, focusVisible);\n },\n\n // Set the download URL\n setDownloadUrl() {\n const button = this.elements.buttons.download;\n\n // Bail if no button\n if (!is.element(button)) {\n return;\n }\n\n // Set attribute\n button.setAttribute('href', this.download);\n },\n\n // Build the default HTML\n create(data) {\n const {\n bindMenuItemShortcuts,\n createButton,\n createProgress,\n createRange,\n createTime,\n setQualityMenu,\n setSpeedMenu,\n showMenuPanel,\n } = controls;\n this.elements.controls = null;\n\n // Larger overlaid play button\n if (is.array(this.config.controls) && this.config.controls.includes('play-large')) {\n this.elements.container.appendChild(createButton.call(this, 'play-large'));\n }\n\n // Create the container\n const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));\n this.elements.controls = container;\n\n // Default item attributes\n const defaultAttributes = { class: 'plyr__controls__item' };\n\n // Loop through controls in order\n dedupe(is.array(this.config.controls) ? this.config.controls : []).forEach((control) => {\n // Restart button\n if (control === 'restart') {\n container.appendChild(createButton.call(this, 'restart', defaultAttributes));\n }\n\n // Rewind button\n if (control === 'rewind') {\n container.appendChild(createButton.call(this, 'rewind', defaultAttributes));\n }\n\n // Play/Pause button\n if (control === 'play') {\n container.appendChild(createButton.call(this, 'play', defaultAttributes));\n }\n\n // Fast forward button\n if (control === 'fast-forward') {\n container.appendChild(createButton.call(this, 'fast-forward', defaultAttributes));\n }\n\n // Progress\n if (control === 'progress') {\n const progressContainer = createElement('div', {\n class: `${defaultAttributes.class} plyr__progress__container`,\n });\n\n const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));\n\n // Seek range slider\n progress.appendChild(\n createRange.call(this, 'seek', {\n id: `plyr-seek-${data.id}`,\n }),\n );\n\n // Buffer progress\n progress.appendChild(createProgress.call(this, 'buffer'));\n\n // TODO: Add loop display indicator\n\n // Seek tooltip\n if (this.config.tooltips.seek) {\n const tooltip = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '00:00',\n );\n\n progress.appendChild(tooltip);\n this.elements.display.seekTooltip = tooltip;\n }\n\n this.elements.progress = progress;\n progressContainer.appendChild(this.elements.progress);\n container.appendChild(progressContainer);\n }\n\n // Media current time display\n if (control === 'current-time') {\n container.appendChild(createTime.call(this, 'currentTime', defaultAttributes));\n }\n\n // Media duration display\n if (control === 'duration') {\n container.appendChild(createTime.call(this, 'duration', defaultAttributes));\n }\n\n // Volume controls\n if (control === 'mute' || control === 'volume') {\n let { volume } = this.elements;\n\n // Create the volume container if needed\n if (!is.element(volume) || !container.contains(volume)) {\n volume = createElement(\n 'div',\n extend({}, defaultAttributes, {\n class: `${defaultAttributes.class} plyr__volume`.trim(),\n }),\n );\n\n this.elements.volume = volume;\n\n container.appendChild(volume);\n }\n\n // Toggle mute button\n if (control === 'mute') {\n volume.appendChild(createButton.call(this, 'mute'));\n }\n\n // Volume range control\n // Ignored on iOS as it's handled globally\n // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html\n if (control === 'volume' && !browser.isIos && !browser.isIPadOS) {\n // Set the attributes\n const attributes = {\n max: 1,\n step: 0.05,\n value: this.config.volume,\n };\n\n // Create the volume range slider\n volume.appendChild(\n createRange.call(\n this,\n 'volume',\n extend(attributes, {\n id: `plyr-volume-${data.id}`,\n }),\n ),\n );\n }\n }\n\n // Toggle captions button\n if (control === 'captions') {\n container.appendChild(createButton.call(this, 'captions', defaultAttributes));\n }\n\n // Settings button / menu\n if (control === 'settings' && !is.empty(this.config.settings)) {\n const wrapper = createElement(\n 'div',\n extend({}, defaultAttributes, {\n class: `${defaultAttributes.class} plyr__menu`.trim(),\n hidden: '',\n }),\n );\n\n wrapper.appendChild(\n createButton.call(this, 'settings', {\n 'aria-haspopup': true,\n 'aria-controls': `plyr-settings-${data.id}`,\n 'aria-expanded': false,\n }),\n );\n\n const popup = createElement('div', {\n class: 'plyr__menu__container',\n id: `plyr-settings-${data.id}`,\n hidden: '',\n });\n\n const inner = createElement('div');\n\n const home = createElement('div', {\n id: `plyr-settings-${data.id}-home`,\n });\n\n // Create the menu\n const menu = createElement('div', {\n role: 'menu',\n });\n\n home.appendChild(menu);\n inner.appendChild(home);\n this.elements.settings.panels.home = home;\n\n // Build the menu items\n this.config.settings.forEach((type) => {\n // TODO: bundle this with the createMenuItem helper and bindings\n const menuItem = createElement(\n 'button',\n extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,\n role: 'menuitem',\n 'aria-haspopup': true,\n hidden: '',\n }),\n );\n\n // Bind menu shortcuts for keyboard users\n bindMenuItemShortcuts.call(this, menuItem, type);\n\n // Show menu on click\n on.call(this, menuItem, 'click', () => {\n showMenuPanel.call(this, type, false);\n });\n\n const flex = createElement('span', null, i18n.get(type, this.config));\n\n const value = createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n // Speed contains HTML entities\n value.innerHTML = data[type];\n\n flex.appendChild(value);\n menuItem.appendChild(flex);\n menu.appendChild(menuItem);\n\n // Build the panes\n const pane = createElement('div', {\n id: `plyr-settings-${data.id}-${type}`,\n hidden: '',\n });\n\n // Back button\n const backButton = createElement('button', {\n type: 'button',\n class: `${this.config.classNames.control} ${this.config.classNames.control}--back`,\n });\n\n // Visible label\n backButton.appendChild(\n createElement(\n 'span',\n {\n 'aria-hidden': true,\n },\n i18n.get(type, this.config),\n ),\n );\n\n // Screen reader label\n backButton.appendChild(\n createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n i18n.get('menuBack', this.config),\n ),\n );\n\n // Go back via keyboard\n on.call(\n this,\n pane,\n 'keydown',\n (event) => {\n if (event.key !== 'ArrowLeft') return;\n\n // Prevent seek\n event.preventDefault();\n event.stopPropagation();\n\n // Show the respective menu\n showMenuPanel.call(this, 'home', true);\n },\n false,\n );\n\n // Go back via button click\n on.call(this, backButton, 'click', () => {\n showMenuPanel.call(this, 'home', false);\n });\n\n // Add to pane\n pane.appendChild(backButton);\n\n // Menu\n pane.appendChild(\n createElement('div', {\n role: 'menu',\n }),\n );\n\n inner.appendChild(pane);\n\n this.elements.settings.buttons[type] = menuItem;\n this.elements.settings.panels[type] = pane;\n });\n\n popup.appendChild(inner);\n wrapper.appendChild(popup);\n container.appendChild(wrapper);\n\n this.elements.settings.popup = popup;\n this.elements.settings.menu = wrapper;\n }\n\n // Picture in picture button\n if (control === 'pip' && support.pip) {\n container.appendChild(createButton.call(this, 'pip', defaultAttributes));\n }\n\n // Airplay button\n if (control === 'airplay' && support.airplay) {\n container.appendChild(createButton.call(this, 'airplay', defaultAttributes));\n }\n\n // Download button\n if (control === 'download') {\n const attributes = extend({}, defaultAttributes, {\n element: 'a',\n href: this.download,\n target: '_blank',\n });\n\n // Set download attribute for HTML5 only\n if (this.isHTML5) {\n attributes.download = '';\n }\n\n const { download } = this.config.urls;\n\n if (!is.url(download) && this.isEmbed) {\n extend(attributes, {\n icon: `logo-${this.provider}`,\n label: this.provider,\n });\n }\n\n container.appendChild(createButton.call(this, 'download', attributes));\n }\n\n // Toggle fullscreen button\n if (control === 'fullscreen') {\n container.appendChild(createButton.call(this, 'fullscreen', defaultAttributes));\n }\n });\n\n // Set available quality levels\n if (this.isHTML5) {\n setQualityMenu.call(this, html5.getQualityOptions.call(this));\n }\n\n setSpeedMenu.call(this);\n\n return container;\n },\n\n // Insert controls\n inject() {\n // Sprite\n if (this.config.loadSprite) {\n const icon = controls.getIconUrl.call(this);\n\n // Only load external sprite using AJAX\n if (icon.cors) {\n loadSprite(icon.url, 'sprite-plyr');\n }\n }\n\n // Create a unique ID\n this.id = Math.floor(Math.random() * 10000);\n\n // Null by default\n let container = null;\n this.elements.controls = null;\n\n // Set template properties\n const props = {\n id: this.id,\n seektime: this.config.seekTime,\n title: this.config.title,\n };\n let update = true;\n\n // If function, run it and use output\n if (is.function(this.config.controls)) {\n this.config.controls = this.config.controls.call(this, props);\n }\n\n // Convert falsy controls to empty array (primarily for empty strings)\n if (!this.config.controls) {\n this.config.controls = [];\n }\n\n if (is.element(this.config.controls) || is.string(this.config.controls)) {\n // HTMLElement or Non-empty string passed as the option\n container = this.config.controls;\n } else {\n // Create controls\n container = controls.create.call(this, {\n id: this.id,\n seektime: this.config.seekTime,\n speed: this.speed,\n quality: this.quality,\n captions: captions.getLabel.call(this),\n // TODO: Looping\n // loop: 'None',\n });\n update = false;\n }\n\n // Replace props with their value\n const replace = (input) => {\n let result = input;\n\n Object.entries(props).forEach(([key, value]) => {\n result = replaceAll(result, `{${key}}`, value);\n });\n\n return result;\n };\n\n // Update markup\n if (update) {\n if (is.string(this.config.controls)) {\n container = replace(container);\n }\n }\n\n // Controls container\n let target;\n\n // Inject to custom location\n if (is.string(this.config.selectors.controls.container)) {\n target = document.querySelector(this.config.selectors.controls.container);\n }\n\n // Inject into the container by default\n if (!is.element(target)) {\n target = this.elements.container;\n }\n\n // Inject controls HTML (needs to be before captions, hence \"afterbegin\")\n const insertMethod = is.element(container) ? 'insertAdjacentElement' : 'insertAdjacentHTML';\n target[insertMethod]('afterbegin', container);\n\n // Find the elements if need be\n if (!is.element(this.elements.controls)) {\n controls.findElements.call(this);\n }\n\n // Add pressed property to buttons\n if (!is.empty(this.elements.buttons)) {\n const addProperty = (button) => {\n const className = this.config.classNames.controlPressed;\n button.setAttribute('aria-pressed', 'false');\n\n Object.defineProperty(button, 'pressed', {\n configurable: true,\n enumerable: true,\n get() {\n return hasClass(button, className);\n },\n set(pressed = false) {\n toggleClass(button, className, pressed);\n button.setAttribute('aria-pressed', pressed ? 'true' : 'false');\n },\n });\n };\n\n // Toggle classname when pressed property is set\n Object.values(this.elements.buttons)\n .filter(Boolean)\n .forEach((button) => {\n if (is.array(button) || is.nodeList(button)) {\n Array.from(button).filter(Boolean).forEach(addProperty);\n } else {\n addProperty(button);\n }\n });\n }\n\n // Edge sometimes doesn't finish the paint so force a repaint\n if (browser.isEdge) {\n repaint(target);\n }\n\n // Setup tooltips\n if (this.config.tooltips.controls) {\n const { classNames, selectors } = this.config;\n const selector = `${selectors.controls.wrapper} ${selectors.labels} .${classNames.hidden}`;\n const labels = getElements.call(this, selector);\n\n Array.from(labels).forEach((label) => {\n toggleClass(label, this.config.classNames.hidden, false);\n toggleClass(label, this.config.classNames.tooltip, true);\n });\n }\n },\n\n // Set media metadata\n setMediaMetadata() {\n try {\n if ('mediaSession' in navigator) {\n navigator.mediaSession.metadata = new window.MediaMetadata({\n title: this.config.mediaMetadata.title,\n artist: this.config.mediaMetadata.artist,\n album: this.config.mediaMetadata.album,\n artwork: this.config.mediaMetadata.artwork,\n });\n }\n } catch (_) {\n // Do nothing\n }\n },\n\n // Add markers\n setMarkers() {\n if (!this.duration || this.elements.markers) return;\n\n // Get valid points\n const points = this.config.markers?.points?.filter(({ time }) => time > 0 && time < this.duration);\n if (!points?.length) return;\n\n const containerFragment = document.createDocumentFragment();\n const pointsFragment = document.createDocumentFragment();\n let tipElement = null;\n const tipVisible = `${this.config.classNames.tooltip}--visible`;\n const toggleTip = (show) => toggleClass(tipElement, tipVisible, show);\n\n // Inject markers to progress container\n points.forEach((point) => {\n const markerElement = createElement(\n 'span',\n {\n class: this.config.classNames.marker,\n },\n '',\n );\n\n const left = `${(point.time / this.duration) * 100}%`;\n\n if (tipElement) {\n // Show on hover\n markerElement.addEventListener('mouseenter', () => {\n if (point.label) return;\n tipElement.style.left = left;\n tipElement.innerHTML = point.label;\n toggleTip(true);\n });\n\n // Hide on leave\n markerElement.addEventListener('mouseleave', () => {\n toggleTip(false);\n });\n }\n\n markerElement.addEventListener('click', () => {\n this.currentTime = point.time;\n });\n\n markerElement.style.left = left;\n pointsFragment.appendChild(markerElement);\n });\n\n containerFragment.appendChild(pointsFragment);\n\n // Inject a tooltip if needed\n if (!this.config.tooltips.seek) {\n tipElement = createElement(\n 'span',\n {\n class: this.config.classNames.tooltip,\n },\n '',\n );\n\n containerFragment.appendChild(tipElement);\n }\n\n this.elements.markers = {\n points: pointsFragment,\n tip: tipElement,\n };\n\n this.elements.progress.appendChild(containerFragment);\n },\n};\n\nexport default controls;\n","// ==========================================================================\n// URL utils\n// ==========================================================================\n\nimport is from './is';\n\n/**\n * Parse a string to a URL object\n * @param {String} input - the URL to be parsed\n * @param {Boolean} safe - failsafe parsing\n */\nexport function parseUrl(input, safe = true) {\n let url = input;\n\n if (safe) {\n const parser = document.createElement('a');\n parser.href = url;\n url = parser.href;\n }\n\n try {\n return new URL(url);\n } catch (_) {\n return null;\n }\n}\n\n// Convert object to URLSearchParams\nexport function buildUrlParams(input) {\n const params = new URLSearchParams();\n\n if (is.object(input)) {\n Object.entries(input).forEach(([key, value]) => {\n params.set(key, value);\n });\n }\n\n return params;\n}\n","// ==========================================================================\n// Plyr Captions\n// TODO: Create as class\n// ==========================================================================\n\nimport controls from './controls';\nimport support from './support';\nimport { dedupe } from './utils/arrays';\nimport browser from './utils/browser';\nimport {\n createElement,\n emptyElement,\n getAttributesFromSelector,\n insertAfter,\n removeElement,\n toggleClass,\n} from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport fetch from './utils/fetch';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport { getHTML } from './utils/strings';\nimport { parseUrl } from './utils/urls';\n\nconst captions = {\n // Setup captions\n setup() {\n // Requires UI support\n if (!this.supported.ui) {\n return;\n }\n\n // Only Vimeo and HTML5 video supported at this point\n if (!this.isVideo || this.isYouTube || (this.isHTML5 && !support.textTracks)) {\n // Clear menu and hide\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n\n return;\n }\n\n // Inject the container\n if (!is.element(this.elements.captions)) {\n this.elements.captions = createElement('div', getAttributesFromSelector(this.config.selectors.captions));\n this.elements.captions.setAttribute('dir', 'auto');\n\n insertAfter(this.elements.captions, this.elements.wrapper);\n }\n\n // Fix IE captions if CORS is used\n // Fetch captions and inject as blobs instead (data URIs not supported!)\n if (browser.isIE && window.URL) {\n const elements = this.media.querySelectorAll('track');\n\n Array.from(elements).forEach((track) => {\n const src = track.getAttribute('src');\n const url = parseUrl(src);\n\n if (\n url !== null &&\n url.hostname !== window.location.href.hostname &&\n ['http:', 'https:'].includes(url.protocol)\n ) {\n fetch(src, 'blob')\n .then((blob) => {\n track.setAttribute('src', window.URL.createObjectURL(blob));\n })\n .catch(() => {\n removeElement(track);\n });\n }\n });\n }\n\n // Get and set initial data\n // The \"preferred\" options are not realized unless / until the wanted language has a match\n // * languages: Array of user's browser languages.\n // * language: The language preferred by user settings or config\n // * active: The state preferred by user settings or config\n // * toggled: The real captions state\n\n const browserLanguages = navigator.languages || [navigator.language || navigator.userLanguage || 'en'];\n const languages = dedupe(browserLanguages.map((language) => language.split('-')[0]));\n let language = (this.storage.get('language') || this.config.captions.language || 'auto').toLowerCase();\n\n // Use first browser language when language is 'auto'\n if (language === 'auto') {\n [language] = languages;\n }\n\n let active = this.storage.get('captions');\n if (!is.boolean(active)) {\n ({ active } = this.config.captions);\n }\n\n Object.assign(this.captions, {\n toggled: false,\n active,\n language,\n languages,\n });\n\n // Watch changes to textTracks and update captions menu\n if (this.isHTML5) {\n const trackEvents = this.config.captions.update ? 'addtrack removetrack' : 'removetrack';\n on.call(this, this.media.textTracks, trackEvents, captions.update.bind(this));\n }\n\n // Update available languages in list next tick (the event must not be triggered before the listeners)\n setTimeout(captions.update.bind(this), 0);\n },\n\n // Update available language options in settings based on tracks\n update() {\n const tracks = captions.getTracks.call(this, true);\n // Get the wanted language\n const { active, language, meta, currentTrackNode } = this.captions;\n const languageExists = Boolean(tracks.find((track) => track.language === language));\n\n // Handle tracks (add event listener and \"pseudo\"-default)\n if (this.isHTML5 && this.isVideo) {\n tracks\n .filter((track) => !meta.get(track))\n .forEach((track) => {\n this.debug.log('Track added', track);\n\n // Attempt to store if the original dom element was \"default\"\n meta.set(track, {\n default: track.mode === 'showing',\n });\n\n // Turn off native caption rendering to avoid double captions\n // Note: mode='hidden' forces a track to download. To ensure every track\n // isn't downloaded at once, only 'showing' tracks should be reassigned\n // eslint-disable-next-line no-param-reassign\n if (track.mode === 'showing') {\n // eslint-disable-next-line no-param-reassign\n track.mode = 'hidden';\n }\n\n // Add event listener for cue changes\n on.call(this, track, 'cuechange', () => captions.updateCues.call(this));\n });\n }\n\n // Update language first time it matches, or if the previous matching track was removed\n if ((languageExists && this.language !== language) || !tracks.includes(currentTrackNode)) {\n captions.setLanguage.call(this, language);\n captions.toggle.call(this, active && languageExists);\n }\n\n // Enable or disable captions based on track length\n if (this.elements) {\n toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is.empty(tracks));\n }\n\n // Update available languages in list\n if (\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n this.config.settings.includes('captions')\n ) {\n controls.setCaptionsMenu.call(this);\n }\n },\n\n // Toggle captions display\n // Used internally for the toggleCaptions method, with the passive option forced to false\n toggle(input, passive = true) {\n // If there's no full support\n if (!this.supported.ui) {\n return;\n }\n\n const { toggled } = this.captions; // Current state\n const activeClass = this.config.classNames.captions.active;\n // Get the next state\n // If the method is called without parameter, toggle based on current value\n const active = is.nullOrUndefined(input) ? !toggled : input;\n\n // Update state and trigger event\n if (active !== toggled) {\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.active = active;\n this.storage.set({ captions: active });\n }\n\n // Force language if the call isn't passive and there is no matching language to toggle to\n if (!this.language && active && !passive) {\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [this.captions.language, ...this.captions.languages], true);\n\n // Override user preferences to avoid switching languages if a matching track is added\n this.captions.language = track.language;\n\n // Set caption, but don't store in localStorage as user preference\n captions.set.call(this, tracks.indexOf(track));\n return;\n }\n\n // Toggle button if it's enabled\n if (this.elements.buttons.captions) {\n this.elements.buttons.captions.pressed = active;\n }\n\n // Add class hook\n toggleClass(this.elements.container, activeClass, active);\n\n this.captions.toggled = active;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // Trigger event (not used internally)\n triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');\n }\n\n // Wait for the call stack to clear before setting mode='hidden'\n // on the active track - forcing the browser to download it\n setTimeout(() => {\n if (active && this.captions.toggled) {\n this.captions.currentTrackNode.mode = 'hidden';\n }\n });\n },\n\n // Set captions by track index\n // Used internally for the currentTrack setter with the passive option forced to false\n set(index, passive = true) {\n const tracks = captions.getTracks.call(this);\n\n // Disable captions if setting to -1\n if (index === -1) {\n captions.toggle.call(this, false, passive);\n return;\n }\n\n if (!is.number(index)) {\n this.debug.warn('Invalid caption argument', index);\n return;\n }\n\n if (!(index in tracks)) {\n this.debug.warn('Track not found', index);\n return;\n }\n\n if (this.captions.currentTrack !== index) {\n this.captions.currentTrack = index;\n const track = tracks[index];\n const { language } = track || {};\n\n // Store reference to node for invalidation on remove\n this.captions.currentTrackNode = track;\n\n // Update settings menu\n controls.updateSetting.call(this, 'captions');\n\n // When passive, don't override user preferences\n if (!passive) {\n this.captions.language = language;\n this.storage.set({ language });\n }\n\n // Handle Vimeo captions\n if (this.isVimeo) {\n this.embed.enableTextTrack(language);\n }\n\n // Trigger event\n triggerEvent.call(this, this.media, 'languagechange');\n }\n\n // Show captions\n captions.toggle.call(this, true, passive);\n\n if (this.isHTML5 && this.isVideo) {\n // If we change the active track while a cue is already displayed we need to update it\n captions.updateCues.call(this);\n }\n },\n\n // Set captions by language\n // Used internally for the language setter with the passive option forced to false\n setLanguage(input, passive = true) {\n if (!is.string(input)) {\n this.debug.warn('Invalid language argument', input);\n return;\n }\n // Normalize\n const language = input.toLowerCase();\n this.captions.language = language;\n\n // Set currentTrack\n const tracks = captions.getTracks.call(this);\n const track = captions.findTrack.call(this, [language]);\n captions.set.call(this, tracks.indexOf(track), passive);\n },\n\n // Get current valid caption tracks\n // If update is false it will also ignore tracks without metadata\n // This is used to \"freeze\" the language options when captions.update is false\n getTracks(update = false) {\n // Handle media or textTracks missing or null\n const tracks = Array.from((this.media || {}).textTracks || []);\n // For HTML5, use cache instead of current tracks when it exists (if captions.update is false)\n // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)\n return tracks\n .filter((track) => !this.isHTML5 || update || this.captions.meta.has(track))\n .filter((track) => ['captions', 'subtitles'].includes(track.kind));\n },\n\n // Match tracks based on languages and get the first\n findTrack(languages, force = false) {\n const tracks = captions.getTracks.call(this);\n const sortIsDefault = (track) => Number((this.captions.meta.get(track) || {}).default);\n const sorted = Array.from(tracks).sort((a, b) => sortIsDefault(b) - sortIsDefault(a));\n let track;\n\n languages.every((language) => {\n track = sorted.find((t) => t.language === language);\n return !track; // Break iteration if there is a match\n });\n\n // If no match is found but is required, get first\n return track || (force ? sorted[0] : undefined);\n },\n\n // Get the current track\n getCurrentTrack() {\n return captions.getTracks.call(this)[this.currentTrack];\n },\n\n // Get UI label for track\n getLabel(track) {\n let currentTrack = track;\n\n if (!is.track(currentTrack) && support.textTracks && this.captions.toggled) {\n currentTrack = captions.getCurrentTrack.call(this);\n }\n\n if (is.track(currentTrack)) {\n if (!is.empty(currentTrack.label)) {\n return currentTrack.label;\n }\n\n if (!is.empty(currentTrack.language)) {\n return track.language.toUpperCase();\n }\n\n return i18n.get('enabled', this.config);\n }\n\n return i18n.get('disabled', this.config);\n },\n\n // Update captions using current track's active cues\n // Also optional array argument in case there isn't any track (ex: vimeo)\n updateCues(input) {\n // Requires UI\n if (!this.supported.ui) {\n return;\n }\n\n if (!is.element(this.elements.captions)) {\n this.debug.warn('No captions element to render to');\n return;\n }\n\n // Only accept array or empty input\n if (!is.nullOrUndefined(input) && !Array.isArray(input)) {\n this.debug.warn('updateCues: Invalid input', input);\n return;\n }\n\n let cues = input;\n\n // Get cues from track\n if (!cues) {\n const track = captions.getCurrentTrack.call(this);\n\n cues = Array.from((track || {}).activeCues || [])\n .map((cue) => cue.getCueAsHTML())\n .map(getHTML);\n }\n\n // Set new caption text\n const content = cues.map((cueText) => cueText.trim()).join('\\n');\n const changed = content !== this.elements.captions.innerHTML;\n\n if (changed) {\n // Empty the container and create a new child element\n emptyElement(this.elements.captions);\n const caption = createElement('span', getAttributesFromSelector(this.config.selectors.caption));\n caption.innerHTML = content;\n this.elements.captions.appendChild(caption);\n\n // Trigger event\n triggerEvent.call(this, this.media, 'cuechange');\n }\n },\n};\n\nexport default captions;\n","// ==========================================================================\n// Plyr default config\n// ==========================================================================\n\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Only allow one media playing at once (vimeo only)\n autopause: true,\n\n // Allow inline playback on iOS\n playsinline: true,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration on load in the current time position\n // If you have opted to display both duration and currentTime, this is ignored\n displayDuration: true,\n\n // Invert the current time to be a countdown\n invertTime: true,\n\n // Clicking the currentTime inverts it's value to show time left rather than elapsed\n toggleInvert: true,\n\n // Force an aspect ratio\n // The format must be `'w:h'` (e.g. `'16:9'`)\n ratio: null,\n\n // Click video container to play/pause\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Reset to start when playback ended\n resetOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/3.7.8/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 576,\n // The options to display in the UI, if available for the source media\n options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],\n forced: false,\n onChange: null,\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: 'auto',\n // Listen to new tracks added after Plyr is initialized.\n // This is needed for streaming captions, but may result in unselectable options\n update: false,\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback using full viewport/window\n iosNative: false, // Use the native fullscreen in iOS (disables custom controls)\n // Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode\n // Non-ancestors of the player element will be ignored\n // container: null, // defaults to the player element\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n // 'restart',\n // 'rewind',\n 'play',\n // 'fast-forward',\n 'progress',\n 'current-time',\n // 'duration',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n // 'download',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime}s',\n play: 'Play',\n pause: 'Pause',\n fastForward: 'Forward {seektime}s',\n seek: 'Seek',\n seekLabel: '{currentTime} of {duration}',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n mute: 'Mute',\n unmute: 'Unmute',\n enableCaptions: 'Enable captions',\n disableCaptions: 'Disable captions',\n download: 'Download',\n enterFullscreen: 'Enter fullscreen',\n exitFullscreen: 'Exit fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n pip: 'PIP',\n menuBack: 'Go back to previous menu',\n speed: 'Speed',\n normal: 'Normal',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n disabled: 'Disabled',\n enabled: 'Enabled',\n advertisement: 'Ad',\n qualityBadge: {\n 2160: '4K',\n 1440: 'HD',\n 1080: 'HD',\n 720: 'HD',\n 576: 'SD',\n 480: 'SD',\n },\n },\n\n // URLs\n urls: {\n download: null,\n vimeo: {\n sdk: 'https://player.vimeo.com/api/player.js',\n iframe: 'https://player.vimeo.com/video/{0}?{1}',\n api: 'https://vimeo.com/api/oembed.json?url={0}',\n },\n youtube: {\n sdk: 'https://www.youtube.com/iframe_api',\n api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}',\n },\n googleIMA: {\n sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n fastForward: null,\n mute: null,\n volume: null,\n captions: null,\n download: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'download',\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n\n // Quality\n 'qualitychange',\n\n // Ads\n 'adsloaded',\n 'adscontentpause',\n 'adscontentresume',\n 'adstarted',\n 'adsmidpoint',\n 'adscomplete',\n 'adsallcomplete',\n 'adsimpression',\n 'adsclick',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n fastForward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n download: '[data-plyr=\"download\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress__buffer',\n loop: '.plyr__progress__loop', // Used later\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n caption: '.plyr__caption',\n },\n\n // Class hooks added to the player in different states\n classNames: {\n type: 'plyr--{0}',\n provider: 'plyr--{0}',\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n videoFixedRatio: 'plyr__video-wrapper--fixed-ratio',\n embedContainer: 'plyr__video-embed__container',\n poster: 'plyr__poster',\n posterEnabled: 'plyr__poster-enabled',\n ads: 'plyr__ads',\n control: 'plyr__control',\n controlPressed: 'plyr__control--pressed',\n playing: 'plyr--playing',\n paused: 'plyr--paused',\n stopped: 'plyr--stopped',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n cues: 'plyr__cues',\n marker: 'plyr__progress__marker',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n noTransition: 'plyr--no-transition',\n display: {\n time: 'plyr__time',\n },\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n open: 'plyr--menu-open',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n previewThumbnails: {\n // Tooltip thumbs\n thumbContainer: 'plyr__preview-thumb',\n thumbContainerShown: 'plyr__preview-thumb--is-shown',\n imageContainer: 'plyr__preview-thumb__image-container',\n timeContainer: 'plyr__preview-thumb__time-container',\n // Scrubbing\n scrubbingContainer: 'plyr__preview-scrubbing',\n scrubbingContainerShown: 'plyr__preview-scrubbing--is-shown',\n },\n },\n\n // Embed attributes\n attributes: {\n embed: {\n provider: 'data-plyr-provider',\n id: 'data-plyr-embed-id',\n hash: 'data-plyr-embed-hash',\n },\n },\n\n // Advertisements plugin\n // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio\n ads: {\n enabled: false,\n publisherId: '',\n tagUrl: '',\n },\n\n // Preview Thumbnails plugin\n previewThumbnails: {\n enabled: false,\n src: '',\n },\n\n // Vimeo plugin\n vimeo: {\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: false,\n // Custom settings from Plyr\n customControls: true,\n referrerPolicy: null, // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy\n // Whether the owner of the video has a Pro or Business account\n // (which allows us to properly hide controls without CSS hacks, etc)\n premium: false,\n },\n\n // YouTube plugin\n youtube: {\n rel: 0, // No related vids\n showinfo: 0, // Hide info\n iv_load_policy: 3, // Hide annotations\n modestbranding: 1, // Hide logos as much as possible (they still show one in the corner when paused)\n // Custom settings from Plyr\n customControls: true,\n noCookie: false, // Whether to use an alternative version of YouTube without cookies\n },\n\n // Media Metadata\n mediaMetadata: {\n title: '',\n artist: '',\n album: '',\n artwork: [],\n },\n\n // Markers\n markers: {\n enabled: false,\n points: [],\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr states\n// ==========================================================================\n\nexport const pip = {\n active: 'picture-in-picture',\n inactive: 'inline',\n};\n\nexport default { pip };\n","// ==========================================================================\n// Plyr supported types and providers\n// ==========================================================================\n\nexport const providers = {\n html5: 'html5',\n youtube: 'youtube',\n vimeo: 'vimeo',\n};\n\nexport const types = {\n audio: 'audio',\n video: 'video',\n};\n\n/**\n * Get provider by URL\n * @param {String} url\n */\nexport function getProviderByUrl(url) {\n // YouTube\n if (/^(https?:\\/\\/)?(www\\.)?(youtube\\.com|youtube-nocookie\\.com|youtu\\.?be)\\/.+$/.test(url)) {\n return providers.youtube;\n }\n\n // Vimeo\n if (/^https?:\\/\\/player.vimeo.com\\/video\\/\\d{0,9}(?=\\b|\\/)/.test(url)) {\n return providers.vimeo;\n }\n\n return null;\n}\n\nexport default { providers, types };\n","// ==========================================================================\n// Console wrapper\n// ==========================================================================\n\nconst noop = () => {};\n\nexport default class Console {\n constructor(enabled = false) {\n this.enabled = window.console && enabled;\n\n if (this.enabled) {\n this.log('Debugging enabled');\n }\n }\n\n get log() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.log, console) : noop;\n }\n\n get warn() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.warn, console) : noop;\n }\n\n get error() {\n // eslint-disable-next-line no-console\n return this.enabled ? Function.prototype.bind.call(console.error, console) : noop;\n }\n}\n","// ==========================================================================\n// Fullscreen wrapper\n// https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API#prefixing\n// https://webkit.org/blog/7929/designing-websites-for-iphone-x/\n// ==========================================================================\n\nimport browser from './utils/browser';\nimport { closest, getElements, hasClass, toggleClass } from './utils/elements';\nimport { on, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\n\nclass Fullscreen {\n constructor(player) {\n // Keep reference to parent\n this.player = player;\n\n // Get prefix\n this.prefix = Fullscreen.prefix;\n this.property = Fullscreen.property;\n\n // Scroll position\n this.scrollPosition = { x: 0, y: 0 };\n\n // Force the use of 'full window/browser' rather than fullscreen\n this.forceFallback = player.config.fullscreen.fallback === 'force';\n\n // Get the fullscreen element\n // Checks container is an ancestor, defaults to null\n this.player.elements.fullscreen =\n player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container);\n\n // Register event listeners\n // Handle event (incase user presses escape etc)\n on.call(\n this.player,\n document,\n this.prefix === 'ms' ? 'MSFullscreenChange' : `${this.prefix}fullscreenchange`,\n () => {\n // TODO: Filter for target??\n this.onChange();\n },\n );\n\n // Fullscreen toggle on double click\n on.call(this.player, this.player.elements.container, 'dblclick', (event) => {\n // Ignore double click in controls\n if (is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {\n return;\n }\n\n this.player.listeners.proxy(event, this.toggle, 'fullscreen');\n });\n\n // Tap focus when in fullscreen\n on.call(this, this.player.elements.container, 'keydown', (event) => this.trapFocus(event));\n\n // Update the UI\n this.update();\n }\n\n // Determine if native supported\n static get nativeSupported() {\n return !!(\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled\n );\n }\n\n // If we're actually using native\n get useNative() {\n return Fullscreen.nativeSupported && !this.forceFallback;\n }\n\n // Get the prefix for handlers\n static get prefix() {\n // No prefix\n if (is.function(document.exitFullscreen)) return '';\n\n // Check for fullscreen support by vendor prefix\n let value = '';\n const prefixes = ['webkit', 'moz', 'ms'];\n\n prefixes.some((pre) => {\n if (is.function(document[`${pre}ExitFullscreen`]) || is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n }\n\n return false;\n });\n\n return value;\n }\n\n static get property() {\n return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';\n }\n\n // Determine if fullscreen is supported\n get supported() {\n return [\n // Fullscreen is enabled in config\n this.player.config.fullscreen.enabled,\n // Must be a video\n this.player.isVideo,\n // Either native is supported or fallback enabled\n Fullscreen.nativeSupported || this.player.config.fullscreen.fallback,\n // YouTube has no way to trigger fullscreen, so on devices with no native support, playsinline\n // must be enabled and iosNative fullscreen must be disabled to offer the fullscreen fallback\n !this.player.isYouTube ||\n Fullscreen.nativeSupported ||\n !browser.isIos ||\n (this.player.config.playsinline && !this.player.config.fullscreen.iosNative),\n ].every(Boolean);\n }\n\n // Get active state\n get active() {\n if (!this.supported) return false;\n\n // Fallback using classname\n if (!Fullscreen.nativeSupported || this.forceFallback) {\n return hasClass(this.target, this.player.config.classNames.fullscreen.fallback);\n }\n\n const element = !this.prefix\n ? this.target.getRootNode().fullscreenElement\n : this.target.getRootNode()[`${this.prefix}${this.property}Element`];\n\n return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;\n }\n\n // Get target element\n get target() {\n return browser.isIos && this.player.config.fullscreen.iosNative\n ? this.player.media\n : this.player.elements.fullscreen ?? this.player.elements.container;\n }\n\n onChange = () => {\n if (!this.supported) return;\n\n // Update toggle button\n const button = this.player.elements.buttons.fullscreen;\n if (is.element(button)) {\n button.pressed = this.active;\n }\n\n // Always trigger events on the plyr / media element (not a fullscreen container) and let them bubble up\n const target = this.target === this.player.media ? this.target : this.player.elements.container;\n // Trigger an event\n triggerEvent.call(this.player, target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);\n };\n\n toggleFallback = (toggle = false) => {\n // Store or restore scroll position\n if (toggle) {\n this.scrollPosition = {\n x: window.scrollX ?? 0,\n y: window.scrollY ?? 0,\n };\n } else {\n window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);\n }\n\n // Toggle scroll\n document.body.style.overflow = toggle ? 'hidden' : '';\n\n // Toggle class hook\n toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle);\n\n // Force full viewport on iPhone X+\n if (browser.isIos) {\n let viewport = document.head.querySelector('meta[name=\"viewport\"]');\n const property = 'viewport-fit=cover';\n\n // Inject the viewport meta if required\n if (!viewport) {\n viewport = document.createElement('meta');\n viewport.setAttribute('name', 'viewport');\n }\n\n // Check if the property already exists\n const hasProperty = is.string(viewport.content) && viewport.content.includes(property);\n\n if (toggle) {\n this.cleanupViewport = !hasProperty;\n if (!hasProperty) viewport.content += `,${property}`;\n } else if (this.cleanupViewport) {\n viewport.content = viewport.content\n .split(',')\n .filter((part) => part.trim() !== property)\n .join(',');\n }\n }\n\n // Toggle button and fire events\n this.onChange();\n };\n\n // Trap focus inside container\n trapFocus = (event) => {\n // Bail if iOS/iPadOS, not active, not the tab key\n if (browser.isIos || browser.isIPadOS || !this.active || event.key !== 'Tab') return;\n\n // Get the current focused element\n const focused = document.activeElement;\n const focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');\n const [first] = focusable;\n const last = focusable[focusable.length - 1];\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n };\n\n // Update UI\n update = () => {\n if (this.supported) {\n let mode;\n\n if (this.forceFallback) mode = 'Fallback (forced)';\n else if (Fullscreen.nativeSupported) mode = 'Native';\n else mode = 'Fallback';\n\n this.player.debug.log(`${mode} fullscreen enabled`);\n } else {\n this.player.debug.log('Fullscreen not supported and fallback disabled');\n }\n\n // Add styling hook to show button\n toggleClass(this.player.elements.container, this.player.config.classNames.fullscreen.enabled, this.supported);\n };\n\n // Make an element fullscreen\n enter = () => {\n if (!this.supported) return;\n\n // iOS native fullscreen doesn't need the request step\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.isVimeo) {\n this.player.embed.requestFullscreen();\n } else {\n this.target.webkitEnterFullscreen();\n }\n } else if (!Fullscreen.nativeSupported || this.forceFallback) {\n this.toggleFallback(true);\n } else if (!this.prefix) {\n this.target.requestFullscreen({ navigationUI: 'hide' });\n } else if (!is.empty(this.prefix)) {\n this.target[`${this.prefix}Request${this.property}`]();\n }\n };\n\n // Bail from fullscreen\n exit = () => {\n if (!this.supported) return;\n\n // iOS native fullscreen\n if (browser.isIos && this.player.config.fullscreen.iosNative) {\n if (this.player.isVimeo) {\n this.player.embed.exitFullscreen();\n } else {\n this.target.webkitEnterFullscreen();\n }\n silencePromise(this.player.play());\n } else if (!Fullscreen.nativeSupported || this.forceFallback) {\n this.toggleFallback(false);\n } else if (!this.prefix) {\n (document.cancelFullScreen || document.exitFullscreen).call(document);\n } else if (!is.empty(this.prefix)) {\n const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';\n document[`${this.prefix}${action}${this.property}`]();\n }\n };\n\n // Toggle state\n toggle = () => {\n if (!this.active) this.enter();\n else this.exit();\n };\n}\n\nexport default Fullscreen;\n","// ==========================================================================\n// Load image avoiding xhr/fetch CORS issues\n// Server status can't be obtained this way unfortunately, so this uses \"naturalWidth\" to determine if the image has loaded\n// By default it checks if it is at least 1px, but you can add a second argument to change this\n// ==========================================================================\n\nexport default function loadImage(src, minWidth = 1) {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n const handler = () => {\n delete image.onload;\n delete image.onerror;\n (image.naturalWidth >= minWidth ? resolve : reject)(image);\n };\n\n Object.assign(image, { onload: handler, onerror: handler, src });\n });\n}\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport captions from './captions';\nimport controls from './controls';\nimport support from './support';\nimport { getElement, toggleClass } from './utils/elements';\nimport { ready, triggerEvent } from './utils/events';\nimport i18n from './utils/i18n';\nimport is from './utils/is';\nimport loadImage from './utils/load-image';\n\nconst ui = {\n addStyleHook() {\n toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle = false) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling?\n this.listeners.media();\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.debug.warn(`Basic support only for ${this.provider} ${this.type}`);\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!is.element(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n this.listeners.controls();\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup captions for HTML5\n if (this.isHTML5) {\n captions.setup.call(this);\n }\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality setting\n this.quality = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset volume display\n controls.updateVolume.call(this);\n\n // Reset time display\n controls.timeUpdate.call(this);\n\n // Reset duration display\n controls.durationUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Check for picture-in-picture support\n toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.isHTML5 && this.isVideo,\n );\n\n // Check for airplay support\n toggleClass(this.elements.container, this.config.classNames.airplay.supported, support.airplay && this.isHTML5);\n\n // Add touch class\n toggleClass(this.elements.container, this.config.classNames.isTouch, this.touch);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n setTimeout(() => {\n triggerEvent.call(this, this.media, 'ready');\n }, 0);\n\n // Set the title\n ui.setTitle.call(this);\n\n // Assure the poster image is set, if the property was added before the element was created\n if (this.poster) {\n ui.setPoster.call(this, this.poster, false).catch(() => {});\n }\n\n // Manually set the duration if user has overridden it.\n // The event listeners for it doesn't get called if preload is disabled (#701)\n if (this.config.duration) {\n controls.durationUpdate.call(this);\n }\n\n // Media metadata\n if (this.config.mediaMetadata) {\n controls.setMediaMetadata.call(this);\n }\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = i18n.get('play', this.config);\n\n // If there's a media title set, use that for the label\n if (is.string(this.config.title) && !is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n }\n\n // If there's a play button, set label\n Array.from(this.elements.buttons.play || []).forEach((button) => {\n button.setAttribute('aria-label', label);\n });\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = getElement.call(this, 'iframe');\n\n if (!is.element(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !is.empty(this.config.title) ? this.config.title : 'video';\n const format = i18n.get('frameTitle', this.config);\n\n iframe.setAttribute('title', format.replace('{title}', title));\n }\n },\n\n // Toggle poster\n togglePoster(enable) {\n toggleClass(this.elements.container, this.config.classNames.posterEnabled, enable);\n },\n\n // Set the poster image (async)\n // Used internally for the poster setter, with the passive option forced to false\n setPoster(poster, passive = true) {\n // Don't override if call is passive\n if (passive && this.poster) {\n return Promise.reject(new Error('Poster already set'));\n }\n\n // Set property synchronously to respect the call order\n this.media.setAttribute('data-poster', poster);\n\n // Show the poster\n this.elements.poster.removeAttribute('hidden');\n\n // Wait until ui is ready\n return (\n ready\n .call(this)\n // Load image\n .then(() => loadImage(poster))\n .catch((error) => {\n // Hide poster on error unless it's been set by another call\n if (poster === this.poster) {\n ui.togglePoster.call(this, false);\n }\n // Rethrow\n throw error;\n })\n .then(() => {\n // Prevent race conditions\n if (poster !== this.poster) {\n throw new Error('setPoster cancelled by later call to setPoster');\n }\n })\n .then(() => {\n Object.assign(this.elements.poster.style, {\n backgroundImage: `url('${poster}')`,\n // Reset backgroundSize as well (since it can be set to \"cover\" for padded thumbnails for youtube)\n backgroundSize: '',\n });\n\n ui.togglePoster.call(this, true);\n\n return poster;\n })\n );\n },\n\n // Check playing state\n checkPlaying(event) {\n // Class hooks\n toggleClass(this.elements.container, this.config.classNames.playing, this.playing);\n toggleClass(this.elements.container, this.config.classNames.paused, this.paused);\n toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped);\n\n // Set state\n Array.from(this.elements.buttons.play || []).forEach((target) => {\n Object.assign(target, { pressed: this.playing });\n target.setAttribute('aria-label', i18n.get(this.playing ? 'pause' : 'play', this.config));\n });\n\n // Only update controls on non timeupdate events\n if (is.event(event) && event.type === 'timeupdate') {\n return;\n }\n\n // Toggle controls\n ui.toggleControls.call(this);\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = ['stalled', 'waiting'].includes(event.type);\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(\n () => {\n // Update progress bar loading class state\n toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Update controls visibility\n ui.toggleControls.call(this);\n },\n this.loading ? 250 : 0,\n );\n },\n\n // Toggle controls based on state and `force` argument\n toggleControls(force) {\n const { controls: controlsElement } = this.elements;\n\n if (controlsElement && this.config.hideControls) {\n // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.)\n const recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now();\n\n // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide\n this.toggleControls(\n Boolean(\n force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek,\n ),\n );\n }\n },\n\n // Migrate any custom properties from the media to the parent\n migrateStyles() {\n // Loop through values (as they are the keys when the object is spread 🤔)\n Object.values({ ...this.media.style })\n // We're only fussed about Plyr specific properties\n .filter((key) => !is.empty(key) && is.string(key) && key.startsWith('--plyr'))\n .forEach((key) => {\n // Set on the container\n this.elements.container.style.setProperty(key, this.media.style.getPropertyValue(key));\n\n // Clean up from media element\n this.media.style.removeProperty(key);\n });\n\n // Remove attribute if empty\n if (is.empty(this.media.style)) {\n this.media.removeAttribute('style');\n }\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport controls from './controls';\nimport ui from './ui';\nimport { repaint } from './utils/animation';\nimport browser from './utils/browser';\nimport { getElement, getElements, matches, toggleClass } from './utils/elements';\nimport { off, on, once, toggleListener, triggerEvent } from './utils/events';\nimport is from './utils/is';\nimport { silencePromise } from './utils/promise';\nimport { getAspectRatio, getViewportSize, supportsCSS } from './utils/style';\n\nclass Listeners {\n constructor(player) {\n this.player = player;\n this.lastKey = null;\n this.focusTimer = null;\n this.lastKeyDown = null;\n\n this.handleKey = this.handleKey.bind(this);\n this.toggleMenu = this.toggleMenu.bind(this);\n this.firstTouch = this.firstTouch.bind(this);\n }\n\n // Handle key presses\n handleKey(event) {\n const { player } = this;\n const { elements } = player;\n const { key, type, altKey, ctrlKey, metaKey, shiftKey } = event;\n const pressed = type === 'keydown';\n const repeat = pressed && key === this.lastKey;\n\n // Bail if a modifier key is set\n if (altKey || ctrlKey || metaKey || shiftKey) {\n return;\n }\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the key for whatever reason\n if (!key) {\n return;\n }\n\n // Seek by increment\n const seekByIncrement = (increment) => {\n // Divide the max duration into 10th's and times by the number value\n player.currentTime = (player.duration / 10) * increment;\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = document.activeElement;\n if (is.element(focused)) {\n const { editable } = player.config.selectors;\n const { seek } = elements.inputs;\n\n if (focused !== seek && matches(focused, editable)) {\n return;\n }\n\n if (event.key === ' ' && matches(focused, 'button, [role^=\"menuitem\"]')) {\n return;\n }\n }\n\n // Which keys should we prevent default\n const preventDefault = [\n ' ',\n 'ArrowLeft',\n 'ArrowUp',\n 'ArrowRight',\n 'ArrowDown',\n\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n\n 'c',\n 'f',\n 'k',\n 'l',\n 'm',\n ];\n\n // If the key is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(key)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (key) {\n case '0':\n case '1':\n case '2':\n case '3':\n case '4':\n case '5':\n case '6':\n case '7':\n case '8':\n case '9':\n if (!repeat) {\n seekByIncrement(parseInt(key, 10));\n }\n break;\n\n case ' ':\n case 'k':\n if (!repeat) {\n silencePromise(player.togglePlay());\n }\n break;\n\n case 'ArrowUp':\n player.increaseVolume(0.1);\n break;\n\n case 'ArrowDown':\n player.decreaseVolume(0.1);\n break;\n\n case 'm':\n if (!repeat) {\n player.muted = !player.muted;\n }\n break;\n\n case 'ArrowRight':\n player.forward();\n break;\n\n case 'ArrowLeft':\n player.rewind();\n break;\n\n case 'f':\n player.fullscreen.toggle();\n break;\n\n case 'c':\n if (!repeat) {\n player.toggleCaptions();\n }\n break;\n\n case 'l':\n player.loop = !player.loop;\n break;\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (key === 'Escape' && !player.fullscreen.usingNative && player.fullscreen.active) {\n player.fullscreen.toggle();\n }\n\n // Store last key for next cycle\n this.lastKey = key;\n } else {\n this.lastKey = null;\n }\n }\n\n // Toggle menu\n toggleMenu(event) {\n controls.toggleMenu.call(this.player, event);\n }\n\n // Device is touch enabled\n firstTouch = () => {\n const { player } = this;\n const { elements } = player;\n\n player.touch = true;\n\n // Add touch class\n toggleClass(elements.container, player.config.classNames.isTouch, true);\n };\n\n // Global window & document listeners\n global = (toggle = true) => {\n const { player } = this;\n\n // Keyboard shortcuts\n if (player.config.keyboard.global) {\n toggleListener.call(player, window, 'keydown keyup', this.handleKey, toggle, false);\n }\n\n // Click anywhere closes menu\n toggleListener.call(player, document.body, 'click', this.toggleMenu, toggle);\n\n // Detect touch by events\n once.call(player, document.body, 'touchstart', this.firstTouch);\n };\n\n // Container listeners\n container = () => {\n const { player } = this;\n const { config, elements, timers } = player;\n\n // Keyboard shortcuts\n if (!config.keyboard.global && config.keyboard.focused) {\n on.call(player, elements.container, 'keydown keyup', this.handleKey, false);\n }\n\n // Toggle controls on mouse events and entering fullscreen\n on.call(\n player,\n elements.container,\n 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen',\n (event) => {\n const { controls: controlsElement } = elements;\n\n // Remove button states for fullscreen\n if (controlsElement && event.type === 'enterfullscreen') {\n controlsElement.pressed = false;\n controlsElement.hover = false;\n }\n\n // Show, then hide after a timeout unless another control event occurs\n const show = ['touchstart', 'touchmove', 'mousemove'].includes(event.type);\n let delay = 0;\n\n if (show) {\n ui.toggleControls.call(player, true);\n // Use longer timeout for touch devices\n delay = player.touch ? 3000 : 2000;\n }\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Set new timer to prevent flicker when seeking\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n },\n );\n\n // Set a gutter for Vimeo\n const setGutter = () => {\n if (!player.isVimeo || player.config.vimeo.premium) {\n return;\n }\n\n const target = elements.wrapper;\n const { active } = player.fullscreen;\n const [videoWidth, videoHeight] = getAspectRatio.call(player);\n const useNativeAspectRatio = supportsCSS(`aspect-ratio: ${videoWidth} / ${videoHeight}`);\n\n // If not active, remove styles\n if (!active) {\n if (useNativeAspectRatio) {\n target.style.width = null;\n target.style.height = null;\n } else {\n target.style.maxWidth = null;\n target.style.margin = null;\n }\n return;\n }\n\n // Determine which dimension will overflow and constrain view\n const [viewportWidth, viewportHeight] = getViewportSize();\n const overflow = viewportWidth / viewportHeight > videoWidth / videoHeight;\n\n if (useNativeAspectRatio) {\n target.style.width = overflow ? 'auto' : '100%';\n target.style.height = overflow ? '100%' : 'auto';\n } else {\n target.style.maxWidth = overflow ? `${(viewportHeight / videoHeight) * videoWidth}px` : null;\n target.style.margin = overflow ? '0 auto' : null;\n }\n };\n\n // Handle resizing\n const resized = () => {\n clearTimeout(timers.resized);\n timers.resized = setTimeout(setGutter, 50);\n };\n\n on.call(player, elements.container, 'enterfullscreen exitfullscreen', (event) => {\n const { target } = player.fullscreen;\n\n // Ignore events not from target\n if (target !== elements.container) {\n return;\n }\n\n // If it's not an embed and no ratio specified\n if (!player.isEmbed && is.empty(player.config.ratio)) {\n return;\n }\n\n // Set Vimeo gutter\n setGutter();\n\n // Watch for resizes\n const method = event.type === 'enterfullscreen' ? on : off;\n method.call(player, window, 'resize', resized);\n });\n };\n\n // Listen for media events\n media = () => {\n const { player } = this;\n const { elements } = player;\n\n // Time change on media\n on.call(player, player.media, 'timeupdate seeking seeked', (event) => controls.timeUpdate.call(player, event));\n\n // Display duration\n on.call(player, player.media, 'durationchange loadeddata loadedmetadata', (event) =>\n controls.durationUpdate.call(player, event),\n );\n\n // Handle the media finishing\n on.call(player, player.media, 'ended', () => {\n // Show poster on end\n if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {\n // Restart\n player.restart();\n\n // Call pause otherwise IE11 will start playing the video again\n player.pause();\n }\n });\n\n // Check for buffer progress\n on.call(player, player.media, 'progress playing seeking seeked', (event) =>\n controls.updateProgress.call(player, event),\n );\n\n // Handle volume changes\n on.call(player, player.media, 'volumechange', (event) => controls.updateVolume.call(player, event));\n\n // Handle play/pause\n on.call(player, player.media, 'playing play pause ended emptied timeupdate', (event) =>\n ui.checkPlaying.call(player, event),\n );\n\n // Loading state\n on.call(player, player.media, 'waiting canplay seeked playing', (event) => ui.checkLoading.call(player, event));\n\n // Click video\n if (player.supported.ui && player.config.clickToPlay && !player.isAudio) {\n // Re-fetch the wrapper\n const wrapper = getElement.call(player, `.${player.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!is.element(wrapper)) {\n return;\n }\n\n // On click play, pause or restart\n on.call(player, elements.container, 'click', (event) => {\n const targets = [elements.container, wrapper];\n\n // Ignore if click if not container or in video wrapper\n if (!targets.includes(event.target) && !wrapper.contains(event.target)) {\n return;\n }\n\n // Touch devices will just show controls (if hidden)\n if (player.touch && player.config.hideControls) {\n return;\n }\n\n if (player.ended) {\n this.proxy(event, player.restart, 'restart');\n this.proxy(\n event,\n () => {\n silencePromise(player.play());\n },\n 'play',\n );\n } else {\n this.proxy(\n event,\n () => {\n silencePromise(player.togglePlay());\n },\n 'play',\n );\n }\n });\n }\n\n // Disable right click\n if (player.supported.ui && player.config.disableContextMenu) {\n on.call(\n player,\n elements.wrapper,\n 'contextmenu',\n (event) => {\n event.preventDefault();\n },\n false,\n );\n }\n\n // Volume change\n on.call(player, player.media, 'volumechange', () => {\n // Save to storage\n player.storage.set({\n volume: player.volume,\n muted: player.muted,\n });\n });\n\n // Speed change\n on.call(player, player.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(player, 'speed');\n\n // Save to storage\n player.storage.set({ speed: player.speed });\n });\n\n // Quality change\n on.call(player, player.media, 'qualitychange', (event) => {\n // Update UI\n controls.updateSetting.call(player, 'quality', null, event.detail.quality);\n });\n\n // Update download link when ready and if quality changes\n on.call(player, player.media, 'ready qualitychange', () => {\n controls.setDownloadUrl.call(player);\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n const proxyEvents = player.config.events.concat(['keyup', 'keydown']).join(' ');\n\n on.call(player, player.media, proxyEvents, (event) => {\n let { detail = {} } = event;\n\n // Get error details from media\n if (event.type === 'error') {\n detail = player.media.error;\n }\n\n triggerEvent.call(player, elements.container, event.type, true, detail);\n });\n };\n\n // Run default and custom handlers\n proxy = (event, defaultHandler, customHandlerKey) => {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n let returned = true;\n\n // Execute custom handler\n if (hasCustomHandler) {\n returned = customHandler.call(player, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (returned !== false && is.function(defaultHandler)) {\n defaultHandler.call(player, event);\n }\n };\n\n // Trigger custom and default handlers\n bind = (element, type, defaultHandler, customHandlerKey, passive = true) => {\n const { player } = this;\n const customHandler = player.config.listeners[customHandlerKey];\n const hasCustomHandler = is.function(customHandler);\n\n on.call(\n player,\n element,\n type,\n (event) => this.proxy(event, defaultHandler, customHandlerKey),\n passive && !hasCustomHandler,\n );\n };\n\n // Listen for control events\n controls = () => {\n const { player } = this;\n const { elements } = player;\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Play/pause toggle\n if (elements.buttons.play) {\n Array.from(elements.buttons.play).forEach((button) => {\n this.bind(\n button,\n 'click',\n () => {\n silencePromise(player.togglePlay());\n },\n 'play',\n );\n });\n }\n\n // Pause\n this.bind(elements.buttons.restart, 'click', player.restart, 'restart');\n\n // Rewind\n this.bind(\n elements.buttons.rewind,\n 'click',\n () => {\n // Record seek time so we can prevent hiding controls for a few seconds after rewind\n player.lastSeekTime = Date.now();\n player.rewind();\n },\n 'rewind',\n );\n\n // Rewind\n this.bind(\n elements.buttons.fastForward,\n 'click',\n () => {\n // Record seek time so we can prevent hiding controls for a few seconds after fast forward\n player.lastSeekTime = Date.now();\n player.forward();\n },\n 'fastForward',\n );\n\n // Mute toggle\n this.bind(\n elements.buttons.mute,\n 'click',\n () => {\n player.muted = !player.muted;\n },\n 'mute',\n );\n\n // Captions toggle\n this.bind(elements.buttons.captions, 'click', () => player.toggleCaptions());\n\n // Download\n this.bind(\n elements.buttons.download,\n 'click',\n () => {\n triggerEvent.call(player, player.media, 'download');\n },\n 'download',\n );\n\n // Fullscreen toggle\n this.bind(\n elements.buttons.fullscreen,\n 'click',\n () => {\n player.fullscreen.toggle();\n },\n 'fullscreen',\n );\n\n // Picture-in-Picture\n this.bind(\n elements.buttons.pip,\n 'click',\n () => {\n player.pip = 'toggle';\n },\n 'pip',\n );\n\n // Airplay\n this.bind(elements.buttons.airplay, 'click', player.airplay, 'airplay');\n\n // Settings menu - click toggle\n this.bind(\n elements.buttons.settings,\n 'click',\n (event) => {\n // Prevent the document click listener closing the menu\n event.stopPropagation();\n event.preventDefault();\n\n controls.toggleMenu.call(player, event);\n },\n null,\n false,\n ); // Can't be passive as we're preventing default\n\n // Settings menu - keyboard toggle\n // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143\n this.bind(\n elements.buttons.settings,\n 'keyup',\n (event) => {\n if (![' ', 'Enter'].includes(event.key)) {\n return;\n }\n\n // Because return triggers a click anyway, all we need to do is set focus\n if (event.key === 'Enter') {\n controls.focusFirstMenuItem.call(player, null, true);\n return;\n }\n\n // Prevent scroll\n event.preventDefault();\n\n // Prevent playing video (Firefox)\n event.stopPropagation();\n\n // Toggle menu\n controls.toggleMenu.call(player, event);\n },\n null,\n false, // Can't be passive as we're preventing default\n );\n\n // Escape closes menu\n this.bind(elements.settings.menu, 'keydown', (event) => {\n if (event.key === 'Escape') {\n controls.toggleMenu.call(player, event);\n }\n });\n\n // Set range input alternative \"value\", which matches the tooltip time (#954)\n this.bind(elements.inputs.seek, 'mousedown mousemove', (event) => {\n const rect = elements.progress.getBoundingClientRect();\n const percent = (100 / rect.width) * (event.pageX - rect.left);\n event.currentTarget.setAttribute('seek-value', percent);\n });\n\n // Pause while seeking\n this.bind(elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', (event) => {\n const seek = event.currentTarget;\n const attribute = 'play-on-seeked';\n\n if (is.keyboardEvent(event) && !['ArrowLeft', 'ArrowRight'].includes(event.key)) {\n return;\n }\n\n // Record seek time so we can prevent hiding controls for a few seconds after seek\n player.lastSeekTime = Date.now();\n\n // Was playing before?\n const play = seek.hasAttribute(attribute);\n // Done seeking\n const done = ['mouseup', 'touchend', 'keyup'].includes(event.type);\n\n // If we're done seeking and it was playing, resume playback\n if (play && done) {\n seek.removeAttribute(attribute);\n silencePromise(player.play());\n } else if (!done && player.playing) {\n seek.setAttribute(attribute, '');\n player.pause();\n }\n });\n\n // Fix range inputs on iOS\n // Super weird iOS bug where after you interact with an <input type=\"range\">,\n // it takes over further interactions on the page. This is a hack\n if (browser.isIos) {\n const inputs = getElements.call(player, 'input[type=\"range\"]');\n Array.from(inputs).forEach((input) => this.bind(input, inputEvent, (event) => repaint(event.target)));\n }\n\n // Seek\n this.bind(\n elements.inputs.seek,\n inputEvent,\n (event) => {\n const seek = event.currentTarget;\n // If it exists, use seek-value instead of \"value\" for consistency with tooltip time (#954)\n let seekTo = seek.getAttribute('seek-value');\n\n if (is.empty(seekTo)) {\n seekTo = seek.value;\n }\n\n seek.removeAttribute('seek-value');\n\n player.currentTime = (seekTo / seek.max) * player.duration;\n },\n 'seek',\n );\n\n // Seek tooltip\n this.bind(elements.progress, 'mouseenter mouseleave mousemove', (event) =>\n controls.updateSeekTooltip.call(player, event),\n );\n\n // Preview thumbnails plugin\n // TODO: Really need to work on some sort of plug-in wide event bus or pub-sub for this\n this.bind(elements.progress, 'mousemove touchmove', (event) => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startMove(event);\n }\n });\n\n // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering\n this.bind(elements.progress, 'mouseleave touchend click', () => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endMove(false, true);\n }\n });\n\n // Show scrubbing preview\n this.bind(elements.progress, 'mousedown touchstart', (event) => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.startScrubbing(event);\n }\n });\n\n this.bind(elements.progress, 'mouseup touchend', (event) => {\n const { previewThumbnails } = player;\n\n if (previewThumbnails && previewThumbnails.loaded) {\n previewThumbnails.endScrubbing(event);\n }\n });\n\n // Polyfill for lower fill in <input type=\"range\"> for webkit\n if (browser.isWebKit) {\n Array.from(getElements.call(player, 'input[type=\"range\"]')).forEach((element) => {\n this.bind(element, 'input', (event) => controls.updateRangeFill.call(player, event.target));\n });\n }\n\n // Current time invert\n // Only if one time element is used for both currentTime and duration\n if (player.config.toggleInvert && !is.element(elements.display.duration)) {\n this.bind(elements.display.currentTime, 'click', () => {\n // Do nothing if we're at the start\n if (player.currentTime === 0) {\n return;\n }\n\n player.config.invertTime = !player.config.invertTime;\n\n controls.timeUpdate.call(player);\n });\n }\n\n // Volume\n this.bind(\n elements.inputs.volume,\n inputEvent,\n (event) => {\n player.volume = event.target.value;\n },\n 'volume',\n );\n\n // Update controls.hover state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mouseenter mouseleave', (event) => {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n });\n\n // Also update controls.hover state for any non-player children of fullscreen element (as above)\n if (elements.fullscreen) {\n Array.from(elements.fullscreen.children)\n .filter((c) => !c.contains(elements.container))\n .forEach((child) => {\n this.bind(child, 'mouseenter mouseleave', (event) => {\n if (elements.controls) {\n elements.controls.hover = !player.touch && event.type === 'mouseenter';\n }\n });\n });\n }\n\n // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)\n this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', (event) => {\n elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Show controls when they receive focus (e.g., when using keyboard tab key)\n this.bind(elements.controls, 'focusin', () => {\n const { config, timers } = player;\n\n // Skip transition to prevent focus from scrolling the parent element\n toggleClass(elements.controls, config.classNames.noTransition, true);\n\n // Toggle\n ui.toggleControls.call(player, true);\n\n // Restore transition\n setTimeout(() => {\n toggleClass(elements.controls, config.classNames.noTransition, false);\n }, 0);\n\n // Delay a little more for mouse users\n const delay = this.touch ? 3000 : 4000;\n\n // Clear timer\n clearTimeout(timers.controls);\n\n // Hide again after delay\n timers.controls = setTimeout(() => ui.toggleControls.call(player, false), delay);\n });\n\n // Mouse wheel for volume\n this.bind(\n elements.inputs.volume,\n 'wheel',\n (event) => {\n // Detect \"natural\" scroll - supported on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n // Get delta from event. Invert if `inverted` is true\n const [x, y] = [event.deltaX, -event.deltaY].map((value) => (inverted ? -value : value));\n // Using the biggest delta, normalize to 1 or -1 (or 0 if no delta)\n const direction = Math.sign(Math.abs(x) > Math.abs(y) ? x : y);\n\n // Change the volume by 2%\n player.increaseVolume(direction / 50);\n\n // Don't break page scrolling at max and min\n const { volume } = player.media;\n if ((direction === 1 && volume < 1) || (direction === -1 && volume > 0)) {\n event.preventDefault();\n }\n },\n 'volume',\n false,\n );\n };\n}\n\nexport default Listeners;\n","(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.loadjs = factory();\n }\n}(this, function() {\n/**\n * Global dependencies.\n * @global {Object} document - DOM\n */\n\nvar devnull = function() {},\n bundleIdCache = {},\n bundleResultCache = {},\n bundleCallbackQueue = {};\n\n\n/**\n * Subscribe to bundle load event.\n * @param {string[]} bundleIds - Bundle ids\n * @param {Function} callbackFn - The callback function\n */\nfunction subscribe(bundleIds, callbackFn) {\n // listify\n bundleIds = bundleIds.push ? bundleIds : [bundleIds];\n\n var depsNotFound = [],\n i = bundleIds.length,\n numWaiting = i,\n fn,\n bundleId,\n r,\n q;\n\n // define callback function\n fn = function (bundleId, pathsNotFound) {\n if (pathsNotFound.length) depsNotFound.push(bundleId);\n\n numWaiting--;\n if (!numWaiting) callbackFn(depsNotFound);\n };\n\n // register callback\n while (i--) {\n bundleId = bundleIds[i];\n\n // execute callback if in result cache\n r = bundleResultCache[bundleId];\n if (r) {\n fn(bundleId, r);\n continue;\n }\n\n // add to callback queue\n q = bundleCallbackQueue[bundleId] = bundleCallbackQueue[bundleId] || [];\n q.push(fn);\n }\n}\n\n\n/**\n * Publish bundle load event.\n * @param {string} bundleId - Bundle id\n * @param {string[]} pathsNotFound - List of files not found\n */\nfunction publish(bundleId, pathsNotFound) {\n // exit if id isn't defined\n if (!bundleId) return;\n\n var q = bundleCallbackQueue[bundleId];\n\n // cache result\n bundleResultCache[bundleId] = pathsNotFound;\n\n // exit if queue is empty\n if (!q) return;\n\n // empty callback queue\n while (q.length) {\n q[0](bundleId, pathsNotFound);\n q.splice(0, 1);\n }\n}\n\n\n/**\n * Execute callbacks.\n * @param {Object or Function} args - The callback args\n * @param {string[]} depsNotFound - List of dependencies not found\n */\nfunction executeCallbacks(args, depsNotFound) {\n // accept function as argument\n if (args.call) args = {success: args};\n\n // success and error callbacks\n if (depsNotFound.length) (args.error || devnull)(depsNotFound);\n else (args.success || devnull)(args);\n}\n\n\n/**\n * Load individual file.\n * @param {string} path - The file path\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFile(path, callbackFn, args, numTries) {\n var doc = document,\n async = args.async,\n maxTries = (args.numRetries || 0) + 1,\n beforeCallbackFn = args.before || devnull,\n pathname = path.replace(/[\\?|#].*$/, ''),\n pathStripped = path.replace(/^(css|img)!/, ''),\n isLegacyIECss,\n e;\n\n numTries = numTries || 0;\n\n if (/(^css!|\\.css$)/.test(pathname)) {\n // css\n e = doc.createElement('link');\n e.rel = 'stylesheet';\n e.href = pathStripped;\n\n // tag IE9+\n isLegacyIECss = 'hideFocus' in e;\n\n // use preload in IE Edge (to detect load errors)\n if (isLegacyIECss && e.relList) {\n isLegacyIECss = 0;\n e.rel = 'preload';\n e.as = 'style';\n }\n } else if (/(^img!|\\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {\n // image\n e = doc.createElement('img');\n e.src = pathStripped; \n } else {\n // javascript\n e = doc.createElement('script');\n e.src = path;\n e.async = async === undefined ? true : async;\n }\n\n e.onload = e.onerror = e.onbeforeload = function (ev) {\n var result = ev.type[0];\n\n // treat empty stylesheets as failures to get around lack of onerror\n // support in IE9-11\n if (isLegacyIECss) {\n try {\n if (!e.sheet.cssText.length) result = 'e';\n } catch (x) {\n // sheets objects created from load errors don't allow access to\n // `cssText` (unless error is Code:18 SecurityError)\n if (x.code != 18) result = 'e';\n }\n }\n\n // handle retries in case of load failure\n if (result == 'e') {\n // increment counter\n numTries += 1;\n\n // exit function and try again\n if (numTries < maxTries) {\n return loadFile(path, callbackFn, args, numTries);\n }\n } else if (e.rel == 'preload' && e.as == 'style') {\n // activate preloaded stylesheets\n return e.rel = 'stylesheet'; // jshint ignore:line\n }\n \n // execute callback\n callbackFn(path, result, ev.defaultPrevented);\n };\n\n // add to document (unless callback returns `false`)\n if (beforeCallbackFn(path, e) !== false) doc.head.appendChild(e);\n}\n\n\n/**\n * Load multiple files.\n * @param {string[]} paths - The file paths\n * @param {Function} callbackFn - The callback function\n */\nfunction loadFiles(paths, callbackFn, args) {\n // listify paths\n paths = paths.push ? paths : [paths];\n\n var numWaiting = paths.length,\n x = numWaiting,\n pathsNotFound = [],\n fn,\n i;\n\n // define callback function\n fn = function(path, result, defaultPrevented) {\n // handle error\n if (result == 'e') pathsNotFound.push(path);\n\n // handle beforeload event. If defaultPrevented then that means the load\n // will be blocked (ex. Ghostery/ABP on Safari)\n if (result == 'b') {\n if (defaultPrevented) pathsNotFound.push(path);\n else return;\n }\n\n numWaiting--;\n if (!numWaiting) callbackFn(pathsNotFound);\n };\n\n // load scripts\n for (i=0; i < x; i++) loadFile(paths[i], fn, args);\n}\n\n\n/**\n * Initiate script load and register bundle.\n * @param {(string|string[])} paths - The file paths\n * @param {(string|Function|Object)} [arg1] - The (1) bundleId or (2) success\n * callback or (3) object literal with success/error arguments, numRetries,\n * etc.\n * @param {(Function|Object)} [arg2] - The (1) success callback or (2) object\n * literal with success/error arguments, numRetries, etc.\n */\nfunction loadjs(paths, arg1, arg2) {\n var bundleId,\n args;\n\n // bundleId (if string)\n if (arg1 && arg1.trim) bundleId = arg1;\n\n // args (default is {})\n args = (bundleId ? arg2 : arg1) || {};\n\n // throw error if bundle is already defined\n if (bundleId) {\n if (bundleId in bundleIdCache) {\n throw \"LoadJS\";\n } else {\n bundleIdCache[bundleId] = true;\n }\n }\n\n function loadFn(resolve, reject) {\n loadFiles(paths, function (pathsNotFound) {\n // execute callbacks\n executeCallbacks(args, pathsNotFound);\n \n // resolve Promise\n if (resolve) {\n executeCallbacks({success: resolve, error: reject}, pathsNotFound);\n }\n\n // publish bundle load event\n publish(bundleId, pathsNotFound);\n }, args);\n }\n \n if (args.returnPromise) return new Promise(loadFn);\n else loadFn();\n}\n\n\n/**\n * Execute callbacks when dependencies have been satisfied.\n * @param {(string|string[])} deps - List of bundle ids\n * @param {Object} args - success/error arguments\n */\nloadjs.ready = function ready(deps, args) {\n // subscribe to bundle load event\n subscribe(deps, function (depsNotFound) {\n // execute callbacks\n executeCallbacks(args, depsNotFound);\n });\n\n return loadjs;\n};\n\n\n/**\n * Manually satisfy bundle dependencies.\n * @param {string} bundleId - The bundle id\n */\nloadjs.done = function done(bundleId) {\n publish(bundleId, []);\n};\n\n\n/**\n * Reset loadjs dependencies statuses\n */\nloadjs.reset = function reset() {\n bundleIdCache = {};\n bundleResultCache = {};\n bundleCallbackQueue = {};\n};\n\n\n/**\n * Determine if bundle has already been defined\n * @param String} bundleId - The bundle id\n */\nloadjs.isDefined = function isDefined(bundleId) {\n return bundleId in bundleIdCache;\n};\n\n\n// export\nreturn loadjs;\n\n}));\n","// ==========================================================================\n// Load an external script\n// ==========================================================================\n\nimport loadjs from 'loadjs';\n\nexport default function loadScript(url) {\n return new Promise((resolve, reject) => {\n loadjs(url, {\n success: resolve,\n error: reject,\n });\n });\n}\n","// ==========================================================================\n// Vimeo plugin\n// ==========================================================================\n\nimport captions from '../captions';\nimport controls from '../controls';\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadScript from '../utils/load-script';\nimport { format, stripHTML } from '../utils/strings';\nimport { roundAspectRatio, setAspectRatio } from '../utils/style';\nimport { buildUrlParams } from '../utils/urls';\n\n// Parse Vimeo ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n if (is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Try to extract a hash for private videos from the URL\nfunction parseHash(url) {\n /* This regex matches a hexadecimal hash if given in any of these forms:\n * - [https://player.]vimeo.com/video/{id}/{hash}[?params]\n * - [https://player.]vimeo.com/video/{id}?h={hash}[¶ms]\n * - [https://player.]vimeo.com/video/{id}?[params]&h={hash}\n * - video/{id}/{hash}\n * If matched, the hash is available in capture group 4\n */\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+)(\\?.*&*h=|\\/)+([\\d,a-f]+)/;\n const found = url.match(regex);\n\n return found && found.length === 5 ? found[4] : null;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nconst vimeo = {\n setup() {\n const player = this;\n\n // Add embed class for responsive\n toggleClass(player.elements.wrapper, player.config.classNames.embed, true);\n\n // Set speed options from config\n player.options.speed = player.config.speed.options;\n\n // Set intial ratio\n setAspectRatio.call(player);\n\n // Load the SDK if not already\n if (!is.object(window.Vimeo)) {\n loadScript(player.config.urls.vimeo.sdk)\n .then(() => {\n vimeo.ready.call(player);\n })\n .catch((error) => {\n player.debug.warn('Vimeo SDK (player.js) failed to load', error);\n });\n } else {\n vimeo.ready.call(player);\n }\n },\n\n // API Ready\n ready() {\n const player = this;\n const config = player.config.vimeo;\n const { premium, referrerPolicy, ...frameParams } = config;\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n let hash = '';\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(player.config.attributes.embed.id);\n // hash can also be set as attribute on the <div>\n hash = player.media.getAttribute(player.config.attributes.embed.hash);\n } else {\n hash = parseHash(source);\n }\n const hashParam = hash ? { h: hash } : {};\n\n // If the owner has a pro or premium account then we can hide controls etc\n if (premium) {\n Object.assign(frameParams, {\n controls: false,\n sidedock: false,\n });\n }\n\n // Get Vimeo params for the iframe\n const params = buildUrlParams({\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n muted: player.muted,\n gesture: 'media',\n playsinline: player.config.playsinline,\n // hash has to be added to iframe-URL\n ...hashParam,\n ...frameParams,\n });\n\n const id = parseId(source);\n // Build an iframe\n const iframe = createElement('iframe');\n const src = format(player.config.urls.vimeo.iframe, id, params);\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute(\n 'allow',\n ['autoplay', 'fullscreen', 'picture-in-picture', 'encrypted-media', 'accelerometer', 'gyroscope'].join('; '),\n );\n\n // Set the referrer policy if required\n if (!is.empty(referrerPolicy)) {\n iframe.setAttribute('referrerPolicy', referrerPolicy);\n }\n\n // Inject the package\n if (premium || !config.customControls) {\n iframe.setAttribute('data-poster', player.poster);\n player.media = replaceElement(iframe, player.media);\n } else {\n const wrapper = createElement('div', {\n class: player.config.classNames.embedContainer,\n 'data-poster': player.poster,\n });\n wrapper.appendChild(iframe);\n player.media = replaceElement(wrapper, player.media);\n }\n\n // Get poster image\n if (!config.customControls) {\n fetch(format(player.config.urls.vimeo.api, src)).then((response) => {\n if (is.empty(response) || !response.thumbnail_url) {\n return;\n }\n\n // Set and show poster\n ui.setPoster.call(player, response.thumbnail_url).catch(() => {});\n });\n }\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe, {\n autopause: player.config.autopause,\n muted: player.muted,\n });\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Disable native text track rendering\n if (player.supported.ui) {\n player.embed.disableTextTrack();\n }\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n return player.embed.play();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n return player.embed.pause();\n };\n\n player.media.stop = () => {\n player.pause();\n player.currentTime = 0;\n };\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Vimeo will automatically play on seek if the video hasn't been played before\n\n // Get current paused state and volume etc\n const { embed, media, paused, volume } = player;\n const restorePause = paused && !embed.hasPlayed;\n\n // Set seeking state and trigger event\n media.seeking = true;\n triggerEvent.call(player, media, 'seeking');\n\n // If paused, mute until seek is complete\n Promise.resolve(restorePause && embed.setVolume(0))\n // Seek\n .then(() => embed.setCurrentTime(time))\n // Restore paused\n .then(() => restorePause && embed.pause())\n // Restore volume\n .then(() => restorePause && embed.setVolume(volume))\n .catch(() => {\n // Do nothing\n });\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n player.embed\n .setPlaybackRate(input)\n .then(() => {\n speed = input;\n triggerEvent.call(player, player.media, 'ratechange');\n })\n .catch(() => {\n // Cannot set Playback Rate, Video is probably not on Pro account\n player.options.speed = [1];\n });\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n player.embed.setVolume(input).then(() => {\n volume = input;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : false;\n\n player.embed.setMuted(toggle ? true : player.config.muted).then(() => {\n muted = toggle;\n triggerEvent.call(player, player.media, 'volumechange');\n });\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : player.config.loop.active;\n\n player.embed.setLoop(toggle).then(() => {\n loop = toggle;\n });\n },\n });\n\n // Source\n let currentSrc;\n player.embed\n .getVideoUrl()\n .then((value) => {\n currentSrc = value;\n controls.setDownloadUrl.call(player);\n })\n .catch((error) => {\n this.debug.warn(error);\n });\n\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then((dimensions) => {\n const [width, height] = dimensions;\n player.embed.ratio = roundAspectRatio(width, height);\n setAspectRatio.call(this);\n });\n\n // Set autopause\n player.embed.setAutopause(player.config.autopause).then((state) => {\n player.config.autopause = state;\n });\n\n // Get title\n player.embed.getVideoTitle().then((title) => {\n player.config.title = title;\n ui.setTitle.call(this);\n });\n\n // Get current time\n player.embed.getCurrentTime().then((value) => {\n currentTime = value;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then((value) => {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then((tracks) => {\n player.media.textTracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', ({ cues = [] }) => {\n const strippedCues = cues.map((cue) => stripHTML(cue.text));\n captions.updateCues.call(player, strippedCues);\n });\n\n player.embed.on('loaded', () => {\n // Assure state and events are updated on autoplay\n player.embed.getPaused().then((paused) => {\n assurePlaybackState.call(player, !paused);\n if (!paused) {\n triggerEvent.call(player, player.media, 'playing');\n }\n });\n\n if (is.element(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('bufferstart', () => {\n triggerEvent.call(player, player.media, 'waiting');\n });\n\n player.embed.on('bufferend', () => {\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('play', () => {\n assurePlaybackState.call(player, true);\n triggerEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n assurePlaybackState.call(player, false);\n });\n\n player.embed.on('timeupdate', (data) => {\n player.media.seeking = false;\n currentTime = data.seconds;\n triggerEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', (data) => {\n player.media.buffered = data.percent;\n triggerEvent.call(player, player.media, 'progress');\n\n // Check all loaded\n if (parseInt(data.percent, 10) === 1) {\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n\n // Get duration as if we do it before load, it gives an incorrect value\n // https://github.com/sampotts/plyr/issues/891\n player.embed.getDuration().then((value) => {\n if (value !== player.media.duration) {\n player.media.duration = value;\n triggerEvent.call(player, player.media, 'durationchange');\n }\n });\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n triggerEvent.call(player, player.media, 'ended');\n });\n\n player.embed.on('error', (detail) => {\n player.media.error = detail;\n triggerEvent.call(player, player.media, 'error');\n });\n\n // Rebuild UI\n if (config.customControls) {\n setTimeout(() => ui.build.call(player), 0);\n }\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// YouTube plugin\n// ==========================================================================\n\nimport ui from '../ui';\nimport { createElement, replaceElement, toggleClass } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport loadImage from '../utils/load-image';\nimport loadScript from '../utils/load-script';\nimport { extend } from '../utils/objects';\nimport { format, generateId } from '../utils/strings';\nimport { roundAspectRatio, setAspectRatio } from '../utils/style';\n\n// Parse YouTube ID from URL\nfunction parseId(url) {\n if (is.empty(url)) {\n return null;\n }\n\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n}\n\n// Set playback state and trigger change (only on actual change)\nfunction assurePlaybackState(play) {\n if (play && !this.embed.hasPlayed) {\n this.embed.hasPlayed = true;\n }\n if (this.media.paused === play) {\n this.media.paused = !play;\n triggerEvent.call(this, this.media, play ? 'play' : 'pause');\n }\n}\n\nfunction getHost(config) {\n if (config.noCookie) {\n return 'https://www.youtube-nocookie.com';\n }\n\n if (window.location.protocol === 'http:') {\n return 'http://www.youtube.com';\n }\n\n // Use YouTube's default\n return undefined;\n}\n\nconst youtube = {\n setup() {\n // Add embed class for responsive\n toggleClass(this.elements.wrapper, this.config.classNames.embed, true);\n\n // Setup API\n if (is.object(window.YT) && is.function(window.YT.Player)) {\n youtube.ready.call(this);\n } else {\n // Reference current global callback\n const callback = window.onYouTubeIframeAPIReady;\n\n // Set callback to process queue\n window.onYouTubeIframeAPIReady = () => {\n // Call global callback if set\n if (is.function(callback)) {\n callback();\n }\n\n youtube.ready.call(this);\n };\n\n // Load the SDK\n loadScript(this.config.urls.youtube.sdk).catch((error) => {\n this.debug.warn('YouTube API failed to load', error);\n });\n }\n },\n\n // Get the media title\n getTitle(videoId) {\n const url = format(this.config.urls.youtube.api, videoId);\n\n fetch(url)\n .then((data) => {\n if (is.object(data)) {\n const { title, height, width } = data;\n\n // Set title\n this.config.title = title;\n ui.setTitle.call(this);\n\n // Set aspect ratio\n this.embed.ratio = roundAspectRatio(width, height);\n }\n\n setAspectRatio.call(this);\n })\n .catch(() => {\n // Set aspect ratio\n setAspectRatio.call(this);\n });\n },\n\n // API ready\n ready() {\n const player = this;\n const config = player.config.youtube;\n // Ignore already setup (race condition)\n const currentId = player.media && player.media.getAttribute('id');\n if (!is.empty(currentId) && currentId.startsWith('youtube-')) {\n return;\n }\n\n // Get the source URL or ID\n let source = player.media.getAttribute('src');\n\n // Get from <div> if needed\n if (is.empty(source)) {\n source = player.media.getAttribute(this.config.attributes.embed.id);\n }\n\n // Replace the <iframe> with a <div> due to YouTube API issues\n const videoId = parseId(source);\n const id = generateId(player.provider);\n // Replace media element\n const container = createElement('div', { id, 'data-poster': config.customControls ? player.poster : undefined });\n player.media = replaceElement(container, player.media);\n\n // Only load the poster when using custom controls\n if (config.customControls) {\n const posterSrc = (s) => `https://i.ytimg.com/vi/${videoId}/${s}default.jpg`;\n\n // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide)\n loadImage(posterSrc('maxres'), 121) // Highest quality and un-padded\n .catch(() => loadImage(posterSrc('sd'), 121)) // 480p padded 4:3\n .catch(() => loadImage(posterSrc('hq'))) // 360p padded 4:3. Always exists\n .then((image) => ui.setPoster.call(player, image.src))\n .then((src) => {\n // If the image is padded, use background-size \"cover\" instead (like youtube does too with their posters)\n if (!src.includes('maxres')) {\n player.elements.poster.style.backgroundSize = 'cover';\n }\n })\n .catch(() => {});\n }\n\n // Setup instance\n // https://developers.google.com/youtube/iframe_api_reference\n player.embed = new window.YT.Player(player.media, {\n videoId,\n host: getHost(config),\n playerVars: extend(\n {},\n {\n // Autoplay\n autoplay: player.config.autoplay ? 1 : 0,\n // iframe interface language\n hl: player.config.hl,\n // Only show controls if not fully supported or opted out\n controls: player.supported.ui && config.customControls ? 0 : 1,\n // Disable keyboard as we handle it\n disablekb: 1,\n // Allow iOS inline playback\n playsinline: player.config.playsinline && !player.config.fullscreen.iosNative ? 1 : 0,\n // Captions are flaky on YouTube\n cc_load_policy: player.captions.active ? 1 : 0,\n cc_lang_pref: player.config.captions.language,\n // Tracking for stats\n widget_referrer: window ? window.location.href : null,\n },\n config,\n ),\n events: {\n onError(event) {\n // YouTube may fire onError twice, so only handle it once\n if (!player.media.error) {\n const code = event.data;\n // Messages copied from https://developers.google.com/youtube/iframe_api_reference#onError\n const message =\n {\n 2: 'The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.',\n 5: 'The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.',\n 100: 'The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.',\n 101: 'The owner of the requested video does not allow it to be played in embedded players.',\n 150: 'The owner of the requested video does not allow it to be played in embedded players.',\n }[code] || 'An unknown error occurred';\n\n player.media.error = { code, message };\n\n triggerEvent.call(player, player.media, 'error');\n }\n },\n onPlaybackRateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Get current speed\n player.media.playbackRate = instance.getPlaybackRate();\n\n triggerEvent.call(player, player.media, 'ratechange');\n },\n onReady(event) {\n // Bail if onReady has already been called. See issue #1108\n if (is.function(player.media.play)) {\n return;\n }\n // Get the instance\n const instance = event.target;\n\n // Get the title\n youtube.getTitle.call(player, videoId);\n\n // Create a faux HTML5 API using the YouTube API\n player.media.play = () => {\n assurePlaybackState.call(player, true);\n instance.playVideo();\n };\n\n player.media.pause = () => {\n assurePlaybackState.call(player, false);\n instance.pauseVideo();\n };\n\n player.media.stop = () => {\n instance.stopVideo();\n };\n\n player.media.duration = instance.getDuration();\n player.media.paused = true;\n\n // Seeking\n player.media.currentTime = 0;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return Number(instance.getCurrentTime());\n },\n set(time) {\n // If paused and never played, mute audio preventively (YouTube starts playing on seek if the video hasn't been played yet).\n if (player.paused && !player.embed.hasPlayed) {\n player.embed.mute();\n }\n\n // Set seeking state and trigger event\n player.media.seeking = true;\n triggerEvent.call(player, player.media, 'seeking');\n\n // Seek after events sent\n instance.seekTo(time);\n },\n });\n\n // Playback speed\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return instance.getPlaybackRate();\n },\n set(input) {\n instance.setPlaybackRate(input);\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = is.boolean(input) ? input : muted;\n muted = toggle;\n instance[toggle ? 'mute' : 'unMute']();\n instance.setVolume(volume * 100);\n triggerEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Source\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return instance.getVideoUrl();\n },\n });\n\n // Ended\n Object.defineProperty(player.media, 'ended', {\n get() {\n return player.currentTime === player.duration;\n },\n });\n\n // Get available speeds\n const speeds = instance.getAvailablePlaybackRates();\n // Filter based on config\n player.options.speed = speeds.filter((s) => player.config.speed.options.includes(s));\n\n // Set the tabindex to avoid focus entering iframe\n if (player.supported.ui && config.customControls) {\n player.media.setAttribute('tabindex', -1);\n }\n\n triggerEvent.call(player, player.media, 'timeupdate');\n triggerEvent.call(player, player.media, 'durationchange');\n\n // Reset timer\n clearInterval(player.timers.buffering);\n\n // Setup buffering\n player.timers.buffering = setInterval(() => {\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n\n // Trigger progress only when we actually buffer something\n if (player.media.lastBuffered === null || player.media.lastBuffered < player.media.buffered) {\n triggerEvent.call(player, player.media, 'progress');\n }\n\n // Set last buffer point\n player.media.lastBuffered = player.media.buffered;\n\n // Bail if we're at 100%\n if (player.media.buffered === 1) {\n clearInterval(player.timers.buffering);\n\n // Trigger event\n triggerEvent.call(player, player.media, 'canplaythrough');\n }\n }, 200);\n\n // Rebuild UI\n if (config.customControls) {\n setTimeout(() => ui.build.call(player), 50);\n }\n },\n onStateChange(event) {\n // Get the instance\n const instance = event.target;\n\n // Reset timer\n clearInterval(player.timers.playing);\n\n const seeked = player.media.seeking && [1, 2].includes(event.data);\n\n if (seeked) {\n // Unset seeking and fire seeked event\n player.media.seeking = false;\n triggerEvent.call(player, player.media, 'seeked');\n }\n\n // Handle events\n // -1 Unstarted\n // 0 Ended\n // 1 Playing\n // 2 Paused\n // 3 Buffering\n // 5 Video cued\n switch (event.data) {\n case -1:\n // Update scrubber\n triggerEvent.call(player, player.media, 'timeupdate');\n\n // Get loaded % from YouTube\n player.media.buffered = instance.getVideoLoadedFraction();\n triggerEvent.call(player, player.media, 'progress');\n\n break;\n\n case 0:\n assurePlaybackState.call(player, false);\n\n // YouTube doesn't support loop for a single video, so mimick it.\n if (player.media.loop) {\n // YouTube needs a call to `stopVideo` before playing again\n instance.stopVideo();\n instance.playVideo();\n } else {\n triggerEvent.call(player, player.media, 'ended');\n }\n\n break;\n\n case 1:\n // Restore paused state (YouTube starts playing on seek if the video hasn't been played yet)\n if (config.customControls && !player.config.autoplay && player.media.paused && !player.embed.hasPlayed) {\n player.media.pause();\n } else {\n assurePlaybackState.call(player, true);\n\n triggerEvent.call(player, player.media, 'playing');\n\n // Poll to get playback progress\n player.timers.playing = setInterval(() => {\n triggerEvent.call(player, player.media, 'timeupdate');\n }, 50);\n\n // Check duration again due to YouTube bug\n // https://github.com/sampotts/plyr/issues/374\n // https://code.google.com/p/gdata-issues/issues/detail?id=8690\n if (player.media.duration !== instance.getDuration()) {\n player.media.duration = instance.getDuration();\n triggerEvent.call(player, player.media, 'durationchange');\n }\n }\n\n break;\n\n case 2:\n // Restore audio (YouTube starts playing on seek if the video hasn't been played yet)\n if (!player.muted) {\n player.embed.unMute();\n }\n assurePlaybackState.call(player, false);\n\n break;\n\n case 3:\n // Trigger waiting event to add loading classes to container as the video buffers.\n triggerEvent.call(player, player.media, 'waiting');\n\n break;\n\n default:\n break;\n }\n\n triggerEvent.call(player, player.elements.container, 'statechange', false, {\n code: event.data,\n });\n },\n },\n });\n },\n};\n\nexport default youtube;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport html5 from './html5';\nimport vimeo from './plugins/vimeo';\nimport youtube from './plugins/youtube';\nimport { createElement, toggleClass, wrap } from './utils/elements';\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.debug.warn('No media element found!');\n return;\n }\n\n // Add type class\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add provider class\n toggleClass(this.elements.container, this.config.classNames.provider.replace('{0}', this.provider), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n // Inject the player wrapper\n if (this.isVideo) {\n // Create the wrapper div\n this.elements.wrapper = createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n wrap(this.media, this.elements.wrapper);\n\n // Poster image container\n this.elements.poster = createElement('div', {\n class: this.config.classNames.poster,\n });\n\n this.elements.wrapper.appendChild(this.elements.poster);\n }\n\n if (this.isHTML5) {\n html5.setup.call(this);\n } else if (this.isYouTube) {\n youtube.setup.call(this);\n } else if (this.isVimeo) {\n vimeo.setup.call(this);\n }\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Advertisement plugin using Google IMA HTML5 SDK\n// Create an account with our ad partner, vi here:\n// https://www.vi.ai/publisher-video-monetization/\n// ==========================================================================\n\n/* global google */\n\nimport { createElement } from '../utils/elements';\nimport { triggerEvent } from '../utils/events';\nimport i18n from '../utils/i18n';\nimport is from '../utils/is';\nimport loadScript from '../utils/load-script';\nimport { silencePromise } from '../utils/promise';\nimport { formatTime } from '../utils/time';\nimport { buildUrlParams } from '../utils/urls';\n\nconst destroy = (instance) => {\n // Destroy our adsManager\n if (instance.manager) {\n instance.manager.destroy();\n }\n\n // Destroy our adsManager\n if (instance.elements.displayContainer) {\n instance.elements.displayContainer.destroy();\n }\n\n instance.elements.container.remove();\n};\n\nclass Ads {\n /**\n * Ads constructor.\n * @param {Object} player\n * @return {Ads}\n */\n constructor(player) {\n this.player = player;\n this.config = player.config.ads;\n this.playing = false;\n this.initialized = false;\n this.elements = {\n container: null,\n displayContainer: null,\n };\n this.manager = null;\n this.loader = null;\n this.cuePoints = null;\n this.events = {};\n this.safetyTimer = null;\n this.countdownTimer = null;\n\n // Setup a promise to resolve when the IMA manager is ready\n this.managerPromise = new Promise((resolve, reject) => {\n // The ad is loaded and ready\n this.on('loaded', resolve);\n\n // Ads failed\n this.on('error', reject);\n });\n\n this.load();\n }\n\n get enabled() {\n const { config } = this;\n\n return (\n this.player.isHTML5 &&\n this.player.isVideo &&\n config.enabled &&\n (!is.empty(config.publisherId) || is.url(config.tagUrl))\n );\n }\n\n /**\n * Load the IMA SDK\n */\n load = () => {\n if (!this.enabled) {\n return;\n }\n\n // Check if the Google IMA3 SDK is loaded or load it ourselves\n if (!is.object(window.google) || !is.object(window.google.ima)) {\n loadScript(this.player.config.urls.googleIMA.sdk)\n .then(() => {\n this.ready();\n })\n .catch(() => {\n // Script failed to load or is blocked\n this.trigger('error', new Error('Google IMA SDK failed to load'));\n });\n } else {\n this.ready();\n }\n };\n\n /**\n * Get the ads instance ready\n */\n ready = () => {\n // Double check we're enabled\n if (!this.enabled) {\n destroy(this);\n }\n\n // Start ticking our safety timer. If the whole advertisement\n // thing doesn't resolve within our set time; we bail\n this.startSafetyTimer(12000, 'ready()');\n\n // Clear the safety timer\n this.managerPromise.then(() => {\n this.clearSafetyTimer('onAdsManagerLoaded()');\n });\n\n // Set listeners on the Plyr instance\n this.listeners();\n\n // Setup the IMA SDK\n this.setupIMA();\n };\n\n // Build the tag URL\n get tagUrl() {\n const { config } = this;\n\n if (is.url(config.tagUrl)) {\n return config.tagUrl;\n }\n\n const params = {\n AV_PUBLISHERID: '58c25bb0073ef448b1087ad6',\n AV_CHANNELID: '5a0458dc28a06145e4519d21',\n AV_URL: window.location.hostname,\n cb: Date.now(),\n AV_WIDTH: 640,\n AV_HEIGHT: 480,\n AV_CDIM2: config.publisherId,\n };\n\n const base = 'https://go.aniview.com/api/adserver6/vast/';\n\n return `${base}?${buildUrlParams(params)}`;\n }\n\n /**\n * In order for the SDK to display ads for our video, we need to tell it where to put them,\n * so here we define our ad container. This div is set up to render on top of the video player.\n * Using the code below, we tell the SDK to render ads within that div. We also provide a\n * handle to the content video player - the SDK will poll the current time of our player to\n * properly place mid-rolls. After we create the ad display container, we initialize it. On\n * mobile devices, this initialization is done as the result of a user action.\n */\n setupIMA = () => {\n // Create the container for our advertisements\n this.elements.container = createElement('div', {\n class: this.player.config.classNames.ads,\n });\n\n this.player.elements.container.appendChild(this.elements.container);\n\n // So we can run VPAID2\n google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);\n\n // Set language\n google.ima.settings.setLocale(this.player.config.ads.language);\n\n // Set playback for iOS10+\n google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline);\n\n // We assume the adContainer is the video container of the plyr element that will house the ads\n this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media);\n\n // Create ads loader\n this.loader = new google.ima.AdsLoader(this.elements.displayContainer);\n\n // Listen and respond to ads loaded and error events\n this.loader.addEventListener(\n google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,\n (event) => this.onAdsManagerLoaded(event),\n false,\n );\n this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error), false);\n\n // Request video ads to be pre-loaded\n this.requestAds();\n };\n\n /**\n * Request advertisements\n */\n requestAds = () => {\n const { container } = this.player.elements;\n\n try {\n // Request video ads\n const request = new google.ima.AdsRequest();\n request.adTagUrl = this.tagUrl;\n\n // Specify the linear and nonlinear slot sizes. This helps the SDK\n // to select the correct creative if multiple are returned\n request.linearAdSlotWidth = container.offsetWidth;\n request.linearAdSlotHeight = container.offsetHeight;\n request.nonLinearAdSlotWidth = container.offsetWidth;\n request.nonLinearAdSlotHeight = container.offsetHeight;\n\n // We only overlay ads as we only support video.\n request.forceNonLinearFullSlot = false;\n\n // Mute based on current state\n request.setAdWillPlayMuted(!this.player.muted);\n\n this.loader.requestAds(request);\n } catch (error) {\n this.onAdError(error);\n }\n };\n\n /**\n * Update the ad countdown\n * @param {Boolean} start\n */\n pollCountdown = (start = false) => {\n if (!start) {\n clearInterval(this.countdownTimer);\n this.elements.container.removeAttribute('data-badge-text');\n return;\n }\n\n const update = () => {\n const time = formatTime(Math.max(this.manager.getRemainingTime(), 0));\n const label = `${i18n.get('advertisement', this.player.config)} - ${time}`;\n this.elements.container.setAttribute('data-badge-text', label);\n };\n\n this.countdownTimer = setInterval(update, 100);\n };\n\n /**\n * This method is called whenever the ads are ready inside the AdDisplayContainer\n * @param {Event} event - adsManagerLoadedEvent\n */\n onAdsManagerLoaded = (event) => {\n // Load could occur after a source change (race condition)\n if (!this.enabled) {\n return;\n }\n\n // Get the ads manager\n const settings = new google.ima.AdsRenderingSettings();\n\n // Tell the SDK to save and restore content video state on our behalf\n settings.restoreCustomPlaybackStateOnAdBreakComplete = true;\n settings.enablePreloading = true;\n\n // The SDK is polling currentTime on the contentPlayback. And needs a duration\n // so it can determine when to start the mid- and post-roll\n this.manager = event.getAdsManager(this.player, settings);\n\n // Get the cue points for any mid-rolls by filtering out the pre- and post-roll\n this.cuePoints = this.manager.getCuePoints();\n\n // Add listeners to the required events\n // Advertisement error events\n this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, (error) => this.onAdError(error));\n\n // Advertisement regular events\n Object.keys(google.ima.AdEvent.Type).forEach((type) => {\n this.manager.addEventListener(google.ima.AdEvent.Type[type], (e) => this.onAdEvent(e));\n });\n\n // Resolve our adsManager\n this.trigger('loaded');\n };\n\n addCuePoints = () => {\n // Add advertisement cue's within the time line if available\n if (!is.empty(this.cuePoints)) {\n this.cuePoints.forEach((cuePoint) => {\n if (cuePoint !== 0 && cuePoint !== -1 && cuePoint < this.player.duration) {\n const seekElement = this.player.elements.progress;\n\n if (is.element(seekElement)) {\n const cuePercentage = (100 / this.player.duration) * cuePoint;\n const cue = createElement('span', {\n class: this.player.config.classNames.cues,\n });\n\n cue.style.left = `${cuePercentage.toString()}%`;\n seekElement.appendChild(cue);\n }\n }\n });\n }\n };\n\n /**\n * This is where all the event handling takes place. Retrieve the ad from the event. Some\n * events (e.g. ALL_ADS_COMPLETED) don't have the ad object associated\n * https://developers.google.com/interactive-media-ads/docs/sdks/html5/v3/apis#ima.AdEvent.Type\n * @param {Event} event\n */\n onAdEvent = (event) => {\n const { container } = this.player.elements;\n // Retrieve the ad from the event. Some events (e.g. ALL_ADS_COMPLETED)\n // don't have ad object associated\n const ad = event.getAd();\n const adData = event.getAdData();\n\n // Proxy event\n const dispatchEvent = (type) => {\n triggerEvent.call(this.player, this.player.media, `ads${type.replace(/_/g, '').toLowerCase()}`);\n };\n\n // Bubble the event\n dispatchEvent(event.type);\n\n switch (event.type) {\n case google.ima.AdEvent.Type.LOADED:\n // This is the first event sent for an ad - it is possible to determine whether the\n // ad is a video ad or an overlay\n this.trigger('loaded');\n\n // Start countdown\n this.pollCountdown(true);\n\n if (!ad.isLinear()) {\n // Position AdDisplayContainer correctly for overlay\n ad.width = container.offsetWidth;\n ad.height = container.offsetHeight;\n }\n\n // console.info('Ad type: ' + event.getAd().getAdPodInfo().getPodIndex());\n // console.info('Ad time: ' + event.getAd().getAdPodInfo().getTimeOffset());\n\n break;\n\n case google.ima.AdEvent.Type.STARTED:\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n break;\n\n case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:\n // All ads for the current videos are done. We can now request new advertisements\n // in case the video is re-played\n\n // TODO: Example for what happens when a next video in a playlist would be loaded.\n // So here we load a new video when all ads are done.\n // Then we load new ads within a new adsManager. When the video\n // Is started - after - the ads are loaded, then we get ads.\n // You can also easily test cancelling and reloading by running\n // player.ads.cancel() and player.ads.play from the console I guess.\n // this.player.source = {\n // type: 'video',\n // title: 'View From A Blue Moon',\n // sources: [{\n // src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.mp4', type:\n // 'video/mp4', }], poster:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg', tracks:\n // [ { kind: 'captions', label: 'English', srclang: 'en', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt',\n // default: true, }, { kind: 'captions', label: 'French', srclang: 'fr', src:\n // 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.fr.vtt', }, ],\n // };\n\n // TODO: So there is still this thing where a video should only be allowed to start\n // playing when the IMA SDK is ready or has failed\n\n if (this.player.ended) {\n this.loadAds();\n } else {\n // The SDK won't allow new ads to be called without receiving a contentComplete()\n this.loader.contentComplete();\n }\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:\n // This event indicates the ad has started - the video player can adjust the UI,\n // for example display a pause button and remaining time. Fired when content should\n // be paused. This usually happens right before an ad is about to cover the content\n\n this.pauseContent();\n\n break;\n\n case google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED:\n // This event indicates the ad has finished - the video player can perform\n // appropriate UI actions, such as removing the timer for remaining time detection.\n // Fired when content should be resumed. This usually happens when an ad finishes\n // or collapses\n\n this.pollCountdown();\n\n this.resumeContent();\n\n break;\n\n case google.ima.AdEvent.Type.LOG:\n if (adData.adError) {\n this.player.debug.warn(`Non-fatal ad error: ${adData.adError.getMessage()}`);\n }\n\n break;\n\n default:\n break;\n }\n };\n\n /**\n * Any ad error handling comes through here\n * @param {Event} event\n */\n onAdError = (event) => {\n this.cancel();\n this.player.debug.warn('Ads error', event);\n };\n\n /**\n * Setup hooks for Plyr and window events. This ensures\n * the mid- and post-roll launch at the correct time. And\n * resize the advertisement when the player resizes\n */\n listeners = () => {\n const { container } = this.player.elements;\n let time;\n\n this.player.on('canplay', () => {\n this.addCuePoints();\n });\n\n this.player.on('ended', () => {\n this.loader.contentComplete();\n });\n\n this.player.on('timeupdate', () => {\n time = this.player.currentTime;\n });\n\n this.player.on('seeked', () => {\n const seekedTime = this.player.currentTime;\n\n if (is.empty(this.cuePoints)) {\n return;\n }\n\n this.cuePoints.forEach((cuePoint, index) => {\n if (time < cuePoint && cuePoint < seekedTime) {\n this.manager.discardAdBreak();\n this.cuePoints.splice(index, 1);\n }\n });\n });\n\n // Listen to the resizing of the window. And resize ad accordingly\n // TODO: eventually implement ResizeObserver\n window.addEventListener('resize', () => {\n if (this.manager) {\n this.manager.resize(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n }\n });\n };\n\n /**\n * Initialize the adsManager and start playing advertisements\n */\n play = () => {\n const { container } = this.player.elements;\n\n if (!this.managerPromise) {\n this.resumeContent();\n }\n\n // Play the requested advertisement whenever the adsManager is ready\n this.managerPromise\n .then(() => {\n // Set volume to match player\n this.manager.setVolume(this.player.volume);\n\n // Initialize the container. Must be done via a user action on mobile devices\n this.elements.displayContainer.initialize();\n\n try {\n if (!this.initialized) {\n // Initialize the ads manager. Ad rules playlist will start at this time\n this.manager.init(container.offsetWidth, container.offsetHeight, google.ima.ViewMode.NORMAL);\n\n // Call play to start showing the ad. Single video and overlay ads will\n // start at this time; the call will be ignored for ad rules\n this.manager.start();\n }\n\n this.initialized = true;\n } catch (adError) {\n // An error may be thrown if there was a problem with the\n // VAST response\n this.onAdError(adError);\n }\n })\n .catch(() => {});\n };\n\n /**\n * Resume our video\n */\n resumeContent = () => {\n // Hide the advertisement container\n this.elements.container.style.zIndex = '';\n\n // Ad is stopped\n this.playing = false;\n\n // Play video\n silencePromise(this.player.media.play());\n };\n\n /**\n * Pause our video\n */\n pauseContent = () => {\n // Show the advertisement container\n this.elements.container.style.zIndex = 3;\n\n // Ad is playing\n this.playing = true;\n\n // Pause our video.\n this.player.media.pause();\n };\n\n /**\n * Destroy the adsManager so we can grab new ads after this. If we don't then we're not\n * allowed to call new ads based on google policies, as they interpret this as an accidental\n * video requests. https://developers.google.com/interactive-\n * media-ads/docs/sdks/android/faq#8\n */\n cancel = () => {\n // Pause our video\n if (this.initialized) {\n this.resumeContent();\n }\n\n // Tell our instance that we're done for now\n this.trigger('error');\n\n // Re-create our adsManager\n this.loadAds();\n };\n\n /**\n * Re-create our adsManager\n */\n loadAds = () => {\n // Tell our adsManager to go bye bye\n this.managerPromise\n .then(() => {\n // Destroy our adsManager\n if (this.manager) {\n this.manager.destroy();\n }\n\n // Re-set our adsManager promises\n this.managerPromise = new Promise((resolve) => {\n this.on('loaded', resolve);\n this.player.debug.log(this.manager);\n });\n // Now that the manager has been destroyed set it to also be un-initialized\n this.initialized = false;\n\n // Now request some new advertisements\n this.requestAds();\n })\n .catch(() => {});\n };\n\n /**\n * Handles callbacks after an ad event was invoked\n * @param {String} event - Event type\n * @param args\n */\n trigger = (event, ...args) => {\n const handlers = this.events[event];\n\n if (is.array(handlers)) {\n handlers.forEach((handler) => {\n if (is.function(handler)) {\n handler.apply(this, args);\n }\n });\n }\n };\n\n /**\n * Add event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n * @return {Ads}\n */\n on = (event, callback) => {\n if (!is.array(this.events[event])) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n };\n\n /**\n * Setup a safety timer for when the ad network doesn't respond for whatever reason.\n * The advertisement has 12 seconds to get its things together. We stop this timer when the\n * advertisement is playing, or when a user action is required to start, then we clear the\n * timer on ad ready\n * @param {Number} time\n * @param {String} from\n */\n startSafetyTimer = (time, from) => {\n this.player.debug.log(`Safety timer invoked from: ${from}`);\n\n this.safetyTimer = setTimeout(() => {\n this.cancel();\n this.clearSafetyTimer('startSafetyTimer()');\n }, time);\n };\n\n /**\n * Clear our safety timer(s)\n * @param {String} from\n */\n clearSafetyTimer = (from) => {\n if (!is.nullOrUndefined(this.safetyTimer)) {\n this.player.debug.log(`Safety timer cleared from: ${from}`);\n\n clearTimeout(this.safetyTimer);\n this.safetyTimer = null;\n }\n };\n}\n\nexport default Ads;\n","/**\n * Returns a number whose value is limited to the given range.\n *\n * Example: limit the output of this computation to between 0 and 255\n * (x * 255).clamp(0, 255)\n *\n * @param {Number} input\n * @param {Number} min The lower boundary of the output range\n * @param {Number} max The upper boundary of the output range\n * @returns A number within the bounds of min and max\n * @type Number\n */\nexport function clamp(input = 0, min = 0, max = 255) {\n return Math.min(Math.max(input, min), max);\n}\n\nexport default { clamp };\n","import { createElement } from '../utils/elements';\nimport { once } from '../utils/events';\nimport fetch from '../utils/fetch';\nimport is from '../utils/is';\nimport { clamp } from '../utils/numbers';\nimport { formatTime } from '../utils/time';\n\n// Arg: vttDataString example: \"WEBVTT\\n\\n1\\n00:00:05.000 --> 00:00:10.000\\n1080p-00001.jpg\"\nconst parseVtt = (vttDataString) => {\n const processedList = [];\n const frames = vttDataString.split(/\\r\\n\\r\\n|\\n\\n|\\r\\r/);\n\n frames.forEach((frame) => {\n const result = {};\n const lines = frame.split(/\\r\\n|\\n|\\r/);\n\n lines.forEach((line) => {\n if (!is.number(result.startTime)) {\n // The line with start and end times on it is the first line of interest\n const matchTimes = line.match(\n /([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})( ?--> ?)([0-9]{2})?:?([0-9]{2}):([0-9]{2}).([0-9]{2,3})/,\n ); // Note that this currently ignores caption formatting directives that are optionally on the end of this line - fine for non-captions VTT\n\n if (matchTimes) {\n result.startTime =\n Number(matchTimes[1] || 0) * 60 * 60 +\n Number(matchTimes[2]) * 60 +\n Number(matchTimes[3]) +\n Number(`0.${matchTimes[4]}`);\n result.endTime =\n Number(matchTimes[6] || 0) * 60 * 60 +\n Number(matchTimes[7]) * 60 +\n Number(matchTimes[8]) +\n Number(`0.${matchTimes[9]}`);\n }\n } else if (!is.empty(line.trim()) && is.empty(result.text)) {\n // If we already have the startTime, then we're definitely up to the text line(s)\n const lineSplit = line.trim().split('#xywh=');\n [result.text] = lineSplit;\n\n // If there's content in lineSplit[1], then we have sprites. If not, then it's just one frame per image\n if (lineSplit[1]) {\n [result.x, result.y, result.w, result.h] = lineSplit[1].split(',');\n }\n }\n });\n\n if (result.text) {\n processedList.push(result);\n }\n });\n\n return processedList;\n};\n\n/**\n * Preview thumbnails for seek hover and scrubbing\n * Seeking: Hover over the seek bar (desktop only): shows a small preview container above the seek bar\n * Scrubbing: Click and drag the seek bar (desktop and mobile): shows the preview image over the entire video, as if the video is scrubbing at very high speed\n *\n * Notes:\n * - Thumbs are set via JS settings on Plyr init, not HTML5 'track' property. Using the track property would be a bit gross, because it doesn't support custom 'kinds'. kind=metadata might be used for something else, and we want to allow multiple thumbnails tracks. Tracks must have a unique combination of 'kind' and 'label'. We would have to do something like kind=metadata,label=thumbnails1 / kind=metadata,label=thumbnails2. Square peg, round hole\n * - VTT info: the image URL is relative to the VTT, not the current document. But if the url starts with a slash, it will naturally be relative to the current domain. https://support.jwplayer.com/articles/how-to-add-preview-thumbnails\n * - This implementation uses multiple separate img elements. Other implementations use background-image on one element. This would be nice and simple, but Firefox and Safari have flickering issues with replacing backgrounds of larger images. It seems that YouTube perhaps only avoids this because they don't have the option for high-res previews (even the fullscreen ones, when mousedown/seeking). Images appear over the top of each other, and previous ones are discarded once the new ones have been rendered\n */\n\nconst fitRatio = (ratio, outer) => {\n const targetRatio = outer.width / outer.height;\n const result = {};\n if (ratio > targetRatio) {\n result.width = outer.width;\n result.height = (1 / ratio) * outer.width;\n } else {\n result.height = outer.height;\n result.width = ratio * outer.height;\n }\n\n return result;\n};\n\nclass PreviewThumbnails {\n /**\n * PreviewThumbnails constructor.\n * @param {Plyr} player\n * @return {PreviewThumbnails}\n */\n constructor(player) {\n this.player = player;\n this.thumbnails = [];\n this.loaded = false;\n this.lastMouseMoveTime = Date.now();\n this.mouseDown = false;\n this.loadedImages = [];\n\n this.elements = {\n thumb: {},\n scrubbing: {},\n };\n\n this.load();\n }\n\n get enabled() {\n return this.player.isHTML5 && this.player.isVideo && this.player.config.previewThumbnails.enabled;\n }\n\n load = () => {\n // Toggle the regular seek tooltip\n if (this.player.elements.display.seekTooltip) {\n this.player.elements.display.seekTooltip.hidden = this.enabled;\n }\n\n if (!this.enabled) return;\n\n this.getThumbnails().then(() => {\n if (!this.enabled) {\n return;\n }\n\n // Render DOM elements\n this.render();\n\n // Check to see if thumb container size was specified manually in CSS\n this.determineContainerAutoSizing();\n\n // Set up listeners\n this.listeners();\n\n this.loaded = true;\n });\n };\n\n // Download VTT files and parse them\n getThumbnails = () => {\n return new Promise((resolve) => {\n const { src } = this.player.config.previewThumbnails;\n\n if (is.empty(src)) {\n throw new Error('Missing previewThumbnails.src config attribute');\n }\n\n // Resolve promise\n const sortAndResolve = () => {\n // Sort smallest to biggest (e.g., [120p, 480p, 1080p])\n this.thumbnails.sort((x, y) => x.height - y.height);\n\n this.player.debug.log('Preview thumbnails', this.thumbnails);\n\n resolve();\n };\n\n // Via callback()\n if (is.function(src)) {\n src((thumbnails) => {\n this.thumbnails = thumbnails;\n sortAndResolve();\n });\n }\n // VTT urls\n else {\n // If string, convert into single-element list\n const urls = is.string(src) ? [src] : src;\n // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails\n const promises = urls.map((u) => this.getThumbnail(u));\n // Resolve\n Promise.all(promises).then(sortAndResolve);\n }\n });\n };\n\n // Process individual VTT file\n getThumbnail = (url) => {\n return new Promise((resolve) => {\n fetch(url).then((response) => {\n const thumbnail = {\n frames: parseVtt(response),\n height: null,\n urlPrefix: '',\n };\n\n // If the URLs don't start with '/', then we need to set their relative path to be the location of the VTT file\n // If the URLs do start with '/', then they obviously don't need a prefix, so it will remain blank\n // If the thumbnail URLs start with with none of '/', 'http://' or 'https://', then we need to set their relative path to be the location of the VTT file\n if (\n !thumbnail.frames[0].text.startsWith('/') &&\n !thumbnail.frames[0].text.startsWith('http://') &&\n !thumbnail.frames[0].text.startsWith('https://')\n ) {\n thumbnail.urlPrefix = url.substring(0, url.lastIndexOf('/') + 1);\n }\n\n // Download the first frame, so that we can determine/set the height of this thumbnailsDef\n const tempImage = new Image();\n\n tempImage.onload = () => {\n thumbnail.height = tempImage.naturalHeight;\n thumbnail.width = tempImage.naturalWidth;\n\n this.thumbnails.push(thumbnail);\n\n resolve();\n };\n\n tempImage.src = thumbnail.urlPrefix + thumbnail.frames[0].text;\n });\n });\n };\n\n startMove = (event) => {\n if (!this.loaded) return;\n\n if (!is.event(event) || !['touchmove', 'mousemove'].includes(event.type)) return;\n\n // Wait until media has a duration\n if (!this.player.media.duration) return;\n\n if (event.type === 'touchmove') {\n // Calculate seek hover position as approx video seconds\n this.seekTime = this.player.media.duration * (this.player.elements.inputs.seek.value / 100);\n } else {\n // Calculate seek hover position as approx video seconds\n const clientRect = this.player.elements.progress.getBoundingClientRect();\n const percentage = (100 / clientRect.width) * (event.pageX - clientRect.left);\n this.seekTime = this.player.media.duration * (percentage / 100);\n\n if (this.seekTime < 0) {\n // The mousemove fires for 10+px out to the left\n this.seekTime = 0;\n }\n\n if (this.seekTime > this.player.media.duration - 1) {\n // Took 1 second off the duration for safety, because different players can disagree on the real duration of a video\n this.seekTime = this.player.media.duration - 1;\n }\n\n this.mousePosX = event.pageX;\n\n // Set time text inside image container\n this.elements.thumb.time.innerText = formatTime(this.seekTime);\n\n // Get marker point for time\n const point = this.player.config.markers?.points?.find(({ time: t }) => t === Math.round(this.seekTime));\n\n // Append the point label to the tooltip\n if (point) {\n // this.elements.thumb.time.innerText.concat('\\n');\n this.elements.thumb.time.insertAdjacentHTML('afterbegin', `${point.label}<br>`);\n }\n }\n\n // Download and show image\n this.showImageAtCurrentTime();\n };\n\n endMove = () => {\n this.toggleThumbContainer(false, true);\n };\n\n startScrubbing = (event) => {\n // Only act on left mouse button (0), or touch device (event.button does not exist or is false)\n if (is.nullOrUndefined(event.button) || event.button === false || event.button === 0) {\n this.mouseDown = true;\n\n // Wait until media has a duration\n if (this.player.media.duration) {\n this.toggleScrubbingContainer(true);\n this.toggleThumbContainer(false, true);\n\n // Download and show image\n this.showImageAtCurrentTime();\n }\n }\n };\n\n endScrubbing = () => {\n this.mouseDown = false;\n\n // Hide scrubbing preview. But wait until the video has successfully seeked before hiding the scrubbing preview\n if (Math.ceil(this.lastTime) === Math.ceil(this.player.media.currentTime)) {\n // The video was already seeked/loaded at the chosen time - hide immediately\n this.toggleScrubbingContainer(false);\n } else {\n // The video hasn't seeked yet. Wait for that\n once.call(this.player, this.player.media, 'timeupdate', () => {\n // Re-check mousedown - we might have already started scrubbing again\n if (!this.mouseDown) {\n this.toggleScrubbingContainer(false);\n }\n });\n }\n };\n\n /**\n * Setup hooks for Plyr and window events\n */\n listeners = () => {\n // Hide thumbnail preview - on mouse click, mouse leave (in listeners.js for now), and video play/seek. All four are required, e.g., for buffering\n this.player.on('play', () => {\n this.toggleThumbContainer(false, true);\n });\n\n this.player.on('seeked', () => {\n this.toggleThumbContainer(false);\n });\n\n this.player.on('timeupdate', () => {\n this.lastTime = this.player.media.currentTime;\n });\n };\n\n /**\n * Create HTML elements for image containers\n */\n render = () => {\n // Create HTML element: plyr__preview-thumbnail-container\n this.elements.thumb.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.thumbContainer,\n });\n\n // Wrapper for the image for styling\n this.elements.thumb.imageContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.imageContainer,\n });\n this.elements.thumb.container.appendChild(this.elements.thumb.imageContainer);\n\n // Create HTML element, parent+span: time text (e.g., 01:32:00)\n const timeContainer = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.timeContainer,\n });\n\n this.elements.thumb.time = createElement('span', {}, '00:00');\n timeContainer.appendChild(this.elements.thumb.time);\n\n this.elements.thumb.imageContainer.appendChild(timeContainer);\n\n // Inject the whole thumb\n if (is.element(this.player.elements.progress)) {\n this.player.elements.progress.appendChild(this.elements.thumb.container);\n }\n\n // Create HTML element: plyr__preview-scrubbing-container\n this.elements.scrubbing.container = createElement('div', {\n class: this.player.config.classNames.previewThumbnails.scrubbingContainer,\n });\n\n this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);\n };\n\n destroy = () => {\n if (this.elements.thumb.container) {\n this.elements.thumb.container.remove();\n }\n if (this.elements.scrubbing.container) {\n this.elements.scrubbing.container.remove();\n }\n };\n\n showImageAtCurrentTime = () => {\n if (this.mouseDown) {\n this.setScrubbingContainerSize();\n } else {\n this.setThumbContainerSizeAndPos();\n }\n\n // Find the desired thumbnail index\n // TODO: Handle a video longer than the thumbs where thumbNum is null\n const thumbNum = this.thumbnails[0].frames.findIndex(\n (frame) => this.seekTime >= frame.startTime && this.seekTime <= frame.endTime,\n );\n const hasThumb = thumbNum >= 0;\n let qualityIndex = 0;\n\n // Show the thumb container if we're not scrubbing\n if (!this.mouseDown) {\n this.toggleThumbContainer(hasThumb);\n }\n\n // No matching thumb found\n if (!hasThumb) {\n return;\n }\n\n // Check to see if we've already downloaded higher quality versions of this image\n this.thumbnails.forEach((thumbnail, index) => {\n if (this.loadedImages.includes(thumbnail.frames[thumbNum].text)) {\n qualityIndex = index;\n }\n });\n\n // Only proceed if either thumb num or thumbfilename has changed\n if (thumbNum !== this.showingThumb) {\n this.showingThumb = thumbNum;\n this.loadImage(qualityIndex);\n }\n };\n\n // Show the image that's currently specified in this.showingThumb\n loadImage = (qualityIndex = 0) => {\n const thumbNum = this.showingThumb;\n const thumbnail = this.thumbnails[qualityIndex];\n const { urlPrefix } = thumbnail;\n const frame = thumbnail.frames[thumbNum];\n const thumbFilename = thumbnail.frames[thumbNum].text;\n const thumbUrl = urlPrefix + thumbFilename;\n\n if (!this.currentImageElement || this.currentImageElement.dataset.filename !== thumbFilename) {\n // If we're already loading a previous image, remove its onload handler - we don't want it to load after this one\n // Only do this if not using sprites. Without sprites we really want to show as many images as possible, as a best-effort\n if (this.loadingImage && this.usingSprites) {\n this.loadingImage.onload = null;\n }\n\n // We're building and adding a new image. In other implementations of similar functionality (YouTube), background image\n // is instead used. But this causes issues with larger images in Firefox and Safari - switching between background\n // images causes a flicker. Putting a new image over the top does not\n const previewImage = new Image();\n previewImage.src = thumbUrl;\n previewImage.dataset.index = thumbNum;\n previewImage.dataset.filename = thumbFilename;\n this.showingThumbFilename = thumbFilename;\n\n this.player.debug.log(`Loading image: ${thumbUrl}`);\n\n // For some reason, passing the named function directly causes it to execute immediately. So I've wrapped it in an anonymous function...\n previewImage.onload = () => this.showImage(previewImage, frame, qualityIndex, thumbNum, thumbFilename, true);\n this.loadingImage = previewImage;\n this.removeOldImages(previewImage);\n } else {\n // Update the existing image\n this.showImage(this.currentImageElement, frame, qualityIndex, thumbNum, thumbFilename, false);\n this.currentImageElement.dataset.index = thumbNum;\n this.removeOldImages(this.currentImageElement);\n }\n };\n\n showImage = (previewImage, frame, qualityIndex, thumbNum, thumbFilename, newImage = true) => {\n this.player.debug.log(\n `Showing thumb: ${thumbFilename}. num: ${thumbNum}. qual: ${qualityIndex}. newimg: ${newImage}`,\n );\n this.setImageSizeAndOffset(previewImage, frame);\n\n if (newImage) {\n this.currentImageContainer.appendChild(previewImage);\n this.currentImageElement = previewImage;\n\n if (!this.loadedImages.includes(thumbFilename)) {\n this.loadedImages.push(thumbFilename);\n }\n }\n\n // Preload images before and after the current one\n // Show higher quality of the same frame\n // Each step here has a short time delay, and only continues if still hovering/seeking the same spot. This is to protect slow connections from overloading\n this.preloadNearby(thumbNum, true)\n .then(this.preloadNearby(thumbNum, false))\n .then(this.getHigherQuality(qualityIndex, previewImage, frame, thumbFilename));\n };\n\n // Remove all preview images that aren't the designated current image\n removeOldImages = (currentImage) => {\n // Get a list of all images, convert it from a DOM list to an array\n Array.from(this.currentImageContainer.children).forEach((image) => {\n if (image.tagName.toLowerCase() !== 'img') {\n return;\n }\n\n const removeDelay = this.usingSprites ? 500 : 1000;\n\n if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) {\n // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients\n // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function\n // eslint-disable-next-line no-param-reassign\n image.dataset.deleting = true;\n\n // This has to be set before the timeout - to prevent issues switching between hover and scrub\n const { currentImageContainer } = this;\n\n setTimeout(() => {\n currentImageContainer.removeChild(image);\n this.player.debug.log(`Removing thumb: ${image.dataset.filename}`);\n }, removeDelay);\n }\n });\n };\n\n // Preload images before and after the current one. Only if the user is still hovering/seeking the same frame\n // This will only preload the lowest quality\n preloadNearby = (thumbNum, forward = true) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n const oldThumbFilename = this.thumbnails[0].frames[thumbNum].text;\n\n if (this.showingThumbFilename === oldThumbFilename) {\n // Find the nearest thumbs with different filenames. Sometimes it'll be the next index, but in the case of sprites, it might be 100+ away\n let thumbnailsClone;\n if (forward) {\n thumbnailsClone = this.thumbnails[0].frames.slice(thumbNum);\n } else {\n thumbnailsClone = this.thumbnails[0].frames.slice(0, thumbNum).reverse();\n }\n\n let foundOne = false;\n\n thumbnailsClone.forEach((frame) => {\n const newThumbFilename = frame.text;\n\n if (newThumbFilename !== oldThumbFilename) {\n // Found one with a different filename. Make sure it hasn't already been loaded on this page visit\n if (!this.loadedImages.includes(newThumbFilename)) {\n foundOne = true;\n this.player.debug.log(`Preloading thumb filename: ${newThumbFilename}`);\n\n const { urlPrefix } = this.thumbnails[0];\n const thumbURL = urlPrefix + newThumbFilename;\n const previewImage = new Image();\n previewImage.src = thumbURL;\n previewImage.onload = () => {\n this.player.debug.log(`Preloaded thumb filename: ${newThumbFilename}`);\n if (!this.loadedImages.includes(newThumbFilename)) this.loadedImages.push(newThumbFilename);\n\n // We don't resolve until the thumb is loaded\n resolve();\n };\n }\n }\n });\n\n // If there are none to preload then we want to resolve immediately\n if (!foundOne) {\n resolve();\n }\n }\n }, 300);\n });\n };\n\n // If user has been hovering current image for half a second, look for a higher quality one\n getHigherQuality = (currentQualityIndex, previewImage, frame, thumbFilename) => {\n if (currentQualityIndex < this.thumbnails.length - 1) {\n // Only use the higher quality version if it's going to look any better - if the current thumb is of a lower pixel density than the thumbnail container\n let previewImageHeight = previewImage.naturalHeight;\n\n if (this.usingSprites) {\n previewImageHeight = frame.h;\n }\n\n if (previewImageHeight < this.thumbContainerHeight) {\n // Recurse back to the loadImage function - show a higher quality one, but only if the viewer is on this frame for a while\n setTimeout(() => {\n // Make sure the mouse hasn't already moved on and started hovering at another image\n if (this.showingThumbFilename === thumbFilename) {\n this.player.debug.log(`Showing higher quality thumb for: ${thumbFilename}`);\n this.loadImage(currentQualityIndex + 1);\n }\n }, 300);\n }\n }\n };\n\n get currentImageContainer() {\n return this.mouseDown ? this.elements.scrubbing.container : this.elements.thumb.imageContainer;\n }\n\n get usingSprites() {\n return Object.keys(this.thumbnails[0].frames[0]).includes('w');\n }\n\n get thumbAspectRatio() {\n if (this.usingSprites) {\n return this.thumbnails[0].frames[0].w / this.thumbnails[0].frames[0].h;\n }\n\n return this.thumbnails[0].width / this.thumbnails[0].height;\n }\n\n get thumbContainerHeight() {\n if (this.mouseDown) {\n const { height } = fitRatio(this.thumbAspectRatio, {\n width: this.player.media.clientWidth,\n height: this.player.media.clientHeight,\n });\n return height;\n }\n\n // If css is used this needs to return the css height for sprites to work (see setImageSizeAndOffset)\n if (this.sizeSpecifiedInCSS) {\n return this.elements.thumb.imageContainer.clientHeight;\n }\n\n return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);\n }\n\n get currentImageElement() {\n return this.mouseDown ? this.currentScrubbingImageElement : this.currentThumbnailImageElement;\n }\n\n set currentImageElement(element) {\n if (this.mouseDown) {\n this.currentScrubbingImageElement = element;\n } else {\n this.currentThumbnailImageElement = element;\n }\n }\n\n toggleThumbContainer = (toggle = false, clearShowing = false) => {\n const className = this.player.config.classNames.previewThumbnails.thumbContainerShown;\n this.elements.thumb.container.classList.toggle(className, toggle);\n\n if (!toggle && clearShowing) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n };\n\n toggleScrubbingContainer = (toggle = false) => {\n const className = this.player.config.classNames.previewThumbnails.scrubbingContainerShown;\n this.elements.scrubbing.container.classList.toggle(className, toggle);\n\n if (!toggle) {\n this.showingThumb = null;\n this.showingThumbFilename = null;\n }\n };\n\n determineContainerAutoSizing = () => {\n if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {\n // This will prevent auto sizing in this.setThumbContainerSizeAndPos()\n this.sizeSpecifiedInCSS = true;\n }\n };\n\n // Set the size to be about a quarter of the size of video. Unless option dynamicSize === false, in which case it needs to be set in CSS\n setThumbContainerSizeAndPos = () => {\n const { imageContainer } = this.elements.thumb;\n\n if (!this.sizeSpecifiedInCSS) {\n const thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);\n imageContainer.style.height = `${this.thumbContainerHeight}px`;\n imageContainer.style.width = `${thumbWidth}px`;\n } else if (imageContainer.clientHeight > 20 && imageContainer.clientWidth < 20) {\n const thumbWidth = Math.floor(imageContainer.clientHeight * this.thumbAspectRatio);\n imageContainer.style.width = `${thumbWidth}px`;\n } else if (imageContainer.clientHeight < 20 && imageContainer.clientWidth > 20) {\n const thumbHeight = Math.floor(imageContainer.clientWidth / this.thumbAspectRatio);\n imageContainer.style.height = `${thumbHeight}px`;\n }\n\n this.setThumbContainerPos();\n };\n\n setThumbContainerPos = () => {\n const scrubberRect = this.player.elements.progress.getBoundingClientRect();\n const containerRect = this.player.elements.container.getBoundingClientRect();\n const { container } = this.elements.thumb;\n // Find the lowest and highest desired left-position, so we don't slide out the side of the video container\n const min = containerRect.left - scrubberRect.left + 10;\n const max = containerRect.right - scrubberRect.left - container.clientWidth - 10;\n // Set preview container position to: mousepos, minus seekbar.left, minus half of previewContainer.clientWidth\n const position = this.mousePosX - scrubberRect.left - container.clientWidth / 2;\n const clamped = clamp(position, min, max);\n\n // Move the popover position\n container.style.left = `${clamped}px`;\n\n // The arrow can follow the cursor\n container.style.setProperty('--preview-arrow-offset', `${position - clamped}px`);\n };\n\n // Can't use 100% width, in case the video is a different aspect ratio to the video container\n setScrubbingContainerSize = () => {\n const { width, height } = fitRatio(this.thumbAspectRatio, {\n width: this.player.media.clientWidth,\n height: this.player.media.clientHeight,\n });\n this.elements.scrubbing.container.style.width = `${width}px`;\n this.elements.scrubbing.container.style.height = `${height}px`;\n };\n\n // Sprites need to be offset to the correct location\n setImageSizeAndOffset = (previewImage, frame) => {\n if (!this.usingSprites) return;\n\n // Find difference between height and preview container height\n const multiplier = this.thumbContainerHeight / frame.h;\n\n // eslint-disable-next-line no-param-reassign\n previewImage.style.height = `${previewImage.naturalHeight * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.width = `${previewImage.naturalWidth * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.left = `-${frame.x * multiplier}px`;\n // eslint-disable-next-line no-param-reassign\n previewImage.style.top = `-${frame.y * multiplier}px`;\n };\n}\n\nexport default PreviewThumbnails;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport { providers } from './config/types';\nimport html5 from './html5';\nimport media from './media';\nimport PreviewThumbnails from './plugins/preview-thumbnails';\nimport support from './support';\nimport ui from './ui';\nimport { createElement, insertElement, removeElement } from './utils/elements';\nimport is from './utils/is';\nimport { getDeep } from './utils/objects';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (is.string(attributes)) {\n insertElement(type, this.media, {\n src: attributes,\n });\n } else if (is.array(attributes)) {\n attributes.forEach((attribute) => {\n insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!getDeep(input, 'sources.length')) {\n this.debug.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // Reset quality options\n this.options.quality = [];\n\n // Remove elements\n removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (is.element(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type and provider\n const { sources, type } = input;\n const [{ provider = providers.html5, src }] = sources;\n const tagName = provider === 'html5' ? type : 'div';\n const attributes = provider === 'html5' ? {} : { src };\n\n Object.assign(this, {\n provider,\n type,\n // Check for support\n supported: support.check(type, provider, this.config.playsinline),\n // Create new element\n media: createElement(tagName, attributes),\n });\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if (!is.empty(input.poster)) {\n this.poster = input.poster;\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.playsinline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hook\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if (Object.keys(input).includes('tracks')) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n\n // Load HTML5 sources\n if (this.isHTML5) {\n this.media.load();\n }\n\n // Update previewThumbnails config & reload plugin\n if (!is.empty(input.previewThumbnails)) {\n Object.assign(this.config.previewThumbnails, input.previewThumbnails);\n\n // Cleanup previewThumbnails plugin if it was loaded\n if (this.previewThumbnails && this.previewThumbnails.loaded) {\n this.previewThumbnails.destroy();\n this.previewThumbnails = null;\n }\n\n // Create new instance if it is still enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // Update the fullscreen support\n this.fullscreen.update();\n },\n true,\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.7.8\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport captions from './captions';\nimport defaults from './config/defaults';\nimport { pip } from './config/states';\nimport { getProviderByUrl, providers, types } from './config/types';\nimport Console from './console';\nimport controls from './controls';\nimport Fullscreen from './fullscreen';\nimport html5 from './html5';\nimport Listeners from './listeners';\nimport media from './media';\nimport Ads from './plugins/ads';\nimport PreviewThumbnails from './plugins/preview-thumbnails';\nimport source from './source';\nimport Storage from './storage';\nimport support from './support';\nimport ui from './ui';\nimport { closest } from './utils/arrays';\nimport { createElement, hasClass, removeElement, replaceElement, toggleClass, wrap } from './utils/elements';\nimport { off, on, once, triggerEvent, unbindListeners } from './utils/events';\nimport is from './utils/is';\nimport loadSprite from './utils/load-sprite';\nimport { clamp } from './utils/numbers';\nimport { cloneDeep, extend } from './utils/objects';\nimport { silencePromise } from './utils/promise';\nimport { getAspectRatio, reduceAspectRatio, setAspectRatio, validateAspectRatio } from './utils/style';\nimport { parseUrl } from './utils/urls';\n\n// Private properties\n// TODO: Use a WeakMap for private globals\n// const globals = new WeakMap();\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n\n // State\n this.ready = false;\n this.loading = false;\n this.failed = false;\n\n // Touch device\n this.touch = support.touch;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = extend(\n {},\n defaults,\n Plyr.defaults,\n options || {},\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr-config'));\n } catch (_) {\n return {};\n }\n })(),\n );\n\n // Elements cache\n this.elements = {\n container: null,\n fullscreen: null,\n captions: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n popup: null,\n menu: null,\n panels: {},\n buttons: {},\n },\n };\n\n // Captions\n this.captions = {\n active: null,\n currentTrack: -1,\n meta: new WeakMap(),\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n // TODO: move to globals\n this.debug = new Console(this.config.debug);\n\n // Log config options and support\n this.debug.log('Config', this.config);\n this.debug.log('Support', support);\n\n // We need an element to setup\n if (is.nullOrUndefined(this.media) || !is.element(this.media)) {\n this.debug.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.debug.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.debug.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n const clone = this.media.cloneNode(true);\n clone.autoplay = false;\n this.elements.original = clone;\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n // Embed properties\n let iframe = null;\n let url = null;\n\n // Different setup based on type\n switch (type) {\n case 'div':\n // Find the frame\n iframe = this.media.querySelector('iframe');\n\n // <iframe> type\n if (is.element(iframe)) {\n // Detect provider\n url = parseUrl(iframe.getAttribute('src'));\n this.provider = getProviderByUrl(url.toString());\n\n // Rework elements\n this.elements.container = this.media;\n this.media = iframe;\n\n // Reset classname\n this.elements.container.className = '';\n\n // Get attributes from URL and set config\n if (url.search.length) {\n const truthy = ['1', 'true'];\n\n if (truthy.includes(url.searchParams.get('autoplay'))) {\n this.config.autoplay = true;\n }\n if (truthy.includes(url.searchParams.get('loop'))) {\n this.config.loop.active = true;\n }\n\n // TODO: replace fullscreen.iosNative with this playsinline config option\n // YouTube requires the playsinline in the URL\n if (this.isYouTube) {\n this.config.playsinline = truthy.includes(url.searchParams.get('playsinline'));\n this.config.youtube.hl = url.searchParams.get('hl'); // TODO: Should this be setting language?\n } else {\n this.config.playsinline = true;\n }\n }\n } else {\n // <div> with attributes\n this.provider = this.media.getAttribute(this.config.attributes.embed.provider);\n\n // Remove attribute\n this.media.removeAttribute(this.config.attributes.embed.provider);\n }\n\n // Unsupported or missing provider\n if (is.empty(this.provider) || !Object.values(providers).includes(this.provider)) {\n this.debug.error('Setup failed: Invalid provider');\n return;\n }\n\n // Audio will come later for external providers\n this.type = types.video;\n\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n this.provider = providers.html5;\n\n // Get config from attributes\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline') || this.media.hasAttribute('webkit-playsinline')) {\n this.config.playsinline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.debug.error('Setup failed: unsupported type');\n return;\n }\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.provider);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.debug.error('Setup failed: no support');\n return;\n }\n\n this.eventListeners = [];\n\n // Create listeners\n this.listeners = new Listeners(this);\n\n // Setup local storage for user settings\n this.storage = new Storage(this);\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n if (!is.element(this.elements.container)) {\n this.elements.container = createElement('div');\n wrap(this.media, this.elements.container);\n }\n\n // Migrate custom properties from media to container (so they work 😉)\n ui.migrateStyles.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n on.call(this, this.elements.container, this.config.events.join(' '), (event) => {\n this.debug.log(`event: ${event.type}`);\n });\n }\n\n // Setup fullscreen\n this.fullscreen = new Fullscreen(this);\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n\n // Container listeners\n this.listeners.container();\n\n // Global listeners\n this.listeners.global();\n\n // Setup ads if provided\n if (this.config.ads.enabled) {\n this.ads = new Ads(this);\n }\n\n // Autoplay if required\n if (this.isHTML5 && this.config.autoplay) {\n this.once('canplay', () => silencePromise(this.play()));\n }\n\n // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek\n this.lastSeekTime = 0;\n\n // Setup preview thumbnails if enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * Types and provider helpers\n */\n get isHTML5() {\n return this.provider === providers.html5;\n }\n\n get isEmbed() {\n return this.isYouTube || this.isVimeo;\n }\n\n get isYouTube() {\n return this.provider === providers.youtube;\n }\n\n get isVimeo() {\n return this.provider === providers.vimeo;\n }\n\n get isVideo() {\n return this.type === types.video;\n }\n\n get isAudio() {\n return this.type === types.audio;\n }\n\n /**\n * Play the media, or play the advertisement (if they are not blocked)\n */\n play = () => {\n if (!is.function(this.media.play)) {\n return null;\n }\n\n // Intecept play with ads\n if (this.ads && this.ads.enabled) {\n this.ads.managerPromise.then(() => this.ads.play()).catch(() => silencePromise(this.media.play()));\n }\n\n // Return the promise (for HTML5)\n return this.media.play();\n };\n\n /**\n * Pause the media\n */\n pause = () => {\n if (!this.playing || !is.function(this.media.pause)) {\n return null;\n }\n\n return this.media.pause();\n };\n\n /**\n * Get playing state\n */\n get playing() {\n return Boolean(this.ready && !this.paused && !this.ended);\n }\n\n /**\n * Get paused state\n */\n get paused() {\n return Boolean(this.media.paused);\n }\n\n /**\n * Get stopped state\n */\n get stopped() {\n return Boolean(this.paused && this.currentTime === 0);\n }\n\n /**\n * Get ended state\n */\n get ended() {\n return Boolean(this.media.ended);\n }\n\n /**\n * Toggle playback based on current status\n * @param {Boolean} input\n */\n togglePlay = (input) => {\n // Toggle based on current state if nothing passed\n const toggle = is.boolean(input) ? input : !this.playing;\n\n if (toggle) {\n return this.play();\n }\n\n return this.pause();\n };\n\n /**\n * Stop playback\n */\n stop = () => {\n if (this.isHTML5) {\n this.pause();\n this.restart();\n } else if (is.function(this.media.stop)) {\n this.media.stop();\n }\n };\n\n /**\n * Restart playback\n */\n restart = () => {\n this.currentTime = 0;\n };\n\n /**\n * Rewind\n * @param {Number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind = (seekTime) => {\n this.currentTime -= is.number(seekTime) ? seekTime : this.config.seekTime;\n };\n\n /**\n * Fast forward\n * @param {Number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward = (seekTime) => {\n this.currentTime += is.number(seekTime) ? seekTime : this.config.seekTime;\n };\n\n /**\n * Seek to a time\n * @param {Number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n // Bail if media duration isn't available yet\n if (!this.duration) {\n return;\n }\n\n // Validate input\n const inputIsValid = is.number(input) && input > 0;\n\n // Set\n this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0;\n\n // Logging\n this.debug.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n /**\n * Get current time\n */\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n /**\n * Get buffered\n */\n get buffered() {\n const { buffered } = this.media;\n\n // YouTube / Vimeo return a float between 0-1\n if (is.number(buffered)) {\n return buffered;\n }\n\n // HTML5\n // TODO: Handle buffered chunks of the media\n // (i.e. seek to another section buffers only that section)\n if (buffered && buffered.length && this.duration > 0) {\n return buffered.end(0) / this.duration;\n }\n\n return 0;\n }\n\n /**\n * Get seeking status\n */\n get seeking() {\n return Boolean(this.media.seeking);\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseFloat(this.config.duration);\n // Media duration can be NaN or Infinity before the media has loaded\n const realDuration = (this.media || {}).duration;\n const duration = !is.number(realDuration) || realDuration === Infinity ? 0 : realDuration;\n\n // If config duration is funky, use regular duration\n return fauxDuration || duration;\n }\n\n /**\n * Set the player volume\n * @param {Number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!is.number(volume)) {\n volume = this.storage.get('volume');\n }\n\n // Use config if all else fails\n if (!is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume manually, reset muted state\n if (!is.empty(value) && this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return Number(this.media.volume);\n }\n\n /**\n * Increase volume\n * @param {Boolean} step - How much to decrease by (between 0 and 1)\n */\n increaseVolume = (step) => {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + (is.number(step) ? step : 0);\n };\n\n /**\n * Decrease volume\n * @param {Boolean} step - How much to decrease by (between 0 and 1)\n */\n decreaseVolume = (step) => {\n this.increaseVolume(-step);\n };\n\n /**\n * Set muted state\n * @param {Boolean} mute\n */\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!is.boolean(toggle)) {\n toggle = this.storage.get('muted');\n }\n\n // Use config if all else fails\n if (!is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n /**\n * Get current muted state\n */\n get muted() {\n return Boolean(this.media.muted);\n }\n\n /**\n * Check if the media has audio\n */\n get hasAudio() {\n // Assume yes for all non HTML5 (as we can't tell...)\n if (!this.isHTML5) {\n return true;\n }\n\n if (this.isAudio) {\n return true;\n }\n\n // Get audio tracks\n return (\n Boolean(this.media.mozHasAudio) ||\n Boolean(this.media.webkitAudioDecodedByteCount) ||\n Boolean(this.media.audioTracks && this.media.audioTracks.length)\n );\n }\n\n /**\n * Set playback speed\n * @param {Number} input - the speed of playback (0.5-2.0)\n */\n set speed(input) {\n let speed = null;\n\n if (is.number(input)) {\n speed = input;\n }\n\n if (!is.number(speed)) {\n speed = this.storage.get('speed');\n }\n\n if (!is.number(speed)) {\n speed = this.config.speed.selected;\n }\n\n // Clamp to min/max\n const { minimumSpeed: min, maximumSpeed: max } = this;\n speed = clamp(speed, min, max);\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n setTimeout(() => {\n if (this.media) {\n this.media.playbackRate = speed;\n }\n }, 0);\n }\n\n /**\n * Get current playback speed\n */\n get speed() {\n return Number(this.media.playbackRate);\n }\n\n /**\n * Get the minimum allowed speed\n */\n get minimumSpeed() {\n if (this.isYouTube) {\n // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n return Math.min(...this.options.speed);\n }\n\n if (this.isVimeo) {\n // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n return 0.5;\n }\n\n // https://stackoverflow.com/a/32320020/1191319\n return 0.0625;\n }\n\n /**\n * Get the maximum allowed speed\n */\n get maximumSpeed() {\n if (this.isYouTube) {\n // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate\n return Math.max(...this.options.speed);\n }\n\n if (this.isVimeo) {\n // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror\n return 2;\n }\n\n // https://stackoverflow.com/a/32320020/1191319\n return 16;\n }\n\n /**\n * Set playback quality\n * Currently HTML5 & YouTube only\n * @param {Number} input - Quality level\n */\n set quality(input) {\n const config = this.config.quality;\n const options = this.options.quality;\n\n if (!options.length) {\n return;\n }\n\n let quality = [\n !is.empty(input) && Number(input),\n this.storage.get('quality'),\n config.selected,\n config.default,\n ].find(is.number);\n\n let updateStorage = true;\n\n if (!options.includes(quality)) {\n const value = closest(options, quality);\n this.debug.warn(`Unsupported quality option: ${quality}, using ${value} instead`);\n quality = value;\n\n // Don't update storage if quality is not supported\n updateStorage = false;\n }\n\n // Update config\n config.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n\n // Save to storage\n if (updateStorage) {\n this.storage.set({ quality });\n }\n }\n\n /**\n * Get current quality level\n */\n get quality() {\n return this.media.quality;\n }\n\n /**\n * Toggle loop\n * TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n * @param {Boolean} input - Whether to loop or not\n */\n set loop(input) {\n const toggle = is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n /**\n * Get current loop state\n */\n get loop() {\n return Boolean(this.media.loop);\n }\n\n /**\n * Set new media source\n * @param {Object} input - The new source object (see docs)\n */\n set source(input) {\n source.change.call(this, input);\n }\n\n /**\n * Get current source\n */\n get source() {\n return this.media.currentSrc;\n }\n\n /**\n * Get a download URL (either source or custom)\n */\n get download() {\n const { download } = this.config.urls;\n\n return is.url(download) ? download : this.source;\n }\n\n /**\n * Set the download URL\n */\n set download(input) {\n if (!is.url(input)) {\n return;\n }\n\n this.config.urls.download = input;\n\n controls.setDownloadUrl.call(this);\n }\n\n /**\n * Set the poster image for a video\n * @param {String} input - the URL for the new poster image\n */\n set poster(input) {\n if (!this.isVideo) {\n this.debug.warn('Poster can only be set for video');\n return;\n }\n\n ui.setPoster.call(this, input, false).catch(() => {});\n }\n\n /**\n * Get the current poster image\n */\n get poster() {\n if (!this.isVideo) {\n return null;\n }\n\n return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');\n }\n\n /**\n * Get the current aspect ratio in use\n */\n get ratio() {\n if (!this.isVideo) {\n return null;\n }\n\n const ratio = reduceAspectRatio(getAspectRatio.call(this));\n\n return is.array(ratio) ? ratio.join(':') : ratio;\n }\n\n /**\n * Set video aspect ratio\n */\n set ratio(input) {\n if (!this.isVideo) {\n this.debug.warn('Aspect ratio can only be set for video');\n return;\n }\n\n if (!is.string(input) || !validateAspectRatio(input)) {\n this.debug.error(`Invalid aspect ratio specified (${input})`);\n return;\n }\n\n this.config.ratio = reduceAspectRatio(input);\n\n setAspectRatio.call(this);\n }\n\n /**\n * Set the autoplay state\n * @param {Boolean} input - Whether to autoplay or not\n */\n set autoplay(input) {\n this.config.autoplay = is.boolean(input) ? input : this.config.autoplay;\n }\n\n /**\n * Get the current autoplay state\n */\n get autoplay() {\n return Boolean(this.config.autoplay);\n }\n\n /**\n * Toggle captions\n * @param {Boolean} input - Whether to enable captions\n */\n toggleCaptions(input) {\n captions.toggle.call(this, input, false);\n }\n\n /**\n * Set the caption track by index\n * @param {Number} input - Caption index\n */\n set currentTrack(input) {\n captions.set.call(this, input, false);\n captions.setup.call(this);\n }\n\n /**\n * Get the current caption track index (-1 if disabled)\n */\n get currentTrack() {\n const { toggled, currentTrack } = this.captions;\n return toggled ? currentTrack : -1;\n }\n\n /**\n * Set the wanted language for captions\n * Since tracks can be added later it won't update the actual caption track until there is a matching track\n * @param {String} input - Two character ISO language code (e.g. EN, FR, PT, etc)\n */\n set language(input) {\n captions.setLanguage.call(this, input, false);\n }\n\n /**\n * Get the current track's language\n */\n get language() {\n return (captions.getCurrentTrack.call(this) || {}).language;\n }\n\n /**\n * Toggle picture-in-picture playback on WebKit/MacOS\n * TODO: update player with state, support, enabled\n * TODO: detect outside changes\n */\n set pip(input) {\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = is.boolean(input) ? input : !this.pip;\n\n // Toggle based on current state\n // Safari\n if (is.function(this.media.webkitSetPresentationMode)) {\n this.media.webkitSetPresentationMode(toggle ? pip.active : pip.inactive);\n }\n\n // Chrome\n if (is.function(this.media.requestPictureInPicture)) {\n if (!this.pip && toggle) {\n this.media.requestPictureInPicture();\n } else if (this.pip && !toggle) {\n document.exitPictureInPicture();\n }\n }\n }\n\n /**\n * Get the current picture-in-picture state\n */\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n // Safari\n if (!is.empty(this.media.webkitPresentationMode)) {\n return this.media.webkitPresentationMode === pip.active;\n }\n\n // Chrome\n return this.media === document.pictureInPictureElement;\n }\n\n /**\n * Sets the preview thumbnails for the current source\n */\n setPreviewThumbnails(thumbnailSource) {\n if (this.previewThumbnails && this.previewThumbnails.loaded) {\n this.previewThumbnails.destroy();\n this.previewThumbnails = null;\n }\n\n Object.assign(this.config.previewThumbnails, thumbnailSource);\n\n // Create new instance if it is still enabled\n if (this.config.previewThumbnails.enabled) {\n this.previewThumbnails = new PreviewThumbnails(this);\n }\n }\n\n /**\n * Trigger the airplay dialog\n * TODO: update player with state, support, enabled\n */\n airplay = () => {\n // Show dialog if supported\n if (support.airplay) {\n this.media.webkitShowPlaybackTargetPicker();\n }\n };\n\n /**\n * Toggle the player controls\n * @param {Boolean} [toggle] - Whether to show the controls\n */\n toggleControls = (toggle) => {\n // Don't toggle if missing UI support or if it's audio\n if (this.supported.ui && !this.isAudio) {\n // Get state before change\n const isHidden = hasClass(this.elements.container, this.config.classNames.hideControls);\n // Negate the argument if not undefined since adding the class to hides the controls\n const force = typeof toggle === 'undefined' ? undefined : !toggle;\n // Apply and get updated state\n const hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force);\n\n // Close menu\n if (\n hiding &&\n is.array(this.config.controls) &&\n this.config.controls.includes('settings') &&\n !is.empty(this.config.settings)\n ) {\n controls.toggleMenu.call(this, false);\n }\n\n // Trigger event on change\n if (hiding !== isHidden) {\n const eventName = hiding ? 'controlshidden' : 'controlsshown';\n triggerEvent.call(this, this.media, eventName);\n }\n\n return !hiding;\n }\n\n return false;\n };\n\n /**\n * Add event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n on = (event, callback) => {\n on.call(this, this.elements.container, event, callback);\n };\n\n /**\n * Add event listeners once\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n once = (event, callback) => {\n once.call(this, this.elements.container, event, callback);\n };\n\n /**\n * Remove event listeners\n * @param {String} event - Event type\n * @param {Function} callback - Callback for when event occurs\n */\n off = (event, callback) => {\n off(this.elements.container, event, callback);\n };\n\n /**\n * Destroy an instance\n * Event listeners are removed when elements are removed\n * http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n * @param {Function} callback - Callback for when destroy is complete\n * @param {Boolean} soft - Whether it's a soft destroy (for source changes etc)\n */\n destroy = (callback, soft = false) => {\n if (!this.ready) {\n return;\n }\n\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove elements\n removeElement(this.elements.buttons.play);\n removeElement(this.elements.captions);\n removeElement(this.elements.controls);\n removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (is.function(callback)) {\n callback();\n }\n } else {\n // Unbind listeners\n unbindListeners.call(this);\n\n // Cancel current network requests\n html5.cancelRequests.call(this);\n\n // Replace the container with the original element provided\n replaceElement(this.elements.original, this.elements.container);\n\n // Event\n triggerEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Reset state\n this.ready = false;\n\n // Clear for garbage collection\n setTimeout(() => {\n this.elements = null;\n this.media = null;\n }, 200);\n }\n };\n\n // Stop playback\n this.stop();\n\n // Clear timeouts\n clearTimeout(this.timers.loading);\n clearTimeout(this.timers.controls);\n clearTimeout(this.timers.resized);\n\n // Provider specific stuff\n if (this.isHTML5) {\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n } else if (this.isYouTube) {\n // Clear timers\n clearInterval(this.timers.buffering);\n clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n if (this.embed !== null && is.function(this.embed.destroy)) {\n this.embed.destroy();\n }\n\n // Clean up\n done();\n } else if (this.isVimeo) {\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n if (this.embed !== null) {\n this.embed.unload().then(done);\n }\n\n // Vimeo does not always return\n setTimeout(done, 200);\n }\n };\n\n /**\n * Check for support for a mime type (HTML5 only)\n * @param {String} type - Mime type\n */\n supports = (type) => support.mime.call(this, type);\n\n /**\n * Check for support\n * @param {String} type - Player type (audio/video)\n * @param {String} provider - Provider (html5/youtube/vimeo)\n */\n static supported(type, provider) {\n return support.check(type, provider);\n }\n\n /**\n * Load an SVG sprite into the page\n * @param {String} url - URL for the SVG sprite\n * @param {String} [id] - Unique ID\n */\n static loadSprite(url, id) {\n return loadSprite(url, id);\n }\n\n /**\n * Setup multiple instances\n * @param {*} selector\n * @param {Object} options\n */\n static setup(selector, options = {}) {\n let targets = null;\n\n if (is.string(selector)) {\n targets = Array.from(document.querySelectorAll(selector));\n } else if (is.nodeList(selector)) {\n targets = Array.from(selector);\n } else if (is.array(selector)) {\n targets = selector.filter(is.element);\n }\n\n if (is.empty(targets)) {\n return null;\n }\n\n return targets.map((t) => new Plyr(t, options));\n }\n}\n\nPlyr.defaults = cloneDeep(defaults);\n\nexport default Plyr;\n","import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject<T>\n */\nexport class BehaviorSubject<T> extends Subject<T> {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<T>): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n","import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable<T>\n */\nexport class Observable<T> implements Subscribable<T> {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable<any> | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator<any, T> | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = <T>(subscribe?: (subscriber: Subscriber<T>) => TeardownLogic) => {\n return new Observable<T>(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift<R>(operator?: Operator<T, R>): Observable<R> {\n const observable = new Observable<R>();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial<Observer<T>> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * <span class=\"informal\">Use it when you have all these Observables, but still nothing is happening.</span>\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber<T>): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise<void>;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise<void>;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise<void> {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor<void>((resolve, reject) => {\n const subscriber = new SafeSubscriber<T>({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise<void>;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<any>): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable<T>;\n pipe<A>(op1: OperatorFunction<T, A>): Observable<A>;\n pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;\n pipe<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Observable<C>;\n pipe<A, B, C, D>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>\n ): Observable<D>;\n pipe<A, B, C, D, E>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>\n ): Observable<E>;\n pipe<A, B, C, D, E, F>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>,\n op6: OperatorFunction<E, F>\n ): Observable<F>;\n pipe<A, B, C, D, E, F, G>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>,\n op6: OperatorFunction<E, F>,\n op7: OperatorFunction<F, G>\n ): Observable<G>;\n pipe<A, B, C, D, E, F, G, H>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>,\n op6: OperatorFunction<E, F>,\n op7: OperatorFunction<F, G>,\n op8: OperatorFunction<G, H>\n ): Observable<H>;\n pipe<A, B, C, D, E, F, G, H, I>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>,\n op6: OperatorFunction<E, F>,\n op7: OperatorFunction<F, G>,\n op8: OperatorFunction<G, H>,\n op9: OperatorFunction<H, I>\n ): Observable<I>;\n pipe<A, B, C, D, E, F, G, H, I>(\n op1: OperatorFunction<T, A>,\n op2: OperatorFunction<A, B>,\n op3: OperatorFunction<B, C>,\n op4: OperatorFunction<C, D>,\n op5: OperatorFunction<D, E>,\n op6: OperatorFunction<E, F>,\n op7: OperatorFunction<F, G>,\n op8: OperatorFunction<G, H>,\n op9: OperatorFunction<H, I>,\n ...operations: OperatorFunction<any, any>[]\n ): Observable<unknown>;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction<any, any>[]): Observable<any> {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise<T | undefined>;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise<T | undefined>;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise<T | undefined>;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise<T | undefined> {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise<T | undefined>;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver<T>(value: any): value is Observer<T> {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber<T>(value: any): value is Subscriber<T> {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n","import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject<T> extends Subject<T> {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<T>): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n","import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n","import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject<T> extends Observable<T> implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer<T>[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer<T>[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = <T>(destination: Observer<T>, source: Observable<T>): AnonymousSubject<T> => {\n return new AnonymousSubject<T>(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift<R>(operator: Operator<T, R>): Observable<R> {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber<T>): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<T>): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber<any>) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber<any>) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable<T> {\n const observable: any = new Observable<T>();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject<T>\n */\nexport class AnonymousSubject<T> extends Subject<T> {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer<T>,\n source?: Observable<T>\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<T>): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n","import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification<T>(value: T) {\n return createNotification('N', value, undefined) as NextNotification<T>;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n","import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber<T>\n */\nexport class Subscriber<T> extends Subscription implements Observer<T> {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create<T>(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber<T> {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber<any> | Observer<any>; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber<any> | Observer<any>) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind<Fn extends (...args: any[]) => any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver<T> implements Observer<T> {\n constructor(private partialObserver: Partial<Observer<T>>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber<T> extends Subscriber<T> {\n constructor(\n observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial<Observer<T>>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification<any>, subscriber: Subscriber<any>) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly<Observer<any>> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n","import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n","import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude<TeardownLogic, void>[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude<TeardownLogic, void>): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n","import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification<any>, subscriber: Subscriber<any>) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n","import { Observable } from './Observable';\nimport { EmptyError } from './util/EmptyError';\nimport { SafeSubscriber } from './Subscriber';\n\nexport interface FirstValueFromConfig<T> {\n defaultValue: T;\n}\n\nexport function firstValueFrom<T, D>(source: Observable<T>, config: FirstValueFromConfig<D>): Promise<T | D>;\nexport function firstValueFrom<T>(source: Observable<T>): Promise<T>;\n\n/**\n * Converts an observable to a promise by subscribing to the observable,\n * and returning a promise that will resolve as soon as the first value\n * arrives from the observable. The subscription will then be closed.\n *\n * If the observable stream completes before any values were emitted, the\n * returned promise will reject with {@link EmptyError} or will resolve\n * with the default value if a default was specified.\n *\n * If the observable stream emits an error, the returned promise will reject\n * with that error.\n *\n * **WARNING**: Only use this with observables you *know* will emit at least one value,\n * *OR* complete. If the source observable does not emit one value or complete, you will\n * end up with a promise that is hung up, and potentially all of the state of an\n * async function hanging out in memory. To avoid this situation, look into adding\n * something like {@link timeout}, {@link take}, {@link takeWhile}, or {@link takeUntil}\n * amongst others.\n *\n * ## Example\n *\n * Wait for the first value from a stream and emit it from a promise in\n * an async function\n *\n * ```ts\n * import { interval, firstValueFrom } from 'rxjs';\n *\n * async function execute() {\n * const source$ = interval(2000);\n * const firstNumber = await firstValueFrom(source$);\n * console.log(`The first number is ${ firstNumber }`);\n * }\n *\n * execute();\n *\n * // Expected output:\n * // 'The first number is 0'\n * ```\n *\n * @see {@link lastValueFrom}\n *\n * @param source the observable to convert to a promise\n * @param config a configuration object to define the `defaultValue` to use if the source completes without emitting a value\n */\nexport function firstValueFrom<T, D>(source: Observable<T>, config?: FirstValueFromConfig<D>): Promise<T | D> {\n const hasConfig = typeof config === 'object';\n return new Promise<T | D>((resolve, reject) => {\n const subscriber = new SafeSubscriber<T>({\n next: (value) => {\n resolve(value);\n subscriber.unsubscribe();\n },\n error: reject,\n complete: () => {\n if (hasConfig) {\n resolve(config!.defaultValue);\n } else {\n reject(new EmptyError());\n }\n },\n });\n source.subscribe(subscriber);\n });\n}\n","import { Observable } from '../Observable';\nimport { ObservableInput, SchedulerLike, ObservedValueOf, ObservableInputTuple } from '../types';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject';\nimport { Subscriber } from '../Subscriber';\nimport { from } from './from';\nimport { identity } from '../util/identity';\nimport { Subscription } from '../Subscription';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { popResultSelector, popScheduler } from '../util/args';\nimport { createObject } from '../util/createObject';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { AnyCatcher } from '../AnyCatcher';\nimport { executeSchedule } from '../util/executeSchedule';\n\n// combineLatest(any)\n// We put this first because we need to catch cases where the user has supplied\n// _exactly `any`_ as the argument. Since `any` literally matches _anything_,\n// we don't want it to randomly hit one of the other type signatures below,\n// as we have no idea at build-time what type we should be returning when given an any.\n\n/**\n * You have passed `any` here, we can't figure out if it is\n * an array or an object, so you're getting `unknown`. Use better types.\n * @param arg Something typed as `any`\n */\nexport function combineLatest<T extends AnyCatcher>(arg: T): Observable<unknown>;\n\n// combineLatest([a, b, c])\nexport function combineLatest(sources: []): Observable<never>;\nexport function combineLatest<A extends readonly unknown[]>(sources: readonly [...ObservableInputTuple<A>]): Observable<A>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `combineLatestAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function combineLatest<A extends readonly unknown[], R>(\n sources: readonly [...ObservableInputTuple<A>],\n resultSelector: (...values: A) => R,\n scheduler: SchedulerLike\n): Observable<R>;\nexport function combineLatest<A extends readonly unknown[], R>(\n sources: readonly [...ObservableInputTuple<A>],\n resultSelector: (...values: A) => R\n): Observable<R>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `combineLatestAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function combineLatest<A extends readonly unknown[]>(\n sources: readonly [...ObservableInputTuple<A>],\n scheduler: SchedulerLike\n): Observable<A>;\n\n// combineLatest(a, b, c)\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function combineLatest<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `combineLatestAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function combineLatest<A extends readonly unknown[], R>(\n ...sourcesAndResultSelectorAndScheduler: [...ObservableInputTuple<A>, (...values: A) => R, SchedulerLike]\n): Observable<R>;\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function combineLatest<A extends readonly unknown[], R>(\n ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]\n): Observable<R>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `combineLatestAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function combineLatest<A extends readonly unknown[]>(\n ...sourcesAndScheduler: [...ObservableInputTuple<A>, SchedulerLike]\n): Observable<A>;\n\n// combineLatest({a, b, c})\nexport function combineLatest(sourcesObject: { [K in any]: never }): Observable<never>;\nexport function combineLatest<T extends Record<string, ObservableInput<any>>>(\n sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are\n * calculated from the latest values of each of its input Observables.\n *\n * <span class=\"informal\">Whenever any input Observable emits a value, it\n * computes a formula using the latest values from all the inputs, then emits\n * the output of that formula.</span>\n *\n * ![](combineLatest.png)\n *\n * `combineLatest` combines the values from all the Observables passed in the\n * observables array. This is done by subscribing to each Observable in order and,\n * whenever any Observable emits, collecting an array of the most recent\n * values from each Observable. So if you pass `n` Observables to this operator,\n * the returned Observable will always emit an array of `n` values, in an order\n * corresponding to the order of the passed Observables (the value from the first Observable\n * will be at index 0 of the array and so on).\n *\n * Static version of `combineLatest` accepts an array of Observables. Note that an array of\n * Observables is a good choice, if you don't know beforehand how many Observables\n * you will combine. Passing an empty array will result in an Observable that\n * completes immediately.\n *\n * To ensure the output array always has the same length, `combineLatest` will\n * actually wait for all input Observables to emit at least once,\n * before it starts emitting results. This means if some Observable emits\n * values before other Observables started emitting, all these values but the last\n * will be lost. On the other hand, if some Observable does not emit a value but\n * completes, resulting Observable will complete at the same moment without\n * emitting anything, since it will now be impossible to include a value from the\n * completed Observable in the resulting array. Also, if some input Observable does\n * not emit any value and never completes, `combineLatest` will also never emit\n * and never complete, since, again, it will wait for all streams to emit some\n * value.\n *\n * If at least one Observable was passed to `combineLatest` and all passed Observables\n * emitted something, the resulting Observable will complete when all combined\n * streams complete. So even if some Observable completes, the result of\n * `combineLatest` will still emit values when other Observables do. In case\n * of a completed Observable, its value from now on will always be the last\n * emitted value. On the other hand, if any Observable errors, `combineLatest`\n * will error immediately as well, and all other Observables will be unsubscribed.\n *\n * ## Examples\n *\n * Combine two timer Observables\n *\n * ```ts\n * import { timer, combineLatest } from 'rxjs';\n *\n * const firstTimer = timer(0, 1000); // emit 0, 1, 2... after every second, starting from now\n * const secondTimer = timer(500, 1000); // emit 0, 1, 2... after every second, starting 0,5s from now\n * const combinedTimers = combineLatest([firstTimer, secondTimer]);\n * combinedTimers.subscribe(value => console.log(value));\n * // Logs\n * // [0, 0] after 0.5s\n * // [1, 0] after 1s\n * // [1, 1] after 1.5s\n * // [2, 1] after 2s\n * ```\n *\n * Combine a dictionary of Observables\n *\n * ```ts\n * import { of, delay, startWith, combineLatest } from 'rxjs';\n *\n * const observables = {\n * a: of(1).pipe(delay(1000), startWith(0)),\n * b: of(5).pipe(delay(5000), startWith(0)),\n * c: of(10).pipe(delay(10000), startWith(0))\n * };\n * const combined = combineLatest(observables);\n * combined.subscribe(value => console.log(value));\n * // Logs\n * // { a: 0, b: 0, c: 0 } immediately\n * // { a: 1, b: 0, c: 0 } after 1s\n * // { a: 1, b: 5, c: 0 } after 5s\n * // { a: 1, b: 5, c: 10 } after 10s\n * ```\n *\n * Combine an array of Observables\n *\n * ```ts\n * import { of, delay, startWith, combineLatest } from 'rxjs';\n *\n * const observables = [1, 5, 10].map(\n * n => of(n).pipe(\n * delay(n * 1000), // emit 0 and then emit n after n seconds\n * startWith(0)\n * )\n * );\n * const combined = combineLatest(observables);\n * combined.subscribe(value => console.log(value));\n * // Logs\n * // [0, 0, 0] immediately\n * // [1, 0, 0] after 1s\n * // [1, 5, 0] after 5s\n * // [1, 5, 10] after 10s\n * ```\n *\n * Use map operator to dynamically calculate the Body-Mass Index\n *\n * ```ts\n * import { of, combineLatest, map } from 'rxjs';\n *\n * const weight = of(70, 72, 76, 79, 75);\n * const height = of(1.76, 1.77, 1.78);\n * const bmi = combineLatest([weight, height]).pipe(\n * map(([w, h]) => w / (h * h)),\n * );\n * bmi.subscribe(x => console.log('BMI is ' + x));\n *\n * // With output to console:\n * // BMI is 24.212293388429753\n * // BMI is 23.93948099205209\n * // BMI is 23.671253629592222\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link merge}\n * @see {@link withLatestFrom}\n *\n * @param {ObservableInput} [observables] An array of input Observables to combine with each other.\n * An array of Observables must be given as the first argument.\n * @param {function} [project] An optional function to project the values from\n * the combined latest values into a new value on the output Observable.\n * @param {SchedulerLike} [scheduler=null] The {@link SchedulerLike} to use for subscribing to\n * each input Observable.\n * @return {Observable} An Observable of projected values from the most recent\n * values from each input Observable, or an array of the most recent values from\n * each input Observable.\n */\nexport function combineLatest<O extends ObservableInput<any>, R>(...args: any[]): Observable<R> | Observable<ObservedValueOf<O>[]> {\n const scheduler = popScheduler(args);\n const resultSelector = popResultSelector(args);\n\n const { args: observables, keys } = argsArgArrayOrObject(args);\n\n if (observables.length === 0) {\n // If no observables are passed, or someone has passed an empty array\n // of observables, or even an empty object POJO, we need to just\n // complete (EMPTY), but we have to honor the scheduler provided if any.\n return from([], scheduler as any);\n }\n\n const result = new Observable<ObservedValueOf<O>[]>(\n combineLatestInit(\n observables as ObservableInput<ObservedValueOf<O>>[],\n scheduler,\n keys\n ? // A handler for scrubbing the array of args into a dictionary.\n (values) => createObject(keys, values)\n : // A passthrough to just return the array\n identity\n )\n );\n\n return resultSelector ? (result.pipe(mapOneOrManyArgs(resultSelector)) as Observable<R>) : result;\n}\n\nexport function combineLatestInit(\n observables: ObservableInput<any>[],\n scheduler?: SchedulerLike,\n valueTransform: (values: any[]) => any = identity\n) {\n return (subscriber: Subscriber<any>) => {\n // The outer subscription. We're capturing this in a function\n // because we may have to schedule it.\n maybeSchedule(\n scheduler,\n () => {\n const { length } = observables;\n // A store for the values each observable has emitted so far. We match observable to value on index.\n const values = new Array(length);\n // The number of currently active subscriptions, as they complete, we decrement this number to see if\n // we are all done combining values, so we can complete the result.\n let active = length;\n // The number of inner sources that still haven't emitted the first value\n // We need to track this because all sources need to emit one value in order\n // to start emitting values.\n let remainingFirstValues = length;\n // The loop to kick off subscription. We're keying everything on index `i` to relate the observables passed\n // in to the slot in the output array or the key in the array of keys in the output dictionary.\n for (let i = 0; i < length; i++) {\n maybeSchedule(\n scheduler,\n () => {\n const source = from(observables[i], scheduler as any);\n let hasFirstValue = false;\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n // When we get a value, record it in our set of values.\n values[i] = value;\n if (!hasFirstValue) {\n // If this is our first value, record that.\n hasFirstValue = true;\n remainingFirstValues--;\n }\n if (!remainingFirstValues) {\n // We're not waiting for any more\n // first values, so we can emit!\n subscriber.next(valueTransform(values.slice()));\n }\n },\n () => {\n if (!--active) {\n // We only complete the result if we have no more active\n // inner observables.\n subscriber.complete();\n }\n }\n )\n );\n },\n subscriber\n );\n }\n },\n subscriber\n );\n };\n}\n\n/**\n * A small utility to handle the couple of locations where we want to schedule if a scheduler was provided,\n * but we don't if there was no scheduler.\n */\nfunction maybeSchedule(scheduler: SchedulerLike | undefined, execute: () => void, subscription: Subscription) {\n if (scheduler) {\n executeSchedule(subscription, scheduler, execute);\n } else {\n execute();\n }\n}\n","import { Observable } from '../Observable';\nimport { ObservableInputTuple, SchedulerLike } from '../types';\nimport { concatAll } from '../operators/concatAll';\nimport { popScheduler } from '../util/args';\nimport { from } from './from';\n\nexport function concat<T extends readonly unknown[]>(...inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\nexport function concat<T extends readonly unknown[]>(\n ...inputsAndScheduler: [...ObservableInputTuple<T>, SchedulerLike]\n): Observable<T[number]>;\n\n/**\n * Creates an output Observable which sequentially emits all values from the first given\n * Observable and then moves on to the next.\n *\n * <span class=\"informal\">Concatenates multiple Observables together by\n * sequentially emitting their values, one Observable after the other.</span>\n *\n * ![](concat.png)\n *\n * `concat` joins multiple Observables together, by subscribing to them one at a time and\n * merging their results into the output Observable. You can pass either an array of\n * Observables, or put them directly as arguments. Passing an empty array will result\n * in Observable that completes immediately.\n *\n * `concat` will subscribe to first input Observable and emit all its values, without\n * changing or affecting them in any way. When that Observable completes, it will\n * subscribe to then next Observable passed and, again, emit its values. This will be\n * repeated, until the operator runs out of Observables. When last input Observable completes,\n * `concat` will complete as well. At any given moment only one Observable passed to operator\n * emits values. If you would like to emit values from passed Observables concurrently, check out\n * {@link merge} instead, especially with optional `concurrent` parameter. As a matter of fact,\n * `concat` is an equivalent of `merge` operator with `concurrent` parameter set to `1`.\n *\n * Note that if some input Observable never completes, `concat` will also never complete\n * and Observables following the one that did not complete will never be subscribed. On the other\n * hand, if some Observable simply completes immediately after it is subscribed, it will be\n * invisible for `concat`, which will just move on to the next Observable.\n *\n * If any Observable in chain errors, instead of passing control to the next Observable,\n * `concat` will error immediately as well. Observables that would be subscribed after\n * the one that emitted error, never will.\n *\n * If you pass to `concat` the same Observable many times, its stream of values\n * will be \"replayed\" on every subscription, which means you can repeat given Observable\n * as many times as you like. If passing the same Observable to `concat` 1000 times becomes tedious,\n * you can always use {@link repeat}.\n *\n * ## Examples\n *\n * Concatenate a timer counting from 0 to 3 with a synchronous sequence from 1 to 10\n *\n * ```ts\n * import { interval, take, range, concat } from 'rxjs';\n *\n * const timer = interval(1000).pipe(take(4));\n * const sequence = range(1, 10);\n * const result = concat(timer, sequence);\n * result.subscribe(x => console.log(x));\n *\n * // results in:\n * // 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3 -immediate-> 1 ... 10\n * ```\n *\n * Concatenate 3 Observables\n *\n * ```ts\n * import { interval, take, concat } from 'rxjs';\n *\n * const timer1 = interval(1000).pipe(take(10));\n * const timer2 = interval(2000).pipe(take(6));\n * const timer3 = interval(500).pipe(take(10));\n *\n * const result = concat(timer1, timer2, timer3);\n * result.subscribe(x => console.log(x));\n *\n * // results in the following:\n * // (Prints to console sequentially)\n * // -1000ms-> 0 -1000ms-> 1 -1000ms-> ... 9\n * // -2000ms-> 0 -2000ms-> 1 -2000ms-> ... 5\n * // -500ms-> 0 -500ms-> 1 -500ms-> ... 9\n * ```\n *\n * Concatenate the same Observable to repeat it\n *\n * ```ts\n * import { interval, take, concat } from 'rxjs';\n *\n * const timer = interval(1000).pipe(take(2));\n *\n * concat(timer, timer) // concatenating the same Observable!\n * .subscribe({\n * next: value => console.log(value),\n * complete: () => console.log('...and it is done!')\n * });\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 0 after 3s\n * // 1 after 4s\n * // '...and it is done!' also after 4s\n * ```\n *\n * @see {@link concatAll}\n * @see {@link concatMap}\n * @see {@link concatMapTo}\n * @see {@link startWith}\n * @see {@link endWith}\n *\n * @param args Input Observables to concatenate.\n */\nexport function concat(...args: any[]): Observable<unknown> {\n return concatAll()(from(args, popScheduler(args)));\n}\n","import { mergeAll } from './mergeAll';\nimport { OperatorFunction, ObservableInput, ObservedValueOf } from '../types';\n\n/**\n * Converts a higher-order Observable into a first-order Observable by\n * concatenating the inner Observables in order.\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables by putting one\n * inner Observable after the other.</span>\n *\n * ![](concatAll.svg)\n *\n * Joins every Observable emitted by the source (a higher-order Observable), in\n * a serial fashion. It subscribes to each inner Observable only after the\n * previous inner Observable has completed, and merges all of their values into\n * the returned observable.\n *\n * __Warning:__ If the source Observable emits Observables quickly and\n * endlessly, and the inner Observables it emits generally complete slower than\n * the source emits, you can run into memory issues as the incoming Observables\n * collect in an unbounded buffer.\n *\n * Note: `concatAll` is equivalent to `mergeAll` with concurrency parameter set\n * to `1`.\n *\n * ## Example\n *\n * For each click event, tick every second from 0 to 3, with no concurrency\n *\n * ```ts\n * import { fromEvent, map, interval, take, concatAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n * map(() => interval(1000).pipe(take(4)))\n * );\n * const firstOrder = higherOrder.pipe(concatAll());\n * firstOrder.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // (results are not concurrent)\n * // For every click on the \"document\" it will emit values 0 to 3 spaced\n * // on a 1000ms interval\n * // one click = 1000ms-> 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concat}\n * @see {@link concatMap}\n * @see {@link concatMapTo}\n * @see {@link exhaustAll}\n * @see {@link mergeAll}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link zipAll}\n *\n * @return A function that returns an Observable emitting values from all the\n * inner Observables concatenated.\n */\nexport function concatAll<O extends ObservableInput<any>>(): OperatorFunction<O, ObservedValueOf<O>> {\n return mergeAll(1);\n}\n","import { Observable } from '../Observable';\nimport { ObservedValueOf, ObservableInput } from '../types';\nimport { innerFrom } from './innerFrom';\n\n/**\n * Creates an Observable that, on subscribe, calls an Observable factory to\n * make an Observable for each new Observer.\n *\n * <span class=\"informal\">Creates the Observable lazily, that is, only when it\n * is subscribed.\n * </span>\n *\n * ![](defer.png)\n *\n * `defer` allows you to create an Observable only when the Observer\n * subscribes. It waits until an Observer subscribes to it, calls the given\n * factory function to get an Observable -- where a factory function typically\n * generates a new Observable -- and subscribes the Observer to this Observable.\n * In case the factory function returns a falsy value, then EMPTY is used as\n * Observable instead. Last but not least, an exception during the factory\n * function call is transferred to the Observer by calling `error`.\n *\n * ## Example\n *\n * Subscribe to either an Observable of clicks or an Observable of interval, at random\n *\n * ```ts\n * import { defer, fromEvent, interval } from 'rxjs';\n *\n * const clicksOrInterval = defer(() => {\n * return Math.random() > 0.5\n * ? fromEvent(document, 'click')\n * : interval(1000);\n * });\n * clicksOrInterval.subscribe(x => console.log(x));\n *\n * // Results in the following behavior:\n * // If the result of Math.random() is greater than 0.5 it will listen\n * // for clicks anywhere on the \"document\"; when document is clicked it\n * // will log a MouseEvent object to the console. If the result is less\n * // than 0.5 it will emit ascending numbers, one every second(1000ms).\n * ```\n *\n * @see {@link Observable}\n *\n * @param {function(): ObservableInput} observableFactory The Observable\n * factory function to invoke for each Observer that subscribes to the output\n * Observable. May also return a Promise, which will be converted on the fly\n * to an Observable.\n * @return {Observable} An Observable whose Observers' subscriptions trigger\n * an invocation of the given Observable factory function.\n */\nexport function defer<R extends ObservableInput<any>>(observableFactory: () => R): Observable<ObservedValueOf<R>> {\n return new Observable<ObservedValueOf<R>>((subscriber) => {\n innerFrom(observableFactory()).subscribe(subscriber);\n });\n}\n","import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * <span class=\"informal\">Just emits 'complete', and nothing else.</span>\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable<never>((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable<never>((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n","import { Observable } from '../Observable';\nimport { ObservedValueOf, ObservableInputTuple, ObservableInput } from '../types';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject';\nimport { innerFrom } from './innerFrom';\nimport { popResultSelector } from '../util/args';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { createObject } from '../util/createObject';\nimport { AnyCatcher } from '../AnyCatcher';\n\n// forkJoin(any)\n// We put this first because we need to catch cases where the user has supplied\n// _exactly `any`_ as the argument. Since `any` literally matches _anything_,\n// we don't want it to randomly hit one of the other type signatures below,\n// as we have no idea at build-time what type we should be returning when given an any.\n\n/**\n * You have passed `any` here, we can't figure out if it is\n * an array or an object, so you're getting `unknown`. Use better types.\n * @param arg Something typed as `any`\n */\nexport function forkJoin<T extends AnyCatcher>(arg: T): Observable<unknown>;\n\n// forkJoin(null | undefined)\nexport function forkJoin(scheduler: null | undefined): Observable<never>;\n\n// forkJoin([a, b, c])\nexport function forkJoin(sources: readonly []): Observable<never>;\nexport function forkJoin<A extends readonly unknown[]>(sources: readonly [...ObservableInputTuple<A>]): Observable<A>;\nexport function forkJoin<A extends readonly unknown[], R>(\n sources: readonly [...ObservableInputTuple<A>],\n resultSelector: (...values: A) => R\n): Observable<R>;\n\n// forkJoin(a, b, c)\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function forkJoin<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A>;\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function forkJoin<A extends readonly unknown[], R>(\n ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]\n): Observable<R>;\n\n// forkJoin({a, b, c})\nexport function forkJoin(sourcesObject: { [K in any]: never }): Observable<never>;\nexport function forkJoin<T extends Record<string, ObservableInput<any>>>(\n sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Accepts an `Array` of {@link ObservableInput} or a dictionary `Object` of {@link ObservableInput} and returns\n * an {@link Observable} that emits either an array of values in the exact same order as the passed array,\n * or a dictionary of values in the same shape as the passed dictionary.\n *\n * <span class=\"informal\">Wait for Observables to complete and then combine last values they emitted;\n * complete immediately if an empty array is passed.</span>\n *\n * ![](forkJoin.png)\n *\n * `forkJoin` is an operator that takes any number of input observables which can be passed either as an array\n * or a dictionary of input observables. If no input observables are provided (e.g. an empty array is passed),\n * then the resulting stream will complete immediately.\n *\n * `forkJoin` will wait for all passed observables to emit and complete and then it will emit an array or an object with last\n * values from corresponding observables.\n *\n * If you pass an array of `n` observables to the operator, then the resulting\n * array will have `n` values, where the first value is the last one emitted by the first observable,\n * second value is the last one emitted by the second observable and so on.\n *\n * If you pass a dictionary of observables to the operator, then the resulting\n * objects will have the same keys as the dictionary passed, with their last values they have emitted\n * located at the corresponding key.\n *\n * That means `forkJoin` will not emit more than once and it will complete after that. If you need to emit combined\n * values not only at the end of the lifecycle of passed observables, but also throughout it, try out {@link combineLatest}\n * or {@link zip} instead.\n *\n * In order for the resulting array to have the same length as the number of input observables, whenever any of\n * the given observables completes without emitting any value, `forkJoin` will complete at that moment as well\n * and it will not emit anything either, even if it already has some last values from other observables.\n * Conversely, if there is an observable that never completes, `forkJoin` will never complete either,\n * unless at any point some other observable completes without emitting a value, which brings us back to\n * the previous case. Overall, in order for `forkJoin` to emit a value, all given observables\n * have to emit something at least once and complete.\n *\n * If any given observable errors at some point, `forkJoin` will error as well and immediately unsubscribe\n * from the other observables.\n *\n * Optionally `forkJoin` accepts a `resultSelector` function, that will be called with values which normally\n * would land in the emitted array. Whatever is returned by the `resultSelector`, will appear in the output\n * observable instead. This means that the default `resultSelector` can be thought of as a function that takes\n * all its arguments and puts them into an array. Note that the `resultSelector` will be called only\n * when `forkJoin` is supposed to emit a result.\n *\n * ## Examples\n *\n * Use `forkJoin` with a dictionary of observable inputs\n *\n * ```ts\n * import { forkJoin, of, timer } from 'rxjs';\n *\n * const observable = forkJoin({\n * foo: of(1, 2, 3, 4),\n * bar: Promise.resolve(8),\n * baz: timer(4000)\n * });\n * observable.subscribe({\n * next: value => console.log(value),\n * complete: () => console.log('This is how it ends!'),\n * });\n *\n * // Logs:\n * // { foo: 4, bar: 8, baz: 0 } after 4 seconds\n * // 'This is how it ends!' immediately after\n * ```\n *\n * Use `forkJoin` with an array of observable inputs\n *\n * ```ts\n * import { forkJoin, of, timer } from 'rxjs';\n *\n * const observable = forkJoin([\n * of(1, 2, 3, 4),\n * Promise.resolve(8),\n * timer(4000)\n * ]);\n * observable.subscribe({\n * next: value => console.log(value),\n * complete: () => console.log('This is how it ends!'),\n * });\n *\n * // Logs:\n * // [4, 8, 0] after 4 seconds\n * // 'This is how it ends!' immediately after\n * ```\n *\n * @see {@link combineLatest}\n * @see {@link zip}\n *\n * @param {...ObservableInput} args Any number of Observables provided either as an array or as an arguments\n * passed directly to the operator.\n * @param {function} [project] Function that takes values emitted by input Observables and returns value\n * that will appear in resulting Observable instead of default array.\n * @return {Observable} Observable emitting either an array of last values emitted by passed Observables\n * or value from project function.\n */\nexport function forkJoin(...args: any[]): Observable<any> {\n const resultSelector = popResultSelector(args);\n const { args: sources, keys } = argsArgArrayOrObject(args);\n const result = new Observable((subscriber) => {\n const { length } = sources;\n if (!length) {\n subscriber.complete();\n return;\n }\n const values = new Array(length);\n let remainingCompletions = length;\n let remainingEmissions = length;\n for (let sourceIndex = 0; sourceIndex < length; sourceIndex++) {\n let hasValue = false;\n innerFrom(sources[sourceIndex]).subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n if (!hasValue) {\n hasValue = true;\n remainingEmissions--;\n }\n values[sourceIndex] = value;\n },\n () => remainingCompletions--,\n undefined,\n () => {\n if (!remainingCompletions || !hasValue) {\n if (!remainingEmissions) {\n subscriber.next(keys ? createObject(keys, values) : values);\n }\n subscriber.complete();\n }\n }\n )\n );\n }\n });\n return resultSelector ? result.pipe(mapOneOrManyArgs(resultSelector)) : result;\n}\n","import { MonoTypeOperatorFunction, SchedulerLike } from '../types';\nimport { operate } from '../util/lift';\n\n/**\n * Asynchronously subscribes Observers to this Observable on the specified {@link SchedulerLike}.\n *\n * With `subscribeOn` you can decide what type of scheduler a specific Observable will be using when it is subscribed to.\n *\n * Schedulers control the speed and order of emissions to observers from an Observable stream.\n *\n * ![](subscribeOn.png)\n *\n * ## Example\n *\n * Given the following code:\n *\n * ```ts\n * import { of, merge } from 'rxjs';\n *\n * const a = of(1, 2, 3);\n * const b = of(4, 5, 6);\n *\n * merge(a, b).subscribe(console.log);\n *\n * // Outputs\n * // 1\n * // 2\n * // 3\n * // 4\n * // 5\n * // 6\n * ```\n *\n * Both Observable `a` and `b` will emit their values directly and synchronously once they are subscribed to.\n *\n * If we instead use the `subscribeOn` operator declaring that we want to use the {@link asyncScheduler} for values emitted by Observable `a`:\n *\n * ```ts\n * import { of, subscribeOn, asyncScheduler, merge } from 'rxjs';\n *\n * const a = of(1, 2, 3).pipe(subscribeOn(asyncScheduler));\n * const b = of(4, 5, 6);\n *\n * merge(a, b).subscribe(console.log);\n *\n * // Outputs\n * // 4\n * // 5\n * // 6\n * // 1\n * // 2\n * // 3\n * ```\n *\n * The reason for this is that Observable `b` emits its values directly and synchronously like before\n * but the emissions from `a` are scheduled on the event loop because we are now using the {@link asyncScheduler} for that specific Observable.\n *\n * @param scheduler The {@link SchedulerLike} to perform subscription actions on.\n * @param delay A delay to pass to the scheduler to delay subscriptions\n * @return A function that returns an Observable modified so that its\n * subscriptions happen on the specified {@link SchedulerLike}.\n */\nexport function subscribeOn<T>(scheduler: SchedulerLike, delay: number = 0): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n subscriber.add(scheduler.schedule(() => source.subscribe(subscriber), delay));\n });\n}\n","import { SchedulerLike } from '../types';\nimport { Observable } from '../Observable';\nimport { executeSchedule } from '../util/executeSchedule';\n\nexport function scheduleAsyncIterable<T>(input: AsyncIterable<T>, scheduler: SchedulerLike) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n return new Observable<T>((subscriber) => {\n executeSchedule(subscriber, scheduler, () => {\n const iterator = input[Symbol.asyncIterator]();\n executeSchedule(\n subscriber,\n scheduler,\n () => {\n iterator.next().then((result) => {\n if (result.done) {\n // This will remove the subscriptions from\n // the parent subscription.\n subscriber.complete();\n } else {\n subscriber.next(result.value);\n }\n });\n },\n 0,\n true\n );\n });\n });\n}\n","import { Observable } from '../Observable';\nimport { ObservableInput, SchedulerLike, ObservedValueOf } from '../types';\nimport { scheduled } from '../scheduled/scheduled';\nimport { innerFrom } from './innerFrom';\n\nexport function from<O extends ObservableInput<any>>(input: O): Observable<ObservedValueOf<O>>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function from<O extends ObservableInput<any>>(input: O, scheduler: SchedulerLike | undefined): Observable<ObservedValueOf<O>>;\n\n/**\n * Creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.\n *\n * <span class=\"informal\">Converts almost anything to an Observable.</span>\n *\n * ![](from.png)\n *\n * `from` converts various other objects and data types into Observables. It also converts a Promise, an array-like, or an\n * <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable\" target=\"_blank\">iterable</a>\n * object into an Observable that emits the items in that promise, array, or iterable. A String, in this context, is treated\n * as an array of characters. Observable-like objects (contains a function named with the ES2015 Symbol for Observable) can also be\n * converted through this operator.\n *\n * ## Examples\n *\n * Converts an array to an Observable\n *\n * ```ts\n * import { from } from 'rxjs';\n *\n * const array = [10, 20, 30];\n * const result = from(array);\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 10\n * // 20\n * // 30\n * ```\n *\n * Convert an infinite iterable (from a generator) to an Observable\n *\n * ```ts\n * import { from, take } from 'rxjs';\n *\n * function* generateDoubles(seed) {\n * let i = seed;\n * while (true) {\n * yield i;\n * i = 2 * i; // double it\n * }\n * }\n *\n * const iterator = generateDoubles(3);\n * const result = from(iterator).pipe(take(10));\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 3\n * // 6\n * // 12\n * // 24\n * // 48\n * // 96\n * // 192\n * // 384\n * // 768\n * // 1536\n * ```\n *\n * With `asyncScheduler`\n *\n * ```ts\n * import { from, asyncScheduler } from 'rxjs';\n *\n * console.log('start');\n *\n * const array = [10, 20, 30];\n * const result = from(array, asyncScheduler);\n *\n * result.subscribe(x => console.log(x));\n *\n * console.log('end');\n *\n * // Logs:\n * // 'start'\n * // 'end'\n * // 10\n * // 20\n * // 30\n * ```\n *\n * @see {@link fromEvent}\n * @see {@link fromEventPattern}\n *\n * @param {ObservableInput<T>} A subscription object, a Promise, an Observable-like,\n * an Array, an iterable, or an array-like object to be converted.\n * @param {SchedulerLike} An optional {@link SchedulerLike} on which to schedule the emission of values.\n * @return {Observable<T>}\n */\nexport function from<T>(input: ObservableInput<T>, scheduler?: SchedulerLike): Observable<T> {\n return scheduler ? scheduled(input, scheduler) : innerFrom(input);\n}\n","import { scheduleObservable } from './scheduleObservable';\nimport { schedulePromise } from './schedulePromise';\nimport { scheduleArray } from './scheduleArray';\nimport { scheduleIterable } from './scheduleIterable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isPromise } from '../util/isPromise';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isIterable } from '../util/isIterable';\nimport { ObservableInput, SchedulerLike } from '../types';\nimport { Observable } from '../Observable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isReadableStreamLike } from '../util/isReadableStreamLike';\nimport { scheduleReadableStreamLike } from './scheduleReadableStreamLike';\n\n/**\n * Converts from a common {@link ObservableInput} type to an observable where subscription and emissions\n * are scheduled on the provided scheduler.\n *\n * @see {@link from}\n * @see {@link of}\n *\n * @param input The observable, array, promise, iterable, etc you would like to schedule\n * @param scheduler The scheduler to use to schedule the subscription and emissions from\n * the returned observable.\n */\nexport function scheduled<T>(input: ObservableInput<T>, scheduler: SchedulerLike): Observable<T> {\n if (input != null) {\n if (isInteropObservable(input)) {\n return scheduleObservable(input, scheduler);\n }\n if (isArrayLike(input)) {\n return scheduleArray(input, scheduler);\n }\n if (isPromise(input)) {\n return schedulePromise(input, scheduler);\n }\n if (isAsyncIterable(input)) {\n return scheduleAsyncIterable(input, scheduler);\n }\n if (isIterable(input)) {\n return scheduleIterable(input, scheduler);\n }\n if (isReadableStreamLike(input)) {\n return scheduleReadableStreamLike(input, scheduler);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\n","import { innerFrom } from '../observable/innerFrom';\nimport { observeOn } from '../operators/observeOn';\nimport { subscribeOn } from '../operators/subscribeOn';\nimport { InteropObservable, SchedulerLike } from '../types';\n\nexport function scheduleObservable<T>(input: InteropObservable<T>, scheduler: SchedulerLike) {\n return innerFrom(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n","import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\nexport function scheduleArray<T>(input: ArrayLike<T>, scheduler: SchedulerLike) {\n return new Observable<T>((subscriber) => {\n // The current array index.\n let i = 0;\n // Start iterating over the array like on a schedule.\n return scheduler.schedule(function () {\n if (i === input.length) {\n // If we have hit the end of the array like in the\n // previous job, we can complete.\n subscriber.complete();\n } else {\n // Otherwise let's next the value at the current index,\n // then increment our index.\n subscriber.next(input[i++]);\n // If the last emission didn't cause us to close the subscriber\n // (via take or some side effect), reschedule the job and we'll\n // make another pass.\n if (!subscriber.closed) {\n this.schedule();\n }\n }\n });\n });\n}\n","import { innerFrom } from '../observable/innerFrom';\nimport { observeOn } from '../operators/observeOn';\nimport { subscribeOn } from '../operators/subscribeOn';\nimport { SchedulerLike } from '../types';\n\nexport function schedulePromise<T>(input: PromiseLike<T>, scheduler: SchedulerLike) {\n return innerFrom(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n","import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from '../util/isFunction';\nimport { executeSchedule } from '../util/executeSchedule';\n\n/**\n * Used in {@link scheduled} to create an observable from an Iterable.\n * @param input The iterable to create an observable from\n * @param scheduler The scheduler to use\n */\nexport function scheduleIterable<T>(input: Iterable<T>, scheduler: SchedulerLike) {\n return new Observable<T>((subscriber) => {\n let iterator: Iterator<T, T>;\n\n // Schedule the initial creation of the iterator from\n // the iterable. This is so the code in the iterable is\n // not called until the scheduled job fires.\n executeSchedule(subscriber, scheduler, () => {\n // Create the iterator.\n iterator = (input as any)[Symbol_iterator]();\n\n executeSchedule(\n subscriber,\n scheduler,\n () => {\n let value: T;\n let done: boolean | undefined;\n try {\n // Pull the value out of the iterator\n ({ value, done } = iterator.next());\n } catch (err) {\n // We got an error while pulling from the iterator\n subscriber.error(err);\n return;\n }\n\n if (done) {\n // If it is \"done\" we just complete. This mimics the\n // behavior of JavaScript's `for..of` consumption of\n // iterables, which will not emit the value from an iterator\n // result of `{ done: true: value: 'here' }`.\n subscriber.complete();\n } else {\n // The iterable is not done, emit the value.\n subscriber.next(value);\n }\n },\n 0,\n true\n );\n });\n\n // During finalization, if we see this iterator has a `return` method,\n // then we know it is a Generator, and not just an Iterator. So we call\n // the `return()` function. This will ensure that any `finally { }` blocks\n // inside of the generator we can hit will be hit properly.\n return () => isFunction(iterator?.return) && iterator.return();\n });\n}\n","import { SchedulerLike, ReadableStreamLike } from '../types';\nimport { Observable } from '../Observable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { readableStreamLikeToAsyncGenerator } from '../util/isReadableStreamLike';\n\nexport function scheduleReadableStreamLike<T>(input: ReadableStreamLike<T>, scheduler: SchedulerLike): Observable<T> {\n return scheduleAsyncIterable(readableStreamLikeToAsyncGenerator(input), scheduler);\n}\n","import { innerFrom } from '../observable/innerFrom';\nimport { Observable } from '../Observable';\nimport { mergeMap } from '../operators/mergeMap';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isFunction } from '../util/isFunction';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\n\n// These constants are used to create handler registry functions using array mapping below.\nconst nodeEventEmitterMethods = ['addListener', 'removeListener'] as const;\nconst eventTargetMethods = ['addEventListener', 'removeEventListener'] as const;\nconst jqueryMethods = ['on', 'off'] as const;\n\nexport interface NodeStyleEventEmitter {\n addListener(eventName: string | symbol, handler: NodeEventHandler): this;\n removeListener(eventName: string | symbol, handler: NodeEventHandler): this;\n}\n\nexport type NodeEventHandler = (...args: any[]) => void;\n\n// For APIs that implement `addListener` and `removeListener` methods that may\n// not use the same arguments or return EventEmitter values\n// such as React Native\nexport interface NodeCompatibleEventEmitter {\n addListener(eventName: string, handler: NodeEventHandler): void | {};\n removeListener(eventName: string, handler: NodeEventHandler): void | {};\n}\n\n// Use handler types like those in @types/jquery. See:\n// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/847731ba1d7fa6db6b911c0e43aa0afe596e7723/types/jquery/misc.d.ts#L6395\nexport interface JQueryStyleEventEmitter<TContext, T> {\n on(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void;\n off(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void;\n}\n\nexport interface EventListenerObject<E> {\n handleEvent(evt: E): void;\n}\n\nexport interface HasEventTargetAddRemove<E> {\n addEventListener(\n type: string,\n listener: ((evt: E) => void) | EventListenerObject<E> | null,\n options?: boolean | AddEventListenerOptions\n ): void;\n removeEventListener(\n type: string,\n listener: ((evt: E) => void) | EventListenerObject<E> | null,\n options?: EventListenerOptions | boolean\n ): void;\n}\n\nexport interface EventListenerOptions {\n capture?: boolean;\n passive?: boolean;\n once?: boolean;\n}\n\nexport interface AddEventListenerOptions extends EventListenerOptions {\n once?: boolean;\n passive?: boolean;\n}\n\nexport function fromEvent<T>(target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>, eventName: string): Observable<T>;\nexport function fromEvent<T, R>(\n target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n eventName: string,\n resultSelector: (event: T) => R\n): Observable<R>;\nexport function fromEvent<T>(\n target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n eventName: string,\n options: EventListenerOptions\n): Observable<T>;\nexport function fromEvent<T, R>(\n target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n eventName: string,\n options: EventListenerOptions,\n resultSelector: (event: T) => R\n): Observable<R>;\n\nexport function fromEvent(target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>, eventName: string): Observable<unknown>;\n/** @deprecated Do not specify explicit type parameters. Signatures with type parameters that cannot be inferred will be removed in v8. */\nexport function fromEvent<T>(target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>, eventName: string): Observable<T>;\nexport function fromEvent<R>(\n target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>,\n eventName: string,\n resultSelector: (...args: any[]) => R\n): Observable<R>;\n\nexport function fromEvent(\n target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>,\n eventName: string\n): Observable<unknown>;\n/** @deprecated Do not specify explicit type parameters. Signatures with type parameters that cannot be inferred will be removed in v8. */\nexport function fromEvent<T>(target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>, eventName: string): Observable<T>;\nexport function fromEvent<R>(\n target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>,\n eventName: string,\n resultSelector: (...args: any[]) => R\n): Observable<R>;\n\nexport function fromEvent<T>(\n target: JQueryStyleEventEmitter<any, T> | ArrayLike<JQueryStyleEventEmitter<any, T>>,\n eventName: string\n): Observable<T>;\nexport function fromEvent<T, R>(\n target: JQueryStyleEventEmitter<any, T> | ArrayLike<JQueryStyleEventEmitter<any, T>>,\n eventName: string,\n resultSelector: (value: T, ...args: any[]) => R\n): Observable<R>;\n\n/**\n * Creates an Observable that emits events of a specific type coming from the\n * given event target.\n *\n * <span class=\"informal\">Creates an Observable from DOM events, or Node.js\n * EventEmitter events or others.</span>\n *\n * ![](fromEvent.png)\n *\n * `fromEvent` accepts as a first argument event target, which is an object with methods\n * for registering event handler functions. As a second argument it takes string that indicates\n * type of event we want to listen for. `fromEvent` supports selected types of event targets,\n * which are described in detail below. If your event target does not match any of the ones listed,\n * you should use {@link fromEventPattern}, which can be used on arbitrary APIs.\n * When it comes to APIs supported by `fromEvent`, their methods for adding and removing event\n * handler functions have different names, but they all accept a string describing event type\n * and function itself, which will be called whenever said event happens.\n *\n * Every time resulting Observable is subscribed, event handler function will be registered\n * to event target on given event type. When that event fires, value\n * passed as a first argument to registered function will be emitted by output Observable.\n * When Observable is unsubscribed, function will be unregistered from event target.\n *\n * Note that if event target calls registered function with more than one argument, second\n * and following arguments will not appear in resulting stream. In order to get access to them,\n * you can pass to `fromEvent` optional project function, which will be called with all arguments\n * passed to event handler. Output Observable will then emit value returned by project function,\n * instead of the usual value.\n *\n * Remember that event targets listed below are checked via duck typing. It means that\n * no matter what kind of object you have and no matter what environment you work in,\n * you can safely use `fromEvent` on that object if it exposes described methods (provided\n * of course they behave as was described above). So for example if Node.js library exposes\n * event target which has the same method names as DOM EventTarget, `fromEvent` is still\n * a good choice.\n *\n * If the API you use is more callback then event handler oriented (subscribed\n * callback function fires only once and thus there is no need to manually\n * unregister it), you should use {@link bindCallback} or {@link bindNodeCallback}\n * instead.\n *\n * `fromEvent` supports following types of event targets:\n *\n * **DOM EventTarget**\n *\n * This is an object with `addEventListener` and `removeEventListener` methods.\n *\n * In the browser, `addEventListener` accepts - apart from event type string and event\n * handler function arguments - optional third parameter, which is either an object or boolean,\n * both used for additional configuration how and when passed function will be called. When\n * `fromEvent` is used with event target of that type, you can provide this values\n * as third parameter as well.\n *\n * **Node.js EventEmitter**\n *\n * An object with `addListener` and `removeListener` methods.\n *\n * **JQuery-style event target**\n *\n * An object with `on` and `off` methods\n *\n * **DOM NodeList**\n *\n * List of DOM Nodes, returned for example by `document.querySelectorAll` or `Node.childNodes`.\n *\n * Although this collection is not event target in itself, `fromEvent` will iterate over all Nodes\n * it contains and install event handler function in every of them. When returned Observable\n * is unsubscribed, function will be removed from all Nodes.\n *\n * **DOM HtmlCollection**\n *\n * Just as in case of NodeList it is a collection of DOM nodes. Here as well event handler function is\n * installed and removed in each of elements.\n *\n *\n * ## Examples\n *\n * Emit clicks happening on the DOM document\n *\n * ```ts\n * import { fromEvent } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * clicks.subscribe(x => console.log(x));\n *\n * // Results in:\n * // MouseEvent object logged to console every time a click\n * // occurs on the document.\n * ```\n *\n * Use `addEventListener` with capture option\n *\n * ```ts\n * import { fromEvent } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * // note optional configuration parameter which will be passed to addEventListener\n * const clicksInDocument = fromEvent(document, 'click', { capture: true });\n * const clicksInDiv = fromEvent(div, 'click');\n *\n * clicksInDocument.subscribe(() => console.log('document'));\n * clicksInDiv.subscribe(() => console.log('div'));\n *\n * // By default events bubble UP in DOM tree, so normally\n * // when we would click on div in document\n * // \"div\" would be logged first and then \"document\".\n * // Since we specified optional `capture` option, document\n * // will catch event when it goes DOWN DOM tree, so console\n * // will log \"document\" and then \"div\".\n * ```\n *\n * @see {@link bindCallback}\n * @see {@link bindNodeCallback}\n * @see {@link fromEventPattern}\n *\n * @param {FromEventTarget<T>} target The DOM EventTarget, Node.js\n * EventEmitter, JQuery-like event target, NodeList or HTMLCollection to attach the event handler to.\n * @param {string} eventName The event name of interest, being emitted by the\n * `target`.\n * @param {EventListenerOptions} [options] Options to pass through to addEventListener\n * @return {Observable<T>}\n */\nexport function fromEvent<T>(\n target: any,\n eventName: string,\n options?: EventListenerOptions | ((...args: any[]) => T),\n resultSelector?: (...args: any[]) => T\n): Observable<T> {\n if (isFunction(options)) {\n resultSelector = options;\n options = undefined;\n }\n if (resultSelector) {\n return fromEvent<T>(target, eventName, options as EventListenerOptions).pipe(mapOneOrManyArgs(resultSelector));\n }\n\n // Figure out our add and remove methods. In order to do this,\n // we are going to analyze the target in a preferred order, if\n // the target matches a given signature, we take the two \"add\" and \"remove\"\n // method names and apply them to a map to create opposite versions of the\n // same function. This is because they all operate in duplicate pairs,\n // `addListener(name, handler)`, `removeListener(name, handler)`, for example.\n // The call only differs by method name, as to whether or not you're adding or removing.\n const [add, remove] =\n // If it is an EventTarget, we need to use a slightly different method than the other two patterns.\n isEventTarget(target)\n ? eventTargetMethods.map((methodName) => (handler: any) => target[methodName](eventName, handler, options as EventListenerOptions))\n : // In all other cases, the call pattern is identical with the exception of the method names.\n isNodeStyleEventEmitter(target)\n ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName))\n : isJQueryStyleEventEmitter(target)\n ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName))\n : [];\n\n // If add is falsy, it's because we didn't match a pattern above.\n // Check to see if it is an ArrayLike, because if it is, we want to\n // try to apply fromEvent to all of it's items. We do this check last,\n // because there are may be some types that are both ArrayLike *and* implement\n // event registry points, and we'd rather delegate to that when possible.\n if (!add) {\n if (isArrayLike(target)) {\n return mergeMap((subTarget: any) => fromEvent(subTarget, eventName, options as EventListenerOptions))(\n innerFrom(target)\n ) as Observable<T>;\n }\n }\n\n // If add is falsy and we made it here, it's because we didn't\n // match any valid target objects above.\n if (!add) {\n throw new TypeError('Invalid event target');\n }\n\n return new Observable<T>((subscriber) => {\n // The handler we are going to register. Forwards the event object, by itself, or\n // an array of arguments to the event handler, if there is more than one argument,\n // to the consumer.\n const handler = (...args: any[]) => subscriber.next(1 < args.length ? args : args[0]);\n // Do the work of adding the handler to the target.\n add(handler);\n // When we finalize, we want to remove the handler and free up memory.\n return () => remove!(handler);\n });\n}\n\n/**\n * Used to create `add` and `remove` functions to register and unregister event handlers\n * from a target in the most common handler pattern, where there are only two arguments.\n * (e.g. `on(name, fn)`, `off(name, fn)`, `addListener(name, fn)`, or `removeListener(name, fn)`)\n * @param target The target we're calling methods on\n * @param eventName The event name for the event we're creating register or unregister functions for\n */\nfunction toCommonHandlerRegistry(target: any, eventName: string) {\n return (methodName: string) => (handler: any) => target[methodName](eventName, handler);\n}\n\n/**\n * Checks to see if the target implements the required node-style EventEmitter methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isNodeStyleEventEmitter(target: any): target is NodeStyleEventEmitter {\n return isFunction(target.addListener) && isFunction(target.removeListener);\n}\n\n/**\n * Checks to see if the target implements the required jQuery-style EventEmitter methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isJQueryStyleEventEmitter(target: any): target is JQueryStyleEventEmitter<any, any> {\n return isFunction(target.on) && isFunction(target.off);\n}\n\n/**\n * Checks to see if the target implements the required EventTarget methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isEventTarget(target: any): target is HasEventTargetAddRemove<any> {\n return isFunction(target.addEventListener) && isFunction(target.removeEventListener);\n}\n","import { Observable } from '../Observable';\nimport { defer } from './defer';\nimport { ObservableInput } from '../types';\n\n/**\n * Checks a boolean at subscription time, and chooses between one of two observable sources\n *\n * `iif` expects a function that returns a boolean (the `condition` function), and two sources,\n * the `trueResult` and the `falseResult`, and returns an Observable.\n *\n * At the moment of subscription, the `condition` function is called. If the result is `true`, the\n * subscription will be to the source passed as the `trueResult`, otherwise, the subscription will be\n * to the source passed as the `falseResult`.\n *\n * If you need to check more than two options to choose between more than one observable, have a look at the {@link defer} creation method.\n *\n * ## Examples\n *\n * Change at runtime which Observable will be subscribed\n *\n * ```ts\n * import { iif, of } from 'rxjs';\n *\n * let subscribeToFirst;\n * const firstOrSecond = iif(\n * () => subscribeToFirst,\n * of('first'),\n * of('second')\n * );\n *\n * subscribeToFirst = true;\n * firstOrSecond.subscribe(value => console.log(value));\n *\n * // Logs:\n * // 'first'\n *\n * subscribeToFirst = false;\n * firstOrSecond.subscribe(value => console.log(value));\n *\n * // Logs:\n * // 'second'\n * ```\n *\n * Control access to an Observable\n *\n * ```ts\n * import { iif, of, EMPTY } from 'rxjs';\n *\n * let accessGranted;\n * const observableIfYouHaveAccess = iif(\n * () => accessGranted,\n * of('It seems you have an access...'),\n * EMPTY\n * );\n *\n * accessGranted = true;\n * observableIfYouHaveAccess.subscribe({\n * next: value => console.log(value),\n * complete: () => console.log('The end')\n * });\n *\n * // Logs:\n * // 'It seems you have an access...'\n * // 'The end'\n *\n * accessGranted = false;\n * observableIfYouHaveAccess.subscribe({\n * next: value => console.log(value),\n * complete: () => console.log('The end')\n * });\n *\n * // Logs:\n * // 'The end'\n * ```\n *\n * @see {@link defer}\n *\n * @param condition Condition which Observable should be chosen.\n * @param trueResult An Observable that will be subscribed if condition is true.\n * @param falseResult An Observable that will be subscribed if condition is false.\n * @return An observable that proxies to `trueResult` or `falseResult`, depending on the result of the `condition` function.\n */\nexport function iif<T, F>(condition: () => boolean, trueResult: ObservableInput<T>, falseResult: ObservableInput<F>): Observable<T | F> {\n return defer(() => (condition() ? trueResult : falseResult));\n}\n","import { isArrayLike } from '../util/isArrayLike';\nimport { isPromise } from '../util/isPromise';\nimport { Observable } from '../Observable';\nimport { ObservableInput, ObservedValueOf, ReadableStreamLike } from '../types';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isIterable } from '../util/isIterable';\nimport { isReadableStreamLike, readableStreamLikeToAsyncGenerator } from '../util/isReadableStreamLike';\nimport { Subscriber } from '../Subscriber';\nimport { isFunction } from '../util/isFunction';\nimport { reportUnhandledError } from '../util/reportUnhandledError';\nimport { observable as Symbol_observable } from '../symbol/observable';\n\nexport function innerFrom<O extends ObservableInput<any>>(input: O): Observable<ObservedValueOf<O>>;\nexport function innerFrom<T>(input: ObservableInput<T>): Observable<T> {\n if (input instanceof Observable) {\n return input;\n }\n if (input != null) {\n if (isInteropObservable(input)) {\n return fromInteropObservable(input);\n }\n if (isArrayLike(input)) {\n return fromArrayLike(input);\n }\n if (isPromise(input)) {\n return fromPromise(input);\n }\n if (isAsyncIterable(input)) {\n return fromAsyncIterable(input);\n }\n if (isIterable(input)) {\n return fromIterable(input);\n }\n if (isReadableStreamLike(input)) {\n return fromReadableStreamLike(input);\n }\n }\n\n throw createInvalidObservableTypeError(input);\n}\n\n/**\n * Creates an RxJS Observable from an object that implements `Symbol.observable`.\n * @param obj An object that properly implements `Symbol.observable`.\n */\nexport function fromInteropObservable<T>(obj: any) {\n return new Observable((subscriber: Subscriber<T>) => {\n const obs = obj[Symbol_observable]();\n if (isFunction(obs.subscribe)) {\n return obs.subscribe(subscriber);\n }\n // Should be caught by observable subscribe function error handling.\n throw new TypeError('Provided object does not correctly implement Symbol.observable');\n });\n}\n\n/**\n * Synchronously emits the values of an array like and completes.\n * This is exported because there are creation functions and operators that need to\n * make direct use of the same logic, and there's no reason to make them run through\n * `from` conditionals because we *know* they're dealing with an array.\n * @param array The array to emit values from\n */\nexport function fromArrayLike<T>(array: ArrayLike<T>) {\n return new Observable((subscriber: Subscriber<T>) => {\n // Loop over the array and emit each value. Note two things here:\n // 1. We're making sure that the subscriber is not closed on each loop.\n // This is so we don't continue looping over a very large array after\n // something like a `take`, `takeWhile`, or other synchronous unsubscription\n // has already unsubscribed.\n // 2. In this form, reentrant code can alter that array we're looping over.\n // This is a known issue, but considered an edge case. The alternative would\n // be to copy the array before executing the loop, but this has\n // performance implications.\n for (let i = 0; i < array.length && !subscriber.closed; i++) {\n subscriber.next(array[i]);\n }\n subscriber.complete();\n });\n}\n\nexport function fromPromise<T>(promise: PromiseLike<T>) {\n return new Observable((subscriber: Subscriber<T>) => {\n promise\n .then(\n (value) => {\n if (!subscriber.closed) {\n subscriber.next(value);\n subscriber.complete();\n }\n },\n (err: any) => subscriber.error(err)\n )\n .then(null, reportUnhandledError);\n });\n}\n\nexport function fromIterable<T>(iterable: Iterable<T>) {\n return new Observable((subscriber: Subscriber<T>) => {\n for (const value of iterable) {\n subscriber.next(value);\n if (subscriber.closed) {\n return;\n }\n }\n subscriber.complete();\n });\n}\n\nexport function fromAsyncIterable<T>(asyncIterable: AsyncIterable<T>) {\n return new Observable((subscriber: Subscriber<T>) => {\n process(asyncIterable, subscriber).catch((err) => subscriber.error(err));\n });\n}\n\nexport function fromReadableStreamLike<T>(readableStream: ReadableStreamLike<T>) {\n return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));\n}\n\nasync function process<T>(asyncIterable: AsyncIterable<T>, subscriber: Subscriber<T>) {\n for await (const value of asyncIterable) {\n subscriber.next(value);\n // A side-effect may have closed our subscriber,\n // check before the next iteration.\n if (subscriber.closed) {\n return;\n }\n }\n subscriber.complete();\n}\n","import { Observable } from '../Observable';\nimport { ObservableInput, ObservableInputTuple, SchedulerLike } from '../types';\nimport { mergeAll } from '../operators/mergeAll';\nimport { innerFrom } from './innerFrom';\nimport { EMPTY } from './empty';\nimport { popNumber, popScheduler } from '../util/args';\nimport { from } from './from';\n\nexport function merge<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A[number]>;\nexport function merge<A extends readonly unknown[]>(...sourcesAndConcurrency: [...ObservableInputTuple<A>, number?]): Observable<A[number]>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `mergeAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function merge<A extends readonly unknown[]>(\n ...sourcesAndScheduler: [...ObservableInputTuple<A>, SchedulerLike?]\n): Observable<A[number]>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `mergeAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function merge<A extends readonly unknown[]>(\n ...sourcesAndConcurrencyAndScheduler: [...ObservableInputTuple<A>, number?, SchedulerLike?]\n): Observable<A[number]>;\n\n/**\n * Creates an output Observable which concurrently emits all values from every\n * given input Observable.\n *\n * <span class=\"informal\">Flattens multiple Observables together by blending\n * their values into one Observable.</span>\n *\n * ![](merge.png)\n *\n * `merge` subscribes to each given input Observable (as arguments), and simply\n * forwards (without doing any transformation) all the values from all the input\n * Observables to the output Observable. The output Observable only completes\n * once all input Observables have completed. Any error delivered by an input\n * Observable will be immediately emitted on the output Observable.\n *\n * ## Examples\n *\n * Merge together two Observables: 1s interval and clicks\n *\n * ```ts\n * import { merge, fromEvent, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const timer = interval(1000);\n * const clicksOrTimer = merge(clicks, timer);\n * clicksOrTimer.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // timer will emit ascending values, one every second(1000ms) to console\n * // clicks logs MouseEvents to console every time the \"document\" is clicked\n * // Since the two streams are merged you see these happening\n * // as they occur.\n * ```\n *\n * Merge together 3 Observables, but run only 2 concurrently\n *\n * ```ts\n * import { interval, take, merge } from 'rxjs';\n *\n * const timer1 = interval(1000).pipe(take(10));\n * const timer2 = interval(2000).pipe(take(6));\n * const timer3 = interval(500).pipe(take(10));\n *\n * const concurrent = 2; // the argument\n * const merged = merge(timer1, timer2, timer3, concurrent);\n * merged.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // - First timer1 and timer2 will run concurrently\n * // - timer1 will emit a value every 1000ms for 10 iterations\n * // - timer2 will emit a value every 2000ms for 6 iterations\n * // - after timer1 hits its max iteration, timer2 will\n * // continue, and timer3 will start to run concurrently with timer2\n * // - when timer2 hits its max iteration it terminates, and\n * // timer3 will continue to emit a value every 500ms until it is complete\n * ```\n *\n * @see {@link mergeAll}\n * @see {@link mergeMap}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n *\n * @param {...ObservableInput} observables Input Observables to merge together.\n * @param {number} [concurrent=Infinity] Maximum number of input\n * Observables being subscribed to concurrently.\n * @param {SchedulerLike} [scheduler=null] The {@link SchedulerLike} to use for managing\n * concurrency of input Observables.\n * @return {Observable} an Observable that emits items that are the result of\n * every input Observable.\n */\nexport function merge(...args: (ObservableInput<unknown> | number | SchedulerLike)[]): Observable<unknown> {\n const scheduler = popScheduler(args);\n const concurrent = popNumber(args, Infinity);\n const sources = args as ObservableInput<unknown>[];\n return !sources.length\n ? // No source provided\n EMPTY\n : sources.length === 1\n ? // One source? Just return it.\n innerFrom(sources[0])\n : // Merge all sources\n mergeAll(concurrent)(from(sources, scheduler));\n}\n","import { Observable } from '../Observable';\nimport { noop } from '../util/noop';\n\n/**\n * An Observable that emits no items to the Observer and never completes.\n *\n * ![](never.png)\n *\n * A simple Observable that emits neither values nor errors nor the completion\n * notification. It can be used for testing purposes or for composing with other\n * Observables. Please note that by never emitting a complete notification, this\n * Observable keeps the subscription from being disposed automatically.\n * Subscriptions need to be manually disposed.\n *\n * ## Example\n *\n * Emit the number 7, then never emit anything else (not even complete)\n *\n * ```ts\n * import { NEVER, startWith } from 'rxjs';\n *\n * const info = () => console.log('Will not be called');\n *\n * const result = NEVER.pipe(startWith(7));\n * result.subscribe({\n * next: x => console.log(x),\n * error: info,\n * complete: info\n * });\n * ```\n *\n * @see {@link Observable}\n * @see {@link EMPTY}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const NEVER = new Observable<never>(noop);\n\n/**\n * @deprecated Replaced with the {@link NEVER} constant. Will be removed in v8.\n */\nexport function never() {\n return NEVER;\n}\n","import { SchedulerLike, ValueFromArray } from '../types';\nimport { Observable } from '../Observable';\nimport { popScheduler } from '../util/args';\nimport { from } from './from';\n\n// Devs are more likely to pass null or undefined than they are a scheduler\n// without accompanying values. To make things easier for (naughty) devs who\n// use the `strictNullChecks: false` TypeScript compiler option, these\n// overloads with explicit null and undefined values are included.\n\nexport function of(value: null): Observable<null>;\nexport function of(value: undefined): Observable<undefined>;\n\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function of(scheduler: SchedulerLike): Observable<never>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function of<A extends readonly unknown[]>(...valuesAndScheduler: [...A, SchedulerLike]): Observable<ValueFromArray<A>>;\n\nexport function of(): Observable<never>;\n/** @deprecated Do not specify explicit type parameters. Signatures with type parameters that cannot be inferred will be removed in v8. */\nexport function of<T>(): Observable<T>;\nexport function of<T>(value: T): Observable<T>;\nexport function of<A extends readonly unknown[]>(...values: A): Observable<ValueFromArray<A>>;\n\n/**\n * Converts the arguments to an observable sequence.\n *\n * <span class=\"informal\">Each argument becomes a `next` notification.</span>\n *\n * ![](of.png)\n *\n * Unlike {@link from}, it does not do any flattening and emits each argument in whole\n * as a separate `next` notification.\n *\n * ## Examples\n *\n * Emit the values `10, 20, 30`\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * of(10, 20, 30)\n * .subscribe({\n * next: value => console.log('next:', value),\n * error: err => console.log('error:', err),\n * complete: () => console.log('the end'),\n * });\n *\n * // Outputs\n * // next: 10\n * // next: 20\n * // next: 30\n * // the end\n * ```\n *\n * Emit the array `[1, 2, 3]`\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * of([1, 2, 3])\n * .subscribe({\n * next: value => console.log('next:', value),\n * error: err => console.log('error:', err),\n * complete: () => console.log('the end'),\n * });\n *\n * // Outputs\n * // next: [1, 2, 3]\n * // the end\n * ```\n *\n * @see {@link from}\n * @see {@link range}\n *\n * @param {...T} values A comma separated list of arguments you want to be emitted\n * @return {Observable} An Observable that emits the arguments\n * described above and then completes.\n */\nexport function of<T>(...args: Array<T | SchedulerLike>): Observable<T> {\n const scheduler = popScheduler(args);\n return from(args as T[], scheduler);\n}\n","import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { SchedulerLike } from '../types';\nimport { isFunction } from '../util/isFunction';\n\n/**\n * Creates an observable that will create an error instance and push it to the consumer as an error\n * immediately upon subscription.\n *\n * <span class=\"informal\">Just errors and does nothing else</span>\n *\n * ![](throw.png)\n *\n * This creation function is useful for creating an observable that will create an error and error every\n * time it is subscribed to. Generally, inside of most operators when you might want to return an errored\n * observable, this is unnecessary. In most cases, such as in the inner return of {@link concatMap},\n * {@link mergeMap}, {@link defer}, and many others, you can simply throw the error, and RxJS will pick\n * that up and notify the consumer of the error.\n *\n * ## Example\n *\n * Create a simple observable that will create a new error with a timestamp and log it\n * and the message every time you subscribe to it\n *\n * ```ts\n * import { throwError } from 'rxjs';\n *\n * let errorCount = 0;\n *\n * const errorWithTimestamp$ = throwError(() => {\n * const error: any = new Error(`This is error number ${ ++errorCount }`);\n * error.timestamp = Date.now();\n * return error;\n * });\n *\n * errorWithTimestamp$.subscribe({\n * error: err => console.log(err.timestamp, err.message)\n * });\n *\n * errorWithTimestamp$.subscribe({\n * error: err => console.log(err.timestamp, err.message)\n * });\n *\n * // Logs the timestamp and a new error message for each subscription\n * ```\n *\n * ### Unnecessary usage\n *\n * Using `throwError` inside of an operator or creation function\n * with a callback, is usually not necessary\n *\n * ```ts\n * import { of, concatMap, timer, throwError } from 'rxjs';\n *\n * const delays$ = of(1000, 2000, Infinity, 3000);\n *\n * delays$.pipe(\n * concatMap(ms => {\n * if (ms < 10000) {\n * return timer(ms);\n * } else {\n * // This is probably overkill.\n * return throwError(() => new Error(`Invalid time ${ ms }`));\n * }\n * })\n * )\n * .subscribe({\n * next: console.log,\n * error: console.error\n * });\n * ```\n *\n * You can just throw the error instead\n *\n * ```ts\n * import { of, concatMap, timer } from 'rxjs';\n *\n * const delays$ = of(1000, 2000, Infinity, 3000);\n *\n * delays$.pipe(\n * concatMap(ms => {\n * if (ms < 10000) {\n * return timer(ms);\n * } else {\n * // Cleaner and easier to read for most folks.\n * throw new Error(`Invalid time ${ ms }`);\n * }\n * })\n * )\n * .subscribe({\n * next: console.log,\n * error: console.error\n * });\n * ```\n *\n * @param errorFactory A factory function that will create the error instance that is pushed.\n */\nexport function throwError(errorFactory: () => any): Observable<never>;\n\n/**\n * Returns an observable that will error with the specified error immediately upon subscription.\n *\n * @param error The error instance to emit\n * @deprecated Support for passing an error value will be removed in v8. Instead, pass a factory function to `throwError(() => new Error('test'))`. This is\n * because it will create the error at the moment it should be created and capture a more appropriate stack trace. If\n * for some reason you need to create the error ahead of time, you can still do that: `const err = new Error('test'); throwError(() => err);`.\n */\nexport function throwError(error: any): Observable<never>;\n\n/**\n * Notifies the consumer of an error using a given scheduler by scheduling it at delay `0` upon subscription.\n *\n * @param errorOrErrorFactory An error instance or error factory\n * @param scheduler A scheduler to use to schedule the error notification\n * @deprecated The `scheduler` parameter will be removed in v8.\n * Use `throwError` in combination with {@link observeOn}: `throwError(() => new Error('test')).pipe(observeOn(scheduler));`.\n * Details: https://rxjs.dev/deprecations/scheduler-argument\n */\nexport function throwError(errorOrErrorFactory: any, scheduler: SchedulerLike): Observable<never>;\n\nexport function throwError(errorOrErrorFactory: any, scheduler?: SchedulerLike): Observable<never> {\n const errorFactory = isFunction(errorOrErrorFactory) ? errorOrErrorFactory : () => errorOrErrorFactory;\n const init = (subscriber: Subscriber<never>) => subscriber.error(errorFactory());\n return new Observable(scheduler ? (subscriber) => scheduler.schedule(init as any, 0, subscriber) : init);\n}\n","import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\n\n/**\n * Creates an observable that will wait for a specified time period, or exact date, before\n * emitting the number 0.\n *\n * <span class=\"informal\">Used to emit a notification after a delay.</span>\n *\n * This observable is useful for creating delays in code, or racing against other values\n * for ad-hoc timeouts.\n *\n * The `delay` is specified by default in milliseconds, however providing a custom scheduler could\n * create a different behavior.\n *\n * ## Examples\n *\n * Wait 3 seconds and start another observable\n *\n * You might want to use `timer` to delay subscription to an\n * observable by a set amount of time. Here we use a timer with\n * {@link concatMapTo} or {@link concatMap} in order to wait\n * a few seconds and start a subscription to a source.\n *\n * ```ts\n * import { of, timer, concatMap } from 'rxjs';\n *\n * // This could be any observable\n * const source = of(1, 2, 3);\n *\n * timer(3000)\n * .pipe(concatMap(() => source))\n * .subscribe(console.log);\n * ```\n *\n * Take all values until the start of the next minute\n *\n * Using a `Date` as the trigger for the first emission, you can\n * do things like wait until midnight to fire an event, or in this case,\n * wait until a new minute starts (chosen so the example wouldn't take\n * too long to run) in order to stop watching a stream. Leveraging\n * {@link takeUntil}.\n *\n * ```ts\n * import { interval, takeUntil, timer } from 'rxjs';\n *\n * // Build a Date object that marks the\n * // next minute.\n * const currentDate = new Date();\n * const startOfNextMinute = new Date(\n * currentDate.getFullYear(),\n * currentDate.getMonth(),\n * currentDate.getDate(),\n * currentDate.getHours(),\n * currentDate.getMinutes() + 1\n * );\n *\n * // This could be any observable stream\n * const source = interval(1000);\n *\n * const result = source.pipe(\n * takeUntil(timer(startOfNextMinute))\n * );\n *\n * result.subscribe(console.log);\n * ```\n *\n * ### Known Limitations\n *\n * - The {@link asyncScheduler} uses `setTimeout` which has limitations for how far in the future it can be scheduled.\n *\n * - If a `scheduler` is provided that returns a timestamp other than an epoch from `now()`, and\n * a `Date` object is passed to the `dueTime` argument, the calculation for when the first emission\n * should occur will be incorrect. In this case, it would be best to do your own calculations\n * ahead of time, and pass a `number` in as the `dueTime`.\n *\n * @param due If a `number`, the amount of time in milliseconds to wait before emitting.\n * If a `Date`, the exact time at which to emit.\n * @param scheduler The scheduler to use to schedule the delay. Defaults to {@link asyncScheduler}.\n */\nexport function timer(due: number | Date, scheduler?: SchedulerLike): Observable<0>;\n\n/**\n * Creates an observable that starts an interval after a specified delay, emitting incrementing numbers -- starting at `0` --\n * on each interval after words.\n *\n * The `delay` and `intervalDuration` are specified by default in milliseconds, however providing a custom scheduler could\n * create a different behavior.\n *\n * ## Example\n *\n * ### Start an interval that starts right away\n *\n * Since {@link interval} waits for the passed delay before starting,\n * sometimes that's not ideal. You may want to start an interval immediately.\n * `timer` works well for this. Here we have both side-by-side so you can\n * see them in comparison.\n *\n * Note that this observable will never complete.\n *\n * ```ts\n * import { timer, interval } from 'rxjs';\n *\n * timer(0, 1000).subscribe(n => console.log('timer', n));\n * interval(1000).subscribe(n => console.log('interval', n));\n * ```\n *\n * ### Known Limitations\n *\n * - The {@link asyncScheduler} uses `setTimeout` which has limitations for how far in the future it can be scheduled.\n *\n * - If a `scheduler` is provided that returns a timestamp other than an epoch from `now()`, and\n * a `Date` object is passed to the `dueTime` argument, the calculation for when the first emission\n * should occur will be incorrect. In this case, it would be best to do your own calculations\n * ahead of time, and pass a `number` in as the `startDue`.\n * @param startDue If a `number`, is the time to wait before starting the interval.\n * If a `Date`, is the exact time at which to start the interval.\n * @param intervalDuration The delay between each value emitted in the interval. Passing a\n * negative number here will result in immediate completion after the first value is emitted, as though\n * no `intervalDuration` was passed at all.\n * @param scheduler The scheduler to use to schedule the delay. Defaults to {@link asyncScheduler}.\n */\nexport function timer(startDue: number | Date, intervalDuration: number, scheduler?: SchedulerLike): Observable<number>;\n\n/**\n * @deprecated The signature allowing `undefined` to be passed for `intervalDuration` will be removed in v8. Use the `timer(dueTime, scheduler?)` signature instead.\n */\nexport function timer(dueTime: number | Date, unused: undefined, scheduler?: SchedulerLike): Observable<0>;\n\nexport function timer(\n dueTime: number | Date = 0,\n intervalOrScheduler?: number | SchedulerLike,\n scheduler: SchedulerLike = asyncScheduler\n): Observable<number> {\n // Since negative intervalDuration is treated as though no\n // interval was specified at all, we start with a negative number.\n let intervalDuration = -1;\n\n if (intervalOrScheduler != null) {\n // If we have a second argument, and it's a scheduler,\n // override the scheduler we had defaulted. Otherwise,\n // it must be an interval.\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n } else {\n // Note that this *could* be negative, in which case\n // it's like not passing an intervalDuration at all.\n intervalDuration = intervalOrScheduler;\n }\n }\n\n return new Observable((subscriber) => {\n // If a valid date is passed, calculate how long to wait before\n // executing the first value... otherwise, if it's a number just schedule\n // that many milliseconds (or scheduler-specified unit size) in the future.\n let due = isValidDate(dueTime) ? +dueTime - scheduler!.now() : dueTime;\n\n if (due < 0) {\n // Ensure we don't schedule in the future.\n due = 0;\n }\n\n // The incrementing value we emit.\n let n = 0;\n\n // Start the timer.\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n // Emit the next value and increment.\n subscriber.next(n++);\n\n if (0 <= intervalDuration) {\n // If we have a interval after the initial timer,\n // reschedule with the period.\n this.schedule(undefined, intervalDuration);\n } else {\n // We didn't have an interval. So just complete.\n subscriber.complete();\n }\n }\n }, due);\n });\n}\n","import { Observable } from '../Observable';\nimport { ObservableInputTuple } from '../types';\nimport { innerFrom } from './innerFrom';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { EMPTY } from './empty';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { popResultSelector } from '../util/args';\n\nexport function zip<A extends readonly unknown[]>(sources: [...ObservableInputTuple<A>]): Observable<A>;\nexport function zip<A extends readonly unknown[], R>(\n sources: [...ObservableInputTuple<A>],\n resultSelector: (...values: A) => R\n): Observable<R>;\nexport function zip<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A>;\nexport function zip<A extends readonly unknown[], R>(\n ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]\n): Observable<R>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are calculated from the values, in order, of each\n * of its input Observables.\n *\n * If the last parameter is a function, this function is used to compute the created value from the input values.\n * Otherwise, an array of the input values is returned.\n *\n * ## Example\n *\n * Combine age and name from different sources\n *\n * ```ts\n * import { of, zip, map } from 'rxjs';\n *\n * const age$ = of(27, 25, 29);\n * const name$ = of('Foo', 'Bar', 'Beer');\n * const isDev$ = of(true, true, false);\n *\n * zip(age$, name$, isDev$).pipe(\n * map(([age, name, isDev]) => ({ age, name, isDev }))\n * )\n * .subscribe(x => console.log(x));\n *\n * // Outputs\n * // { age: 27, name: 'Foo', isDev: true }\n * // { age: 25, name: 'Bar', isDev: true }\n * // { age: 29, name: 'Beer', isDev: false }\n * ```\n *\n * @param sources\n * @return {Observable<R>}\n */\nexport function zip(...args: unknown[]): Observable<unknown> {\n const resultSelector = popResultSelector(args);\n\n const sources = argsOrArgArray(args) as Observable<unknown>[];\n\n return sources.length\n ? new Observable<unknown[]>((subscriber) => {\n // A collection of buffers of values from each source.\n // Keyed by the same index with which the sources were passed in.\n let buffers: unknown[][] = sources.map(() => []);\n\n // An array of flags of whether or not the sources have completed.\n // This is used to check to see if we should complete the result.\n // Keyed by the same index with which the sources were passed in.\n let completed = sources.map(() => false);\n\n // When everything is done, release the arrays above.\n subscriber.add(() => {\n buffers = completed = null!;\n });\n\n // Loop over our sources and subscribe to each one. The index `i` is\n // especially important here, because we use it in closures below to\n // access the related buffers and completion properties\n for (let sourceIndex = 0; !subscriber.closed && sourceIndex < sources.length; sourceIndex++) {\n innerFrom(sources[sourceIndex]).subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n buffers[sourceIndex].push(value);\n // if every buffer has at least one value in it, then we\n // can shift out the oldest value from each buffer and emit\n // them as an array.\n if (buffers.every((buffer) => buffer.length)) {\n const result: any = buffers.map((buffer) => buffer.shift()!);\n // Emit the array. If theres' a result selector, use that.\n subscriber.next(resultSelector ? resultSelector(...result) : result);\n // If any one of the sources is both complete and has an empty buffer\n // then we complete the result. This is because we cannot possibly have\n // any more values to zip together.\n if (buffers.some((buffer, i) => !buffer.length && completed[i])) {\n subscriber.complete();\n }\n }\n },\n () => {\n // This source completed. Mark it as complete so we can check it later\n // if we have to.\n completed[sourceIndex] = true;\n // But, if this complete source has nothing in its buffer, then we\n // can complete the result, because we can't possibly have any more\n // values from this to zip together with the other values.\n !buffers[sourceIndex].length && subscriber.complete();\n }\n )\n );\n }\n\n // When everything is done, release the arrays above.\n return () => {\n buffers = completed = null!;\n };\n })\n : EMPTY;\n}\n","import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber<T>(\n destination: Subscriber<any>,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber<T> {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber<T> extends Subscriber<T> {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber<any>,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber<T>, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber<T>, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber<T>) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n","import { Observable } from '../Observable';\n\nimport { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';\nimport { Subscription } from '../Subscription';\nimport { innerFrom } from '../observable/innerFrom';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { operate } from '../util/lift';\n\n/* tslint:disable:max-line-length */\nexport function catchError<T, O extends ObservableInput<any>>(\n selector: (err: any, caught: Observable<T>) => O\n): OperatorFunction<T, T | ObservedValueOf<O>>;\n/* tslint:enable:max-line-length */\n\n/**\n * Catches errors on the observable to be handled by returning a new observable or throwing an error.\n *\n * <span class=\"informal\">\n * It only listens to the error channel and ignores notifications.\n * Handles errors from the source observable, and maps them to a new observable.\n * The error may also be rethrown, or a new error can be thrown to emit an error from the result.\n * </span>\n *\n * ![](catch.png)\n *\n * This operator handles errors, but forwards along all other events to the resulting observable.\n * If the source observable terminates with an error, it will map that error to a new observable,\n * subscribe to it, and forward all of its events to the resulting observable.\n *\n * ## Examples\n *\n * Continue with a different Observable when there's an error\n *\n * ```ts\n * import { of, map, catchError } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n * .pipe(\n * map(n => {\n * if (n === 4) {\n * throw 'four!';\n * }\n * return n;\n * }),\n * catchError(err => of('I', 'II', 'III', 'IV', 'V'))\n * )\n * .subscribe(x => console.log(x));\n * // 1, 2, 3, I, II, III, IV, V\n * ```\n *\n * Retry the caught source Observable again in case of error, similar to `retry()` operator\n *\n * ```ts\n * import { of, map, catchError, take } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n * .pipe(\n * map(n => {\n * if (n === 4) {\n * throw 'four!';\n * }\n * return n;\n * }),\n * catchError((err, caught) => caught),\n * take(30)\n * )\n * .subscribe(x => console.log(x));\n * // 1, 2, 3, 1, 2, 3, ...\n * ```\n *\n * Throw a new error when the source Observable throws an error\n *\n * ```ts\n * import { of, map, catchError } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n * .pipe(\n * map(n => {\n * if (n === 4) {\n * throw 'four!';\n * }\n * return n;\n * }),\n * catchError(err => {\n * throw 'error in source. Details: ' + err;\n * })\n * )\n * .subscribe({\n * next: x => console.log(x),\n * error: err => console.log(err)\n * });\n * // 1, 2, 3, error in source. Details: four!\n * ```\n *\n * @see {@link onErrorResumeNext}\n * @see {@link repeat}\n * @see {@link repeatWhen}\n * @see {@link retry }\n * @see {@link retryWhen}\n *\n * @param {function} selector a function that takes as arguments `err`, which is the error, and `caught`, which\n * is the source observable, in case you'd like to \"retry\" that observable by returning it again. Whatever observable\n * is returned by the `selector` will be used to continue the observable chain.\n * @return A function that returns an Observable that originates from either\n * the source or the Observable returned by the `selector` function.\n */\nexport function catchError<T, O extends ObservableInput<any>>(\n selector: (err: any, caught: Observable<T>) => O\n): OperatorFunction<T, T | ObservedValueOf<O>> {\n return operate((source, subscriber) => {\n let innerSub: Subscription | null = null;\n let syncUnsub = false;\n let handledResult: Observable<ObservedValueOf<O>>;\n\n innerSub = source.subscribe(\n createOperatorSubscriber(subscriber, undefined, undefined, (err) => {\n handledResult = innerFrom(selector(err, catchError(selector)(source)));\n if (innerSub) {\n innerSub.unsubscribe();\n innerSub = null;\n handledResult.subscribe(subscriber);\n } else {\n // We don't have an innerSub yet, that means the error was synchronous\n // because the subscribe call hasn't returned yet.\n syncUnsub = true;\n }\n })\n );\n\n if (syncUnsub) {\n // We have a synchronous error, we need to make sure to\n // finalize right away. This ensures that callbacks in the `finalize` operator are called\n // at the right time, and that finalization occurs at the expected\n // time between the source error and the subscription to the\n // next observable.\n innerSub.unsubscribe();\n innerSub = null;\n handledResult!.subscribe(subscriber);\n }\n });\n}\n","import { mergeMap } from './mergeMap';\nimport { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';\nimport { isFunction } from '../util/isFunction';\n\n/* tslint:disable:max-line-length */\nexport function concatMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function concatMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: undefined\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function concatMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, R>;\n/* tslint:enable:max-line-length */\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable, in a serialized fashion waiting for each one to complete before\n * merging the next.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link concatAll}.</span>\n *\n * ![](concatMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. Each new inner Observable is\n * concatenated with the previous inner Observable.\n *\n * __Warning:__ if source values arrive endlessly and faster than their\n * corresponding inner Observables can complete, it will result in memory issues\n * as inner Observables amass in an unbounded buffer waiting for their turn to\n * be subscribed to.\n *\n * Note: `concatMap` is equivalent to `mergeMap` with concurrency parameter set\n * to `1`.\n *\n * ## Example\n *\n * For each click event, tick every second from 0 to 3, with no concurrency\n *\n * ```ts\n * import { fromEvent, concatMap, interval, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n * concatMap(ev => interval(1000).pipe(take(4)))\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // (results are not concurrent)\n * // For every click on the \"document\" it will emit values 0 to 3 spaced\n * // on a 1000ms interval\n * // one click = 1000ms-> 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3\n * ```\n *\n * @see {@link concat}\n * @see {@link concatAll}\n * @see {@link concatMapTo}\n * @see {@link exhaustMap}\n * @see {@link mergeMap}\n * @see {@link switchMap}\n *\n * @param {function(value: T, ?index: number): ObservableInput} project A function\n * that, when applied to an item emitted by the source Observable, returns an\n * Observable.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function (and the optional deprecated\n * `resultSelector`) to each item emitted by the source Observable and taking\n * values from each projected inner Observable sequentially.\n */\nexport function concatMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector?: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, ObservedValueOf<O> | R> {\n return isFunction(resultSelector) ? mergeMap(project, resultSelector, 1) : mergeMap(project, 1);\n}\n","import { asyncScheduler } from '../scheduler/async';\nimport { Subscription } from '../Subscription';\nimport { MonoTypeOperatorFunction, SchedulerAction, SchedulerLike } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Emits a notification from the source Observable only after a particular time span\n * has passed without another source emission.\n *\n * <span class=\"informal\">It's like {@link delay}, but passes only the most\n * recent notification from each burst of emissions.</span>\n *\n * ![](debounceTime.png)\n *\n * `debounceTime` delays notifications emitted by the source Observable, but drops\n * previous pending delayed emissions if a new notification arrives on the source\n * Observable. This operator keeps track of the most recent notification from the\n * source Observable, and emits that only when `dueTime` has passed\n * without any other notification appearing on the source Observable. If a new value\n * appears before `dueTime` silence occurs, the previous notification will be dropped\n * and will not be emitted and a new `dueTime` is scheduled.\n * If the completing event happens during `dueTime` the last cached notification\n * is emitted before the completion event is forwarded to the output observable.\n * If the error event happens during `dueTime` or after it only the error event is\n * forwarded to the output observable. The cache notification is not emitted in this case.\n *\n * This is a rate-limiting operator, because it is impossible for more than one\n * notification to be emitted in any time window of duration `dueTime`, but it is also\n * a delay-like operator since output emissions do not occur at the same time as\n * they did on the source Observable. Optionally takes a {@link SchedulerLike} for\n * managing timers.\n *\n * ## Example\n *\n * Emit the most recent click after a burst of clicks\n *\n * ```ts\n * import { fromEvent, debounceTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(debounceTime(1000));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link auditTime}\n * @see {@link debounce}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link throttle}\n * @see {@link throttleTime}\n *\n * @param {number} dueTime The timeout duration in milliseconds (or the time\n * unit determined internally by the optional `scheduler`) for the window of\n * time required to wait for emission silence before emitting the most recent\n * source value.\n * @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for\n * managing the timers that handle the timeout for each value.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by the specified `dueTime`, and may drop some values\n * if they occur too frequently.\n */\nexport function debounceTime<T>(dueTime: number, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n let activeTask: Subscription | null = null;\n let lastValue: T | null = null;\n let lastTime: number | null = null;\n\n const emit = () => {\n if (activeTask) {\n // We have a value! Free up memory first, then emit the value.\n activeTask.unsubscribe();\n activeTask = null;\n const value = lastValue!;\n lastValue = null;\n subscriber.next(value);\n }\n };\n function emitWhenIdle(this: SchedulerAction<unknown>) {\n // This is called `dueTime` after the first value\n // but we might have received new values during this window!\n\n const targetTime = lastTime! + dueTime;\n const now = scheduler.now();\n if (now < targetTime) {\n // On that case, re-schedule to the new target\n activeTask = this.schedule(undefined, targetTime - now);\n subscriber.add(activeTask);\n return;\n }\n\n emit();\n }\n\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value: T) => {\n lastValue = value;\n lastTime = scheduler.now();\n\n // Only set up a task if it's not already up\n if (!activeTask) {\n activeTask = scheduler.schedule(emitWhenIdle, dueTime);\n subscriber.add(activeTask);\n }\n },\n () => {\n // Source completed.\n // Emit any pending debounced values then complete\n emit();\n subscriber.complete();\n },\n // Pass all errors through to consumer.\n undefined,\n () => {\n // Finalization.\n lastValue = activeTask = null;\n }\n )\n );\n });\n}\n","import { OperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Emits a given value if the source Observable completes without emitting any\n * `next` value, otherwise mirrors the source Observable.\n *\n * <span class=\"informal\">If the source Observable turns out to be empty, then\n * this operator will emit a default value.</span>\n *\n * ![](defaultIfEmpty.png)\n *\n * `defaultIfEmpty` emits the values emitted by the source Observable or a\n * specified default value if the source Observable is empty (completes without\n * having emitted any `next` value).\n *\n * ## Example\n *\n * If no clicks happen in 5 seconds, then emit 'no clicks'\n *\n * ```ts\n * import { fromEvent, takeUntil, interval, defaultIfEmpty } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const clicksBeforeFive = clicks.pipe(takeUntil(interval(5000)));\n * const result = clicksBeforeFive.pipe(defaultIfEmpty('no clicks'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link empty}\n * @see {@link last}\n *\n * @param defaultValue The default value used if the source\n * Observable is empty.\n * @return A function that returns an Observable that emits either the\n * specified `defaultValue` if the source Observable emits no items, or the\n * values emitted by the source Observable.\n */\nexport function defaultIfEmpty<T, R>(defaultValue: R): OperatorFunction<T, T | R> {\n return operate((source, subscriber) => {\n let hasValue = false;\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n hasValue = true;\n subscriber.next(value);\n },\n () => {\n if (!hasValue) {\n subscriber.next(defaultValue!);\n }\n subscriber.complete();\n }\n )\n );\n });\n}\n","import { Observable } from '../Observable';\nimport { MonoTypeOperatorFunction, ObservableInput } from '../types';\nimport { concat } from '../observable/concat';\nimport { take } from './take';\nimport { ignoreElements } from './ignoreElements';\nimport { mapTo } from './mapTo';\nimport { mergeMap } from './mergeMap';\nimport { innerFrom } from '../observable/innerFrom';\n\n/** @deprecated The `subscriptionDelay` parameter will be removed in v8. */\nexport function delayWhen<T>(\n delayDurationSelector: (value: T, index: number) => ObservableInput<any>,\n subscriptionDelay: Observable<any>\n): MonoTypeOperatorFunction<T>;\nexport function delayWhen<T>(delayDurationSelector: (value: T, index: number) => ObservableInput<any>): MonoTypeOperatorFunction<T>;\n\n/**\n * Delays the emission of items from the source Observable by a given time span\n * determined by the emissions of another Observable.\n *\n * <span class=\"informal\">It's like {@link delay}, but the time span of the\n * delay duration is determined by a second Observable.</span>\n *\n * ![](delayWhen.png)\n *\n * `delayWhen` operator shifts each emitted value from the source Observable by\n * a time span determined by another Observable. When the source emits a value,\n * the `delayDurationSelector` function is called with the value emitted from\n * the source Observable as the first argument to the `delayDurationSelector`.\n * The `delayDurationSelector` function should return an {@link ObservableInput},\n * that is internally converted to an Observable that is called the \"duration\"\n * Observable.\n *\n * The source value is emitted on the output Observable only when the \"duration\"\n * Observable emits ({@link guide/glossary-and-semantics#next next}s) any value.\n * Upon that, the \"duration\" Observable gets unsubscribed.\n *\n * Before RxJS V7, the {@link guide/glossary-and-semantics#complete completion}\n * of the \"duration\" Observable would have been triggering the emission of the\n * source value to the output Observable, but with RxJS V7, this is not the case\n * anymore.\n *\n * Only next notifications (from the \"duration\" Observable) trigger values from\n * the source Observable to be passed to the output Observable. If the \"duration\"\n * Observable only emits the complete notification (without next), the value\n * emitted by the source Observable will never get to the output Observable - it\n * will be swallowed. If the \"duration\" Observable errors, the error will be\n * propagated to the output Observable.\n *\n * Optionally, `delayWhen` takes a second argument, `subscriptionDelay`, which\n * is an Observable. When `subscriptionDelay` emits its first value or\n * completes, the source Observable is subscribed to and starts behaving like\n * described in the previous paragraph. If `subscriptionDelay` is not provided,\n * `delayWhen` will subscribe to the source Observable as soon as the output\n * Observable is subscribed.\n *\n * ## Example\n *\n * Delay each click by a random amount of time, between 0 and 5 seconds\n *\n * ```ts\n * import { fromEvent, delayWhen, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const delayedClicks = clicks.pipe(\n * delayWhen(() => interval(Math.random() * 5000))\n * );\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link delay}\n * @see {@link throttle}\n * @see {@link throttleTime}\n * @see {@link debounce}\n * @see {@link debounceTime}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link audit}\n * @see {@link auditTime}\n *\n * @param delayDurationSelector A function that returns an `ObservableInput` for\n * each `value` emitted by the source Observable, which is then used to delay the\n * emission of that `value` on the output Observable until the `ObservableInput`\n * returned from this function emits a next value. When called, beside `value`,\n * this function receives a zero-based `index` of the emission order.\n * @param subscriptionDelay An Observable that triggers the subscription to the\n * source Observable once it emits any value.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by an amount of time specified by the Observable\n * returned by `delayDurationSelector`.\n */\nexport function delayWhen<T>(\n delayDurationSelector: (value: T, index: number) => ObservableInput<any>,\n subscriptionDelay?: Observable<any>\n): MonoTypeOperatorFunction<T> {\n if (subscriptionDelay) {\n // DEPRECATED PATH\n return (source: Observable<T>) =>\n concat(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));\n }\n\n return mergeMap((value, index) => innerFrom(delayDurationSelector(value, index)).pipe(take(1), mapTo(value)));\n}\n","import { asyncScheduler } from '../scheduler/async';\nimport { MonoTypeOperatorFunction, SchedulerLike } from '../types';\nimport { delayWhen } from './delayWhen';\nimport { timer } from '../observable/timer';\n\n/**\n * Delays the emission of items from the source Observable by a given timeout or\n * until a given Date.\n *\n * <span class=\"informal\">Time shifts each item by some specified amount of\n * milliseconds.</span>\n *\n * ![](delay.svg)\n *\n * If the delay argument is a Number, this operator time shifts the source\n * Observable by that amount of time expressed in milliseconds. The relative\n * time intervals between the values are preserved.\n *\n * If the delay argument is a Date, this operator time shifts the start of the\n * Observable execution until the given date occurs.\n *\n * ## Examples\n *\n * Delay each click by one second\n *\n * ```ts\n * import { fromEvent, delay } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const delayedClicks = clicks.pipe(delay(1000)); // each click emitted after 1 second\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * Delay all clicks until a future date happens\n *\n * ```ts\n * import { fromEvent, delay } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const date = new Date('March 15, 2050 12:00:00'); // in the future\n * const delayedClicks = clicks.pipe(delay(date)); // click emitted only after that date\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link delayWhen}\n * @see {@link throttle}\n * @see {@link throttleTime}\n * @see {@link debounce}\n * @see {@link debounceTime}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link audit}\n * @see {@link auditTime}\n *\n * @param {number|Date} due The delay duration in milliseconds (a `number`) or\n * a `Date` until which the emission of the source items is delayed.\n * @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for\n * managing the timers that handle the time-shift for each item.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by the specified timeout or Date.\n */\nexport function delay<T>(due: number | Date, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n const duration = timer(due, scheduler);\n return delayWhen(() => duration);\n}\n","import { MonoTypeOperatorFunction } from '../types';\nimport { identity } from '../util/identity';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\nexport function distinctUntilChanged<T>(comparator?: (previous: T, current: T) => boolean): MonoTypeOperatorFunction<T>;\nexport function distinctUntilChanged<T, K>(\n comparator: (previous: K, current: K) => boolean,\n keySelector: (value: T) => K\n): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns a result {@link Observable} that emits all values pushed by the source observable if they\n * are distinct in comparison to the last value the result observable emitted.\n *\n * When provided without parameters or with the first parameter (`{@link distinctUntilChanged#comparator comparator}`),\n * it behaves like this:\n *\n * 1. It will always emit the first value from the source.\n * 2. For all subsequent values pushed by the source, they will be compared to the previously emitted values\n * using the provided `comparator` or an `===` equality check.\n * 3. If the value pushed by the source is determined to be unequal by this check, that value is emitted and\n * becomes the new \"previously emitted value\" internally.\n *\n * When the second parameter (`{@link distinctUntilChanged#keySelector keySelector}`) is provided, the behavior\n * changes:\n *\n * 1. It will always emit the first value from the source.\n * 2. The `keySelector` will be run against all values, including the first value.\n * 3. For all values after the first, the selected key will be compared against the key selected from\n * the previously emitted value using the `comparator`.\n * 4. If the keys are determined to be unequal by this check, the value (not the key), is emitted\n * and the selected key from that value is saved for future comparisons against other keys.\n *\n * ## Examples\n *\n * A very basic example with no `{@link distinctUntilChanged#comparator comparator}`. Note that `1` is emitted more than once,\n * because it's distinct in comparison to the _previously emitted_ value,\n * not in comparison to _all other emitted values_.\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * of(1, 1, 1, 2, 2, 2, 1, 1, 3, 3)\n * .pipe(distinctUntilChanged())\n * .subscribe(console.log);\n * // Logs: 1, 2, 1, 3\n * ```\n *\n * With a `{@link distinctUntilChanged#comparator comparator}`, you can do custom comparisons. Let's say\n * you only want to emit a value when all of its components have\n * changed:\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * const totallyDifferentBuilds$ = of(\n * { engineVersion: '1.1.0', transmissionVersion: '1.2.0' },\n * { engineVersion: '1.1.0', transmissionVersion: '1.4.0' },\n * { engineVersion: '1.3.0', transmissionVersion: '1.4.0' },\n * { engineVersion: '1.3.0', transmissionVersion: '1.5.0' },\n * { engineVersion: '2.0.0', transmissionVersion: '1.5.0' }\n * ).pipe(\n * distinctUntilChanged((prev, curr) => {\n * return (\n * prev.engineVersion === curr.engineVersion ||\n * prev.transmissionVersion === curr.transmissionVersion\n * );\n * })\n * );\n *\n * totallyDifferentBuilds$.subscribe(console.log);\n *\n * // Logs:\n * // { engineVersion: '1.1.0', transmissionVersion: '1.2.0' }\n * // { engineVersion: '1.3.0', transmissionVersion: '1.4.0' }\n * // { engineVersion: '2.0.0', transmissionVersion: '1.5.0' }\n * ```\n *\n * You can also provide a custom `{@link distinctUntilChanged#comparator comparator}` to check that emitted\n * changes are only in one direction. Let's say you only want to get\n * the next record temperature:\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * const temps$ = of(30, 31, 20, 34, 33, 29, 35, 20);\n *\n * const recordHighs$ = temps$.pipe(\n * distinctUntilChanged((prevHigh, temp) => {\n * // If the current temp is less than\n * // or the same as the previous record,\n * // the record hasn't changed.\n * return temp <= prevHigh;\n * })\n * );\n *\n * recordHighs$.subscribe(console.log);\n * // Logs: 30, 31, 34, 35\n * ```\n *\n * Selecting update events only when the `updatedBy` field shows\n * the account changed hands.\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * // A stream of updates to a given account\n * const accountUpdates$ = of(\n * { updatedBy: 'blesh', data: [] },\n * { updatedBy: 'blesh', data: [] },\n * { updatedBy: 'ncjamieson', data: [] },\n * { updatedBy: 'ncjamieson', data: [] },\n * { updatedBy: 'blesh', data: [] }\n * );\n *\n * // We only want the events where it changed hands\n * const changedHands$ = accountUpdates$.pipe(\n * distinctUntilChanged(undefined, update => update.updatedBy)\n * );\n *\n * changedHands$.subscribe(console.log);\n * // Logs:\n * // { updatedBy: 'blesh', data: Array[0] }\n * // { updatedBy: 'ncjamieson', data: Array[0] }\n * // { updatedBy: 'blesh', data: Array[0] }\n * ```\n *\n * @see {@link distinct}\n * @see {@link distinctUntilKeyChanged}\n *\n * @param comparator A function used to compare the previous and current keys for\n * equality. Defaults to a `===` check.\n * @param keySelector Used to select a key value to be passed to the `comparator`.\n *\n * @return A function that returns an Observable that emits items from the\n * source Observable with distinct values.\n */\nexport function distinctUntilChanged<T, K>(\n comparator?: (previous: K, current: K) => boolean,\n keySelector: (value: T) => K = identity as (value: T) => K\n): MonoTypeOperatorFunction<T> {\n // We've been allowing `null` do be passed as the `compare`, so we can't do\n // a default value for the parameter, because that will only work\n // for `undefined`.\n comparator = comparator ?? defaultCompare;\n\n return operate((source, subscriber) => {\n // The previous key, used to compare against keys selected\n // from new arrivals to determine \"distinctiveness\".\n let previousKey: K;\n // Whether or not this is the first value we've gotten.\n let first = true;\n\n source.subscribe(\n createOperatorSubscriber(subscriber, (value) => {\n // We always call the key selector.\n const currentKey = keySelector(value);\n\n // If it's the first value, we always emit it.\n // Otherwise, we compare this key to the previous key, and\n // if the comparer returns false, we emit.\n if (first || !comparator!(previousKey, currentKey)) {\n // Update our state *before* we emit the value\n // as emission can be the source of re-entrant code\n // in functional libraries like this. We only really\n // need to do this if it's the first value, or if the\n // key we're tracking in previous needs to change.\n first = false;\n previousKey = currentKey;\n\n // Emit the value!\n subscriber.next(value);\n }\n })\n );\n });\n}\n\nfunction defaultCompare(a: any, b: any) {\n return a === b;\n}\n","import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';\nimport { map } from './map';\nimport { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/* tslint:disable:max-line-length */\nexport function exhaustMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function exhaustMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: undefined\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function exhaustMap<T, I, R>(\n project: (value: T, index: number) => ObservableInput<I>,\n resultSelector: (outerValue: T, innerValue: I, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, R>;\n/* tslint:enable:max-line-length */\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable only if the previous projected Observable has completed.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link exhaustAll}.</span>\n *\n * ![](exhaustMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. When it projects a source value to\n * an Observable, the output Observable begins emitting the items emitted by\n * that projected Observable. However, `exhaustMap` ignores every new projected\n * Observable if the previous projected Observable has not yet completed. Once\n * that one completes, it will accept and flatten the next projected Observable\n * and repeat this process.\n *\n * ## Example\n *\n * Run a finite timer for each click, only if there is no currently active timer\n *\n * ```ts\n * import { fromEvent, exhaustMap, interval, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n * exhaustMap(() => interval(1000).pipe(take(5)))\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaust}\n * @see {@link mergeMap}\n * @see {@link switchMap}\n *\n * @param {function(value: T, ?index: number): ObservableInput} project A function\n * that, when applied to an item emitted by the source Observable, returns an\n * Observable.\n * @return A function that returns an Observable containing projected\n * Observables of each item of the source, ignoring projected Observables that\n * start before their preceding Observable has completed.\n */\nexport function exhaustMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector?: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, ObservedValueOf<O> | R> {\n if (resultSelector) {\n // DEPRECATED PATH\n return (source: Observable<T>) =>\n source.pipe(exhaustMap((a, i) => innerFrom(project(a, i)).pipe(map((b: any, ii: any) => resultSelector(a, b, i, ii)))));\n }\n return operate((source, subscriber) => {\n let index = 0;\n let innerSub: Subscriber<T> | null = null;\n let isComplete = false;\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (outerValue) => {\n if (!innerSub) {\n innerSub = createOperatorSubscriber(subscriber, undefined, () => {\n innerSub = null;\n isComplete && subscriber.complete();\n });\n innerFrom(project(outerValue, index++)).subscribe(innerSub);\n }\n },\n () => {\n isComplete = true;\n !innerSub && subscriber.complete();\n }\n )\n );\n });\n}\n","import { OperatorFunction, MonoTypeOperatorFunction, TruthyTypesOf } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function filter<T, S extends T, A>(predicate: (this: A, value: T, index: number) => value is S, thisArg: A): OperatorFunction<T, S>;\nexport function filter<T, S extends T>(predicate: (value: T, index: number) => value is S): OperatorFunction<T, S>;\nexport function filter<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function filter<T, A>(predicate: (this: A, value: T, index: number) => boolean, thisArg: A): MonoTypeOperatorFunction<T>;\nexport function filter<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Filter items emitted by the source Observable by only emitting those that\n * satisfy a specified predicate.\n *\n * <span class=\"informal\">Like\n * [Array.prototype.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),\n * it only emits a value from the source if it passes a criterion function.</span>\n *\n * ![](filter.png)\n *\n * Similar to the well-known `Array.prototype.filter` method, this operator\n * takes values from the source Observable, passes them through a `predicate`\n * function and only emits those values that yielded `true`.\n *\n * ## Example\n *\n * Emit only click events whose target was a DIV element\n *\n * ```ts\n * import { fromEvent, filter } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const clicksOnDivs = clicks.pipe(filter(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * clicksOnDivs.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link distinct}\n * @see {@link distinctUntilChanged}\n * @see {@link distinctUntilKeyChanged}\n * @see {@link ignoreElements}\n * @see {@link partition}\n * @see {@link skip}\n *\n * @param predicate A function that\n * evaluates each value emitted by the source Observable. If it returns `true`,\n * the value is emitted, if `false` the value is not passed to the output\n * Observable. The `index` parameter is the number `i` for the i-th source\n * emission that has happened since the subscription, starting from the number\n * `0`.\n * @param thisArg An optional argument to determine the value of `this`\n * in the `predicate` function.\n * @return A function that returns an Observable that emits items from the\n * source Observable that satisfy the specified `predicate`.\n */\nexport function filter<T>(predicate: (value: T, index: number) => boolean, thisArg?: any): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n // An index passed to our predicate function on each call.\n let index = 0;\n\n // Subscribe to the source, all errors and completions are\n // forwarded to the consumer.\n source.subscribe(\n // Call the predicate with the appropriate `this` context,\n // if the predicate returns `true`, then send the value\n // to the consumer.\n createOperatorSubscriber(subscriber, (value) => predicate.call(thisArg, value, index++) && subscriber.next(value))\n );\n });\n}\n","import { MonoTypeOperatorFunction } from '../types';\nimport { operate } from '../util/lift';\n\n/**\n * Returns an Observable that mirrors the source Observable, but will call a specified function when\n * the source terminates on complete or error.\n * The specified function will also be called when the subscriber explicitly unsubscribes.\n *\n * ## Examples\n *\n * Execute callback function when the observable completes\n *\n * ```ts\n * import { interval, take, finalize } from 'rxjs';\n *\n * // emit value in sequence every 1 second\n * const source = interval(1000);\n * const example = source.pipe(\n * take(5), //take only the first 5 values\n * finalize(() => console.log('Sequence complete')) // Execute when the observable completes\n * );\n * const subscribe = example.subscribe(val => console.log(val));\n *\n * // results:\n * // 0\n * // 1\n * // 2\n * // 3\n * // 4\n * // 'Sequence complete'\n * ```\n *\n * Execute callback function when the subscriber explicitly unsubscribes\n *\n * ```ts\n * import { interval, finalize, tap, noop, timer } from 'rxjs';\n *\n * const source = interval(100).pipe(\n * finalize(() => console.log('[finalize] Called')),\n * tap({\n * next: () => console.log('[next] Called'),\n * error: () => console.log('[error] Not called'),\n * complete: () => console.log('[tap complete] Not called')\n * })\n * );\n *\n * const sub = source.subscribe({\n * next: x => console.log(x),\n * error: noop,\n * complete: () => console.log('[complete] Not called')\n * });\n *\n * timer(150).subscribe(() => sub.unsubscribe());\n *\n * // results:\n * // '[next] Called'\n * // 0\n * // '[finalize] Called'\n * ```\n *\n * @param {function} callback Function to be called when source terminates.\n * @return A function that returns an Observable that mirrors the source, but\n * will call the specified function on termination.\n */\nexport function finalize<T>(callback: () => void): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n // TODO: This try/finally was only added for `useDeprecatedSynchronousErrorHandling`.\n // REMOVE THIS WHEN THAT HOT GARBAGE IS REMOVED IN V8.\n try {\n source.subscribe(subscriber);\n } finally {\n subscriber.add(callback);\n }\n });\n}\n","import { Observable } from '../Observable';\nimport { EmptyError } from '../util/EmptyError';\nimport { OperatorFunction, TruthyTypesOf } from '../types';\nimport { filter } from './filter';\nimport { take } from './take';\nimport { defaultIfEmpty } from './defaultIfEmpty';\nimport { throwIfEmpty } from './throwIfEmpty';\nimport { identity } from '../util/identity';\n\nexport function first<T, D = T>(predicate?: null, defaultValue?: D): OperatorFunction<T, T | D>;\nexport function first<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function first<T, D>(predicate: BooleanConstructor, defaultValue: D): OperatorFunction<T, TruthyTypesOf<T> | D>;\nexport function first<T, S extends T>(\n predicate: (value: T, index: number, source: Observable<T>) => value is S,\n defaultValue?: S\n): OperatorFunction<T, S>;\nexport function first<T, S extends T, D>(\n predicate: (value: T, index: number, source: Observable<T>) => value is S,\n defaultValue: D\n): OperatorFunction<T, S | D>;\nexport function first<T, D = T>(\n predicate: (value: T, index: number, source: Observable<T>) => boolean,\n defaultValue?: D\n): OperatorFunction<T, T | D>;\n\n/**\n * Emits only the first value (or the first value that meets some condition)\n * emitted by the source Observable.\n *\n * <span class=\"informal\">Emits only the first value. Or emits only the first\n * value that passes some test.</span>\n *\n * ![](first.png)\n *\n * If called with no arguments, `first` emits the first value of the source\n * Observable, then completes. If called with a `predicate` function, `first`\n * emits the first value of the source that matches the specified condition. Throws an error if\n * `defaultValue` was not provided and a matching element is not found.\n *\n * ## Examples\n *\n * Emit only the first click that happens on the DOM\n *\n * ```ts\n * import { fromEvent, first } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(first());\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Emits the first click that happens on a DIV\n *\n * ```ts\n * import { fromEvent, first } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(first(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link filter}\n * @see {@link find}\n * @see {@link take}\n *\n * @throws {EmptyError} Delivers an EmptyError to the Observer's `error`\n * callback if the Observable completes before any `next` notification was sent.\n * This is how `first()` is different from {@link take}(1) which completes instead.\n *\n * @param {function(value: T, index: number, source: Observable<T>): boolean} [predicate]\n * An optional function called with each item to test for condition matching.\n * @param {D} [defaultValue] The default value emitted in case no valid value\n * was found on the source.\n * @return A function that returns an Observable that emits the first item that\n * matches the condition.\n */\nexport function first<T, D>(\n predicate?: ((value: T, index: number, source: Observable<T>) => boolean) | null,\n defaultValue?: D\n): OperatorFunction<T, T | D> {\n const hasDefaultValue = arguments.length >= 2;\n return (source: Observable<T>) =>\n source.pipe(\n predicate ? filter((v, i) => predicate(v, i, source)) : identity,\n take(1),\n hasDefaultValue ? defaultIfEmpty(defaultValue!) : throwIfEmpty(() => new EmptyError())\n );\n}\n","import { OperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { noop } from '../util/noop';\n\n/**\n * Ignores all items emitted by the source Observable and only passes calls of `complete` or `error`.\n *\n * ![](ignoreElements.png)\n *\n * The `ignoreElements` operator suppresses all items emitted by the source Observable,\n * but allows its termination notification (either `error` or `complete`) to pass through unchanged.\n *\n * If you do not care about the items being emitted by an Observable, but you do want to be notified\n * when it completes or when it terminates with an error, you can apply the `ignoreElements` operator\n * to the Observable, which will ensure that it will never call its observers’ `next` handlers.\n *\n * ## Example\n *\n * Ignore all `next` emissions from the source\n *\n * ```ts\n * import { of, ignoreElements } from 'rxjs';\n *\n * of('you', 'talking', 'to', 'me')\n * .pipe(ignoreElements())\n * .subscribe({\n * next: word => console.log(word),\n * error: err => console.log('error:', err),\n * complete: () => console.log('the end'),\n * });\n *\n * // result:\n * // 'the end'\n * ```\n *\n * @return A function that returns an empty Observable that only calls\n * `complete` or `error`, based on which one is called by the source\n * Observable.\n */\nexport function ignoreElements(): OperatorFunction<unknown, never> {\n return operate((source, subscriber) => {\n source.subscribe(createOperatorSubscriber(subscriber, noop));\n });\n}\n","import { OperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\nexport function map<T, R>(project: (value: T, index: number) => R): OperatorFunction<T, R>;\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function map<T, R, A>(project: (this: A, value: T, index: number) => R, thisArg: A): OperatorFunction<T, R>;\n\n/**\n * Applies a given `project` function to each value emitted by the source\n * Observable, and emits the resulting values as an Observable.\n *\n * <span class=\"informal\">Like [Array.prototype.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map),\n * it passes each source value through a transformation function to get\n * corresponding output values.</span>\n *\n * ![](map.png)\n *\n * Similar to the well known `Array.prototype.map` function, this operator\n * applies a projection to each value and emits that projection in the output\n * Observable.\n *\n * ## Example\n *\n * Map every click to the `clientX` position of that click\n *\n * ```ts\n * import { fromEvent, map } from 'rxjs';\n *\n * const clicks = fromEvent<PointerEvent>(document, 'click');\n * const positions = clicks.pipe(map(ev => ev.clientX));\n *\n * positions.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link mapTo}\n * @see {@link pluck}\n *\n * @param {function(value: T, index: number): R} project The function to apply\n * to each `value` emitted by the source Observable. The `index` parameter is\n * the number `i` for the i-th emission that has happened since the\n * subscription, starting from the number `0`.\n * @param {any} [thisArg] An optional argument to define what `this` is in the\n * `project` function.\n * @return A function that returns an Observable that emits the values from the\n * source Observable transformed by the given `project` function.\n */\nexport function map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R> {\n return operate((source, subscriber) => {\n // The index of the value from the source. Used with projection.\n let index = 0;\n // Subscribe to the source, all errors and completions are sent along\n // to the consumer.\n source.subscribe(\n createOperatorSubscriber(subscriber, (value: T) => {\n // Call the projection function with the appropriate this context,\n // and send the resulting value to the consumer.\n subscriber.next(project.call(thisArg, value, index++));\n })\n );\n });\n}\n","import { OperatorFunction } from '../types';\nimport { map } from './map';\n\n/** @deprecated To be removed in v9. Use {@link map} instead: `map(() => value)`. */\nexport function mapTo<R>(value: R): OperatorFunction<unknown, R>;\n/**\n * @deprecated Do not specify explicit type parameters. Signatures with type parameters\n * that cannot be inferred will be removed in v8. `mapTo` itself will be removed in v9,\n * use {@link map} instead: `map(() => value)`.\n * */\nexport function mapTo<T, R>(value: R): OperatorFunction<T, R>;\n\n/**\n * Emits the given constant value on the output Observable every time the source\n * Observable emits a value.\n *\n * <span class=\"informal\">Like {@link map}, but it maps every source value to\n * the same output value every time.</span>\n *\n * ![](mapTo.png)\n *\n * Takes a constant `value` as argument, and emits that whenever the source\n * Observable emits a value. In other words, ignores the actual source value,\n * and simply uses the emission moment to know when to emit the given `value`.\n *\n * ## Example\n *\n * Map every click to the string `'Hi'`\n *\n * ```ts\n * import { fromEvent, mapTo } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const greetings = clicks.pipe(mapTo('Hi'));\n *\n * greetings.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link map}\n *\n * @param value The value to map each source value to.\n * @return A function that returns an Observable that emits the given `value`\n * every time the source Observable emits.\n * @deprecated To be removed in v9. Use {@link map} instead: `map(() => value)`.\n */\nexport function mapTo<R>(value: R): OperatorFunction<unknown, R> {\n return map(() => value);\n}\n","import { mergeMap } from './mergeMap';\nimport { identity } from '../util/identity';\nimport { OperatorFunction, ObservableInput, ObservedValueOf } from '../types';\n\n/**\n * Converts a higher-order Observable into a first-order Observable which\n * concurrently delivers all values that are emitted on the inner Observables.\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables.</span>\n *\n * ![](mergeAll.png)\n *\n * `mergeAll` subscribes to an Observable that emits Observables, also known as\n * a higher-order Observable. Each time it observes one of these emitted inner\n * Observables, it subscribes to that and delivers all the values from the\n * inner Observable on the output Observable. The output Observable only\n * completes once all inner Observables have completed. Any error delivered by\n * a inner Observable will be immediately emitted on the output Observable.\n *\n * ## Examples\n *\n * Spawn a new interval Observable for each click event, and blend their outputs as one Observable\n *\n * ```ts\n * import { fromEvent, map, interval, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(map(() => interval(1000)));\n * const firstOrder = higherOrder.pipe(mergeAll());\n *\n * firstOrder.subscribe(x => console.log(x));\n * ```\n *\n * Count from 0 to 9 every second for each click, but only allow 2 concurrent timers\n *\n * ```ts\n * import { fromEvent, map, interval, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n * map(() => interval(1000).pipe(take(10)))\n * );\n * const firstOrder = higherOrder.pipe(mergeAll(2));\n *\n * firstOrder.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concatAll}\n * @see {@link exhaustAll}\n * @see {@link merge}\n * @see {@link mergeMap}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link zipAll}\n *\n * @param {number} [concurrent=Infinity] Maximum number of inner\n * Observables being subscribed to concurrently.\n * @return A function that returns an Observable that emits values coming from\n * all the inner Observables emitted by the source Observable.\n */\nexport function mergeAll<O extends ObservableInput<any>>(concurrent: number = Infinity): OperatorFunction<O, ObservedValueOf<O>> {\n return mergeMap(identity, concurrent);\n}\n","import { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';\nimport { map } from './map';\nimport { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { mergeInternals } from './mergeInternals';\nimport { isFunction } from '../util/isFunction';\n\n/* tslint:disable:max-line-length */\nexport function mergeMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n concurrent?: number\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function mergeMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: undefined,\n concurrent?: number\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function mergeMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R,\n concurrent?: number\n): OperatorFunction<T, R>;\n/* tslint:enable:max-line-length */\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link mergeAll}.</span>\n *\n * ![](mergeMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an Observable, and then merging those resulting Observables and\n * emitting the results of this merger.\n *\n * ## Example\n *\n * Map and flatten each letter to an Observable ticking every 1 second\n *\n * ```ts\n * import { of, mergeMap, interval, map } from 'rxjs';\n *\n * const letters = of('a', 'b', 'c');\n * const result = letters.pipe(\n * mergeMap(x => interval(1000).pipe(map(i => x + i)))\n * );\n *\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // a0\n * // b0\n * // c0\n * // a1\n * // b1\n * // c1\n * // continues to list a, b, c every second with respective ascending integers\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaustMap}\n * @see {@link merge}\n * @see {@link mergeAll}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n * @see {@link switchMap}\n *\n * @param {function(value: T, ?index: number): ObservableInput} project A function\n * that, when applied to an item emitted by the source Observable, returns an\n * Observable.\n * @param {number} [concurrent=Infinity] Maximum number of input\n * Observables being subscribed to concurrently.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function (and the optional deprecated\n * `resultSelector`) to each item emitted by the source Observable and merging\n * the results of the Observables obtained from this transformation.\n */\nexport function mergeMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector?: ((outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R) | number,\n concurrent: number = Infinity\n): OperatorFunction<T, ObservedValueOf<O> | R> {\n if (isFunction(resultSelector)) {\n // DEPRECATED PATH\n return mergeMap((a, i) => map((b: any, ii: number) => resultSelector(a, b, i, ii))(innerFrom(project(a, i))), concurrent);\n } else if (typeof resultSelector === 'number') {\n concurrent = resultSelector;\n }\n\n return operate((source, subscriber) => mergeInternals(source, subscriber, project, concurrent));\n}\n","import { Observable } from '../Observable';\nimport { innerFrom } from '../observable/innerFrom';\nimport { Subscriber } from '../Subscriber';\nimport { ObservableInput, SchedulerLike } from '../types';\nimport { executeSchedule } from '../util/executeSchedule';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * A process embodying the general \"merge\" strategy. This is used in\n * `mergeMap` and `mergeScan` because the logic is otherwise nearly identical.\n * @param source The original source observable\n * @param subscriber The consumer subscriber\n * @param project The projection function to get our inner sources\n * @param concurrent The number of concurrent inner subscriptions\n * @param onBeforeNext Additional logic to apply before nexting to our consumer\n * @param expand If `true` this will perform an \"expand\" strategy, which differs only\n * in that it recurses, and the inner subscription must be schedule-able.\n * @param innerSubScheduler A scheduler to use to schedule inner subscriptions,\n * this is to support the expand strategy, mostly, and should be deprecated\n */\nexport function mergeInternals<T, R>(\n source: Observable<T>,\n subscriber: Subscriber<R>,\n project: (value: T, index: number) => ObservableInput<R>,\n concurrent: number,\n onBeforeNext?: (innerValue: R) => void,\n expand?: boolean,\n innerSubScheduler?: SchedulerLike,\n additionalFinalizer?: () => void\n) {\n // Buffered values, in the event of going over our concurrency limit\n const buffer: T[] = [];\n // The number of active inner subscriptions.\n let active = 0;\n // An index to pass to our accumulator function\n let index = 0;\n // Whether or not the outer source has completed.\n let isComplete = false;\n\n /**\n * Checks to see if we can complete our result or not.\n */\n const checkComplete = () => {\n // If the outer has completed, and nothing is left in the buffer,\n // and we don't have any active inner subscriptions, then we can\n // Emit the state and complete.\n if (isComplete && !buffer.length && !active) {\n subscriber.complete();\n }\n };\n\n // If we're under our concurrency limit, just start the inner subscription, otherwise buffer and wait.\n const outerNext = (value: T) => (active < concurrent ? doInnerSub(value) : buffer.push(value));\n\n const doInnerSub = (value: T) => {\n // If we're expanding, we need to emit the outer values and the inner values\n // as the inners will \"become outers\" in a way as they are recursively fed\n // back to the projection mechanism.\n expand && subscriber.next(value as any);\n\n // Increment the number of active subscriptions so we can track it\n // against our concurrency limit later.\n active++;\n\n // A flag used to show that the inner observable completed.\n // This is checked during finalization to see if we should\n // move to the next item in the buffer, if there is on.\n let innerComplete = false;\n\n // Start our inner subscription.\n innerFrom(project(value, index++)).subscribe(\n createOperatorSubscriber(\n subscriber,\n (innerValue) => {\n // `mergeScan` has additional handling here. For example\n // taking the inner value and updating state.\n onBeforeNext?.(innerValue);\n\n if (expand) {\n // If we're expanding, then just recurse back to our outer\n // handler. It will emit the value first thing.\n outerNext(innerValue as any);\n } else {\n // Otherwise, emit the inner value.\n subscriber.next(innerValue);\n }\n },\n () => {\n // Flag that we have completed, so we know to check the buffer\n // during finalization.\n innerComplete = true;\n },\n // Errors are passed to the destination.\n undefined,\n () => {\n // During finalization, if the inner completed (it wasn't errored or\n // cancelled), then we want to try the next item in the buffer if\n // there is one.\n if (innerComplete) {\n // We have to wrap this in a try/catch because it happens during\n // finalization, possibly asynchronously, and we want to pass\n // any errors that happen (like in a projection function) to\n // the outer Subscriber.\n try {\n // INNER SOURCE COMPLETE\n // Decrement the active count to ensure that the next time\n // we try to call `doInnerSub`, the number is accurate.\n active--;\n // If we have more values in the buffer, try to process those\n // Note that this call will increment `active` ahead of the\n // next conditional, if there were any more inner subscriptions\n // to start.\n while (buffer.length && active < concurrent) {\n const bufferedValue = buffer.shift()!;\n // Particularly for `expand`, we need to check to see if a scheduler was provided\n // for when we want to start our inner subscription. Otherwise, we just start\n // are next inner subscription.\n if (innerSubScheduler) {\n executeSchedule(subscriber, innerSubScheduler, () => doInnerSub(bufferedValue));\n } else {\n doInnerSub(bufferedValue);\n }\n }\n // Check to see if we can complete, and complete if so.\n checkComplete();\n } catch (err) {\n subscriber.error(err);\n }\n }\n }\n )\n );\n };\n\n // Subscribe to our source observable.\n source.subscribe(\n createOperatorSubscriber(subscriber, outerNext, () => {\n // Outer completed, make a note of it, and check to see if we can complete everything.\n isComplete = true;\n checkComplete();\n })\n );\n\n // Additional finalization (for when the destination is torn down).\n // Other finalization is added implicitly via subscription above.\n return () => {\n additionalFinalizer?.();\n };\n}\n","/** @prettier */\nimport { MonoTypeOperatorFunction, SchedulerLike } from '../types';\nimport { executeSchedule } from '../util/executeSchedule';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Re-emits all notifications from source Observable with specified scheduler.\n *\n * <span class=\"informal\">Ensure a specific scheduler is used, from outside of an Observable.</span>\n *\n * `observeOn` is an operator that accepts a scheduler as a first parameter, which will be used to reschedule\n * notifications emitted by the source Observable. It might be useful, if you do not have control over\n * internal scheduler of a given Observable, but want to control when its values are emitted nevertheless.\n *\n * Returned Observable emits the same notifications (nexted values, complete and error events) as the source Observable,\n * but rescheduled with provided scheduler. Note that this doesn't mean that source Observables internal\n * scheduler will be replaced in any way. Original scheduler still will be used, but when the source Observable emits\n * notification, it will be immediately scheduled again - this time with scheduler passed to `observeOn`.\n * An anti-pattern would be calling `observeOn` on Observable that emits lots of values synchronously, to split\n * that emissions into asynchronous chunks. For this to happen, scheduler would have to be passed into the source\n * Observable directly (usually into the operator that creates it). `observeOn` simply delays notifications a\n * little bit more, to ensure that they are emitted at expected moments.\n *\n * As a matter of fact, `observeOn` accepts second parameter, which specifies in milliseconds with what delay notifications\n * will be emitted. The main difference between {@link delay} operator and `observeOn` is that `observeOn`\n * will delay all notifications - including error notifications - while `delay` will pass through error\n * from source Observable immediately when it is emitted. In general it is highly recommended to use `delay` operator\n * for any kind of delaying of values in the stream, while using `observeOn` to specify which scheduler should be used\n * for notification emissions in general.\n *\n * ## Example\n *\n * Ensure values in subscribe are called just before browser repaint\n *\n * ```ts\n * import { interval, observeOn, animationFrameScheduler } from 'rxjs';\n *\n * const someDiv = document.createElement('div');\n * someDiv.style.cssText = 'width: 200px;background: #09c';\n * document.body.appendChild(someDiv);\n * const intervals = interval(10); // Intervals are scheduled\n * // with async scheduler by default...\n * intervals.pipe(\n * observeOn(animationFrameScheduler) // ...but we will observe on animationFrame\n * ) // scheduler to ensure smooth animation.\n * .subscribe(val => {\n * someDiv.style.height = val + 'px';\n * });\n * ```\n *\n * @see {@link delay}\n *\n * @param scheduler Scheduler that will be used to reschedule notifications from source Observable.\n * @param delay Number of milliseconds that states with what delay every notification should be rescheduled.\n * @return A function that returns an Observable that emits the same\n * notifications as the source Observable, but with provided scheduler.\n */\nexport function observeOn<T>(scheduler: SchedulerLike, delay = 0): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => executeSchedule(subscriber, scheduler, () => subscriber.next(value), delay),\n () => executeSchedule(subscriber, scheduler, () => subscriber.complete(), delay),\n (err) => executeSchedule(subscriber, scheduler, () => subscriber.error(err), delay)\n )\n );\n });\n}\n","import { OperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { scanInternals } from './scanInternals';\n\nexport function scan<V, A = V>(accumulator: (acc: A | V, value: V, index: number) => A): OperatorFunction<V, V | A>;\nexport function scan<V, A>(accumulator: (acc: A, value: V, index: number) => A, seed: A): OperatorFunction<V, A>;\nexport function scan<V, A, S>(accumulator: (acc: A | S, value: V, index: number) => A, seed: S): OperatorFunction<V, A>;\n\n// TODO: link to a \"redux pattern\" section in the guide (location TBD)\n\n/**\n * Useful for encapsulating and managing state. Applies an accumulator (or \"reducer function\")\n * to each value from the source after an initial state is established -- either via\n * a `seed` value (second argument), or from the first value from the source.\n *\n * <span class=\"informal\">It's like {@link reduce}, but emits the current\n * accumulation state after each update</span>\n *\n * ![](scan.png)\n *\n * This operator maintains an internal state and emits it after processing each value as follows:\n *\n * 1. First value arrives\n * - If a `seed` value was supplied (as the second argument to `scan`), let `state = seed` and `value = firstValue`.\n * - If NO `seed` value was supplied (no second argument), let `state = firstValue` and go to 3.\n * 2. Let `state = accumulator(state, value)`.\n * - If an error is thrown by `accumulator`, notify the consumer of an error. The process ends.\n * 3. Emit `state`.\n * 4. Next value arrives, let `value = nextValue`, go to 2.\n *\n * ## Examples\n *\n * An average of previous numbers. This example shows how\n * not providing a `seed` can prime the stream with the\n * first value from the source.\n *\n * ```ts\n * import { of, scan, map } from 'rxjs';\n *\n * const numbers$ = of(1, 2, 3);\n *\n * numbers$\n * .pipe(\n * // Get the sum of the numbers coming in.\n * scan((total, n) => total + n),\n * // Get the average by dividing the sum by the total number\n * // received so far (which is 1 more than the zero-based index).\n * map((sum, index) => sum / (index + 1))\n * )\n * .subscribe(console.log);\n * ```\n *\n * The Fibonacci sequence. This example shows how you can use\n * a seed to prime accumulation process. Also... you know... Fibonacci.\n * So important to like, computers and stuff that its whiteboarded\n * in job interviews. Now you can show them the Rx version! (Please don't, haha)\n *\n * ```ts\n * import { interval, scan, map, startWith } from 'rxjs';\n *\n * const firstTwoFibs = [0, 1];\n * // An endless stream of Fibonacci numbers.\n * const fibonacci$ = interval(1000).pipe(\n * // Scan to get the fibonacci numbers (after 0, 1)\n * scan(([a, b]) => [b, a + b], firstTwoFibs),\n * // Get the second number in the tuple, it's the one you calculated\n * map(([, n]) => n),\n * // Start with our first two digits :)\n * startWith(...firstTwoFibs)\n * );\n *\n * fibonacci$.subscribe(console.log);\n * ```\n *\n * @see {@link expand}\n * @see {@link mergeScan}\n * @see {@link reduce}\n * @see {@link switchScan}\n *\n * @param accumulator A \"reducer function\". This will be called for each value after an initial state is\n * acquired.\n * @param seed The initial state. If this is not provided, the first value from the source will\n * be used as the initial state, and emitted without going through the accumulator. All subsequent values\n * will be processed by the accumulator function. If this is provided, all values will go through\n * the accumulator function.\n * @return A function that returns an Observable of the accumulated values.\n */\nexport function scan<V, A, S>(accumulator: (acc: V | A | S, value: V, index: number) => A, seed?: S): OperatorFunction<V, V | A> {\n // providing a seed of `undefined` *should* be valid and trigger\n // hasSeed! so don't use `seed !== undefined` checks!\n // For this reason, we have to check it here at the original call site\n // otherwise inside Operator/Subscriber we won't know if `undefined`\n // means they didn't provide anything or if they literally provided `undefined`\n return operate(scanInternals(accumulator, seed as S, arguments.length >= 2, true));\n}\n","import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * A basic scan operation. This is used for `scan` and `reduce`.\n * @param accumulator The accumulator to use\n * @param seed The seed value for the state to accumulate\n * @param hasSeed Whether or not a seed was provided\n * @param emitOnNext Whether or not to emit the state on next\n * @param emitBeforeComplete Whether or not to emit the before completion\n */\n\nexport function scanInternals<V, A, S>(\n accumulator: (acc: V | A | S, value: V, index: number) => A,\n seed: S,\n hasSeed: boolean,\n emitOnNext: boolean,\n emitBeforeComplete?: undefined | true\n) {\n return (source: Observable<V>, subscriber: Subscriber<any>) => {\n // Whether or not we have state yet. This will only be\n // false before the first value arrives if we didn't get\n // a seed value.\n let hasState = hasSeed;\n // The state that we're tracking, starting with the seed,\n // if there is one, and then updated by the return value\n // from the accumulator on each emission.\n let state: any = seed;\n // An index to pass to the accumulator function.\n let index = 0;\n\n // Subscribe to our source. All errors and completions are passed through.\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n // Always increment the index.\n const i = index++;\n // Set the state\n state = hasState\n ? // We already have state, so we can get the new state from the accumulator\n accumulator(state, value, i)\n : // We didn't have state yet, a seed value was not provided, so\n\n // we set the state to the first value, and mark that we have state now\n ((hasState = true), value);\n\n // Maybe send it to the consumer.\n emitOnNext && subscriber.next(state);\n },\n // If an onComplete was given, call it, otherwise\n // just pass through the complete notification to the consumer.\n emitBeforeComplete &&\n (() => {\n hasState && subscriber.next(state);\n subscriber.complete();\n })\n )\n );\n };\n}\n","import { innerFrom } from '../observable/innerFrom';\nimport { Subject } from '../Subject';\nimport { SafeSubscriber } from '../Subscriber';\nimport { Subscription } from '../Subscription';\nimport { MonoTypeOperatorFunction, SubjectLike, ObservableInput } from '../types';\nimport { operate } from '../util/lift';\n\nexport interface ShareConfig<T> {\n /**\n * The factory used to create the subject that will connect the source observable to\n * multicast consumers.\n */\n connector?: () => SubjectLike<T>;\n /**\n * If `true`, the resulting observable will reset internal state on error from source and return to a \"cold\" state. This\n * allows the resulting observable to be \"retried\" in the event of an error.\n * If `false`, when an error comes from the source it will push the error into the connecting subject, and the subject\n * will remain the connecting subject, meaning the resulting observable will not go \"cold\" again, and subsequent retries\n * or resubscriptions will resubscribe to that same subject. In all cases, RxJS subjects will emit the same error again, however\n * {@link ReplaySubject} will also push its buffered values before pushing the error.\n * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n */\n resetOnError?: boolean | ((error: any) => ObservableInput<any>);\n /**\n * If `true`, the resulting observable will reset internal state on completion from source and return to a \"cold\" state. This\n * allows the resulting observable to be \"repeated\" after it is done.\n * If `false`, when the source completes, it will push the completion through the connecting subject, and the subject\n * will remain the connecting subject, meaning the resulting observable will not go \"cold\" again, and subsequent repeats\n * or resubscriptions will resubscribe to that same subject.\n * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n */\n resetOnComplete?: boolean | (() => ObservableInput<any>);\n /**\n * If `true`, when the number of subscribers to the resulting observable reaches zero due to those subscribers unsubscribing, the\n * internal state will be reset and the resulting observable will return to a \"cold\" state. This means that the next\n * time the resulting observable is subscribed to, a new subject will be created and the source will be subscribed to\n * again.\n * If `false`, when the number of subscribers to the resulting observable reaches zero due to unsubscription, the subject\n * will remain connected to the source, and new subscriptions to the result will be connected through that same subject.\n * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n */\n resetOnRefCountZero?: boolean | (() => ObservableInput<any>);\n}\n\nexport function share<T>(): MonoTypeOperatorFunction<T>;\n\nexport function share<T>(options: ShareConfig<T>): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one\n * Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will\n * unsubscribe from the source Observable. Because the Observable is multicasting it makes the stream `hot`.\n * This is an alias for `multicast(() => new Subject()), refCount()`.\n *\n * The subscription to the underlying source Observable can be reset (unsubscribe and resubscribe for new subscribers),\n * if the subscriber count to the shared observable drops to 0, or if the source Observable errors or completes. It is\n * possible to use notifier factories for the resets to allow for behaviors like conditional or delayed resets. Please\n * note that resetting on error or complete of the source Observable does not behave like a transparent retry or restart\n * of the source because the error or complete will be forwarded to all subscribers and their subscription will be\n * closed. Only new subscribers after a reset on error or complete happened will cause a fresh subscription to the\n * source. To achieve transparent retries or restarts pipe the source through appropriate operators before sharing.\n *\n * ![](share.png)\n *\n * ## Example\n *\n * Generate new multicast Observable from the `source` Observable value\n *\n * ```ts\n * import { interval, tap, map, take, share } from 'rxjs';\n *\n * const source = interval(1000).pipe(\n * tap(x => console.log('Processing: ', x)),\n * map(x => x * x),\n * take(6),\n * share()\n * );\n *\n * source.subscribe(x => console.log('subscription 1: ', x));\n * source.subscribe(x => console.log('subscription 2: ', x));\n *\n * // Logs:\n * // Processing: 0\n * // subscription 1: 0\n * // subscription 2: 0\n * // Processing: 1\n * // subscription 1: 1\n * // subscription 2: 1\n * // Processing: 2\n * // subscription 1: 4\n * // subscription 2: 4\n * // Processing: 3\n * // subscription 1: 9\n * // subscription 2: 9\n * // Processing: 4\n * // subscription 1: 16\n * // subscription 2: 16\n * // Processing: 5\n * // subscription 1: 25\n * // subscription 2: 25\n * ```\n *\n * ## Example with notifier factory: Delayed reset\n *\n * ```ts\n * import { interval, take, share, timer } from 'rxjs';\n *\n * const source = interval(1000).pipe(\n * take(3),\n * share({\n * resetOnRefCountZero: () => timer(1000)\n * })\n * );\n *\n * const subscriptionOne = source.subscribe(x => console.log('subscription 1: ', x));\n * setTimeout(() => subscriptionOne.unsubscribe(), 1300);\n *\n * setTimeout(() => source.subscribe(x => console.log('subscription 2: ', x)), 1700);\n *\n * setTimeout(() => source.subscribe(x => console.log('subscription 3: ', x)), 5000);\n *\n * // Logs:\n * // subscription 1: 0\n * // (subscription 1 unsubscribes here)\n * // (subscription 2 subscribes here ~400ms later, source was not reset)\n * // subscription 2: 1\n * // subscription 2: 2\n * // (subscription 2 unsubscribes here)\n * // (subscription 3 subscribes here ~2000ms later, source did reset before)\n * // subscription 3: 0\n * // subscription 3: 1\n * // subscription 3: 2\n * ```\n *\n * @see {@link shareReplay}\n *\n * @return A function that returns an Observable that mirrors the source.\n */\nexport function share<T>(options: ShareConfig<T> = {}): MonoTypeOperatorFunction<T> {\n const { connector = () => new Subject<T>(), resetOnError = true, resetOnComplete = true, resetOnRefCountZero = true } = options;\n // It's necessary to use a wrapper here, as the _operator_ must be\n // referentially transparent. Otherwise, it cannot be used in calls to the\n // static `pipe` function - to create a partial pipeline.\n //\n // The _operator function_ - the function returned by the _operator_ - will\n // not be referentially transparent - as it shares its source - but the\n // _operator function_ is called when the complete pipeline is composed via a\n // call to a source observable's `pipe` method - not when the static `pipe`\n // function is called.\n return (wrapperSource) => {\n let connection: SafeSubscriber<T> | undefined;\n let resetConnection: Subscription | undefined;\n let subject: SubjectLike<T> | undefined;\n let refCount = 0;\n let hasCompleted = false;\n let hasErrored = false;\n\n const cancelReset = () => {\n resetConnection?.unsubscribe();\n resetConnection = undefined;\n };\n // Used to reset the internal state to a \"cold\"\n // state, as though it had never been subscribed to.\n const reset = () => {\n cancelReset();\n connection = subject = undefined;\n hasCompleted = hasErrored = false;\n };\n const resetAndUnsubscribe = () => {\n // We need to capture the connection before\n // we reset (if we need to reset).\n const conn = connection;\n reset();\n conn?.unsubscribe();\n };\n\n return operate<T, T>((source, subscriber) => {\n refCount++;\n if (!hasErrored && !hasCompleted) {\n cancelReset();\n }\n\n // Create the subject if we don't have one yet. Grab a local reference to\n // it as well, which avoids non-null assertions when using it and, if we\n // connect to it now, then error/complete need a reference after it was\n // reset.\n const dest = (subject = subject ?? connector());\n\n // Add the finalization directly to the subscriber - instead of returning it -\n // so that the handling of the subscriber's unsubscription will be wired\n // up _before_ the subscription to the source occurs. This is done so that\n // the assignment to the source connection's `closed` property will be seen\n // by synchronous firehose sources.\n subscriber.add(() => {\n refCount--;\n\n // If we're resetting on refCount === 0, and it's 0, we only want to do\n // that on \"unsubscribe\", really. Resetting on error or completion is a different\n // configuration.\n if (refCount === 0 && !hasErrored && !hasCompleted) {\n resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);\n }\n });\n\n // The following line adds the subscription to the subscriber passed.\n // Basically, `subscriber === dest.subscribe(subscriber)` is `true`.\n dest.subscribe(subscriber);\n\n if (\n !connection &&\n // Check this shareReplay is still activate - it can be reset to 0\n // and be \"unsubscribed\" _before_ it actually subscribes.\n // If we were to subscribe then, it'd leak and get stuck.\n refCount > 0\n ) {\n // We need to create a subscriber here - rather than pass an observer and\n // assign the returned subscription to connection - because it's possible\n // for reentrant subscriptions to the shared observable to occur and in\n // those situations we want connection to be already-assigned so that we\n // don't create another connection to the source.\n connection = new SafeSubscriber({\n next: (value) => dest.next(value),\n error: (err) => {\n hasErrored = true;\n cancelReset();\n resetConnection = handleReset(reset, resetOnError, err);\n dest.error(err);\n },\n complete: () => {\n hasCompleted = true;\n cancelReset();\n resetConnection = handleReset(reset, resetOnComplete);\n dest.complete();\n },\n });\n innerFrom(source).subscribe(connection);\n }\n })(wrapperSource);\n };\n}\n\nfunction handleReset<T extends unknown[] = never[]>(\n reset: () => void,\n on: boolean | ((...args: T) => ObservableInput<any>),\n ...args: T\n): Subscription | undefined {\n if (on === true) {\n reset();\n return;\n }\n\n if (on === false) {\n return;\n }\n\n const onSubscriber = new SafeSubscriber({\n next: () => {\n onSubscriber.unsubscribe();\n reset();\n },\n });\n\n return innerFrom(on(...args)).subscribe(onSubscriber);\n}\n","import { ReplaySubject } from '../ReplaySubject';\nimport { MonoTypeOperatorFunction, SchedulerLike } from '../types';\nimport { share } from './share';\n\nexport interface ShareReplayConfig {\n bufferSize?: number;\n windowTime?: number;\n refCount: boolean;\n scheduler?: SchedulerLike;\n}\n\nexport function shareReplay<T>(config: ShareReplayConfig): MonoTypeOperatorFunction<T>;\nexport function shareReplay<T>(bufferSize?: number, windowTime?: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n * Share source and replay specified number of emissions on subscription.\n *\n * This operator is a specialization of `replay` that connects to a source observable\n * and multicasts through a `ReplaySubject` constructed with the specified arguments.\n * A successfully completed source will stay cached in the `shareReplay`ed observable forever,\n * but an errored source can be retried.\n *\n * ## Why use `shareReplay`?\n *\n * You generally want to use `shareReplay` when you have side-effects or taxing computations\n * that you do not wish to be executed amongst multiple subscribers.\n * It may also be valuable in situations where you know you will have late subscribers to\n * a stream that need access to previously emitted values.\n * This ability to replay values on subscription is what differentiates {@link share} and `shareReplay`.\n *\n * ## Reference counting\n *\n * By default `shareReplay` will use `refCount` of false, meaning that it will _not_ unsubscribe the\n * source when the reference counter drops to zero, i.e. the inner `ReplaySubject` will _not_ be unsubscribed\n * (and potentially run for ever).\n * This is the default as it is expected that `shareReplay` is often used to keep around expensive to setup\n * observables which we want to keep running instead of having to do the expensive setup again.\n *\n * As of RXJS version 6.4.0 a new overload signature was added to allow for manual control over what\n * happens when the operators internal reference counter drops to zero.\n * If `refCount` is true, the source will be unsubscribed from once the reference count drops to zero, i.e.\n * the inner `ReplaySubject` will be unsubscribed. All new subscribers will receive value emissions from a\n * new `ReplaySubject` which in turn will cause a new subscription to the source observable.\n *\n * ## Examples\n *\n * Example with a third subscriber coming late to the party\n *\n * ```ts\n * import { interval, take, shareReplay } from 'rxjs';\n *\n * const shared$ = interval(2000).pipe(\n * take(6),\n * shareReplay(3)\n * );\n *\n * shared$.subscribe(x => console.log('sub A: ', x));\n * shared$.subscribe(y => console.log('sub B: ', y));\n *\n * setTimeout(() => {\n * shared$.subscribe(y => console.log('sub C: ', y));\n * }, 11000);\n *\n * // Logs:\n * // (after ~2000 ms)\n * // sub A: 0\n * // sub B: 0\n * // (after ~4000 ms)\n * // sub A: 1\n * // sub B: 1\n * // (after ~6000 ms)\n * // sub A: 2\n * // sub B: 2\n * // (after ~8000 ms)\n * // sub A: 3\n * // sub B: 3\n * // (after ~10000 ms)\n * // sub A: 4\n * // sub B: 4\n * // (after ~11000 ms, sub C gets the last 3 values)\n * // sub C: 2\n * // sub C: 3\n * // sub C: 4\n * // (after ~12000 ms)\n * // sub A: 5\n * // sub B: 5\n * // sub C: 5\n * ```\n *\n * Example for `refCount` usage\n *\n * ```ts\n * import { Observable, tap, interval, shareReplay, take } from 'rxjs';\n *\n * const log = <T>(name: string, source: Observable<T>) => source.pipe(\n * tap({\n * subscribe: () => console.log(`${ name }: subscribed`),\n * next: value => console.log(`${ name }: ${ value }`),\n * complete: () => console.log(`${ name }: completed`),\n * finalize: () => console.log(`${ name }: unsubscribed`)\n * })\n * );\n *\n * const obs$ = log('source', interval(1000));\n *\n * const shared$ = log('shared', obs$.pipe(\n * shareReplay({ bufferSize: 1, refCount: true }),\n * take(2)\n * ));\n *\n * shared$.subscribe(x => console.log('sub A: ', x));\n * shared$.subscribe(y => console.log('sub B: ', y));\n *\n * // PRINTS:\n * // shared: subscribed <-- reference count = 1\n * // source: subscribed\n * // shared: subscribed <-- reference count = 2\n * // source: 0\n * // shared: 0\n * // sub A: 0\n * // shared: 0\n * // sub B: 0\n * // source: 1\n * // shared: 1\n * // sub A: 1\n * // shared: completed <-- take(2) completes the subscription for sub A\n * // shared: unsubscribed <-- reference count = 1\n * // shared: 1\n * // sub B: 1\n * // shared: completed <-- take(2) completes the subscription for sub B\n * // shared: unsubscribed <-- reference count = 0\n * // source: unsubscribed <-- replaySubject unsubscribes from source observable because the reference count dropped to 0 and refCount is true\n *\n * // In case of refCount being false, the unsubscribe is never called on the source and the source would keep on emitting, even if no subscribers\n * // are listening.\n * // source: 2\n * // source: 3\n * // source: 4\n * // ...\n * ```\n *\n * @see {@link publish}\n * @see {@link share}\n * @see {@link publishReplay}\n *\n * @param configOrBufferSize Maximum element count of the replay buffer or {@link ShareReplayConfig configuration}\n * object.\n * @param windowTime Maximum time length of the replay buffer in milliseconds.\n * @param scheduler Scheduler where connected observers within the selector function\n * will be invoked on.\n * @return A function that returns an Observable sequence that contains the\n * elements of a sequence produced by multicasting the source sequence within a\n * selector function.\n */\nexport function shareReplay<T>(\n configOrBufferSize?: ShareReplayConfig | number,\n windowTime?: number,\n scheduler?: SchedulerLike\n): MonoTypeOperatorFunction<T> {\n let bufferSize: number;\n let refCount = false;\n if (configOrBufferSize && typeof configOrBufferSize === 'object') {\n ({ bufferSize = Infinity, windowTime = Infinity, refCount = false, scheduler } = configOrBufferSize);\n } else {\n bufferSize = (configOrBufferSize ?? Infinity) as number;\n }\n return share<T>({\n connector: () => new ReplaySubject(bufferSize, windowTime, scheduler),\n resetOnError: true,\n resetOnComplete: false,\n resetOnRefCountZero: refCount,\n });\n}\n","import { MonoTypeOperatorFunction } from '../types';\nimport { filter } from './filter';\n\n/**\n * Returns an Observable that skips the first `count` items emitted by the source Observable.\n *\n * ![](skip.png)\n *\n * Skips the values until the sent notifications are equal or less than provided skip count. It raises\n * an error if skip count is equal or more than the actual number of emits and source raises an error.\n *\n * ## Example\n *\n * Skip the values before the emission\n *\n * ```ts\n * import { interval, skip } from 'rxjs';\n *\n * // emit every half second\n * const source = interval(500);\n * // skip the first 10 emitted values\n * const result = source.pipe(skip(10));\n *\n * result.subscribe(value => console.log(value));\n * // output: 10...11...12...13...\n * ```\n *\n * @see {@link last}\n * @see {@link skipWhile}\n * @see {@link skipUntil}\n * @see {@link skipLast}\n *\n * @param {Number} count - The number of times, items emitted by source Observable should be skipped.\n * @return A function that returns an Observable that skips the first `count`\n * values emitted by the source Observable.\n */\nexport function skip<T>(count: number): MonoTypeOperatorFunction<T> {\n return filter((_, index) => count <= index);\n}\n","import { concat } from '../observable/concat';\nimport { OperatorFunction, SchedulerLike, ValueFromArray } from '../types';\nimport { popScheduler } from '../util/args';\nimport { operate } from '../util/lift';\n\n// Devs are more likely to pass null or undefined than they are a scheduler\n// without accompanying values. To make things easier for (naughty) devs who\n// use the `strictNullChecks: false` TypeScript compiler option, these\n// overloads with explicit null and undefined values are included.\n\nexport function startWith<T>(value: null): OperatorFunction<T, T | null>;\nexport function startWith<T>(value: undefined): OperatorFunction<T, T | undefined>;\n\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `concatAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function startWith<T, A extends readonly unknown[] = T[]>(\n ...valuesAndScheduler: [...A, SchedulerLike]\n): OperatorFunction<T, T | ValueFromArray<A>>;\nexport function startWith<T, A extends readonly unknown[] = T[]>(...values: A): OperatorFunction<T, T | ValueFromArray<A>>;\n\n/**\n * Returns an observable that, at the moment of subscription, will synchronously emit all\n * values provided to this operator, then subscribe to the source and mirror all of its emissions\n * to subscribers.\n *\n * This is a useful way to know when subscription has occurred on an existing observable.\n *\n * <span class=\"informal\">First emits its arguments in order, and then any\n * emissions from the source.</span>\n *\n * ![](startWith.png)\n *\n * ## Examples\n *\n * Emit a value when a timer starts.\n *\n * ```ts\n * import { timer, map, startWith } from 'rxjs';\n *\n * timer(1000)\n * .pipe(\n * map(() => 'timer emit'),\n * startWith('timer start')\n * )\n * .subscribe(x => console.log(x));\n *\n * // results:\n * // 'timer start'\n * // 'timer emit'\n * ```\n *\n * @param values Items you want the modified Observable to emit first.\n * @return A function that returns an Observable that synchronously emits\n * provided values before subscribing to the source Observable.\n *\n * @see {@link endWith}\n * @see {@link finalize}\n * @see {@link concat}\n */\nexport function startWith<T, D>(...values: D[]): OperatorFunction<T, T | D> {\n const scheduler = popScheduler(values);\n return operate((source, subscriber) => {\n // Here we can't pass `undefined` as a scheduler, because if we did, the\n // code inside of `concat` would be confused by the `undefined`, and treat it\n // like an invalid observable. So we have to split it two different ways.\n (scheduler ? concat(values, source, scheduler) : concat(values, source)).subscribe(subscriber);\n });\n}\n","import { Subscriber } from '../Subscriber';\nimport { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';\nimport { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/* tslint:disable:max-line-length */\nexport function switchMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function switchMap<T, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: undefined\n): OperatorFunction<T, ObservedValueOf<O>>;\n/** @deprecated The `resultSelector` parameter will be removed in v8. Use an inner `map` instead. Details: https://rxjs.dev/deprecations/resultSelector */\nexport function switchMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, R>;\n/* tslint:enable:max-line-length */\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable, emitting values only from the most recently projected Observable.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link switchAll}.</span>\n *\n * ![](switchMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. Each time it observes one of these\n * inner Observables, the output Observable begins emitting the items emitted by\n * that inner Observable. When a new inner Observable is emitted, `switchMap`\n * stops emitting items from the earlier-emitted inner Observable and begins\n * emitting items from the new one. It continues to behave like this for\n * subsequent inner Observables.\n *\n * ## Example\n *\n * Generate new Observable according to source Observable values\n *\n * ```ts\n * import { of, switchMap } from 'rxjs';\n *\n * const switched = of(1, 2, 3).pipe(switchMap(x => of(x, x ** 2, x ** 3)));\n * switched.subscribe(x => console.log(x));\n * // outputs\n * // 1\n * // 1\n * // 1\n * // 2\n * // 4\n * // 8\n * // 3\n * // 9\n * // 27\n * ```\n *\n * Restart an interval Observable on every click event\n *\n * ```ts\n * import { fromEvent, switchMap, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(switchMap(() => interval(1000)));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaustMap}\n * @see {@link mergeMap}\n * @see {@link switchAll}\n * @see {@link switchMapTo}\n *\n * @param {function(value: T, index: number): ObservableInput} project A function\n * that, when applied to an item emitted by the source Observable, returns an\n * Observable.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function (and the optional deprecated\n * `resultSelector`) to each item emitted by the source Observable and taking\n * only the values from the most recently projected inner Observable.\n */\nexport function switchMap<T, R, O extends ObservableInput<any>>(\n project: (value: T, index: number) => O,\n resultSelector?: (outerValue: T, innerValue: ObservedValueOf<O>, outerIndex: number, innerIndex: number) => R\n): OperatorFunction<T, ObservedValueOf<O> | R> {\n return operate((source, subscriber) => {\n let innerSubscriber: Subscriber<ObservedValueOf<O>> | null = null;\n let index = 0;\n // Whether or not the source subscription has completed\n let isComplete = false;\n\n // We only complete the result if the source is complete AND we don't have an active inner subscription.\n // This is called both when the source completes and when the inners complete.\n const checkComplete = () => isComplete && !innerSubscriber && subscriber.complete();\n\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n // Cancel the previous inner subscription if there was one\n innerSubscriber?.unsubscribe();\n let innerIndex = 0;\n const outerIndex = index++;\n // Start the next inner subscription\n innerFrom(project(value, outerIndex)).subscribe(\n (innerSubscriber = createOperatorSubscriber(\n subscriber,\n // When we get a new inner value, next it through. Note that this is\n // handling the deprecate result selector here. This is because with this architecture\n // it ends up being smaller than using the map operator.\n (innerValue) => subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue),\n () => {\n // The inner has completed. Null out the inner subscriber to\n // free up memory and to signal that we have no inner subscription\n // currently.\n innerSubscriber = null!;\n checkComplete();\n }\n ))\n );\n },\n () => {\n isComplete = true;\n checkComplete();\n }\n )\n );\n });\n}\n","import { MonoTypeOperatorFunction } from '../types';\nimport { EMPTY } from '../observable/empty';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Emits only the first `count` values emitted by the source Observable.\n *\n * <span class=\"informal\">Takes the first `count` values from the source, then\n * completes.</span>\n *\n * ![](take.png)\n *\n * `take` returns an Observable that emits only the first `count` values emitted\n * by the source Observable. If the source emits fewer than `count` values then\n * all of its values are emitted. After that, it completes, regardless if the\n * source completes.\n *\n * ## Example\n *\n * Take the first 5 seconds of an infinite 1-second interval Observable\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const intervalCount = interval(1000);\n * const takeFive = intervalCount.pipe(take(5));\n * takeFive.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * // 3\n * // 4\n * ```\n *\n * @see {@link takeLast}\n * @see {@link takeUntil}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param count The maximum number of `next` values to emit.\n * @return A function that returns an Observable that emits only the first\n * `count` values emitted by the source Observable, or all of the values from\n * the source if the source emits fewer than `count` values.\n */\nexport function take<T>(count: number): MonoTypeOperatorFunction<T> {\n return count <= 0\n ? // If we are taking no values, that's empty.\n () => EMPTY\n : operate((source, subscriber) => {\n let seen = 0;\n source.subscribe(\n createOperatorSubscriber(subscriber, (value) => {\n // Increment the number of values we have seen,\n // then check it against the allowed count to see\n // if we are still letting values through.\n if (++seen <= count) {\n subscriber.next(value);\n // If we have met or passed our allowed count,\n // we need to complete. We have to do <= here,\n // because re-entrant code will increment `seen` twice.\n if (count <= seen) {\n subscriber.complete();\n }\n }\n })\n );\n });\n}\n","import { MonoTypeOperatorFunction, ObservableInput } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/innerFrom';\nimport { noop } from '../util/noop';\n\n/**\n * Emits the values emitted by the source Observable until a `notifier`\n * Observable emits a value.\n *\n * <span class=\"informal\">Lets values pass until a second Observable,\n * `notifier`, emits a value. Then, it completes.</span>\n *\n * ![](takeUntil.png)\n *\n * `takeUntil` subscribes and begins mirroring the source Observable. It also\n * monitors a second Observable, `notifier` that you provide. If the `notifier`\n * emits a value, the output Observable stops mirroring the source Observable\n * and completes. If the `notifier` doesn't emit any value and completes\n * then `takeUntil` will pass all values.\n *\n * ## Example\n *\n * Tick every second until the first click happens\n *\n * ```ts\n * import { interval, fromEvent, takeUntil } from 'rxjs';\n *\n * const source = interval(1000);\n * const clicks = fromEvent(document, 'click');\n * const result = source.pipe(takeUntil(clicks));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeLast}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param {Observable} notifier The Observable whose first emitted value will\n * cause the output Observable of `takeUntil` to stop emitting values from the\n * source Observable.\n * @return A function that returns an Observable that emits the values from the\n * source Observable until `notifier` emits its first value.\n */\nexport function takeUntil<T>(notifier: ObservableInput<any>): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n innerFrom(notifier).subscribe(createOperatorSubscriber(subscriber, () => subscriber.complete(), noop));\n !subscriber.closed && source.subscribe(subscriber);\n });\n}\n","import { MonoTypeOperatorFunction, Observer } from '../types';\nimport { isFunction } from '../util/isFunction';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { identity } from '../util/identity';\n\n/**\n * An extension to the {@link Observer} interface used only by the {@link tap} operator.\n *\n * It provides a useful set of callbacks a user can register to do side-effects in\n * cases other than what the usual {@link Observer} callbacks are\n * ({@link guide/glossary-and-semantics#next next},\n * {@link guide/glossary-and-semantics#error error} and/or\n * {@link guide/glossary-and-semantics#complete complete}).\n *\n * ## Example\n *\n * ```ts\n * import { fromEvent, switchMap, tap, interval, take } from 'rxjs';\n *\n * const source$ = fromEvent(document, 'click');\n * const result$ = source$.pipe(\n * switchMap((_, i) => i % 2 === 0\n * ? fromEvent(document, 'mousemove').pipe(\n * tap({\n * subscribe: () => console.log('Subscribed to the mouse move events after click #' + i),\n * unsubscribe: () => console.log('Mouse move events #' + i + ' unsubscribed'),\n * finalize: () => console.log('Mouse move events #' + i + ' finalized')\n * })\n * )\n * : interval(1_000).pipe(\n * take(5),\n * tap({\n * subscribe: () => console.log('Subscribed to the 1-second interval events after click #' + i),\n * unsubscribe: () => console.log('1-second interval events #' + i + ' unsubscribed'),\n * finalize: () => console.log('1-second interval events #' + i + ' finalized')\n * })\n * )\n * )\n * );\n *\n * const subscription = result$.subscribe({\n * next: console.log\n * });\n *\n * setTimeout(() => {\n * console.log('Unsubscribe after 60 seconds');\n * subscription.unsubscribe();\n * }, 60_000);\n * ```\n */\nexport interface TapObserver<T> extends Observer<T> {\n /**\n * The callback that `tap` operator invokes at the moment when the source Observable\n * gets subscribed to.\n */\n subscribe: () => void;\n /**\n * The callback that `tap` operator invokes when an explicit\n * {@link guide/glossary-and-semantics#unsubscription unsubscribe} happens. It won't get invoked on\n * `error` or `complete` events.\n */\n unsubscribe: () => void;\n /**\n * The callback that `tap` operator invokes when any kind of\n * {@link guide/glossary-and-semantics#finalization finalization} happens - either when\n * the source Observable `error`s or `complete`s or when it gets explicitly unsubscribed\n * by the user. There is no difference in using this callback or the {@link finalize}\n * operator, but if you're already using `tap` operator, you can use this callback\n * instead. You'd get the same result in either case.\n */\n finalize: () => void;\n}\nexport function tap<T>(observerOrNext?: Partial<TapObserver<T>> | ((value: T) => void)): MonoTypeOperatorFunction<T>;\n/** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\nexport function tap<T>(\n next?: ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n): MonoTypeOperatorFunction<T>;\n\n/**\n * Used to perform side-effects for notifications from the source observable\n *\n * <span class=\"informal\">Used when you want to affect outside state with a notification without altering the notification</span>\n *\n * ![](tap.png)\n *\n * Tap is designed to allow the developer a designated place to perform side effects. While you _could_ perform side-effects\n * inside of a `map` or a `mergeMap`, that would make their mapping functions impure, which isn't always a big deal, but will\n * make it so you can't do things like memoize those functions. The `tap` operator is designed solely for such side-effects to\n * help you remove side-effects from other operations.\n *\n * For any notification, next, error, or complete, `tap` will call the appropriate callback you have provided to it, via a function\n * reference, or a partial observer, then pass that notification down the stream.\n *\n * The observable returned by `tap` is an exact mirror of the source, with one exception: Any error that occurs -- synchronously -- in a handler\n * provided to `tap` will be emitted as an error from the returned observable.\n *\n * > Be careful! You can mutate objects as they pass through the `tap` operator's handlers.\n *\n * The most common use of `tap` is actually for debugging. You can place a `tap(console.log)` anywhere\n * in your observable `pipe`, log out the notifications as they are emitted by the source returned by the previous\n * operation.\n *\n * ## Examples\n *\n * Check a random number before it is handled. Below is an observable that will use a random number between 0 and 1,\n * and emit `'big'` or `'small'` depending on the size of that number. But we wanted to log what the original number\n * was, so we have added a `tap(console.log)`.\n *\n * ```ts\n * import { of, tap, map } from 'rxjs';\n *\n * of(Math.random()).pipe(\n * tap(console.log),\n * map(n => n > 0.5 ? 'big' : 'small')\n * ).subscribe(console.log);\n * ```\n *\n * Using `tap` to analyze a value and force an error. Below is an observable where in our system we only\n * want to emit numbers 3 or less we get from another source. We can force our observable to error\n * using `tap`.\n *\n * ```ts\n * import { of, tap } from 'rxjs';\n *\n * const source = of(1, 2, 3, 4, 5);\n *\n * source.pipe(\n * tap(n => {\n * if (n > 3) {\n * throw new TypeError(`Value ${ n } is greater than 3`);\n * }\n * })\n * )\n * .subscribe({ next: console.log, error: err => console.log(err.message) });\n * ```\n *\n * We want to know when an observable completes before moving on to the next observable. The system\n * below will emit a random series of `'X'` characters from 3 different observables in sequence. The\n * only way we know when one observable completes and moves to the next one, in this case, is because\n * we have added a `tap` with the side effect of logging to console.\n *\n * ```ts\n * import { of, concatMap, interval, take, map, tap } from 'rxjs';\n *\n * of(1, 2, 3).pipe(\n * concatMap(n => interval(1000).pipe(\n * take(Math.round(Math.random() * 10)),\n * map(() => 'X'),\n * tap({ complete: () => console.log(`Done with ${ n }`) })\n * ))\n * )\n * .subscribe(console.log);\n * ```\n *\n * @see {@link finalize}\n * @see {@link TapObserver}\n *\n * @param observerOrNext A next handler or partial observer\n * @param error An error handler\n * @param complete A completion handler\n * @return A function that returns an Observable identical to the source, but\n * runs the specified Observer or callback(s) for each item.\n */\nexport function tap<T>(\n observerOrNext?: Partial<TapObserver<T>> | ((value: T) => void) | null,\n error?: ((e: any) => void) | null,\n complete?: (() => void) | null\n): MonoTypeOperatorFunction<T> {\n // We have to check to see not only if next is a function,\n // but if error or complete were passed. This is because someone\n // could technically call tap like `tap(null, fn)` or `tap(null, null, fn)`.\n const tapObserver =\n isFunction(observerOrNext) || error || complete\n ? // tslint:disable-next-line: no-object-literal-type-assertion\n ({ next: observerOrNext as Exclude<typeof observerOrNext, Partial<TapObserver<T>>>, error, complete } as Partial<TapObserver<T>>)\n : observerOrNext;\n\n return tapObserver\n ? operate((source, subscriber) => {\n tapObserver.subscribe?.();\n let isUnsub = true;\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n tapObserver.next?.(value);\n subscriber.next(value);\n },\n () => {\n isUnsub = false;\n tapObserver.complete?.();\n subscriber.complete();\n },\n (err) => {\n isUnsub = false;\n tapObserver.error?.(err);\n subscriber.error(err);\n },\n () => {\n if (isUnsub) {\n tapObserver.unsubscribe?.();\n }\n tapObserver.finalize?.();\n }\n )\n );\n })\n : // Tap was called with no valid tap observer or handler\n // (e.g. `tap(null, null, null)` or `tap(null)` or `tap()`)\n // so we're going to just mirror the source.\n identity;\n}\n","import { EmptyError } from '../util/EmptyError';\nimport { MonoTypeOperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * If the source observable completes without emitting a value, it will emit\n * an error. The error will be created at that time by the optional\n * `errorFactory` argument, otherwise, the error will be {@link EmptyError}.\n *\n * ![](throwIfEmpty.png)\n *\n * ## Example\n *\n * Throw an error if the document wasn't clicked within 1 second\n *\n * ```ts\n * import { fromEvent, takeUntil, timer, throwIfEmpty } from 'rxjs';\n *\n * const click$ = fromEvent(document, 'click');\n *\n * click$.pipe(\n * takeUntil(timer(1000)),\n * throwIfEmpty(() => new Error('The document was not clicked within 1 second'))\n * )\n * .subscribe({\n * next() {\n * console.log('The document was clicked');\n * },\n * error(err) {\n * console.error(err.message);\n * }\n * });\n * ```\n *\n * @param errorFactory A factory function called to produce the\n * error to be thrown when the source observable completes without emitting a\n * value.\n * @return A function that returns an Observable that throws an error if the\n * source Observable completed without emitting.\n */\nexport function throwIfEmpty<T>(errorFactory: () => any = defaultErrorFactory): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n let hasValue = false;\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n hasValue = true;\n subscriber.next(value);\n },\n () => (hasValue ? subscriber.complete() : subscriber.error(errorFactory()))\n )\n );\n });\n}\n\nfunction defaultErrorFactory() {\n return new EmptyError();\n}\n","import { asyncScheduler } from '../scheduler/async';\nimport { MonoTypeOperatorFunction, SchedulerLike, OperatorFunction, ObservableInput, ObservedValueOf } from '../types';\nimport { isValidDate } from '../util/isDate';\nimport { Subscription } from '../Subscription';\nimport { operate } from '../util/lift';\nimport { Observable } from '../Observable';\nimport { innerFrom } from '../observable/innerFrom';\nimport { createErrorClass } from '../util/createErrorClass';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { executeSchedule } from '../util/executeSchedule';\n\nexport interface TimeoutConfig<T, O extends ObservableInput<unknown> = ObservableInput<T>, M = unknown> {\n /**\n * The time allowed between values from the source before timeout is triggered.\n */\n each?: number;\n\n /**\n * The relative time as a `number` in milliseconds, or a specific time as a `Date` object,\n * by which the first value must arrive from the source before timeout is triggered.\n */\n first?: number | Date;\n\n /**\n * The scheduler to use with time-related operations within this operator. Defaults to {@link asyncScheduler}\n */\n scheduler?: SchedulerLike;\n\n /**\n * A factory used to create observable to switch to when timeout occurs. Provides\n * a {@link TimeoutInfo} about the source observable's emissions and what delay or\n * exact time triggered the timeout.\n */\n with?: (info: TimeoutInfo<T, M>) => O;\n\n /**\n * Optional additional metadata you can provide to code that handles\n * the timeout, will be provided through the {@link TimeoutError}.\n * This can be used to help identify the source of a timeout or pass along\n * other information related to the timeout.\n */\n meta?: M;\n}\n\nexport interface TimeoutInfo<T, M = unknown> {\n /** Optional metadata that was provided to the timeout configuration. */\n readonly meta: M;\n /** The number of messages seen before the timeout */\n readonly seen: number;\n /** The last message seen */\n readonly lastValue: T | null;\n}\n\n/**\n * An error emitted when a timeout occurs.\n */\nexport interface TimeoutError<T = unknown, M = unknown> extends Error {\n /**\n * The information provided to the error by the timeout\n * operation that created the error. Will be `null` if\n * used directly in non-RxJS code with an empty constructor.\n * (Note that using this constructor directly is not recommended,\n * you should create your own errors)\n */\n info: TimeoutInfo<T, M> | null;\n}\n\nexport interface TimeoutErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new <T = unknown, M = unknown>(info?: TimeoutInfo<T, M>): TimeoutError<T, M>;\n}\n\n/**\n * An error thrown by the {@link timeout} operator.\n *\n * Provided so users can use as a type and do quality comparisons.\n * We recommend you do not subclass this or create instances of this class directly.\n * If you have need of a error representing a timeout, you should\n * create your own error class and use that.\n *\n * @see {@link timeout}\n *\n * @class TimeoutError\n */\nexport const TimeoutError: TimeoutErrorCtor = createErrorClass(\n (_super) =>\n function TimeoutErrorImpl(this: any, info: TimeoutInfo<any> | null = null) {\n _super(this);\n this.message = 'Timeout has occurred';\n this.name = 'TimeoutError';\n this.info = info;\n }\n);\n\n/**\n * If `with` is provided, this will return an observable that will switch to a different observable if the source\n * does not push values within the specified time parameters.\n *\n * <span class=\"informal\">The most flexible option for creating a timeout behavior.</span>\n *\n * The first thing to know about the configuration is if you do not provide a `with` property to the configuration,\n * when timeout conditions are met, this operator will emit a {@link TimeoutError}. Otherwise, it will use the factory\n * function provided by `with`, and switch your subscription to the result of that. Timeout conditions are provided by\n * the settings in `first` and `each`.\n *\n * The `first` property can be either a `Date` for a specific time, a `number` for a time period relative to the\n * point of subscription, or it can be skipped. This property is to check timeout conditions for the arrival of\n * the first value from the source _only_. The timings of all subsequent values from the source will be checked\n * against the time period provided by `each`, if it was provided.\n *\n * The `each` property can be either a `number` or skipped. If a value for `each` is provided, it represents the amount of\n * time the resulting observable will wait between the arrival of values from the source before timing out. Note that if\n * `first` is _not_ provided, the value from `each` will be used to check timeout conditions for the arrival of the first\n * value and all subsequent values. If `first` _is_ provided, `each` will only be use to check all values after the first.\n *\n * ## Examples\n *\n * Emit a custom error if there is too much time between values\n *\n * ```ts\n * import { interval, timeout, throwError } from 'rxjs';\n *\n * class CustomTimeoutError extends Error {\n * constructor() {\n * super('It was too slow');\n * this.name = 'CustomTimeoutError';\n * }\n * }\n *\n * const slow$ = interval(900);\n *\n * slow$.pipe(\n * timeout({\n * each: 1000,\n * with: () => throwError(() => new CustomTimeoutError())\n * })\n * )\n * .subscribe({\n * error: console.error\n * });\n * ```\n *\n * Switch to a faster observable if your source is slow.\n *\n * ```ts\n * import { interval, timeout } from 'rxjs';\n *\n * const slow$ = interval(900);\n * const fast$ = interval(500);\n *\n * slow$.pipe(\n * timeout({\n * each: 1000,\n * with: () => fast$,\n * })\n * )\n * .subscribe(console.log);\n * ```\n * @param config The configuration for the timeout.\n */\nexport function timeout<T, O extends ObservableInput<unknown>, M = unknown>(\n config: TimeoutConfig<T, O, M> & { with: (info: TimeoutInfo<T, M>) => O }\n): OperatorFunction<T, T | ObservedValueOf<O>>;\n\n/**\n * Returns an observable that will error or switch to a different observable if the source does not push values\n * within the specified time parameters.\n *\n * <span class=\"informal\">The most flexible option for creating a timeout behavior.</span>\n *\n * The first thing to know about the configuration is if you do not provide a `with` property to the configuration,\n * when timeout conditions are met, this operator will emit a {@link TimeoutError}. Otherwise, it will use the factory\n * function provided by `with`, and switch your subscription to the result of that. Timeout conditions are provided by\n * the settings in `first` and `each`.\n *\n * The `first` property can be either a `Date` for a specific time, a `number` for a time period relative to the\n * point of subscription, or it can be skipped. This property is to check timeout conditions for the arrival of\n * the first value from the source _only_. The timings of all subsequent values from the source will be checked\n * against the time period provided by `each`, if it was provided.\n *\n * The `each` property can be either a `number` or skipped. If a value for `each` is provided, it represents the amount of\n * time the resulting observable will wait between the arrival of values from the source before timing out. Note that if\n * `first` is _not_ provided, the value from `each` will be used to check timeout conditions for the arrival of the first\n * value and all subsequent values. If `first` _is_ provided, `each` will only be use to check all values after the first.\n *\n * ### Handling TimeoutErrors\n *\n * If no `with` property was provided, subscriptions to the resulting observable may emit an error of {@link TimeoutError}.\n * The timeout error provides useful information you can examine when you're handling the error. The most common way to handle\n * the error would be with {@link catchError}, although you could use {@link tap} or just the error handler in your `subscribe` call\n * directly, if your error handling is only a side effect (such as notifying the user, or logging).\n *\n * In this case, you would check the error for `instanceof TimeoutError` to validate that the error was indeed from `timeout`, and\n * not from some other source. If it's not from `timeout`, you should probably rethrow it if you're in a `catchError`.\n *\n * ## Examples\n *\n * Emit a {@link TimeoutError} if the first value, and _only_ the first value, does not arrive within 5 seconds\n *\n * ```ts\n * import { interval, timeout } from 'rxjs';\n *\n * // A random interval that lasts between 0 and 10 seconds per tick\n * const source$ = interval(Math.round(Math.random() * 10_000));\n *\n * source$.pipe(\n * timeout({ first: 5_000 })\n * )\n * .subscribe({\n * next: console.log,\n * error: console.error\n * });\n * ```\n *\n * Emit a {@link TimeoutError} if the source waits longer than 5 seconds between any two values or the first value\n * and subscription.\n *\n * ```ts\n * import { timer, timeout, expand } from 'rxjs';\n *\n * const getRandomTime = () => Math.round(Math.random() * 10_000);\n *\n * // An observable that waits a random amount of time between each delivered value\n * const source$ = timer(getRandomTime())\n * .pipe(expand(() => timer(getRandomTime())));\n *\n * source$\n * .pipe(timeout({ each: 5_000 }))\n * .subscribe({\n * next: console.log,\n * error: console.error\n * });\n * ```\n *\n * Emit a {@link TimeoutError} if the source does not emit before 7 seconds, _or_ if the source waits longer than\n * 5 seconds between any two values after the first.\n *\n * ```ts\n * import { timer, timeout, expand } from 'rxjs';\n *\n * const getRandomTime = () => Math.round(Math.random() * 10_000);\n *\n * // An observable that waits a random amount of time between each delivered value\n * const source$ = timer(getRandomTime())\n * .pipe(expand(() => timer(getRandomTime())));\n *\n * source$\n * .pipe(timeout({ first: 7_000, each: 5_000 }))\n * .subscribe({\n * next: console.log,\n * error: console.error\n * });\n * ```\n */\nexport function timeout<T, M = unknown>(config: Omit<TimeoutConfig<T, any, M>, 'with'>): OperatorFunction<T, T>;\n\n/**\n * Returns an observable that will error if the source does not push its first value before the specified time passed as a `Date`.\n * This is functionally the same as `timeout({ first: someDate })`.\n *\n * <span class=\"informal\">Errors if the first value doesn't show up before the given date and time</span>\n *\n * ![](timeout.png)\n *\n * @param first The date to at which the resulting observable will timeout if the source observable\n * does not emit at least one value.\n * @param scheduler The scheduler to use. Defaults to {@link asyncScheduler}.\n */\nexport function timeout<T>(first: Date, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an observable that will error if the source does not push a value within the specified time in milliseconds.\n * This is functionally the same as `timeout({ each: milliseconds })`.\n *\n * <span class=\"informal\">Errors if it waits too long between any value</span>\n *\n * ![](timeout.png)\n *\n * @param each The time allowed between each pushed value from the source before the resulting observable\n * will timeout.\n * @param scheduler The scheduler to use. Defaults to {@link asyncScheduler}.\n */\nexport function timeout<T>(each: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n *\n * Errors if Observable does not emit a value in given time span.\n *\n * <span class=\"informal\">Timeouts on Observable that doesn't emit values fast enough.</span>\n *\n * ![](timeout.png)\n *\n * @see {@link timeoutWith}\n *\n * @return A function that returns an Observable that mirrors behaviour of the\n * source Observable, unless timeout happens when it throws an error.\n */\nexport function timeout<T, O extends ObservableInput<any>, M>(\n config: number | Date | TimeoutConfig<T, O, M>,\n schedulerArg?: SchedulerLike\n): OperatorFunction<T, T | ObservedValueOf<O>> {\n // Intentionally terse code.\n // If the first argument is a valid `Date`, then we use it as the `first` config.\n // Otherwise, if the first argument is a `number`, then we use it as the `each` config.\n // Otherwise, it can be assumed the first argument is the configuration object itself, and\n // we destructure that into what we're going to use, setting important defaults as we do.\n // NOTE: The default for `scheduler` will be the `scheduler` argument if it exists, or\n // it will default to the `asyncScheduler`.\n const {\n first,\n each,\n with: _with = timeoutErrorFactory,\n scheduler = schedulerArg ?? asyncScheduler,\n meta = null!,\n } = (isValidDate(config) ? { first: config } : typeof config === 'number' ? { each: config } : config) as TimeoutConfig<T, O, M>;\n\n if (first == null && each == null) {\n // Ensure timeout was provided at runtime.\n throw new TypeError('No timeout provided.');\n }\n\n return operate((source, subscriber) => {\n // This subscription encapsulates our subscription to the\n // source for this operator. We're capturing it separately,\n // because if there is a `with` observable to fail over to,\n // we want to unsubscribe from our original subscription, and\n // hand of the subscription to that one.\n let originalSourceSubscription: Subscription;\n // The subscription for our timeout timer. This changes\n // every time we get a new value.\n let timerSubscription: Subscription;\n // A bit of state we pass to our with and error factories to\n // tell what the last value we saw was.\n let lastValue: T | null = null;\n // A bit of state we pass to the with and error factories to\n // tell how many values we have seen so far.\n let seen = 0;\n const startTimer = (delay: number) => {\n timerSubscription = executeSchedule(\n subscriber,\n scheduler,\n () => {\n try {\n originalSourceSubscription.unsubscribe();\n innerFrom(\n _with!({\n meta,\n lastValue,\n seen,\n })\n ).subscribe(subscriber);\n } catch (err) {\n subscriber.error(err);\n }\n },\n delay\n );\n };\n\n originalSourceSubscription = source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value: T) => {\n // clear the timer so we can emit and start another one.\n timerSubscription?.unsubscribe();\n seen++;\n // Emit\n subscriber.next((lastValue = value));\n // null | undefined are both < 0. Thanks, JavaScript.\n each! > 0 && startTimer(each!);\n },\n undefined,\n undefined,\n () => {\n if (!timerSubscription?.closed) {\n timerSubscription?.unsubscribe();\n }\n // Be sure not to hold the last value in memory after unsubscription\n // it could be quite large.\n lastValue = null;\n }\n )\n );\n\n // Intentionally terse code.\n // If we've `seen` a value, that means the \"first\" clause was met already, if it existed.\n // it also means that a timer was already started for \"each\" (in the next handler above).\n // If `first` was provided, and it's a number, then use it.\n // If `first` was provided and it's not a number, it's a Date, and we get the difference between it and \"now\".\n // If `first` was not provided at all, then our first timer will be the value from `each`.\n !seen && startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler!.now()) : each!);\n });\n}\n\n/**\n * The default function to use to emit an error when timeout occurs and a `with` function\n * is not specified.\n * @param info The information about the timeout to pass along to the error\n */\nfunction timeoutErrorFactory(info: TimeoutInfo<any>): Observable<never> {\n throw new TimeoutError(info);\n}\n","import { OperatorFunction, ObservableInputTuple } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/innerFrom';\nimport { identity } from '../util/identity';\nimport { noop } from '../util/noop';\nimport { popResultSelector } from '../util/args';\n\nexport function withLatestFrom<T, O extends unknown[]>(...inputs: [...ObservableInputTuple<O>]): OperatorFunction<T, [T, ...O]>;\n\nexport function withLatestFrom<T, O extends unknown[], R>(\n ...inputs: [...ObservableInputTuple<O>, (...value: [T, ...O]) => R]\n): OperatorFunction<T, R>;\n\n/**\n * Combines the source Observable with other Observables to create an Observable\n * whose values are calculated from the latest values of each, only when the\n * source emits.\n *\n * <span class=\"informal\">Whenever the source Observable emits a value, it\n * computes a formula using that value plus the latest values from other input\n * Observables, then emits the output of that formula.</span>\n *\n * ![](withLatestFrom.png)\n *\n * `withLatestFrom` combines each value from the source Observable (the\n * instance) with the latest values from the other input Observables only when\n * the source emits a value, optionally using a `project` function to determine\n * the value to be emitted on the output Observable. All input Observables must\n * emit at least one value before the output Observable will emit a value.\n *\n * ## Example\n *\n * On every click event, emit an array with the latest timer event plus the click event\n *\n * ```ts\n * import { fromEvent, interval, withLatestFrom } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const timer = interval(1000);\n * const result = clicks.pipe(withLatestFrom(timer));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatest}\n *\n * @param {ObservableInput} other An input Observable to combine with the source\n * Observable. More than one input Observables may be given as argument.\n * @param {Function} [project] Projection function for combining values\n * together. Receives all values in order of the Observables passed, where the\n * first parameter is a value from the source Observable. (e.g.\n * `a.pipe(withLatestFrom(b, c), map(([a1, b1, c1]) => a1 + b1 + c1))`). If this is not\n * passed, arrays will be emitted on the output Observable.\n * @return A function that returns an Observable of projected values from the\n * most recent values from each input Observable, or an array of the most\n * recent values from each input Observable.\n */\nexport function withLatestFrom<T, R>(...inputs: any[]): OperatorFunction<T, R | any[]> {\n const project = popResultSelector(inputs) as ((...args: any[]) => R) | undefined;\n\n return operate((source, subscriber) => {\n const len = inputs.length;\n const otherValues = new Array(len);\n // An array of whether or not the other sources have emitted. Matched with them by index.\n // TODO: At somepoint, we should investigate the performance implications here, and look\n // into using a `Set()` and checking the `size` to see if we're ready.\n let hasValue = inputs.map(() => false);\n // Flipped true when we have at least one value from all other sources and\n // we are ready to start emitting values.\n let ready = false;\n\n // Other sources. Note that here we are not checking `subscriber.closed`,\n // this causes all inputs to be subscribed to, even if nothing can be emitted\n // from them. This is an important distinction because subscription constitutes\n // a side-effect.\n for (let i = 0; i < len; i++) {\n innerFrom(inputs[i]).subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n otherValues[i] = value;\n if (!ready && !hasValue[i]) {\n // If we're not ready yet, flag to show this observable has emitted.\n hasValue[i] = true;\n // Intentionally terse code.\n // If all of our other observables have emitted, set `ready` to `true`,\n // so we know we can start emitting values, then clean up the `hasValue` array,\n // because we don't need it anymore.\n (ready = hasValue.every(identity)) && (hasValue = null!);\n }\n },\n // Completing one of the other sources has\n // no bearing on the completion of our result.\n noop\n )\n );\n }\n\n // Source subscription\n source.subscribe(\n createOperatorSubscriber(subscriber, (value) => {\n if (ready) {\n // We have at least one value from the other sources. Go ahead and emit.\n const values = [value, ...otherValues];\n subscriber.next(project ? project(...values) : values);\n }\n })\n );\n });\n}\n","import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action<T> extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action<T>\n */\nexport class Action<T> extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction<T>, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n","import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n","import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction<T> extends Action<T> {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n","import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor<T>(this, work).schedule(state, delay);\n }\n}\n","import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array<AsyncAction<any>> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction<any>): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n","let nextHandle = 1;\n// The promise needs to be created lazily otherwise it won't be patched by Zones\nlet resolved: Promise<any>;\nconst activeHandles: { [key: number]: any } = {};\n\n/**\n * Finds the handle in the list of active handles, and removes it.\n * Returns `true` if found, `false` otherwise. Used both to clear\n * Immediate scheduled tasks, and to identify if a task should be scheduled.\n */\nfunction findAndClearHandle(handle: number): boolean {\n if (handle in activeHandles) {\n delete activeHandles[handle];\n return true;\n }\n return false;\n}\n\n/**\n * Helper functions to schedule and unschedule microtasks.\n */\nexport const Immediate = {\n setImmediate(cb: () => void): number {\n const handle = nextHandle++;\n activeHandles[handle] = true;\n if (!resolved) {\n resolved = Promise.resolve();\n }\n resolved.then(() => findAndClearHandle(handle) && cb());\n return handle;\n },\n\n clearImmediate(handle: number): void {\n findAndClearHandle(handle);\n },\n};\n\n/**\n * Used for internal testing purposes only. Do not export from library.\n */\nexport const TestTools = {\n pending() {\n return Object.keys(activeHandles).length;\n }\n};\n","import { Immediate } from '../util/Immediate';\nimport type { TimerHandle } from './timerHandle';\nconst { setImmediate, clearImmediate } = Immediate;\n\ntype SetImmediateFunction = (handler: () => void, ...args: any[]) => TimerHandle;\ntype ClearImmediateFunction = (handle: TimerHandle) => void;\n\ninterface ImmediateProvider {\n setImmediate: SetImmediateFunction;\n clearImmediate: ClearImmediateFunction;\n delegate:\n | {\n setImmediate: SetImmediateFunction;\n clearImmediate: ClearImmediateFunction;\n }\n | undefined;\n}\n\nexport const immediateProvider: ImmediateProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setImmediate(...args) {\n const { delegate } = immediateProvider;\n return (delegate?.setImmediate || setImmediate)(...args);\n },\n clearImmediate(handle) {\n const { delegate } = immediateProvider;\n return (delegate?.clearImmediate || clearImmediate)(handle as any);\n },\n delegate: undefined,\n};\n","import { AsapAction } from './AsapAction';\nimport { AsapScheduler } from './AsapScheduler';\n\n/**\n *\n * Asap Scheduler\n *\n * <span class=\"informal\">Perform task as fast as it can be performed asynchronously</span>\n *\n * `asap` scheduler behaves the same as {@link asyncScheduler} scheduler when you use it to delay task\n * in time. If however you set delay to `0`, `asap` will wait for current synchronously executing\n * code to end and then it will try to execute given task as fast as possible.\n *\n * `asap` scheduler will do its best to minimize time between end of currently executing code\n * and start of scheduled task. This makes it best candidate for performing so called \"deferring\".\n * Traditionally this was achieved by calling `setTimeout(deferredTask, 0)`, but that technique involves\n * some (although minimal) unwanted delay.\n *\n * Note that using `asap` scheduler does not necessarily mean that your task will be first to process\n * after currently executing code. In particular, if some task was also scheduled with `asap` before,\n * that task will execute first. That being said, if you need to schedule task asynchronously, but\n * as soon as possible, `asap` scheduler is your best bet.\n *\n * ## Example\n * Compare async and asap scheduler<\n * ```ts\n * import { asapScheduler, asyncScheduler } from 'rxjs';\n *\n * asyncScheduler.schedule(() => console.log('async')); // scheduling 'async' first...\n * asapScheduler.schedule(() => console.log('asap'));\n *\n * // Logs:\n * // \"asap\"\n * // \"async\"\n * // ... but 'asap' goes first!\n * ```\n */\n\nexport const asapScheduler = new AsapScheduler(AsapAction);\n\n/**\n * @deprecated Renamed to {@link asapScheduler}. Will be removed in v8.\n */\nexport const asap = asapScheduler;\n","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AsapScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction<any>): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n","import { AsyncAction } from './AsyncAction';\nimport { AsapScheduler } from './AsapScheduler';\nimport { SchedulerAction } from '../types';\nimport { immediateProvider } from './immediateProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsapAction<T> extends AsyncAction<T> {\n constructor(protected scheduler: AsapScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AsapScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If a microtask has already been scheduled, don't schedule another\n // one. If a microtask hasn't been scheduled yet, schedule one now. Return\n // the current scheduled microtask id.\n return scheduler._scheduled || (scheduler._scheduled = immediateProvider.setImmediate(scheduler.flush.bind(scheduler, undefined)));\n }\n\n protected recycleAsyncId(scheduler: AsapScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested microtask and set the scheduled flag to undefined\n // so the next AsapAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n immediateProvider.clearImmediate(id);\n if (scheduler._scheduled === id) {\n scheduler._scheduled = undefined;\n }\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * <span class=\"informal\">Schedule task as if you used setTimeout(task, duration)</span>\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n","import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n","import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * <span class=\"informal\">Put every next task on a queue, instead of executing it immediately</span>\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n","import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n","import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction<T> extends AsyncAction<T> {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n","import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n","export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n","/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n","import { createErrorClass } from './createErrorClass';\n\nexport interface EmptyError extends Error {}\n\nexport interface EmptyErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): EmptyError;\n}\n\n/**\n * An error thrown when an Observable or a sequence was queried but has no\n * elements.\n *\n * @see {@link first}\n * @see {@link last}\n * @see {@link single}\n * @see {@link firstValueFrom}\n * @see {@link lastValueFrom}\n *\n * @class EmptyError\n */\nexport const EmptyError: EmptyErrorCtor = createErrorClass((_super) => function EmptyErrorImpl(this: any) {\n _super(this);\n this.name = 'EmptyError';\n this.message = 'no elements in sequence';\n});\n","import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last<T>(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n","const { isArray } = Array;\nconst { getPrototypeOf, prototype: objectProto, keys: getKeys } = Object;\n\n/**\n * Used in functions where either a list of arguments, a single array of arguments, or a\n * dictionary of arguments can be returned. Returns an object with an `args` property with\n * the arguments in an array, if it is a dictionary, it will also return the `keys` in another\n * property.\n */\nexport function argsArgArrayOrObject<T, O extends Record<string, T>>(args: T[] | [O] | [T[]]): { args: T[]; keys: string[] | null } {\n if (args.length === 1) {\n const first = args[0];\n if (isArray(first)) {\n return { args: first, keys: null };\n }\n if (isPOJO(first)) {\n const keys = getKeys(first);\n return {\n args: keys.map((key) => first[key]),\n keys,\n };\n }\n }\n\n return { args: args as T[], keys: null };\n}\n\nfunction isPOJO(obj: any): obj is object {\n return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n}\n","const { isArray } = Array;\n\n/**\n * Used in operators and functions that accept either a list of arguments, or an array of arguments\n * as a single argument.\n */\nexport function argsOrArgArray<T>(args: (T | T[])[]): T[] {\n return args.length === 1 && isArray(args[0]) ? args[0] : (args as T[]);\n}\n","/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove<T>(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n","/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass<T>(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n","export function createObject(keys: string[], values: any[]) {\n return keys.reduce((result, key, i) => ((result[key] = values[i]), result), {} as any);\n}\n","import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n","import { Subscription } from '../Subscription';\nimport { SchedulerAction, SchedulerLike } from '../types';\n\nexport function executeSchedule(\n parentSubscription: Subscription,\n scheduler: SchedulerLike,\n work: () => void,\n delay: number,\n repeat: true\n): void;\nexport function executeSchedule(\n parentSubscription: Subscription,\n scheduler: SchedulerLike,\n work: () => void,\n delay?: number,\n repeat?: false\n): Subscription;\n\nexport function executeSchedule(\n parentSubscription: Subscription,\n scheduler: SchedulerLike,\n work: () => void,\n delay = 0,\n repeat = false\n): Subscription | void {\n const scheduleSubscription = scheduler.schedule(function (this: SchedulerAction<any>) {\n work();\n if (repeat) {\n parentSubscription.add(this.schedule(null, delay));\n } else {\n this.unsubscribe();\n }\n }, delay);\n\n parentSubscription.add(scheduleSubscription);\n\n if (!repeat) {\n // Because user-land scheduler implementations are unlikely to properly reuse\n // Actions for repeat scheduling, we can't trust that the returned subscription\n // will control repeat subscription scenarios. So we're trying to avoid using them\n // incorrectly within this library.\n return scheduleSubscription;\n }\n}\n","/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `<T>(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity<T>(x: T): T {\n return x;\n}\n","export const isArrayLike = (<T>(x: any): x is ArrayLike<T> => x && typeof x.length === 'number' && typeof x !== 'function');","import { isFunction } from './isFunction';\n\nexport function isAsyncIterable<T>(obj: any): obj is AsyncIterable<T> {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n","/**\n * Checks to see if a value is not only a `Date` object,\n * but a *valid* `Date` object that can be converted to a\n * number. For example, `new Date('blah')` is indeed an\n * `instanceof Date`, however it cannot be converted to a\n * number.\n */\nexport function isValidDate(value: any): value is Date {\n return value instanceof Date && !isNaN(value as any);\n}\n","/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n","import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable<any> {\n return isFunction(input[Symbol_observable]);\n}\n","import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable<any> {\n return isFunction(input?.[Symbol_iterator]);\n}\n","import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike<any> {\n return isFunction(value?.then);\n}\n","import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator<T>(readableStream: ReadableStreamLike<T>): AsyncGenerator<T> {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike<T>(obj: any): obj is ReadableStreamLike<T> {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an <iframe>.\n return isFunction(obj?.getReader);\n}\n","import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n","import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType<typeof Observable>['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate<T, R>(\n init: (liftedSource: Observable<T>, subscriber: Subscriber<R>) => (() => void) | void\n): OperatorFunction<T, R> {\n return (source: Observable<T>) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber<R>, liftedSource: Observable<T>) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n","import { OperatorFunction } from \"../types\";\nimport { map } from \"../operators/map\";\n\nconst { isArray } = Array;\n\nfunction callOrApply<T, R>(fn: ((...values: T[]) => R), args: T|T[]): R {\n return isArray(args) ? fn(...args) : fn(args);\n}\n\n/**\n * Used in several -- mostly deprecated -- situations where we need to \n * apply a list of arguments or a single argument to a result selector.\n */\nexport function mapOneOrManyArgs<T, R>(fn: ((...values: T[]) => R)): OperatorFunction<T|T[], R> {\n return map(args => callOrApply(fn, args))\n}","/* tslint:disable:no-empty */\nexport function noop() { }\n","import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe<T, A>(fn1: UnaryFunction<T, A>): UnaryFunction<T, A>;\nexport function pipe<T, A, B>(fn1: UnaryFunction<T, A>, fn2: UnaryFunction<A, B>): UnaryFunction<T, B>;\nexport function pipe<T, A, B, C>(fn1: UnaryFunction<T, A>, fn2: UnaryFunction<A, B>, fn3: UnaryFunction<B, C>): UnaryFunction<T, C>;\nexport function pipe<T, A, B, C, D>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>\n): UnaryFunction<T, D>;\nexport function pipe<T, A, B, C, D, E>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>\n): UnaryFunction<T, E>;\nexport function pipe<T, A, B, C, D, E, F>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>,\n fn6: UnaryFunction<E, F>\n): UnaryFunction<T, F>;\nexport function pipe<T, A, B, C, D, E, F, G>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>,\n fn6: UnaryFunction<E, F>,\n fn7: UnaryFunction<F, G>\n): UnaryFunction<T, G>;\nexport function pipe<T, A, B, C, D, E, F, G, H>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>,\n fn6: UnaryFunction<E, F>,\n fn7: UnaryFunction<F, G>,\n fn8: UnaryFunction<G, H>\n): UnaryFunction<T, H>;\nexport function pipe<T, A, B, C, D, E, F, G, H, I>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>,\n fn6: UnaryFunction<E, F>,\n fn7: UnaryFunction<F, G>,\n fn8: UnaryFunction<G, H>,\n fn9: UnaryFunction<H, I>\n): UnaryFunction<T, I>;\nexport function pipe<T, A, B, C, D, E, F, G, H, I>(\n fn1: UnaryFunction<T, A>,\n fn2: UnaryFunction<A, B>,\n fn3: UnaryFunction<B, C>,\n fn4: UnaryFunction<C, D>,\n fn5: UnaryFunction<D, E>,\n fn6: UnaryFunction<E, F>,\n fn7: UnaryFunction<F, G>,\n fn8: UnaryFunction<G, H>,\n fn9: UnaryFunction<H, I>,\n ...fns: UnaryFunction<any, any>[]\n): UnaryFunction<T, unknown>;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array<UnaryFunction<any, any>>): UnaryFunction<any, any> {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray<T, R>(fns: Array<UnaryFunction<T, R>>): UnaryFunction<T, R> {\n if (fns.length === 0) {\n return identity as UnaryFunction<any, any>;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction<T, R>) => fn(prev), input as any);\n };\n}\n","import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n","/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n","const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default {\n randomUUID\n};","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\nlet getRandomValues;\nconst rnds8 = new Uint8Array(16);\nexport default function rng() {\n // lazy load so that environments that need to polyfill have a chance to do so\n if (!getRandomValues) {\n // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation.\n getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n }\n\n return getRandomValues(rnds8);\n}","import validate from './validate.js';\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\n\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\n\nexport function unsafeStringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();\n}\n\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nexport default stringify;","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\n\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n\n options = options || {};\n const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return unsafeStringify(rnds);\n}\n\nexport default v4;","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {AnimationMetadata, AnimationOptions} from './animation_metadata';\nimport {AnimationPlayer} from './players/animation_player';\n\n/**\n * An injectable service that produces an animation sequence programmatically within an\n * Angular component or directive.\n * Provided by the `BrowserAnimationsModule` or `NoopAnimationsModule`.\n *\n * @usageNotes\n *\n * To use this service, add it to your component or directive as a dependency.\n * The service is instantiated along with your component.\n *\n * Apps do not typically need to create their own animation players, but if you\n * do need to, follow these steps:\n *\n * 1. Use the <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code> method\n * to create a programmatic animation. The method returns an `AnimationFactory` instance.\n *\n * 2. Use the factory object to create an `AnimationPlayer` and attach it to a DOM element.\n *\n * 3. Use the player object to control the animation programmatically.\n *\n * For example:\n *\n * ```ts\n * // import the service from BrowserAnimationsModule\n * import {AnimationBuilder} from '@angular/animations';\n * // require the service as a dependency\n * class MyCmp {\n * constructor(private _builder: AnimationBuilder) {}\n *\n * makeAnimation(element: any) {\n * // first define a reusable animation\n * const myAnimation = this._builder.build([\n * style({ width: 0 }),\n * animate(1000, style({ width: '100px' }))\n * ]);\n *\n * // use the returned factory object to create a player\n * const player = myAnimation.create(element);\n *\n * player.play();\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport abstract class AnimationBuilder {\n /**\n * Builds a factory for producing a defined animation.\n * @param animation A reusable animation definition.\n * @returns A factory object that can create a player for the defined animation.\n * @see `animate()`\n */\n abstract build(animation: AnimationMetadata|AnimationMetadata[]): AnimationFactory;\n}\n\n/**\n * A factory object returned from the\n * <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code>\n * method.\n *\n * @publicApi\n */\nexport abstract class AnimationFactory {\n /**\n * Creates an `AnimationPlayer` instance for the reusable animation defined by\n * the <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code>\n * method that created this factory and attaches the new player a DOM element.\n *\n * @param element The DOM element to which to attach the player.\n * @param options A set of options that can include a time delay and\n * additional developer-defined parameters.\n */\n abstract create(element: any, options?: AnimationOptions): AnimationPlayer;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Represents a set of CSS styles for use in an animation style as a generic.\n */\nexport interface ɵStyleData {\n [key: string]: string|number;\n}\n\n/**\n * Represents a set of CSS styles for use in an animation style as a Map.\n */\nexport type ɵStyleDataMap = Map<string, string|number>;\n\n/**\n * Represents animation-step timing parameters for an animation step.\n * @see `animate()`\n *\n * @publicApi\n */\nexport declare type AnimateTimings = {\n /**\n * The full duration of an animation step. A number and optional time unit,\n * such as \"1s\" or \"10ms\" for one second and 10 milliseconds, respectively.\n * The default unit is milliseconds.\n */\n duration: number,\n /**\n * The delay in applying an animation step. A number and optional time unit.\n * The default unit is milliseconds.\n */\n delay: number,\n /**\n * An easing style that controls how an animations step accelerates\n * and decelerates during its run time. An easing function such as `cubic-bezier()`,\n * or one of the following constants:\n * - `ease-in`\n * - `ease-out`\n * - `ease-in-and-out`\n */\n easing: string | null\n};\n\n/**\n * @description Options that control animation styling and timing.\n *\n * The following animation functions accept `AnimationOptions` data:\n *\n * - `transition()`\n * - `sequence()`\n * - `{@link animations/group group()}`\n * - `query()`\n * - `animation()`\n * - `useAnimation()`\n * - `animateChild()`\n *\n * Programmatic animations built using the `AnimationBuilder` service also\n * make use of `AnimationOptions`.\n *\n * @publicApi\n */\nexport declare interface AnimationOptions {\n /**\n * Sets a time-delay for initiating an animation action.\n * A number and optional time unit, such as \"1s\" or \"10ms\" for one second\n * and 10 milliseconds, respectively.The default unit is milliseconds.\n * Default value is 0, meaning no delay.\n */\n delay?: number|string;\n /**\n * A set of developer-defined parameters that modify styling and timing\n * when an animation action starts. An array of key-value pairs, where the provided value\n * is used as a default.\n */\n params?: {[name: string]: any};\n}\n\n/**\n * Adds duration options to control animation styling and timing for a child animation.\n *\n * @see `animateChild()`\n *\n * @publicApi\n */\nexport declare interface AnimateChildOptions extends AnimationOptions {\n duration?: number|string;\n}\n\n/**\n * @description Constants for the categories of parameters that can be defined for animations.\n *\n * A corresponding function defines a set of parameters for each category, and\n * collects them into a corresponding `AnimationMetadata` object.\n *\n * @publicApi\n */\nexport const enum AnimationMetadataType {\n /**\n * Associates a named animation state with a set of CSS styles.\n * See [`state()`](api/animations/state)\n */\n State = 0,\n /**\n * Data for a transition from one animation state to another.\n * See `transition()`\n */\n Transition = 1,\n /**\n * Contains a set of animation steps.\n * See `sequence()`\n */\n Sequence = 2,\n /**\n * Contains a set of animation steps.\n * See `{@link animations/group group()}`\n */\n Group = 3,\n /**\n * Contains an animation step.\n * See `animate()`\n */\n Animate = 4,\n /**\n * Contains a set of animation steps.\n * See `keyframes()`\n */\n Keyframes = 5,\n /**\n * Contains a set of CSS property-value pairs into a named style.\n * See `style()`\n */\n Style = 6,\n /**\n * Associates an animation with an entry trigger that can be attached to an element.\n * See `trigger()`\n */\n Trigger = 7,\n /**\n * Contains a re-usable animation.\n * See `animation()`\n */\n Reference = 8,\n /**\n * Contains data to use in executing child animations returned by a query.\n * See `animateChild()`\n */\n AnimateChild = 9,\n /**\n * Contains animation parameters for a re-usable animation.\n * See `useAnimation()`\n */\n AnimateRef = 10,\n /**\n * Contains child-animation query data.\n * See `query()`\n */\n Query = 11,\n /**\n * Contains data for staggering an animation sequence.\n * See `stagger()`\n */\n Stagger = 12\n}\n\n/**\n * Specifies automatic styling.\n *\n * @publicApi\n */\nexport const AUTO_STYLE = '*';\n\n/**\n * Base for animation data structures.\n *\n * @publicApi\n */\nexport interface AnimationMetadata {\n type: AnimationMetadataType;\n}\n\n/**\n * Contains an animation trigger. Instantiated and returned by the\n * `trigger()` function.\n *\n * @publicApi\n */\nexport interface AnimationTriggerMetadata extends AnimationMetadata {\n /**\n * The trigger name, used to associate it with an element. Unique within the component.\n */\n name: string;\n /**\n * An animation definition object, containing an array of state and transition declarations.\n */\n definitions: AnimationMetadata[];\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: {params?: {[name: string]: any}}|null;\n}\n\n/**\n * Encapsulates an animation state by associating a state name with a set of CSS styles.\n * Instantiated and returned by the [`state()`](api/animations/state) function.\n *\n * @publicApi\n */\nexport interface AnimationStateMetadata extends AnimationMetadata {\n /**\n * The state name, unique within the component.\n */\n name: string;\n /**\n * The CSS styles associated with this state.\n */\n styles: AnimationStyleMetadata;\n /**\n * An options object containing\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation.\n */\n options?: {params: {[name: string]: any}};\n}\n\n/**\n * Encapsulates an animation transition. Instantiated and returned by the\n * `transition()` function.\n *\n * @publicApi\n */\nexport interface AnimationTransitionMetadata extends AnimationMetadata {\n /**\n * An expression that describes a state change.\n */\n expr: string|\n ((fromState: string, toState: string, element?: any,\n params?: {[key: string]: any}) => boolean);\n /**\n * One or more animation objects to which this transition applies.\n */\n animation: AnimationMetadata|AnimationMetadata[];\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates a reusable animation, which is a collection of individual animation steps.\n * Instantiated and returned by the `animation()` function, and\n * passed to the `useAnimation()` function.\n *\n * @publicApi\n */\nexport interface AnimationReferenceMetadata extends AnimationMetadata {\n /**\n * One or more animation step objects.\n */\n animation: AnimationMetadata|AnimationMetadata[];\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates an animation query. Instantiated and returned by\n * the `query()` function.\n *\n * @publicApi\n */\nexport interface AnimationQueryMetadata extends AnimationMetadata {\n /**\n * The CSS selector for this query.\n */\n selector: string;\n /**\n * One or more animation step objects.\n */\n animation: AnimationMetadata|AnimationMetadata[];\n /**\n * A query options object.\n */\n options: AnimationQueryOptions|null;\n}\n\n/**\n * Encapsulates a keyframes sequence. Instantiated and returned by\n * the `keyframes()` function.\n *\n * @publicApi\n */\nexport interface AnimationKeyframesSequenceMetadata extends AnimationMetadata {\n /**\n * An array of animation styles.\n */\n steps: AnimationStyleMetadata[];\n}\n\n/**\n * Encapsulates an animation style. Instantiated and returned by\n * the `style()` function.\n *\n * @publicApi\n */\nexport interface AnimationStyleMetadata extends AnimationMetadata {\n /**\n * A set of CSS style properties.\n */\n styles: '*'|{[key: string]: string | number}|Array<{[key: string]: string | number}|'*'>;\n /**\n * A percentage of the total animate time at which the style is to be applied.\n */\n offset: number|null;\n}\n\n/**\n * Encapsulates an animation step. Instantiated and returned by\n * the `animate()` function.\n *\n * @publicApi\n */\nexport interface AnimationAnimateMetadata extends AnimationMetadata {\n /**\n * The timing data for the step.\n */\n timings: string|number|AnimateTimings;\n /**\n * A set of styles used in the step.\n */\n styles: AnimationStyleMetadata|AnimationKeyframesSequenceMetadata|null;\n}\n\n/**\n * Encapsulates a child animation, that can be run explicitly when the parent is run.\n * Instantiated and returned by the `animateChild` function.\n *\n * @publicApi\n */\nexport interface AnimationAnimateChildMetadata extends AnimationMetadata {\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates a reusable animation.\n * Instantiated and returned by the `useAnimation()` function.\n *\n * @publicApi\n */\nexport interface AnimationAnimateRefMetadata extends AnimationMetadata {\n /**\n * An animation reference object.\n */\n animation: AnimationReferenceMetadata;\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates an animation sequence.\n * Instantiated and returned by the `sequence()` function.\n *\n * @publicApi\n */\nexport interface AnimationSequenceMetadata extends AnimationMetadata {\n /**\n * An array of animation step objects.\n */\n steps: AnimationMetadata[];\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates an animation group.\n * Instantiated and returned by the `{@link animations/group group()}` function.\n *\n * @publicApi\n */\nexport interface AnimationGroupMetadata extends AnimationMetadata {\n /**\n * One or more animation or style steps that form this group.\n */\n steps: AnimationMetadata[];\n /**\n * An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation. Default delay is 0.\n */\n options: AnimationOptions|null;\n}\n\n/**\n * Encapsulates animation query options.\n * Passed to the `query()` function.\n *\n * @publicApi\n */\nexport declare interface AnimationQueryOptions extends AnimationOptions {\n /**\n * True if this query is optional, false if it is required. Default is false.\n * A required query throws an error if no elements are retrieved when\n * the query is executed. An optional query does not.\n *\n */\n optional?: boolean;\n /**\n * A maximum total number of results to return from the query.\n * If negative, results are limited from the end of the query list towards the beginning.\n * By default, results are not limited.\n */\n limit?: number;\n}\n\n/**\n * Encapsulates parameters for staggering the start times of a set of animation steps.\n * Instantiated and returned by the `stagger()` function.\n *\n * @publicApi\n **/\nexport interface AnimationStaggerMetadata extends AnimationMetadata {\n /**\n * The timing data for the steps.\n */\n timings: string|number;\n /**\n * One or more animation steps.\n */\n animation: AnimationMetadata|AnimationMetadata[];\n}\n\n/**\n * Creates a named animation trigger, containing a list of [`state()`](api/animations/state)\n * and `transition()` entries to be evaluated when the expression\n * bound to the trigger changes.\n *\n * @param name An identifying string.\n * @param definitions An animation definition object, containing an array of\n * [`state()`](api/animations/state) and `transition()` declarations.\n *\n * @return An object that encapsulates the trigger data.\n *\n * @usageNotes\n * Define an animation trigger in the `animations` section of `@Component` metadata.\n * In the template, reference the trigger by name and bind it to a trigger expression that\n * evaluates to a defined animation state, using the following format:\n *\n * `[@triggerName]=\"expression\"`\n *\n * Animation trigger bindings convert all values to strings, and then match the\n * previous and current values against any linked transitions.\n * Booleans can be specified as `1` or `true` and `0` or `false`.\n *\n * ### Usage Example\n *\n * The following example creates an animation trigger reference based on the provided\n * name value.\n * The provided animation value is expected to be an array consisting of state and\n * transition declarations.\n *\n * ```typescript\n * @Component({\n * selector: \"my-component\",\n * templateUrl: \"my-component-tpl.html\",\n * animations: [\n * trigger(\"myAnimationTrigger\", [\n * state(...),\n * state(...),\n * transition(...),\n * transition(...)\n * ])\n * ]\n * })\n * class MyComponent {\n * myStatusExp = \"something\";\n * }\n * ```\n *\n * The template associated with this component makes use of the defined trigger\n * by binding to an element within its template code.\n *\n * ```html\n * <!-- somewhere inside of my-component-tpl.html -->\n * <div [@myAnimationTrigger]=\"myStatusExp\">...</div>\n * ```\n *\n * ### Using an inline function\n * The `transition` animation method also supports reading an inline function which can decide\n * if its associated animation should be run.\n *\n * ```typescript\n * // this method is run each time the `myAnimationTrigger` trigger value changes.\n * function myInlineMatcherFn(fromState: string, toState: string, element: any, params: {[key:\n string]: any}): boolean {\n * // notice that `element` and `params` are also available here\n * return toState == 'yes-please-animate';\n * }\n *\n * @Component({\n * selector: 'my-component',\n * templateUrl: 'my-component-tpl.html',\n * animations: [\n * trigger('myAnimationTrigger', [\n * transition(myInlineMatcherFn, [\n * // the animation sequence code\n * ]),\n * ])\n * ]\n * })\n * class MyComponent {\n * myStatusExp = \"yes-please-animate\";\n * }\n * ```\n *\n * ### Disabling Animations\n * When true, the special animation control binding `@.disabled` binding prevents\n * all animations from rendering.\n * Place the `@.disabled` binding on an element to disable\n * animations on the element itself, as well as any inner animation triggers\n * within the element.\n *\n * The following example shows how to use this feature:\n *\n * ```typescript\n * @Component({\n * selector: 'my-component',\n * template: `\n * <div [@.disabled]=\"isDisabled\">\n * <div [@childAnimation]=\"exp\"></div>\n * </div>\n * `,\n * animations: [\n * trigger(\"childAnimation\", [\n * // ...\n * ])\n * ]\n * })\n * class MyComponent {\n * isDisabled = true;\n * exp = '...';\n * }\n * ```\n *\n * When `@.disabled` is true, it prevents the `@childAnimation` trigger from animating,\n * along with any inner animations.\n *\n * ### Disable animations application-wide\n * When an area of the template is set to have animations disabled,\n * **all** inner components have their animations disabled as well.\n * This means that you can disable all animations for an app\n * by placing a host binding set on `@.disabled` on the topmost Angular component.\n *\n * ```typescript\n * import {Component, HostBinding} from '@angular/core';\n *\n * @Component({\n * selector: 'app-component',\n * templateUrl: 'app.component.html',\n * })\n * class AppComponent {\n * @HostBinding('@.disabled')\n * public animationsDisabled = true;\n * }\n * ```\n *\n * ### Overriding disablement of inner animations\n * Despite inner animations being disabled, a parent animation can `query()`\n * for inner elements located in disabled areas of the template and still animate\n * them if needed. This is also the case for when a sub animation is\n * queried by a parent and then later animated using `animateChild()`.\n *\n * ### Detecting when an animation is disabled\n * If a region of the DOM (or the entire application) has its animations disabled, the animation\n * trigger callbacks still fire, but for zero seconds. When the callback fires, it provides\n * an instance of an `AnimationEvent`. If animations are disabled,\n * the `.disabled` flag on the event is true.\n *\n * @publicApi\n */\nexport function trigger(name: string, definitions: AnimationMetadata[]): AnimationTriggerMetadata {\n return {type: AnimationMetadataType.Trigger, name, definitions, options: {}};\n}\n\n/**\n * Defines an animation step that combines styling information with timing information.\n *\n * @param timings Sets `AnimateTimings` for the parent animation.\n * A string in the format \"duration [delay] [easing]\".\n * - Duration and delay are expressed as a number and optional time unit,\n * such as \"1s\" or \"10ms\" for one second and 10 milliseconds, respectively.\n * The default unit is milliseconds.\n * - The easing value controls how the animation accelerates and decelerates\n * during its runtime. Value is one of `ease`, `ease-in`, `ease-out`,\n * `ease-in-out`, or a `cubic-bezier()` function call.\n * If not supplied, no easing is applied.\n *\n * For example, the string \"1s 100ms ease-out\" specifies a duration of\n * 1000 milliseconds, and delay of 100 ms, and the \"ease-out\" easing style,\n * which decelerates near the end of the duration.\n * @param styles Sets AnimationStyles for the parent animation.\n * A function call to either `style()` or `keyframes()`\n * that returns a collection of CSS style entries to be applied to the parent animation.\n * When null, uses the styles from the destination state.\n * This is useful when describing an animation step that will complete an animation;\n * see \"Animating to the final state\" in `transitions()`.\n * @returns An object that encapsulates the animation step.\n *\n * @usageNotes\n * Call within an animation `sequence()`, `{@link animations/group group()}`, or\n * `transition()` call to specify an animation step\n * that applies given style data to the parent animation for a given amount of time.\n *\n * ### Syntax Examples\n * **Timing examples**\n *\n * The following examples show various `timings` specifications.\n * - `animate(500)` : Duration is 500 milliseconds.\n * - `animate(\"1s\")` : Duration is 1000 milliseconds.\n * - `animate(\"100ms 0.5s\")` : Duration is 100 milliseconds, delay is 500 milliseconds.\n * - `animate(\"5s ease-in\")` : Duration is 5000 milliseconds, easing in.\n * - `animate(\"5s 10ms cubic-bezier(.17,.67,.88,.1)\")` : Duration is 5000 milliseconds, delay is 10\n * milliseconds, easing according to a bezier curve.\n *\n * **Style examples**\n *\n * The following example calls `style()` to set a single CSS style.\n * ```typescript\n * animate(500, style({ background: \"red\" }))\n * ```\n * The following example calls `keyframes()` to set a CSS style\n * to different values for successive keyframes.\n * ```typescript\n * animate(500, keyframes(\n * [\n * style({ background: \"blue\" }),\n * style({ background: \"red\" })\n * ])\n * ```\n *\n * @publicApi\n */\nexport function animate(\n timings: string|number,\n styles: AnimationStyleMetadata|AnimationKeyframesSequenceMetadata|null =\n null): AnimationAnimateMetadata {\n return {type: AnimationMetadataType.Animate, styles, timings};\n}\n\n/**\n * @description Defines a list of animation steps to be run in parallel.\n *\n * @param steps An array of animation step objects.\n * - When steps are defined by `style()` or `animate()`\n * function calls, each call within the group is executed instantly.\n * - To specify offset styles to be applied at a later time, define steps with\n * `keyframes()`, or use `animate()` calls with a delay value.\n * For example:\n *\n * ```typescript\n * group([\n * animate(\"1s\", style({ background: \"black\" })),\n * animate(\"2s\", style({ color: \"white\" }))\n * ])\n * ```\n *\n * @param options An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation.\n *\n * @return An object that encapsulates the group data.\n *\n * @usageNotes\n * Grouped animations are useful when a series of styles must be\n * animated at different starting times and closed off at different ending times.\n *\n * When called within a `sequence()` or a\n * `transition()` call, does not continue to the next\n * instruction until all of the inner animation steps have completed.\n *\n * @publicApi\n */\nexport function group(\n steps: AnimationMetadata[], options: AnimationOptions|null = null): AnimationGroupMetadata {\n return {type: AnimationMetadataType.Group, steps, options};\n}\n\n/**\n * Defines a list of animation steps to be run sequentially, one by one.\n *\n * @param steps An array of animation step objects.\n * - Steps defined by `style()` calls apply the styling data immediately.\n * - Steps defined by `animate()` calls apply the styling data over time\n * as specified by the timing data.\n *\n * ```typescript\n * sequence([\n * style({ opacity: 0 }),\n * animate(\"1s\", style({ opacity: 1 }))\n * ])\n * ```\n *\n * @param options An options object containing a delay and\n * developer-defined parameters that provide styling defaults and\n * can be overridden on invocation.\n *\n * @return An object that encapsulates the sequence data.\n *\n * @usageNotes\n * When you pass an array of steps to a\n * `transition()` call, the steps run sequentially by default.\n * Compare this to the `{@link animations/group group()}` call, which runs animation steps in\n *parallel.\n *\n * When a sequence is used within a `{@link animations/group group()}` or a `transition()` call,\n * execution continues to the next instruction only after each of the inner animation\n * steps have completed.\n *\n * @publicApi\n **/\nexport function sequence(\n steps: AnimationMetadata[], options: AnimationOptions|null = null): AnimationSequenceMetadata {\n return {type: AnimationMetadataType.Sequence, steps, options};\n}\n\n/**\n * Declares a key/value object containing CSS properties/styles that\n * can then be used for an animation [`state`](api/animations/state), within an animation\n *`sequence`, or as styling data for calls to `animate()` and `keyframes()`.\n *\n * @param tokens A set of CSS styles or HTML styles associated with an animation state.\n * The value can be any of the following:\n * - A key-value style pair associating a CSS property with a value.\n * - An array of key-value style pairs.\n * - An asterisk (*), to use auto-styling, where styles are derived from the element\n * being animated and applied to the animation when it starts.\n *\n * Auto-styling can be used to define a state that depends on layout or other\n * environmental factors.\n *\n * @return An object that encapsulates the style data.\n *\n * @usageNotes\n * The following examples create animation styles that collect a set of\n * CSS property values:\n *\n * ```typescript\n * // string values for CSS properties\n * style({ background: \"red\", color: \"blue\" })\n *\n * // numerical pixel values\n * style({ width: 100, height: 0 })\n * ```\n *\n * The following example uses auto-styling to allow an element to animate from\n * a height of 0 up to its full height:\n *\n * ```\n * style({ height: 0 }),\n * animate(\"1s\", style({ height: \"*\" }))\n * ```\n *\n * @publicApi\n **/\nexport function style(tokens: '*'|{[key: string]: string | number}|\n Array<'*'|{[key: string]: string | number}>): AnimationStyleMetadata {\n return {type: AnimationMetadataType.Style, styles: tokens, offset: null};\n}\n\n/**\n * Declares an animation state within a trigger attached to an element.\n *\n * @param name One or more names for the defined state in a comma-separated string.\n * The following reserved state names can be supplied to define a style for specific use\n * cases:\n *\n * - `void` You can associate styles with this name to be used when\n * the element is detached from the application. For example, when an `ngIf` evaluates\n * to false, the state of the associated element is void.\n * - `*` (asterisk) Indicates the default state. You can associate styles with this name\n * to be used as the fallback when the state that is being animated is not declared\n * within the trigger.\n *\n * @param styles A set of CSS styles associated with this state, created using the\n * `style()` function.\n * This set of styles persists on the element once the state has been reached.\n * @param options Parameters that can be passed to the state when it is invoked.\n * 0 or more key-value pairs.\n * @return An object that encapsulates the new state data.\n *\n * @usageNotes\n * Use the `trigger()` function to register states to an animation trigger.\n * Use the `transition()` function to animate between states.\n * When a state is active within a component, its associated styles persist on the element,\n * even when the animation ends.\n *\n * @publicApi\n **/\nexport function state(\n name: string, styles: AnimationStyleMetadata,\n options?: {params: {[name: string]: any}}): AnimationStateMetadata {\n return {type: AnimationMetadataType.State, name, styles, options};\n}\n\n/**\n * Defines a set of animation styles, associating each style with an optional `offset` value.\n *\n * @param steps A set of animation styles with optional offset data.\n * The optional `offset` value for a style specifies a percentage of the total animation\n * time at which that style is applied.\n * @returns An object that encapsulates the keyframes data.\n *\n * @usageNotes\n * Use with the `animate()` call. Instead of applying animations\n * from the current state\n * to the destination state, keyframes describe how each style entry is applied and at what point\n * within the animation arc.\n * Compare [CSS Keyframe Animations](https://www.w3schools.com/css/css3_animations.asp).\n *\n * ### Usage\n *\n * In the following example, the offset values describe\n * when each `backgroundColor` value is applied. The color is red at the start, and changes to\n * blue when 20% of the total time has elapsed.\n *\n * ```typescript\n * // the provided offset values\n * animate(\"5s\", keyframes([\n * style({ backgroundColor: \"red\", offset: 0 }),\n * style({ backgroundColor: \"blue\", offset: 0.2 }),\n * style({ backgroundColor: \"orange\", offset: 0.3 }),\n * style({ backgroundColor: \"black\", offset: 1 })\n * ]))\n * ```\n *\n * If there are no `offset` values specified in the style entries, the offsets\n * are calculated automatically.\n *\n * ```typescript\n * animate(\"5s\", keyframes([\n * style({ backgroundColor: \"red\" }) // offset = 0\n * style({ backgroundColor: \"blue\" }) // offset = 0.33\n * style({ backgroundColor: \"orange\" }) // offset = 0.66\n * style({ backgroundColor: \"black\" }) // offset = 1\n * ]))\n *```\n\n * @publicApi\n */\nexport function keyframes(steps: AnimationStyleMetadata[]): AnimationKeyframesSequenceMetadata {\n return {type: AnimationMetadataType.Keyframes, steps};\n}\n\n/**\n * Declares an animation transition which is played when a certain specified condition is met.\n *\n * @param stateChangeExpr A string with a specific format or a function that specifies when the\n * animation transition should occur (see [State Change Expression](#state-change-expression)).\n *\n * @param steps One or more animation objects that represent the animation's instructions.\n *\n * @param options An options object that can be used to specify a delay for the animation or provide\n * custom parameters for it.\n *\n * @returns An object that encapsulates the transition data.\n *\n * @usageNotes\n *\n * ### State Change Expression\n *\n * The State Change Expression instructs Angular when to run the transition's animations, it can\n *either be\n * - a string with a specific syntax\n * - or a function that compares the previous and current state (value of the expression bound to\n * the element's trigger) and returns `true` if the transition should occur or `false` otherwise\n *\n * The string format can be:\n * - `fromState => toState`, which indicates that the transition's animations should occur then the\n * expression bound to the trigger's element goes from `fromState` to `toState`\n *\n * _Example:_\n * ```typescript\n * transition('open => closed', animate('.5s ease-out', style({ height: 0 }) ))\n * ```\n *\n * - `fromState <=> toState`, which indicates that the transition's animations should occur then\n * the expression bound to the trigger's element goes from `fromState` to `toState` or vice versa\n *\n * _Example:_\n * ```typescript\n * transition('enabled <=> disabled', animate('1s cubic-bezier(0.8,0.3,0,1)'))\n * ```\n *\n * - `:enter`/`:leave`, which indicates that the transition's animations should occur when the\n * element enters or exists the DOM\n *\n * _Example:_\n * ```typescript\n * transition(':enter', [\n * style({ opacity: 0 }),\n * animate('500ms', style({ opacity: 1 }))\n * ])\n * ```\n *\n * - `:increment`/`:decrement`, which indicates that the transition's animations should occur when\n * the numerical expression bound to the trigger's element has increased in value or decreased\n *\n * _Example:_\n * ```typescript\n * transition(':increment', query('@counter', animateChild()))\n * ```\n *\n * - a sequence of any of the above divided by commas, which indicates that transition's animations\n * should occur whenever one of the state change expressions matches\n *\n * _Example:_\n * ```typescript\n * transition(':increment, * => enabled, :enter', animate('1s ease', keyframes([\n * style({ transform: 'scale(1)', offset: 0}),\n * style({ transform: 'scale(1.1)', offset: 0.7}),\n * style({ transform: 'scale(1)', offset: 1})\n * ]))),\n * ```\n *\n * Also note that in such context:\n * - `void` can be used to indicate the absence of the element\n * - asterisks can be used as wildcards that match any state\n * - (as a consequence of the above, `void => *` is equivalent to `:enter` and `* => void` is\n * equivalent to `:leave`)\n * - `true` and `false` also match expression values of `1` and `0` respectively (but do not match\n * _truthy_ and _falsy_ values)\n *\n * <div class=\"alert is-helpful\">\n *\n * Be careful about entering end leaving elements as their transitions present a common\n * pitfall for developers.\n *\n * Note that when an element with a trigger enters the DOM its `:enter` transition always\n * gets executed, but its `:leave` transition will not be executed if the element is removed\n * alongside its parent (as it will be removed \"without warning\" before its transition has\n * a chance to be executed, the only way that such transition can occur is if the element\n * is exiting the DOM on its own).\n *\n *\n * </div>\n *\n * ### Animating to a Final State\n *\n * If the final step in a transition is a call to `animate()` that uses a timing value\n * with no `style` data, that step is automatically considered the final animation arc,\n * for the element to reach the final state, in such case Angular automatically adds or removes\n * CSS styles to ensure that the element is in the correct final state.\n *\n *\n * ### Usage Examples\n *\n * - Transition animations applied based on\n * the trigger's expression value\n *\n * ```HTML\n * <div [@myAnimationTrigger]=\"myStatusExp\">\n * ...\n * </div>\n * ```\n *\n * ```typescript\n * trigger(\"myAnimationTrigger\", [\n * ..., // states\n * transition(\"on => off, open => closed\", animate(500)),\n * transition(\"* <=> error\", query('.indicator', animateChild()))\n * ])\n * ```\n *\n * - Transition animations applied based on custom logic dependent\n * on the trigger's expression value and provided parameters\n *\n * ```HTML\n * <div [@myAnimationTrigger]=\"{\n * value: stepName,\n * params: { target: currentTarget }\n * }\">\n * ...\n * </div>\n * ```\n *\n * ```typescript\n * trigger(\"myAnimationTrigger\", [\n * ..., // states\n * transition(\n * (fromState, toState, _element, params) =>\n * ['firststep', 'laststep'].includes(fromState.toLowerCase())\n * && toState === params?.['target'],\n * animate('1s')\n * )\n * ])\n * ```\n *\n * @publicApi\n **/\nexport function transition(\n stateChangeExpr: string|\n ((fromState: string, toState: string, element?: any, params?: {[key: string]: any}) => boolean),\n steps: AnimationMetadata|AnimationMetadata[],\n options: AnimationOptions|null = null): AnimationTransitionMetadata {\n return {type: AnimationMetadataType.Transition, expr: stateChangeExpr, animation: steps, options};\n}\n\n/**\n * Produces a reusable animation that can be invoked in another animation or sequence,\n * by calling the `useAnimation()` function.\n *\n * @param steps One or more animation objects, as returned by the `animate()`\n * or `sequence()` function, that form a transformation from one state to another.\n * A sequence is used by default when you pass an array.\n * @param options An options object that can contain a delay value for the start of the\n * animation, and additional developer-defined parameters.\n * Provided values for additional parameters are used as defaults,\n * and override values can be passed to the caller on invocation.\n * @returns An object that encapsulates the animation data.\n *\n * @usageNotes\n * The following example defines a reusable animation, providing some default parameter\n * values.\n *\n * ```typescript\n * var fadeAnimation = animation([\n * style({ opacity: '{{ start }}' }),\n * animate('{{ time }}',\n * style({ opacity: '{{ end }}'}))\n * ],\n * { params: { time: '1000ms', start: 0, end: 1 }});\n * ```\n *\n * The following invokes the defined animation with a call to `useAnimation()`,\n * passing in override parameter values.\n *\n * ```js\n * useAnimation(fadeAnimation, {\n * params: {\n * time: '2s',\n * start: 1,\n * end: 0\n * }\n * })\n * ```\n *\n * If any of the passed-in parameter values are missing from this call,\n * the default values are used. If one or more parameter values are missing before a step is\n * animated, `useAnimation()` throws an error.\n *\n * @publicApi\n */\nexport function animation(\n steps: AnimationMetadata|AnimationMetadata[],\n options: AnimationOptions|null = null): AnimationReferenceMetadata {\n return {type: AnimationMetadataType.Reference, animation: steps, options};\n}\n\n/**\n * Executes a queried inner animation element within an animation sequence.\n *\n * @param options An options object that can contain a delay value for the start of the\n * animation, and additional override values for developer-defined parameters.\n * @return An object that encapsulates the child animation data.\n *\n * @usageNotes\n * Each time an animation is triggered in Angular, the parent animation\n * has priority and any child animations are blocked. In order\n * for a child animation to run, the parent animation must query each of the elements\n * containing child animations, and run them using this function.\n *\n * Note that this feature is designed to be used with `query()` and it will only work\n * with animations that are assigned using the Angular animation library. CSS keyframes\n * and transitions are not handled by this API.\n *\n * @publicApi\n */\nexport function animateChild(options: AnimateChildOptions|null = null):\n AnimationAnimateChildMetadata {\n return {type: AnimationMetadataType.AnimateChild, options};\n}\n\n/**\n * Starts a reusable animation that is created using the `animation()` function.\n *\n * @param animation The reusable animation to start.\n * @param options An options object that can contain a delay value for the start of\n * the animation, and additional override values for developer-defined parameters.\n * @return An object that contains the animation parameters.\n *\n * @publicApi\n */\nexport function useAnimation(\n animation: AnimationReferenceMetadata,\n options: AnimationOptions|null = null): AnimationAnimateRefMetadata {\n return {type: AnimationMetadataType.AnimateRef, animation, options};\n}\n\n/**\n * Finds one or more inner elements within the current element that is\n * being animated within a sequence. Use with `animate()`.\n *\n * @param selector The element to query, or a set of elements that contain Angular-specific\n * characteristics, specified with one or more of the following tokens.\n * - `query(\":enter\")` or `query(\":leave\")` : Query for newly inserted/removed elements (not\n * all elements can be queried via these tokens, see\n * [Entering and Leaving Elements](#entering-and-leaving-elements))\n * - `query(\":animating\")` : Query all currently animating elements.\n * - `query(\"@triggerName\")` : Query elements that contain an animation trigger.\n * - `query(\"@*\")` : Query all elements that contain an animation triggers.\n * - `query(\":self\")` : Include the current element into the animation sequence.\n *\n * @param animation One or more animation steps to apply to the queried element or elements.\n * An array is treated as an animation sequence.\n * @param options An options object. Use the 'limit' field to limit the total number of\n * items to collect.\n * @return An object that encapsulates the query data.\n *\n * @usageNotes\n *\n * ### Multiple Tokens\n *\n * Tokens can be merged into a combined query selector string. For example:\n *\n * ```typescript\n * query(':self, .record:enter, .record:leave, @subTrigger', [...])\n * ```\n *\n * The `query()` function collects multiple elements and works internally by using\n * `element.querySelectorAll`. Use the `limit` field of an options object to limit\n * the total number of items to be collected. For example:\n *\n * ```js\n * query('div', [\n * animate(...),\n * animate(...)\n * ], { limit: 1 })\n * ```\n *\n * By default, throws an error when zero items are found. Set the\n * `optional` flag to ignore this error. For example:\n *\n * ```js\n * query('.some-element-that-may-not-be-there', [\n * animate(...),\n * animate(...)\n * ], { optional: true })\n * ```\n *\n * ### Entering and Leaving Elements\n *\n * Not all elements can be queried via the `:enter` and `:leave` tokens, the only ones\n * that can are those that Angular assumes can enter/leave based on their own logic\n * (if their insertion/removal is simply a consequence of that of their parent they\n * should be queried via a different token in their parent's `:enter`/`:leave` transitions).\n *\n * The only elements Angular assumes can enter/leave based on their own logic (thus the only\n * ones that can be queried via the `:enter` and `:leave` tokens) are:\n * - Those inserted dynamically (via `ViewContainerRef`)\n * - Those that have a structural directive (which, under the hood, are a subset of the above ones)\n *\n * <div class=\"alert is-helpful\">\n *\n * Note that elements will be successfully queried via `:enter`/`:leave` even if their\n * insertion/removal is not done manually via `ViewContainerRef`or caused by their structural\n * directive (e.g. they enter/exit alongside their parent).\n *\n * </div>\n *\n * <div class=\"alert is-important\">\n *\n * There is an exception to what previously mentioned, besides elements entering/leaving based on\n * their own logic, elements with an animation trigger can always be queried via `:leave` when\n * their parent is also leaving.\n *\n * </div>\n *\n * ### Usage Example\n *\n * The following example queries for inner elements and animates them\n * individually using `animate()`.\n *\n * ```typescript\n * @Component({\n * selector: 'inner',\n * template: `\n * <div [@queryAnimation]=\"exp\">\n * <h1>Title</h1>\n * <div class=\"content\">\n * Blah blah blah\n * </div>\n * </div>\n * `,\n * animations: [\n * trigger('queryAnimation', [\n * transition('* => goAnimate', [\n * // hide the inner elements\n * query('h1', style({ opacity: 0 })),\n * query('.content', style({ opacity: 0 })),\n *\n * // animate the inner elements in, one by one\n * query('h1', animate(1000, style({ opacity: 1 }))),\n * query('.content', animate(1000, style({ opacity: 1 }))),\n * ])\n * ])\n * ]\n * })\n * class Cmp {\n * exp = '';\n *\n * goAnimate() {\n * this.exp = 'goAnimate';\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport function query(\n selector: string, animation: AnimationMetadata|AnimationMetadata[],\n options: AnimationQueryOptions|null = null): AnimationQueryMetadata {\n return {type: AnimationMetadataType.Query, selector, animation, options};\n}\n\n/**\n * Use within an animation `query()` call to issue a timing gap after\n * each queried item is animated.\n *\n * @param timings A delay value.\n * @param animation One ore more animation steps.\n * @returns An object that encapsulates the stagger data.\n *\n * @usageNotes\n * In the following example, a container element wraps a list of items stamped out\n * by an `ngFor`. The container element contains an animation trigger that will later be set\n * to query for each of the inner items.\n *\n * Each time items are added, the opacity fade-in animation runs,\n * and each removed item is faded out.\n * When either of these animations occur, the stagger effect is\n * applied after each item's animation is started.\n *\n * ```html\n * <!-- list.component.html -->\n * <button (click)=\"toggle()\">Show / Hide Items</button>\n * <hr />\n * <div [@listAnimation]=\"items.length\">\n * <div *ngFor=\"let item of items\">\n * {{ item }}\n * </div>\n * </div>\n * ```\n *\n * Here is the component code:\n *\n * ```typescript\n * import {trigger, transition, style, animate, query, stagger} from '@angular/animations';\n * @Component({\n * templateUrl: 'list.component.html',\n * animations: [\n * trigger('listAnimation', [\n * ...\n * ])\n * ]\n * })\n * class ListComponent {\n * items = [];\n *\n * showItems() {\n * this.items = [0,1,2,3,4];\n * }\n *\n * hideItems() {\n * this.items = [];\n * }\n *\n * toggle() {\n * this.items.length ? this.hideItems() : this.showItems();\n * }\n * }\n * ```\n *\n * Here is the animation trigger code:\n *\n * ```typescript\n * trigger('listAnimation', [\n * transition('* => *', [ // each time the binding value changes\n * query(':leave', [\n * stagger(100, [\n * animate('0.5s', style({ opacity: 0 }))\n * ])\n * ]),\n * query(':enter', [\n * style({ opacity: 0 }),\n * stagger(100, [\n * animate('0.5s', style({ opacity: 1 }))\n * ])\n * ])\n * ])\n * ])\n * ```\n *\n * @publicApi\n */\nexport function stagger(timings: string|number, animation: AnimationMetadata|AnimationMetadata[]):\n AnimationStaggerMetadata {\n return {type: AnimationMetadataType.Stagger, timings, animation};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nexport function scheduleMicroTask(cb: () => any) {\n Promise.resolve().then(cb);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {scheduleMicroTask} from '../util';\n\n/**\n * Provides programmatic control of a reusable animation sequence,\n * built using the <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code>\n * method which returns an `AnimationFactory`, whose\n * <code>[create](api/animations/AnimationFactory#create)()</code> method instantiates and\n * initializes this interface.\n *\n * @see `AnimationBuilder`\n * @see `AnimationFactory`\n * @see `animate()`\n *\n * @publicApi\n */\nexport interface AnimationPlayer {\n /**\n * Provides a callback to invoke when the animation finishes.\n * @param fn The callback function.\n * @see `finish()`\n */\n onDone(fn: () => void): void;\n /**\n * Provides a callback to invoke when the animation starts.\n * @param fn The callback function.\n * @see `run()`\n */\n onStart(fn: () => void): void;\n /**\n * Provides a callback to invoke after the animation is destroyed.\n * @param fn The callback function.\n * @see `destroy()`\n * @see `beforeDestroy()`\n */\n onDestroy(fn: () => void): void;\n /**\n * Initializes the animation.\n */\n init(): void;\n /**\n * Reports whether the animation has started.\n * @returns True if the animation has started, false otherwise.\n */\n hasStarted(): boolean;\n /**\n * Runs the animation, invoking the `onStart()` callback.\n */\n play(): void;\n /**\n * Pauses the animation.\n */\n pause(): void;\n /**\n * Restarts the paused animation.\n */\n restart(): void;\n /**\n * Ends the animation, invoking the `onDone()` callback.\n */\n finish(): void;\n /**\n * Destroys the animation, after invoking the `beforeDestroy()` callback.\n * Calls the `onDestroy()` callback when destruction is completed.\n */\n destroy(): void;\n /**\n * Resets the animation to its initial state.\n */\n reset(): void;\n /**\n * Sets the position of the animation.\n * @param position A 0-based offset into the duration, in milliseconds.\n */\n setPosition(position: any /** TODO #9100 */): void;\n /**\n * Reports the current position of the animation.\n * @returns A 0-based offset into the duration, in milliseconds.\n */\n getPosition(): number;\n /**\n * The parent of this player, if any.\n */\n parentPlayer: AnimationPlayer|null;\n /**\n * The total run time of the animation, in milliseconds.\n */\n readonly totalTime: number;\n /**\n * Provides a callback to invoke before the animation is destroyed.\n */\n beforeDestroy?: () => any;\n /**\n * @internal\n * Internal\n */\n triggerCallback?: (phaseName: string) => void;\n /**\n * @internal\n * Internal\n */\n disabled?: boolean;\n}\n\n/**\n * An empty programmatic controller for reusable animations.\n * Used internally when animations are disabled, to avoid\n * checking for the null case when an animation player is expected.\n *\n * @see `animate()`\n * @see `AnimationPlayer`\n * @see `GroupPlayer`\n *\n * @publicApi\n */\nexport class NoopAnimationPlayer implements AnimationPlayer {\n private _onDoneFns: Function[] = [];\n private _onStartFns: Function[] = [];\n private _onDestroyFns: Function[] = [];\n private _originalOnDoneFns: Function[] = [];\n private _originalOnStartFns: Function[] = [];\n private _started = false;\n private _destroyed = false;\n private _finished = false;\n private _position = 0;\n public parentPlayer: AnimationPlayer|null = null;\n public readonly totalTime: number;\n constructor(duration: number = 0, delay: number = 0) {\n this.totalTime = duration + delay;\n }\n private _onFinish() {\n if (!this._finished) {\n this._finished = true;\n this._onDoneFns.forEach(fn => fn());\n this._onDoneFns = [];\n }\n }\n onStart(fn: () => void): void {\n this._originalOnStartFns.push(fn);\n this._onStartFns.push(fn);\n }\n onDone(fn: () => void): void {\n this._originalOnDoneFns.push(fn);\n this._onDoneFns.push(fn);\n }\n onDestroy(fn: () => void): void {\n this._onDestroyFns.push(fn);\n }\n hasStarted(): boolean {\n return this._started;\n }\n init(): void {}\n play(): void {\n if (!this.hasStarted()) {\n this._onStart();\n this.triggerMicrotask();\n }\n this._started = true;\n }\n\n /** @internal */\n triggerMicrotask() {\n scheduleMicroTask(() => this._onFinish());\n }\n\n private _onStart() {\n this._onStartFns.forEach(fn => fn());\n this._onStartFns = [];\n }\n\n pause(): void {}\n restart(): void {}\n finish(): void {\n this._onFinish();\n }\n destroy(): void {\n if (!this._destroyed) {\n this._destroyed = true;\n if (!this.hasStarted()) {\n this._onStart();\n }\n this.finish();\n this._onDestroyFns.forEach(fn => fn());\n this._onDestroyFns = [];\n }\n }\n reset(): void {\n this._started = false;\n this._finished = false;\n this._onStartFns = this._originalOnStartFns;\n this._onDoneFns = this._originalOnDoneFns;\n }\n setPosition(position: number): void {\n this._position = this.totalTime ? position * this.totalTime : 1;\n }\n getPosition(): number {\n return this.totalTime ? this._position / this.totalTime : 1;\n }\n\n /** @internal */\n triggerCallback(phaseName: string): void {\n const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;\n methods.forEach(fn => fn());\n methods.length = 0;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {scheduleMicroTask} from '../util';\nimport {AnimationPlayer} from './animation_player';\n\n/**\n * A programmatic controller for a group of reusable animations.\n * Used internally to control animations.\n *\n * @see `AnimationPlayer`\n * @see `{@link animations/group group()}`\n *\n */\nexport class AnimationGroupPlayer implements AnimationPlayer {\n private _onDoneFns: Function[] = [];\n private _onStartFns: Function[] = [];\n private _finished = false;\n private _started = false;\n private _destroyed = false;\n private _onDestroyFns: Function[] = [];\n\n public parentPlayer: AnimationPlayer|null = null;\n public totalTime: number = 0;\n public readonly players: AnimationPlayer[];\n\n constructor(_players: AnimationPlayer[]) {\n this.players = _players;\n let doneCount = 0;\n let destroyCount = 0;\n let startCount = 0;\n const total = this.players.length;\n\n if (total == 0) {\n scheduleMicroTask(() => this._onFinish());\n } else {\n this.players.forEach(player => {\n player.onDone(() => {\n if (++doneCount == total) {\n this._onFinish();\n }\n });\n player.onDestroy(() => {\n if (++destroyCount == total) {\n this._onDestroy();\n }\n });\n player.onStart(() => {\n if (++startCount == total) {\n this._onStart();\n }\n });\n });\n }\n\n this.totalTime = this.players.reduce((time, player) => Math.max(time, player.totalTime), 0);\n }\n\n private _onFinish() {\n if (!this._finished) {\n this._finished = true;\n this._onDoneFns.forEach(fn => fn());\n this._onDoneFns = [];\n }\n }\n\n init(): void {\n this.players.forEach(player => player.init());\n }\n\n onStart(fn: () => void): void {\n this._onStartFns.push(fn);\n }\n\n private _onStart() {\n if (!this.hasStarted()) {\n this._started = true;\n this._onStartFns.forEach(fn => fn());\n this._onStartFns = [];\n }\n }\n\n onDone(fn: () => void): void {\n this._onDoneFns.push(fn);\n }\n\n onDestroy(fn: () => void): void {\n this._onDestroyFns.push(fn);\n }\n\n hasStarted() {\n return this._started;\n }\n\n play() {\n if (!this.parentPlayer) {\n this.init();\n }\n this._onStart();\n this.players.forEach(player => player.play());\n }\n\n pause(): void {\n this.players.forEach(player => player.pause());\n }\n\n restart(): void {\n this.players.forEach(player => player.restart());\n }\n\n finish(): void {\n this._onFinish();\n this.players.forEach(player => player.finish());\n }\n\n destroy(): void {\n this._onDestroy();\n }\n\n private _onDestroy() {\n if (!this._destroyed) {\n this._destroyed = true;\n this._onFinish();\n this.players.forEach(player => player.destroy());\n this._onDestroyFns.forEach(fn => fn());\n this._onDestroyFns = [];\n }\n }\n\n reset(): void {\n this.players.forEach(player => player.reset());\n this._destroyed = false;\n this._finished = false;\n this._started = false;\n }\n\n setPosition(p: number): void {\n const timeAtPosition = p * this.totalTime;\n this.players.forEach(player => {\n const position = player.totalTime ? Math.min(1, timeAtPosition / player.totalTime) : 1;\n player.setPosition(position);\n });\n }\n\n getPosition(): number {\n const longestPlayer =\n this.players.reduce((longestSoFar: AnimationPlayer|null, player: AnimationPlayer) => {\n const newPlayerIsLongest =\n longestSoFar === null || player.totalTime > longestSoFar.totalTime;\n return newPlayerIsLongest ? player : longestSoFar;\n }, null);\n return longestPlayer != null ? longestPlayer.getPosition() : 0;\n }\n\n beforeDestroy(): void {\n this.players.forEach(player => {\n if (player.beforeDestroy) {\n player.beforeDestroy();\n }\n });\n }\n\n /** @internal */\n triggerCallback(phaseName: string): void {\n const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns;\n methods.forEach(fn => fn());\n methods.length = 0;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nexport {AnimationGroupPlayer as ɵAnimationGroupPlayer} from './players/animation_group_player';\nexport const ɵPRE_STYLE = '!';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {QueryList} from '@angular/core';\nimport {Subject, Subscription} from 'rxjs';\nimport {\n UP_ARROW,\n DOWN_ARROW,\n LEFT_ARROW,\n RIGHT_ARROW,\n TAB,\n A,\n Z,\n ZERO,\n NINE,\n hasModifierKey,\n HOME,\n END,\n PAGE_UP,\n PAGE_DOWN,\n} from '@angular/cdk/keycodes';\nimport {debounceTime, filter, map, tap} from 'rxjs/operators';\n\n/** This interface is for items that can be passed to a ListKeyManager. */\nexport interface ListKeyManagerOption {\n /** Whether the option is disabled. */\n disabled?: boolean;\n\n /** Gets the label for this option. */\n getLabel?(): string;\n}\n\n/** Modifier keys handled by the ListKeyManager. */\nexport type ListKeyManagerModifierKey = 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey';\n\n/**\n * This class manages keyboard events for selectable lists. If you pass it a query list\n * of items, it will set the active item correctly when arrow events occur.\n */\nexport class ListKeyManager<T extends ListKeyManagerOption> {\n private _activeItemIndex = -1;\n private _activeItem: T | null = null;\n private _wrap = false;\n private readonly _letterKeyStream = new Subject<string>();\n private _typeaheadSubscription = Subscription.EMPTY;\n private _itemChangesSubscription?: Subscription;\n private _vertical = true;\n private _horizontal: 'ltr' | 'rtl' | null;\n private _allowedModifierKeys: ListKeyManagerModifierKey[] = [];\n private _homeAndEnd = false;\n private _pageUpAndDown = {enabled: false, delta: 10};\n\n /**\n * Predicate function that can be used to check whether an item should be skipped\n * by the key manager. By default, disabled items are skipped.\n */\n private _skipPredicateFn = (item: T) => item.disabled;\n\n // Buffer for the letters that the user has pressed when the typeahead option is turned on.\n private _pressedLetters: string[] = [];\n\n constructor(private _items: QueryList<T> | T[]) {\n // We allow for the items to be an array because, in some cases, the consumer may\n // not have access to a QueryList of the items they want to manage (e.g. when the\n // items aren't being collected via `ViewChildren` or `ContentChildren`).\n if (_items instanceof QueryList) {\n this._itemChangesSubscription = _items.changes.subscribe((newItems: QueryList<T>) => {\n if (this._activeItem) {\n const itemArray = newItems.toArray();\n const newIndex = itemArray.indexOf(this._activeItem);\n\n if (newIndex > -1 && newIndex !== this._activeItemIndex) {\n this._activeItemIndex = newIndex;\n }\n }\n });\n }\n }\n\n /**\n * Stream that emits any time the TAB key is pressed, so components can react\n * when focus is shifted off of the list.\n */\n readonly tabOut = new Subject<void>();\n\n /** Stream that emits whenever the active item of the list manager changes. */\n readonly change = new Subject<number>();\n\n /**\n * Sets the predicate function that determines which items should be skipped by the\n * list key manager.\n * @param predicate Function that determines whether the given item should be skipped.\n */\n skipPredicate(predicate: (item: T) => boolean): this {\n this._skipPredicateFn = predicate;\n return this;\n }\n\n /**\n * Configures wrapping mode, which determines whether the active item will wrap to\n * the other end of list when there are no more items in the given direction.\n * @param shouldWrap Whether the list should wrap when reaching the end.\n */\n withWrap(shouldWrap = true): this {\n this._wrap = shouldWrap;\n return this;\n }\n\n /**\n * Configures whether the key manager should be able to move the selection vertically.\n * @param enabled Whether vertical selection should be enabled.\n */\n withVerticalOrientation(enabled: boolean = true): this {\n this._vertical = enabled;\n return this;\n }\n\n /**\n * Configures the key manager to move the selection horizontally.\n * Passing in `null` will disable horizontal movement.\n * @param direction Direction in which the selection can be moved.\n */\n withHorizontalOrientation(direction: 'ltr' | 'rtl' | null): this {\n this._horizontal = direction;\n return this;\n }\n\n /**\n * Modifier keys which are allowed to be held down and whose default actions will be prevented\n * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.\n */\n withAllowedModifierKeys(keys: ListKeyManagerModifierKey[]): this {\n this._allowedModifierKeys = keys;\n return this;\n }\n\n /**\n * Turns on typeahead mode which allows users to set the active item by typing.\n * @param debounceInterval Time to wait after the last keystroke before setting the active item.\n */\n withTypeAhead(debounceInterval: number = 200): this {\n if (\n (typeof ngDevMode === 'undefined' || ngDevMode) &&\n this._items.length &&\n this._items.some(item => typeof item.getLabel !== 'function')\n ) {\n throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');\n }\n\n this._typeaheadSubscription.unsubscribe();\n\n // Debounce the presses of non-navigational keys, collect the ones that correspond to letters\n // and convert those letters back into a string. Afterwards find the first item that starts\n // with that string and select it.\n this._typeaheadSubscription = this._letterKeyStream\n .pipe(\n tap(letter => this._pressedLetters.push(letter)),\n debounceTime(debounceInterval),\n filter(() => this._pressedLetters.length > 0),\n map(() => this._pressedLetters.join('')),\n )\n .subscribe(inputString => {\n const items = this._getItemsArray();\n\n // Start at 1 because we want to start searching at the item immediately\n // following the current active item.\n for (let i = 1; i < items.length + 1; i++) {\n const index = (this._activeItemIndex + i) % items.length;\n const item = items[index];\n\n if (\n !this._skipPredicateFn(item) &&\n item.getLabel!().toUpperCase().trim().indexOf(inputString) === 0\n ) {\n this.setActiveItem(index);\n break;\n }\n }\n\n this._pressedLetters = [];\n });\n\n return this;\n }\n\n /** Cancels the current typeahead sequence. */\n cancelTypeahead(): this {\n this._pressedLetters = [];\n return this;\n }\n\n /**\n * Configures the key manager to activate the first and last items\n * respectively when the Home or End key is pressed.\n * @param enabled Whether pressing the Home or End key activates the first/last item.\n */\n withHomeAndEnd(enabled: boolean = true): this {\n this._homeAndEnd = enabled;\n return this;\n }\n\n /**\n * Configures the key manager to activate every 10th, configured or first/last element in up/down direction\n * respectively when the Page-Up or Page-Down key is pressed.\n * @param enabled Whether pressing the Page-Up or Page-Down key activates the first/last item.\n * @param delta Whether pressing the Home or End key activates the first/last item.\n */\n withPageUpDown(enabled: boolean = true, delta: number = 10): this {\n this._pageUpAndDown = {enabled, delta};\n return this;\n }\n\n /**\n * Sets the active item to the item at the index specified.\n * @param index The index of the item to be set as active.\n */\n setActiveItem(index: number): void;\n\n /**\n * Sets the active item to the specified item.\n * @param item The item to be set as active.\n */\n setActiveItem(item: T): void;\n\n setActiveItem(item: any): void {\n const previousActiveItem = this._activeItem;\n\n this.updateActiveItem(item);\n\n if (this._activeItem !== previousActiveItem) {\n this.change.next(this._activeItemIndex);\n }\n }\n\n /**\n * Sets the active item depending on the key event passed in.\n * @param event Keyboard event to be used for determining which element should be active.\n */\n onKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const modifiers: ListKeyManagerModifierKey[] = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];\n const isModifierAllowed = modifiers.every(modifier => {\n return !event[modifier] || this._allowedModifierKeys.indexOf(modifier) > -1;\n });\n\n switch (keyCode) {\n case TAB:\n this.tabOut.next();\n return;\n\n case DOWN_ARROW:\n if (this._vertical && isModifierAllowed) {\n this.setNextItemActive();\n break;\n } else {\n return;\n }\n\n case UP_ARROW:\n if (this._vertical && isModifierAllowed) {\n this.setPreviousItemActive();\n break;\n } else {\n return;\n }\n\n case RIGHT_ARROW:\n if (this._horizontal && isModifierAllowed) {\n this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();\n break;\n } else {\n return;\n }\n\n case LEFT_ARROW:\n if (this._horizontal && isModifierAllowed) {\n this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();\n break;\n } else {\n return;\n }\n\n case HOME:\n if (this._homeAndEnd && isModifierAllowed) {\n this.setFirstItemActive();\n break;\n } else {\n return;\n }\n\n case END:\n if (this._homeAndEnd && isModifierAllowed) {\n this.setLastItemActive();\n break;\n } else {\n return;\n }\n\n case PAGE_UP:\n if (this._pageUpAndDown.enabled && isModifierAllowed) {\n const targetIndex = this._activeItemIndex - this._pageUpAndDown.delta;\n this._setActiveItemByIndex(targetIndex > 0 ? targetIndex : 0, 1);\n break;\n } else {\n return;\n }\n\n case PAGE_DOWN:\n if (this._pageUpAndDown.enabled && isModifierAllowed) {\n const targetIndex = this._activeItemIndex + this._pageUpAndDown.delta;\n const itemsLength = this._getItemsArray().length;\n this._setActiveItemByIndex(targetIndex < itemsLength ? targetIndex : itemsLength - 1, -1);\n break;\n } else {\n return;\n }\n\n default:\n if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {\n // Attempt to use the `event.key` which also maps it to the user's keyboard language,\n // otherwise fall back to resolving alphanumeric characters via the keyCode.\n if (event.key && event.key.length === 1) {\n this._letterKeyStream.next(event.key.toLocaleUpperCase());\n } else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {\n this._letterKeyStream.next(String.fromCharCode(keyCode));\n }\n }\n\n // Note that we return here, in order to avoid preventing\n // the default action of non-navigational keys.\n return;\n }\n\n this._pressedLetters = [];\n event.preventDefault();\n }\n\n /** Index of the currently active item. */\n get activeItemIndex(): number | null {\n return this._activeItemIndex;\n }\n\n /** The active item. */\n get activeItem(): T | null {\n return this._activeItem;\n }\n\n /** Gets whether the user is currently typing into the manager using the typeahead feature. */\n isTyping(): boolean {\n return this._pressedLetters.length > 0;\n }\n\n /** Sets the active item to the first enabled item in the list. */\n setFirstItemActive(): void {\n this._setActiveItemByIndex(0, 1);\n }\n\n /** Sets the active item to the last enabled item in the list. */\n setLastItemActive(): void {\n this._setActiveItemByIndex(this._items.length - 1, -1);\n }\n\n /** Sets the active item to the next enabled item in the list. */\n setNextItemActive(): void {\n this._activeItemIndex < 0 ? this.setFirstItemActive() : this._setActiveItemByDelta(1);\n }\n\n /** Sets the active item to a previous enabled item in the list. */\n setPreviousItemActive(): void {\n this._activeItemIndex < 0 && this._wrap\n ? this.setLastItemActive()\n : this._setActiveItemByDelta(-1);\n }\n\n /**\n * Allows setting the active without any other effects.\n * @param index Index of the item to be set as active.\n */\n updateActiveItem(index: number): void;\n\n /**\n * Allows setting the active item without any other effects.\n * @param item Item to be set as active.\n */\n updateActiveItem(item: T): void;\n\n updateActiveItem(item: any): void {\n const itemArray = this._getItemsArray();\n const index = typeof item === 'number' ? item : itemArray.indexOf(item);\n const activeItem = itemArray[index];\n\n // Explicitly check for `null` and `undefined` because other falsy values are valid.\n this._activeItem = activeItem == null ? null : activeItem;\n this._activeItemIndex = index;\n }\n\n /** Cleans up the key manager. */\n destroy() {\n this._typeaheadSubscription.unsubscribe();\n this._itemChangesSubscription?.unsubscribe();\n this._letterKeyStream.complete();\n this.tabOut.complete();\n this.change.complete();\n this._pressedLetters = [];\n }\n\n /**\n * This method sets the active item, given a list of items and the delta between the\n * currently active item and the new active item. It will calculate differently\n * depending on whether wrap mode is turned on.\n */\n private _setActiveItemByDelta(delta: -1 | 1): void {\n this._wrap ? this._setActiveInWrapMode(delta) : this._setActiveInDefaultMode(delta);\n }\n\n /**\n * Sets the active item properly given \"wrap\" mode. In other words, it will continue to move\n * down the list until it finds an item that is not disabled, and it will wrap if it\n * encounters either end of the list.\n */\n private _setActiveInWrapMode(delta: -1 | 1): void {\n const items = this._getItemsArray();\n\n for (let i = 1; i <= items.length; i++) {\n const index = (this._activeItemIndex + delta * i + items.length) % items.length;\n const item = items[index];\n\n if (!this._skipPredicateFn(item)) {\n this.setActiveItem(index);\n return;\n }\n }\n }\n\n /**\n * Sets the active item properly given the default mode. In other words, it will\n * continue to move down the list until it finds an item that is not disabled. If\n * it encounters either end of the list, it will stop and not wrap.\n */\n private _setActiveInDefaultMode(delta: -1 | 1): void {\n this._setActiveItemByIndex(this._activeItemIndex + delta, delta);\n }\n\n /**\n * Sets the active item to the first enabled item starting at the index specified. If the\n * item is disabled, it will move in the fallbackDelta direction until it either\n * finds an enabled item or encounters the end of the list.\n */\n private _setActiveItemByIndex(index: number, fallbackDelta: -1 | 1): void {\n const items = this._getItemsArray();\n\n if (!items[index]) {\n return;\n }\n\n while (this._skipPredicateFn(items[index])) {\n index += fallbackDelta;\n\n if (!items[index]) {\n return;\n }\n }\n\n this.setActiveItem(index);\n }\n\n /** Returns the items as an array. */\n private _getItemsArray(): T[] {\n return this._items instanceof QueryList ? this._items.toArray() : this._items;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ListKeyManager, ListKeyManagerOption} from './list-key-manager';\nimport {FocusOrigin} from '../focus-monitor/focus-monitor';\n\n/**\n * This is the interface for focusable items (used by the FocusKeyManager).\n * Each item must know how to focus itself, whether or not it is currently disabled\n * and be able to supply its label.\n */\nexport interface FocusableOption extends ListKeyManagerOption {\n /** Focuses the `FocusableOption`. */\n focus(origin?: FocusOrigin): void;\n}\n\nexport class FocusKeyManager<T> extends ListKeyManager<FocusableOption & T> {\n private _origin: FocusOrigin = 'program';\n\n /**\n * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.\n * @param origin Focus origin to be used when focusing items.\n */\n setFocusOrigin(origin: FocusOrigin): this {\n this._origin = origin;\n return this;\n }\n\n /**\n * Sets the active item to the item at the specified\n * index and focuses the newly active item.\n * @param index Index of the item to be set as active.\n */\n override setActiveItem(index: number): void;\n\n /**\n * Sets the active item to the item that is specified and focuses it.\n * @param item Item to be set as active.\n */\n override setActiveItem(item: T): void;\n\n override setActiveItem(item: any): void {\n super.setActiveItem(item);\n\n if (this.activeItem) {\n this.activeItem.focus(this._origin);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Platform} from '@angular/cdk/platform';\nimport {Injectable} from '@angular/core';\n\n/**\n * Configuration for the isFocusable method.\n */\nexport class IsFocusableConfig {\n /**\n * Whether to count an element as focusable even if it is not currently visible.\n */\n ignoreVisibility: boolean = false;\n}\n\n// The InteractivityChecker leans heavily on the ally.js accessibility utilities.\n// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are\n// supported.\n\n/**\n * Utility for checking the interactivity of an element, such as whether is is focusable or\n * tabbable.\n */\n@Injectable({providedIn: 'root'})\nexport class InteractivityChecker {\n constructor(private _platform: Platform) {}\n\n /**\n * Gets whether an element is disabled.\n *\n * @param element Element to be checked.\n * @returns Whether the element is disabled.\n */\n isDisabled(element: HTMLElement): boolean {\n // This does not capture some cases, such as a non-form control with a disabled attribute or\n // a form control inside of a disabled form, but should capture the most common cases.\n return element.hasAttribute('disabled');\n }\n\n /**\n * Gets whether an element is visible for the purposes of interactivity.\n *\n * This will capture states like `display: none` and `visibility: hidden`, but not things like\n * being clipped by an `overflow: hidden` parent or being outside the viewport.\n *\n * @returns Whether the element is visible.\n */\n isVisible(element: HTMLElement): boolean {\n return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';\n }\n\n /**\n * Gets whether an element can be reached via Tab key.\n * Assumes that the element has already been checked with isFocusable.\n *\n * @param element Element to be checked.\n * @returns Whether the element is tabbable.\n */\n isTabbable(element: HTMLElement): boolean {\n // Nothing is tabbable on the server 😎\n if (!this._platform.isBrowser) {\n return false;\n }\n\n const frameElement = getFrameElement(getWindow(element));\n\n if (frameElement) {\n // Frame elements inherit their tabindex onto all child elements.\n if (getTabIndexValue(frameElement) === -1) {\n return false;\n }\n\n // Browsers disable tabbing to an element inside of an invisible frame.\n if (!this.isVisible(frameElement)) {\n return false;\n }\n }\n\n let nodeName = element.nodeName.toLowerCase();\n let tabIndexValue = getTabIndexValue(element);\n\n if (element.hasAttribute('contenteditable')) {\n return tabIndexValue !== -1;\n }\n\n if (nodeName === 'iframe' || nodeName === 'object') {\n // The frame or object's content may be tabbable depending on the content, but it's\n // not possibly to reliably detect the content of the frames. We always consider such\n // elements as non-tabbable.\n return false;\n }\n\n // In iOS, the browser only considers some specific elements as tabbable.\n if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {\n return false;\n }\n\n if (nodeName === 'audio') {\n // Audio elements without controls enabled are never tabbable, regardless\n // of the tabindex attribute explicitly being set.\n if (!element.hasAttribute('controls')) {\n return false;\n }\n // Audio elements with controls are by default tabbable unless the\n // tabindex attribute is set to `-1` explicitly.\n return tabIndexValue !== -1;\n }\n\n if (nodeName === 'video') {\n // For all video elements, if the tabindex attribute is set to `-1`, the video\n // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`\n // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The\n // tabindex attribute is the source of truth here.\n if (tabIndexValue === -1) {\n return false;\n }\n // If the tabindex is explicitly set, and not `-1` (as per check before), the\n // video element is always tabbable (regardless of whether it has controls or not).\n if (tabIndexValue !== null) {\n return true;\n }\n // Otherwise (when no explicit tabindex is set), a video is only tabbable if it\n // has controls enabled. Firefox is special as videos are always tabbable regardless\n // of whether there are controls or not.\n return this._platform.FIREFOX || element.hasAttribute('controls');\n }\n\n return element.tabIndex >= 0;\n }\n\n /**\n * Gets whether an element can be focused by the user.\n *\n * @param element Element to be checked.\n * @param config The config object with options to customize this method's behavior\n * @returns Whether the element is focusable.\n */\n isFocusable(element: HTMLElement, config?: IsFocusableConfig): boolean {\n // Perform checks in order of left to most expensive.\n // Again, naive approach that does not capture many edge cases and browser quirks.\n return (\n isPotentiallyFocusable(element) &&\n !this.isDisabled(element) &&\n (config?.ignoreVisibility || this.isVisible(element))\n );\n }\n}\n\n/**\n * Returns the frame element from a window object. Since browsers like MS Edge throw errors if\n * the frameElement property is being accessed from a different host address, this property\n * should be accessed carefully.\n */\nfunction getFrameElement(window: Window) {\n try {\n return window.frameElement as HTMLElement;\n } catch {\n return null;\n }\n}\n\n/** Checks whether the specified element has any geometry / rectangles. */\nfunction hasGeometry(element: HTMLElement): boolean {\n // Use logic from jQuery to check for an invisible element.\n // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12\n return !!(\n element.offsetWidth ||\n element.offsetHeight ||\n (typeof element.getClientRects === 'function' && element.getClientRects().length)\n );\n}\n\n/** Gets whether an element's */\nfunction isNativeFormElement(element: Node) {\n let nodeName = element.nodeName.toLowerCase();\n return (\n nodeName === 'input' ||\n nodeName === 'select' ||\n nodeName === 'button' ||\n nodeName === 'textarea'\n );\n}\n\n/** Gets whether an element is an `<input type=\"hidden\">`. */\nfunction isHiddenInput(element: HTMLElement): boolean {\n return isInputElement(element) && element.type == 'hidden';\n}\n\n/** Gets whether an element is an anchor that has an href attribute. */\nfunction isAnchorWithHref(element: HTMLElement): boolean {\n return isAnchorElement(element) && element.hasAttribute('href');\n}\n\n/** Gets whether an element is an input element. */\nfunction isInputElement(element: HTMLElement): element is HTMLInputElement {\n return element.nodeName.toLowerCase() == 'input';\n}\n\n/** Gets whether an element is an anchor element. */\nfunction isAnchorElement(element: HTMLElement): element is HTMLAnchorElement {\n return element.nodeName.toLowerCase() == 'a';\n}\n\n/** Gets whether an element has a valid tabindex. */\nfunction hasValidTabIndex(element: HTMLElement): boolean {\n if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {\n return false;\n }\n\n let tabIndex = element.getAttribute('tabindex');\n return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));\n}\n\n/**\n * Returns the parsed tabindex from the element attributes instead of returning the\n * evaluated tabindex from the browsers defaults.\n */\nfunction getTabIndexValue(element: HTMLElement): number | null {\n if (!hasValidTabIndex(element)) {\n return null;\n }\n\n // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054\n const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);\n\n return isNaN(tabIndex) ? -1 : tabIndex;\n}\n\n/** Checks whether the specified element is potentially tabbable on iOS */\nfunction isPotentiallyTabbableIOS(element: HTMLElement): boolean {\n let nodeName = element.nodeName.toLowerCase();\n let inputType = nodeName === 'input' && (element as HTMLInputElement).type;\n\n return (\n inputType === 'text' ||\n inputType === 'password' ||\n nodeName === 'select' ||\n nodeName === 'textarea'\n );\n}\n\n/**\n * Gets whether an element is potentially focusable without taking current visible/disabled state\n * into account.\n */\nfunction isPotentiallyFocusable(element: HTMLElement): boolean {\n // Inputs are potentially focusable *unless* they're type=\"hidden\".\n if (isHiddenInput(element)) {\n return false;\n }\n\n return (\n isNativeFormElement(element) ||\n isAnchorWithHref(element) ||\n element.hasAttribute('contenteditable') ||\n hasValidTabIndex(element)\n );\n}\n\n/** Gets the parent window of a DOM node with regards of being inside of an iframe. */\nfunction getWindow(node: HTMLElement): Window {\n // ownerDocument is null if `node` itself *is* a document.\n return (node.ownerDocument && node.ownerDocument.defaultView) || window;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, OnDestroy, APP_ID, inject} from '@angular/core';\nimport {Platform} from '@angular/cdk/platform';\nimport {addAriaReferencedId, getAriaReferenceIds, removeAriaReferencedId} from './aria-reference';\n\n/**\n * Interface used to register message elements and keep a count of how many registrations have\n * the same message and the reference to the message element used for the `aria-describedby`.\n */\nexport interface RegisteredMessage {\n /** The element containing the message. */\n messageElement: Element;\n\n /** The number of elements that reference this message element via `aria-describedby`. */\n referenceCount: number;\n}\n\n/**\n * ID used for the body container where all messages are appended.\n * @deprecated No longer being used. To be removed.\n * @breaking-change 14.0.0\n */\nexport const MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';\n\n/**\n * ID prefix used for each created message element.\n * @deprecated To be turned into a private variable.\n * @breaking-change 14.0.0\n */\nexport const CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';\n\n/**\n * Attribute given to each host element that is described by a message element.\n * @deprecated To be turned into a private variable.\n * @breaking-change 14.0.0\n */\nexport const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';\n\n/** Global incremental identifier for each registered message element. */\nlet nextId = 0;\n\n/**\n * Utility that creates visually hidden elements with a message content. Useful for elements that\n * want to use aria-describedby to further describe themselves without adding additional visual\n * content.\n */\n@Injectable({providedIn: 'root'})\nexport class AriaDescriber implements OnDestroy {\n private _document: Document;\n\n /** Map of all registered message elements that have been placed into the document. */\n private _messageRegistry = new Map<string | Element, RegisteredMessage>();\n\n /** Container for all registered messages. */\n private _messagesContainer: HTMLElement | null = null;\n\n /** Unique ID for the service. */\n private readonly _id = `${nextId++}`;\n\n constructor(\n @Inject(DOCUMENT) _document: any,\n /**\n * @deprecated To be turned into a required parameter.\n * @breaking-change 14.0.0\n */\n private _platform?: Platform,\n ) {\n this._document = _document;\n this._id = inject(APP_ID) + '-' + nextId++;\n }\n\n /**\n * Adds to the host element an aria-describedby reference to a hidden element that contains\n * the message. If the same message has already been registered, then it will reuse the created\n * message element.\n */\n describe(hostElement: Element, message: string, role?: string): void;\n\n /**\n * Adds to the host element an aria-describedby reference to an already-existing message element.\n */\n describe(hostElement: Element, message: HTMLElement): void;\n\n describe(hostElement: Element, message: string | HTMLElement, role?: string): void {\n if (!this._canBeDescribed(hostElement, message)) {\n return;\n }\n\n const key = getKey(message, role);\n\n if (typeof message !== 'string') {\n // We need to ensure that the element has an ID.\n setMessageId(message, this._id);\n this._messageRegistry.set(key, {messageElement: message, referenceCount: 0});\n } else if (!this._messageRegistry.has(key)) {\n this._createMessageElement(message, role);\n }\n\n if (!this._isElementDescribedByMessage(hostElement, key)) {\n this._addMessageReference(hostElement, key);\n }\n }\n\n /** Removes the host element's aria-describedby reference to the message. */\n removeDescription(hostElement: Element, message: string, role?: string): void;\n\n /** Removes the host element's aria-describedby reference to the message element. */\n removeDescription(hostElement: Element, message: HTMLElement): void;\n\n removeDescription(hostElement: Element, message: string | HTMLElement, role?: string): void {\n if (!message || !this._isElementNode(hostElement)) {\n return;\n }\n\n const key = getKey(message, role);\n\n if (this._isElementDescribedByMessage(hostElement, key)) {\n this._removeMessageReference(hostElement, key);\n }\n\n // If the message is a string, it means that it's one that we created for the\n // consumer so we can remove it safely, otherwise we should leave it in place.\n if (typeof message === 'string') {\n const registeredMessage = this._messageRegistry.get(key);\n if (registeredMessage && registeredMessage.referenceCount === 0) {\n this._deleteMessageElement(key);\n }\n }\n\n if (this._messagesContainer?.childNodes.length === 0) {\n this._messagesContainer.remove();\n this._messagesContainer = null;\n }\n }\n\n /** Unregisters all created message elements and removes the message container. */\n ngOnDestroy() {\n const describedElements = this._document.querySelectorAll(\n `[${CDK_DESCRIBEDBY_HOST_ATTRIBUTE}=\"${this._id}\"]`,\n );\n\n for (let i = 0; i < describedElements.length; i++) {\n this._removeCdkDescribedByReferenceIds(describedElements[i]);\n describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);\n }\n\n this._messagesContainer?.remove();\n this._messagesContainer = null;\n this._messageRegistry.clear();\n }\n\n /**\n * Creates a new element in the visually hidden message container element with the message\n * as its content and adds it to the message registry.\n */\n private _createMessageElement(message: string, role?: string) {\n const messageElement = this._document.createElement('div');\n setMessageId(messageElement, this._id);\n messageElement.textContent = message;\n\n if (role) {\n messageElement.setAttribute('role', role);\n }\n\n this._createMessagesContainer();\n this._messagesContainer!.appendChild(messageElement);\n this._messageRegistry.set(getKey(message, role), {messageElement, referenceCount: 0});\n }\n\n /** Deletes the message element from the global messages container. */\n private _deleteMessageElement(key: string | Element) {\n this._messageRegistry.get(key)?.messageElement?.remove();\n this._messageRegistry.delete(key);\n }\n\n /** Creates the global container for all aria-describedby messages. */\n private _createMessagesContainer() {\n if (this._messagesContainer) {\n return;\n }\n\n const containerClassName = 'cdk-describedby-message-container';\n const serverContainers = this._document.querySelectorAll(\n `.${containerClassName}[platform=\"server\"]`,\n );\n\n for (let i = 0; i < serverContainers.length; i++) {\n // When going from the server to the client, we may end up in a situation where there's\n // already a container on the page, but we don't have a reference to it. Clear the\n // old container so we don't get duplicates. Doing this, instead of emptying the previous\n // container, should be slightly faster.\n serverContainers[i].remove();\n }\n\n const messagesContainer = this._document.createElement('div');\n\n // We add `visibility: hidden` in order to prevent text in this container from\n // being searchable by the browser's Ctrl + F functionality.\n // Screen-readers will still read the description for elements with aria-describedby even\n // when the description element is not visible.\n messagesContainer.style.visibility = 'hidden';\n // Even though we use `visibility: hidden`, we still apply `cdk-visually-hidden` so that\n // the description element doesn't impact page layout.\n messagesContainer.classList.add(containerClassName);\n messagesContainer.classList.add('cdk-visually-hidden');\n\n // @breaking-change 14.0.0 Remove null check for `_platform`.\n if (this._platform && !this._platform.isBrowser) {\n messagesContainer.setAttribute('platform', 'server');\n }\n\n this._document.body.appendChild(messagesContainer);\n this._messagesContainer = messagesContainer;\n }\n\n /** Removes all cdk-describedby messages that are hosted through the element. */\n private _removeCdkDescribedByReferenceIds(element: Element) {\n // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX\n const originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby').filter(\n id => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0,\n );\n element.setAttribute('aria-describedby', originalReferenceIds.join(' '));\n }\n\n /**\n * Adds a message reference to the element using aria-describedby and increments the registered\n * message's reference count.\n */\n private _addMessageReference(element: Element, key: string | Element) {\n const registeredMessage = this._messageRegistry.get(key)!;\n\n // Add the aria-describedby reference and set the\n // describedby_host attribute to mark the element.\n addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);\n element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, this._id);\n registeredMessage.referenceCount++;\n }\n\n /**\n * Removes a message reference from the element using aria-describedby\n * and decrements the registered message's reference count.\n */\n private _removeMessageReference(element: Element, key: string | Element) {\n const registeredMessage = this._messageRegistry.get(key)!;\n registeredMessage.referenceCount--;\n\n removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);\n element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);\n }\n\n /** Returns true if the element has been described by the provided message ID. */\n private _isElementDescribedByMessage(element: Element, key: string | Element): boolean {\n const referenceIds = getAriaReferenceIds(element, 'aria-describedby');\n const registeredMessage = this._messageRegistry.get(key);\n const messageId = registeredMessage && registeredMessage.messageElement.id;\n\n return !!messageId && referenceIds.indexOf(messageId) != -1;\n }\n\n /** Determines whether a message can be described on a particular element. */\n private _canBeDescribed(element: Element, message: string | HTMLElement | void): boolean {\n if (!this._isElementNode(element)) {\n return false;\n }\n\n if (message && typeof message === 'object') {\n // We'd have to make some assumptions about the description element's text, if the consumer\n // passed in an element. Assume that if an element is passed in, the consumer has verified\n // that it can be used as a description.\n return true;\n }\n\n const trimmedMessage = message == null ? '' : `${message}`.trim();\n const ariaLabel = element.getAttribute('aria-label');\n\n // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the\n // element, because screen readers will end up reading out the same text twice in a row.\n return trimmedMessage ? !ariaLabel || ariaLabel.trim() !== trimmedMessage : false;\n }\n\n /** Checks whether a node is an Element node. */\n private _isElementNode(element: Node): element is Element {\n return element.nodeType === this._document.ELEMENT_NODE;\n }\n}\n\n/** Gets a key that can be used to look messages up in the registry. */\nfunction getKey(message: string | Element, role?: string): string | Element {\n return typeof message === 'string' ? `${role || ''}/${message}` : message;\n}\n\n/** Assigns a unique ID to an element, if it doesn't have one already. */\nfunction setMessageId(element: HTMLElement, serviceId: string) {\n if (!element.id) {\n element.id = `${CDK_DESCRIBEDBY_ID_PREFIX}-${serviceId}-${nextId++}`;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {_getFocusedElementPierceShadowDom} from '@angular/cdk/platform';\nimport {DOCUMENT} from '@angular/common';\nimport {\n AfterContentInit,\n Directive,\n ElementRef,\n Inject,\n Injectable,\n Input,\n NgZone,\n OnDestroy,\n DoCheck,\n SimpleChanges,\n OnChanges,\n} from '@angular/core';\nimport {take} from 'rxjs/operators';\nimport {InteractivityChecker} from '../interactivity-checker/interactivity-checker';\n\n/**\n * Class that allows for trapping focus within a DOM element.\n *\n * This class currently uses a relatively simple approach to focus trapping.\n * It assumes that the tab order is the same as DOM order, which is not necessarily true.\n * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to be misaligned.\n *\n * @deprecated Use `ConfigurableFocusTrap` instead.\n * @breaking-change 11.0.0\n */\nexport class FocusTrap {\n private _startAnchor: HTMLElement | null;\n private _endAnchor: HTMLElement | null;\n private _hasAttached = false;\n\n // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.\n protected startAnchorListener = () => this.focusLastTabbableElement();\n protected endAnchorListener = () => this.focusFirstTabbableElement();\n\n /** Whether the focus trap is active. */\n get enabled(): boolean {\n return this._enabled;\n }\n set enabled(value: boolean) {\n this._enabled = value;\n\n if (this._startAnchor && this._endAnchor) {\n this._toggleAnchorTabIndex(value, this._startAnchor);\n this._toggleAnchorTabIndex(value, this._endAnchor);\n }\n }\n protected _enabled: boolean = true;\n\n constructor(\n readonly _element: HTMLElement,\n private _checker: InteractivityChecker,\n readonly _ngZone: NgZone,\n readonly _document: Document,\n deferAnchors = false,\n ) {\n if (!deferAnchors) {\n this.attachAnchors();\n }\n }\n\n /** Destroys the focus trap by cleaning up the anchors. */\n destroy() {\n const startAnchor = this._startAnchor;\n const endAnchor = this._endAnchor;\n\n if (startAnchor) {\n startAnchor.removeEventListener('focus', this.startAnchorListener);\n startAnchor.remove();\n }\n\n if (endAnchor) {\n endAnchor.removeEventListener('focus', this.endAnchorListener);\n endAnchor.remove();\n }\n\n this._startAnchor = this._endAnchor = null;\n this._hasAttached = false;\n }\n\n /**\n * Inserts the anchors into the DOM. This is usually done automatically\n * in the constructor, but can be deferred for cases like directives with `*ngIf`.\n * @returns Whether the focus trap managed to attach successfully. This may not be the case\n * if the target element isn't currently in the DOM.\n */\n attachAnchors(): boolean {\n // If we're not on the browser, there can be no focus to trap.\n if (this._hasAttached) {\n return true;\n }\n\n this._ngZone.runOutsideAngular(() => {\n if (!this._startAnchor) {\n this._startAnchor = this._createAnchor();\n this._startAnchor!.addEventListener('focus', this.startAnchorListener);\n }\n\n if (!this._endAnchor) {\n this._endAnchor = this._createAnchor();\n this._endAnchor!.addEventListener('focus', this.endAnchorListener);\n }\n });\n\n if (this._element.parentNode) {\n this._element.parentNode.insertBefore(this._startAnchor!, this._element);\n this._element.parentNode.insertBefore(this._endAnchor!, this._element.nextSibling);\n this._hasAttached = true;\n }\n\n return this._hasAttached;\n }\n\n /**\n * Waits for the zone to stabilize, then focuses the first tabbable element.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n focusInitialElementWhenReady(options?: FocusOptions): Promise<boolean> {\n return new Promise<boolean>(resolve => {\n this._executeOnStable(() => resolve(this.focusInitialElement(options)));\n });\n }\n\n /**\n * Waits for the zone to stabilize, then focuses\n * the first tabbable element within the focus trap region.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n focusFirstTabbableElementWhenReady(options?: FocusOptions): Promise<boolean> {\n return new Promise<boolean>(resolve => {\n this._executeOnStable(() => resolve(this.focusFirstTabbableElement(options)));\n });\n }\n\n /**\n * Waits for the zone to stabilize, then focuses\n * the last tabbable element within the focus trap region.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n focusLastTabbableElementWhenReady(options?: FocusOptions): Promise<boolean> {\n return new Promise<boolean>(resolve => {\n this._executeOnStable(() => resolve(this.focusLastTabbableElement(options)));\n });\n }\n\n /**\n * Get the specified boundary element of the trapped region.\n * @param bound The boundary to get (start or end of trapped region).\n * @returns The boundary element.\n */\n private _getRegionBoundary(bound: 'start' | 'end'): HTMLElement | null {\n // Contains the deprecated version of selector, for temporary backwards comparability.\n const markers = this._element.querySelectorAll(\n `[cdk-focus-region-${bound}], ` + `[cdkFocusRegion${bound}], ` + `[cdk-focus-${bound}]`,\n ) as NodeListOf<HTMLElement>;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n for (let i = 0; i < markers.length; i++) {\n // @breaking-change 8.0.0\n if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {\n console.warn(\n `Found use of deprecated attribute 'cdk-focus-${bound}', ` +\n `use 'cdkFocusRegion${bound}' instead. The deprecated ` +\n `attribute will be removed in 8.0.0.`,\n markers[i],\n );\n } else if (markers[i].hasAttribute(`cdk-focus-region-${bound}`)) {\n console.warn(\n `Found use of deprecated attribute 'cdk-focus-region-${bound}', ` +\n `use 'cdkFocusRegion${bound}' instead. The deprecated attribute ` +\n `will be removed in 8.0.0.`,\n markers[i],\n );\n }\n }\n }\n\n if (bound == 'start') {\n return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);\n }\n return markers.length\n ? markers[markers.length - 1]\n : this._getLastTabbableElement(this._element);\n }\n\n /**\n * Focuses the element that should be focused when the focus trap is initialized.\n * @returns Whether focus was moved successfully.\n */\n focusInitialElement(options?: FocusOptions): boolean {\n // Contains the deprecated version of selector, for temporary backwards comparability.\n const redirectToElement = this._element.querySelector(\n `[cdk-focus-initial], ` + `[cdkFocusInitial]`,\n ) as HTMLElement;\n\n if (redirectToElement) {\n // @breaking-change 8.0.0\n if (\n (typeof ngDevMode === 'undefined' || ngDevMode) &&\n redirectToElement.hasAttribute(`cdk-focus-initial`)\n ) {\n console.warn(\n `Found use of deprecated attribute 'cdk-focus-initial', ` +\n `use 'cdkFocusInitial' instead. The deprecated attribute ` +\n `will be removed in 8.0.0`,\n redirectToElement,\n );\n }\n\n // Warn the consumer if the element they've pointed to\n // isn't focusable, when not in production mode.\n if (\n (typeof ngDevMode === 'undefined' || ngDevMode) &&\n !this._checker.isFocusable(redirectToElement)\n ) {\n console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);\n }\n\n if (!this._checker.isFocusable(redirectToElement)) {\n const focusableChild = this._getFirstTabbableElement(redirectToElement) as HTMLElement;\n focusableChild?.focus(options);\n return !!focusableChild;\n }\n\n redirectToElement.focus(options);\n return true;\n }\n\n return this.focusFirstTabbableElement(options);\n }\n\n /**\n * Focuses the first tabbable element within the focus trap region.\n * @returns Whether focus was moved successfully.\n */\n focusFirstTabbableElement(options?: FocusOptions): boolean {\n const redirectToElement = this._getRegionBoundary('start');\n\n if (redirectToElement) {\n redirectToElement.focus(options);\n }\n\n return !!redirectToElement;\n }\n\n /**\n * Focuses the last tabbable element within the focus trap region.\n * @returns Whether focus was moved successfully.\n */\n focusLastTabbableElement(options?: FocusOptions): boolean {\n const redirectToElement = this._getRegionBoundary('end');\n\n if (redirectToElement) {\n redirectToElement.focus(options);\n }\n\n return !!redirectToElement;\n }\n\n /**\n * Checks whether the focus trap has successfully been attached.\n */\n hasAttached(): boolean {\n return this._hasAttached;\n }\n\n /** Get the first tabbable element from a DOM subtree (inclusive). */\n private _getFirstTabbableElement(root: HTMLElement): HTMLElement | null {\n if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {\n return root;\n }\n\n const children = root.children;\n\n for (let i = 0; i < children.length; i++) {\n const tabbableChild =\n children[i].nodeType === this._document.ELEMENT_NODE\n ? this._getFirstTabbableElement(children[i] as HTMLElement)\n : null;\n\n if (tabbableChild) {\n return tabbableChild;\n }\n }\n\n return null;\n }\n\n /** Get the last tabbable element from a DOM subtree (inclusive). */\n private _getLastTabbableElement(root: HTMLElement): HTMLElement | null {\n if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {\n return root;\n }\n\n // Iterate in reverse DOM order.\n const children = root.children;\n\n for (let i = children.length - 1; i >= 0; i--) {\n const tabbableChild =\n children[i].nodeType === this._document.ELEMENT_NODE\n ? this._getLastTabbableElement(children[i] as HTMLElement)\n : null;\n\n if (tabbableChild) {\n return tabbableChild;\n }\n }\n\n return null;\n }\n\n /** Creates an anchor element. */\n private _createAnchor(): HTMLElement {\n const anchor = this._document.createElement('div');\n this._toggleAnchorTabIndex(this._enabled, anchor);\n anchor.classList.add('cdk-visually-hidden');\n anchor.classList.add('cdk-focus-trap-anchor');\n anchor.setAttribute('aria-hidden', 'true');\n return anchor;\n }\n\n /**\n * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.\n * @param isEnabled Whether the focus trap is enabled.\n * @param anchor Anchor on which to toggle the tabindex.\n */\n private _toggleAnchorTabIndex(isEnabled: boolean, anchor: HTMLElement) {\n // Remove the tabindex completely, rather than setting it to -1, because if the\n // element has a tabindex, the user might still hit it when navigating with the arrow keys.\n isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');\n }\n\n /**\n * Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.\n * @param enabled: Whether the anchors should trap Tab.\n */\n protected toggleAnchors(enabled: boolean) {\n if (this._startAnchor && this._endAnchor) {\n this._toggleAnchorTabIndex(enabled, this._startAnchor);\n this._toggleAnchorTabIndex(enabled, this._endAnchor);\n }\n }\n\n /** Executes a function when the zone is stable. */\n private _executeOnStable(fn: () => any): void {\n if (this._ngZone.isStable) {\n fn();\n } else {\n this._ngZone.onStable.pipe(take(1)).subscribe(fn);\n }\n }\n}\n\n/**\n * Factory that allows easy instantiation of focus traps.\n * @deprecated Use `ConfigurableFocusTrapFactory` instead.\n * @breaking-change 11.0.0\n */\n@Injectable({providedIn: 'root'})\nexport class FocusTrapFactory {\n private _document: Document;\n\n constructor(\n private _checker: InteractivityChecker,\n private _ngZone: NgZone,\n @Inject(DOCUMENT) _document: any,\n ) {\n this._document = _document;\n }\n\n /**\n * Creates a focus-trapped region around the given element.\n * @param element The element around which focus will be trapped.\n * @param deferCaptureElements Defers the creation of focus-capturing elements to be done\n * manually by the user.\n * @returns The created focus trap instance.\n */\n create(element: HTMLElement, deferCaptureElements: boolean = false): FocusTrap {\n return new FocusTrap(\n element,\n this._checker,\n this._ngZone,\n this._document,\n deferCaptureElements,\n );\n }\n}\n\n/** Directive for trapping focus within a region. */\n@Directive({\n selector: '[cdkTrapFocus]',\n exportAs: 'cdkTrapFocus',\n})\nexport class CdkTrapFocus implements OnDestroy, AfterContentInit, OnChanges, DoCheck {\n /** Underlying FocusTrap instance. */\n focusTrap: FocusTrap;\n\n /** Previously focused element to restore focus to upon destroy when using autoCapture. */\n private _previouslyFocusedElement: HTMLElement | null = null;\n\n /** Whether the focus trap is active. */\n @Input('cdkTrapFocus')\n get enabled(): boolean {\n return this.focusTrap.enabled;\n }\n set enabled(value: BooleanInput) {\n this.focusTrap.enabled = coerceBooleanProperty(value);\n }\n\n /**\n * Whether the directive should automatically move focus into the trapped region upon\n * initialization and return focus to the previous activeElement upon destruction.\n */\n @Input('cdkTrapFocusAutoCapture')\n get autoCapture(): boolean {\n return this._autoCapture;\n }\n set autoCapture(value: BooleanInput) {\n this._autoCapture = coerceBooleanProperty(value);\n }\n private _autoCapture: boolean;\n\n constructor(\n private _elementRef: ElementRef<HTMLElement>,\n private _focusTrapFactory: FocusTrapFactory,\n /**\n * @deprecated No longer being used. To be removed.\n * @breaking-change 13.0.0\n */\n @Inject(DOCUMENT) _document: any,\n ) {\n this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);\n }\n\n ngOnDestroy() {\n this.focusTrap.destroy();\n\n // If we stored a previously focused element when using autoCapture, return focus to that\n // element now that the trapped region is being destroyed.\n if (this._previouslyFocusedElement) {\n this._previouslyFocusedElement.focus();\n this._previouslyFocusedElement = null;\n }\n }\n\n ngAfterContentInit() {\n this.focusTrap.attachAnchors();\n\n if (this.autoCapture) {\n this._captureFocus();\n }\n }\n\n ngDoCheck() {\n if (!this.focusTrap.hasAttached()) {\n this.focusTrap.attachAnchors();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n const autoCaptureChange = changes['autoCapture'];\n\n if (\n autoCaptureChange &&\n !autoCaptureChange.firstChange &&\n this.autoCapture &&\n this.focusTrap.hasAttached()\n ) {\n this._captureFocus();\n }\n }\n\n private _captureFocus() {\n this._previouslyFocusedElement = _getFocusedElementPierceShadowDom();\n this.focusTrap.focusInitialElementWhenReady();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Gets whether an event could be a faked `mousedown` event dispatched by a screen reader. */\nexport function isFakeMousedownFromScreenReader(event: MouseEvent): boolean {\n // Some screen readers will dispatch a fake `mousedown` event when pressing enter or space on\n // a clickable element. We can distinguish these events when both `offsetX` and `offsetY` are\n // zero or `event.buttons` is zero, depending on the browser:\n // - `event.buttons` works on Firefox, but fails on Chrome.\n // - `offsetX` and `offsetY` work on Chrome, but fail on Firefox.\n // Note that there's an edge case where the user could click the 0x0 spot of the\n // screen themselves, but that is unlikely to contain interactive elements.\n return event.buttons === 0 || (event.offsetX === 0 && event.offsetY === 0);\n}\n\n/** Gets whether an event could be a faked `touchstart` event dispatched by a screen reader. */\nexport function isFakeTouchstartFromScreenReader(event: TouchEvent): boolean {\n const touch: Touch | undefined =\n (event.touches && event.touches[0]) || (event.changedTouches && event.changedTouches[0]);\n\n // A fake `touchstart` can be distinguished from a real one by looking at the `identifier`\n // which is typically >= 0 on a real device versus -1 from a screen reader. Just to be safe,\n // we can also look at `radiusX` and `radiusY`. This behavior was observed against a Windows 10\n // device with a touch screen running NVDA v2020.4 and Firefox 85 or Chrome 88.\n return (\n !!touch &&\n touch.identifier === -1 &&\n (touch.radiusX == null || touch.radiusX === 1) &&\n (touch.radiusY == null || touch.radiusY === 1)\n );\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ALT, CONTROL, MAC_META, META, SHIFT} from '@angular/cdk/keycodes';\nimport {Inject, Injectable, InjectionToken, OnDestroy, Optional, NgZone} from '@angular/core';\nimport {normalizePassiveListenerOptions, Platform, _getEventTarget} from '@angular/cdk/platform';\nimport {DOCUMENT} from '@angular/common';\nimport {BehaviorSubject, Observable} from 'rxjs';\nimport {distinctUntilChanged, skip} from 'rxjs/operators';\nimport {\n isFakeMousedownFromScreenReader,\n isFakeTouchstartFromScreenReader,\n} from '../fake-event-detection';\n\n/**\n * The input modalities detected by this service. Null is used if the input modality is unknown.\n */\nexport type InputModality = 'keyboard' | 'mouse' | 'touch' | null;\n\n/** Options to configure the behavior of the InputModalityDetector. */\nexport interface InputModalityDetectorOptions {\n /** Keys to ignore when detecting keyboard input modality. */\n ignoreKeys?: number[];\n}\n\n/**\n * Injectable options for the InputModalityDetector. These are shallowly merged with the default\n * options.\n */\nexport const INPUT_MODALITY_DETECTOR_OPTIONS = new InjectionToken<InputModalityDetectorOptions>(\n 'cdk-input-modality-detector-options',\n);\n\n/**\n * Default options for the InputModalityDetector.\n *\n * Modifier keys are ignored by default (i.e. when pressed won't cause the service to detect\n * keyboard input modality) for two reasons:\n *\n * 1. Modifier keys are commonly used with mouse to perform actions such as 'right click' or 'open\n * in new tab', and are thus less representative of actual keyboard interaction.\n * 2. VoiceOver triggers some keyboard events when linearly navigating with Control + Option (but\n * confusingly not with Caps Lock). Thus, to have parity with other screen readers, we ignore\n * these keys so as to not update the input modality.\n *\n * Note that we do not by default ignore the right Meta key on Safari because it has the same key\n * code as the ContextMenu key on other browsers. When we switch to using event.key, we can\n * distinguish between the two.\n */\nexport const INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS: InputModalityDetectorOptions = {\n ignoreKeys: [ALT, CONTROL, MAC_META, META, SHIFT],\n};\n\n/**\n * The amount of time needed to pass after a touchstart event in order for a subsequent mousedown\n * event to be attributed as mouse and not touch.\n *\n * This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found\n * that a value of around 650ms seems appropriate.\n */\nexport const TOUCH_BUFFER_MS = 650;\n\n/**\n * Event listener options that enable capturing and also mark the listener as passive if the browser\n * supports it.\n */\nconst modalityEventListenerOptions = normalizePassiveListenerOptions({\n passive: true,\n capture: true,\n});\n\n/**\n * Service that detects the user's input modality.\n *\n * This service does not update the input modality when a user navigates with a screen reader\n * (e.g. linear navigation with VoiceOver, object navigation / browse mode with NVDA, virtual PC\n * cursor mode with JAWS). This is in part due to technical limitations (i.e. keyboard events do not\n * fire as expected in these modes) but is also arguably the correct behavior. Navigating with a\n * screen reader is akin to visually scanning a page, and should not be interpreted as actual user\n * input interaction.\n *\n * When a user is not navigating but *interacting* with a screen reader, this service attempts to\n * update the input modality to keyboard, but in general this service's behavior is largely\n * undefined.\n */\n@Injectable({providedIn: 'root'})\nexport class InputModalityDetector implements OnDestroy {\n /** Emits whenever an input modality is detected. */\n readonly modalityDetected: Observable<InputModality>;\n\n /** Emits when the input modality changes. */\n readonly modalityChanged: Observable<InputModality>;\n\n /** The most recently detected input modality. */\n get mostRecentModality(): InputModality {\n return this._modality.value;\n }\n\n /**\n * The most recently detected input modality event target. Is null if no input modality has been\n * detected or if the associated event target is null for some unknown reason.\n */\n _mostRecentTarget: HTMLElement | null = null;\n\n /** The underlying BehaviorSubject that emits whenever an input modality is detected. */\n private readonly _modality = new BehaviorSubject<InputModality>(null);\n\n /** Options for this InputModalityDetector. */\n private readonly _options: InputModalityDetectorOptions;\n\n /**\n * The timestamp of the last touch input modality. Used to determine whether mousedown events\n * should be attributed to mouse or touch.\n */\n private _lastTouchMs = 0;\n\n /**\n * Handles keydown events. Must be an arrow function in order to preserve the context when it gets\n * bound.\n */\n private _onKeydown = (event: KeyboardEvent) => {\n // If this is one of the keys we should ignore, then ignore it and don't update the input\n // modality to keyboard.\n if (this._options?.ignoreKeys?.some(keyCode => keyCode === event.keyCode)) {\n return;\n }\n\n this._modality.next('keyboard');\n this._mostRecentTarget = _getEventTarget(event);\n };\n\n /**\n * Handles mousedown events. Must be an arrow function in order to preserve the context when it\n * gets bound.\n */\n private _onMousedown = (event: MouseEvent) => {\n // Touches trigger both touch and mouse events, so we need to distinguish between mouse events\n // that were triggered via mouse vs touch. To do so, check if the mouse event occurs closely\n // after the previous touch event.\n if (Date.now() - this._lastTouchMs < TOUCH_BUFFER_MS) {\n return;\n }\n\n // Fake mousedown events are fired by some screen readers when controls are activated by the\n // screen reader. Attribute them to keyboard input modality.\n this._modality.next(isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse');\n this._mostRecentTarget = _getEventTarget(event);\n };\n\n /**\n * Handles touchstart events. Must be an arrow function in order to preserve the context when it\n * gets bound.\n */\n private _onTouchstart = (event: TouchEvent) => {\n // Same scenario as mentioned in _onMousedown, but on touch screen devices, fake touchstart\n // events are fired. Again, attribute to keyboard input modality.\n if (isFakeTouchstartFromScreenReader(event)) {\n this._modality.next('keyboard');\n return;\n }\n\n // Store the timestamp of this touch event, as it's used to distinguish between mouse events\n // triggered via mouse vs touch.\n this._lastTouchMs = Date.now();\n\n this._modality.next('touch');\n this._mostRecentTarget = _getEventTarget(event);\n };\n\n constructor(\n private readonly _platform: Platform,\n ngZone: NgZone,\n @Inject(DOCUMENT) document: Document,\n @Optional()\n @Inject(INPUT_MODALITY_DETECTOR_OPTIONS)\n options?: InputModalityDetectorOptions,\n ) {\n this._options = {\n ...INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS,\n ...options,\n };\n\n // Skip the first emission as it's null.\n this.modalityDetected = this._modality.pipe(skip(1));\n this.modalityChanged = this.modalityDetected.pipe(distinctUntilChanged());\n\n // If we're not in a browser, this service should do nothing, as there's no relevant input\n // modality to detect.\n if (_platform.isBrowser) {\n ngZone.runOutsideAngular(() => {\n document.addEventListener('keydown', this._onKeydown, modalityEventListenerOptions);\n document.addEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);\n document.addEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);\n });\n }\n }\n\n ngOnDestroy() {\n this._modality.complete();\n\n if (this._platform.isBrowser) {\n document.removeEventListener('keydown', this._onKeydown, modalityEventListenerOptions);\n document.removeEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);\n document.removeEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n Platform,\n normalizePassiveListenerOptions,\n _getShadowRoot,\n _getEventTarget,\n} from '@angular/cdk/platform';\nimport {\n Directive,\n ElementRef,\n EventEmitter,\n Inject,\n Injectable,\n InjectionToken,\n NgZone,\n OnDestroy,\n Optional,\n Output,\n AfterViewInit,\n} from '@angular/core';\nimport {Observable, of as observableOf, Subject, Subscription} from 'rxjs';\nimport {takeUntil} from 'rxjs/operators';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {DOCUMENT} from '@angular/common';\nimport {InputModalityDetector, TOUCH_BUFFER_MS} from '../input-modality/input-modality-detector';\n\nexport type FocusOrigin = 'touch' | 'mouse' | 'keyboard' | 'program' | null;\n\n/**\n * Corresponds to the options that can be passed to the native `focus` event.\n * via https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus\n */\nexport interface FocusOptions {\n /** Whether the browser should scroll to the element when it is focused. */\n preventScroll?: boolean;\n}\n\n/** Detection mode used for attributing the origin of a focus event. */\nexport const enum FocusMonitorDetectionMode {\n /**\n * Any mousedown, keydown, or touchstart event that happened in the previous\n * tick or the current tick will be used to assign a focus event's origin (to\n * either mouse, keyboard, or touch). This is the default option.\n */\n IMMEDIATE,\n /**\n * A focus event's origin is always attributed to the last corresponding\n * mousedown, keydown, or touchstart event, no matter how long ago it occurred.\n */\n EVENTUAL,\n}\n\n/** Injectable service-level options for FocusMonitor. */\nexport interface FocusMonitorOptions {\n detectionMode?: FocusMonitorDetectionMode;\n}\n\n/** InjectionToken for FocusMonitorOptions. */\nexport const FOCUS_MONITOR_DEFAULT_OPTIONS = new InjectionToken<FocusMonitorOptions>(\n 'cdk-focus-monitor-default-options',\n);\n\ntype MonitoredElementInfo = {\n checkChildren: boolean;\n readonly subject: Subject<FocusOrigin>;\n rootNode: HTMLElement | ShadowRoot | Document;\n};\n\n/**\n * Event listener options that enable capturing and also\n * mark the listener as passive if the browser supports it.\n */\nconst captureEventListenerOptions = normalizePassiveListenerOptions({\n passive: true,\n capture: true,\n});\n\n/** Monitors mouse and keyboard events to determine the cause of focus events. */\n@Injectable({providedIn: 'root'})\nexport class FocusMonitor implements OnDestroy {\n /** The focus origin that the next focus event is a result of. */\n private _origin: FocusOrigin = null;\n\n /** The FocusOrigin of the last focus event tracked by the FocusMonitor. */\n private _lastFocusOrigin: FocusOrigin;\n\n /** Whether the window has just been focused. */\n private _windowFocused = false;\n\n /** The timeout id of the window focus timeout. */\n private _windowFocusTimeoutId: number;\n\n /** The timeout id of the origin clearing timeout. */\n private _originTimeoutId: number;\n\n /**\n * Whether the origin was determined via a touch interaction. Necessary as properly attributing\n * focus events to touch interactions requires special logic.\n */\n private _originFromTouchInteraction = false;\n\n /** Map of elements being monitored to their info. */\n private _elementInfo = new Map<HTMLElement, MonitoredElementInfo>();\n\n /** The number of elements currently being monitored. */\n private _monitoredElementCount = 0;\n\n /**\n * Keeps track of the root nodes to which we've currently bound a focus/blur handler,\n * as well as the number of monitored elements that they contain. We have to treat focus/blur\n * handlers differently from the rest of the events, because the browser won't emit events\n * to the document when focus moves inside of a shadow root.\n */\n private _rootNodeFocusListenerCount = new Map<HTMLElement | Document | ShadowRoot, number>();\n\n /**\n * The specified detection mode, used for attributing the origin of a focus\n * event.\n */\n private readonly _detectionMode: FocusMonitorDetectionMode;\n\n /**\n * Event listener for `focus` events on the window.\n * Needs to be an arrow function in order to preserve the context when it gets bound.\n */\n private _windowFocusListener = () => {\n // Make a note of when the window regains focus, so we can\n // restore the origin info for the focused element.\n this._windowFocused = true;\n this._windowFocusTimeoutId = window.setTimeout(() => (this._windowFocused = false));\n };\n\n /** Used to reference correct document/window */\n protected _document?: Document;\n\n /** Subject for stopping our InputModalityDetector subscription. */\n private readonly _stopInputModalityDetector = new Subject<void>();\n\n constructor(\n private _ngZone: NgZone,\n private _platform: Platform,\n private readonly _inputModalityDetector: InputModalityDetector,\n /** @breaking-change 11.0.0 make document required */\n @Optional() @Inject(DOCUMENT) document: any | null,\n @Optional() @Inject(FOCUS_MONITOR_DEFAULT_OPTIONS) options: FocusMonitorOptions | null,\n ) {\n this._document = document;\n this._detectionMode = options?.detectionMode || FocusMonitorDetectionMode.IMMEDIATE;\n }\n /**\n * Event listener for `focus` and 'blur' events on the document.\n * Needs to be an arrow function in order to preserve the context when it gets bound.\n */\n private _rootNodeFocusAndBlurListener = (event: Event) => {\n const target = _getEventTarget<HTMLElement>(event);\n\n // We need to walk up the ancestor chain in order to support `checkChildren`.\n for (let element = target; element; element = element.parentElement) {\n if (event.type === 'focus') {\n this._onFocus(event as FocusEvent, element);\n } else {\n this._onBlur(event as FocusEvent, element);\n }\n }\n };\n\n /**\n * Monitors focus on an element and applies appropriate CSS classes.\n * @param element The element to monitor\n * @param checkChildren Whether to count the element as focused when its children are focused.\n * @returns An observable that emits when the focus state of the element changes.\n * When the element is blurred, null will be emitted.\n */\n monitor(element: HTMLElement, checkChildren?: boolean): Observable<FocusOrigin>;\n\n /**\n * Monitors focus on an element and applies appropriate CSS classes.\n * @param element The element to monitor\n * @param checkChildren Whether to count the element as focused when its children are focused.\n * @returns An observable that emits when the focus state of the element changes.\n * When the element is blurred, null will be emitted.\n */\n monitor(element: ElementRef<HTMLElement>, checkChildren?: boolean): Observable<FocusOrigin>;\n\n monitor(\n element: HTMLElement | ElementRef<HTMLElement>,\n checkChildren: boolean = false,\n ): Observable<FocusOrigin> {\n const nativeElement = coerceElement(element);\n\n // Do nothing if we're not on the browser platform or the passed in node isn't an element.\n if (!this._platform.isBrowser || nativeElement.nodeType !== 1) {\n return observableOf(null);\n }\n\n // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to\n // the shadow root, rather than the `document`, because the browser won't emit focus events\n // to the `document`, if focus is moving within the same shadow root.\n const rootNode = _getShadowRoot(nativeElement) || this._getDocument();\n const cachedInfo = this._elementInfo.get(nativeElement);\n\n // Check if we're already monitoring this element.\n if (cachedInfo) {\n if (checkChildren) {\n // TODO(COMP-318): this can be problematic, because it'll turn all non-checkChildren\n // observers into ones that behave as if `checkChildren` was turned on. We need a more\n // robust solution.\n cachedInfo.checkChildren = true;\n }\n\n return cachedInfo.subject;\n }\n\n // Create monitored element info.\n const info: MonitoredElementInfo = {\n checkChildren: checkChildren,\n subject: new Subject<FocusOrigin>(),\n rootNode,\n };\n this._elementInfo.set(nativeElement, info);\n this._registerGlobalListeners(info);\n\n return info.subject;\n }\n\n /**\n * Stops monitoring an element and removes all focus classes.\n * @param element The element to stop monitoring.\n */\n stopMonitoring(element: HTMLElement): void;\n\n /**\n * Stops monitoring an element and removes all focus classes.\n * @param element The element to stop monitoring.\n */\n stopMonitoring(element: ElementRef<HTMLElement>): void;\n\n stopMonitoring(element: HTMLElement | ElementRef<HTMLElement>): void {\n const nativeElement = coerceElement(element);\n const elementInfo = this._elementInfo.get(nativeElement);\n\n if (elementInfo) {\n elementInfo.subject.complete();\n\n this._setClasses(nativeElement);\n this._elementInfo.delete(nativeElement);\n this._removeGlobalListeners(elementInfo);\n }\n }\n\n /**\n * Focuses the element via the specified focus origin.\n * @param element Element to focus.\n * @param origin Focus origin.\n * @param options Options that can be used to configure the focus behavior.\n */\n focusVia(element: HTMLElement, origin: FocusOrigin, options?: FocusOptions): void;\n\n /**\n * Focuses the element via the specified focus origin.\n * @param element Element to focus.\n * @param origin Focus origin.\n * @param options Options that can be used to configure the focus behavior.\n */\n focusVia(element: ElementRef<HTMLElement>, origin: FocusOrigin, options?: FocusOptions): void;\n\n focusVia(\n element: HTMLElement | ElementRef<HTMLElement>,\n origin: FocusOrigin,\n options?: FocusOptions,\n ): void {\n const nativeElement = coerceElement(element);\n const focusedElement = this._getDocument().activeElement;\n\n // If the element is focused already, calling `focus` again won't trigger the event listener\n // which means that the focus classes won't be updated. If that's the case, update the classes\n // directly without waiting for an event.\n if (nativeElement === focusedElement) {\n this._getClosestElementsInfo(nativeElement).forEach(([currentElement, info]) =>\n this._originChanged(currentElement, origin, info),\n );\n } else {\n this._setOrigin(origin);\n\n // `focus` isn't available on the server\n if (typeof nativeElement.focus === 'function') {\n nativeElement.focus(options);\n }\n }\n }\n\n ngOnDestroy() {\n this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));\n }\n\n /** Access injected document if available or fallback to global document reference */\n private _getDocument(): Document {\n return this._document || document;\n }\n\n /** Use defaultView of injected document if available or fallback to global window reference */\n private _getWindow(): Window {\n const doc = this._getDocument();\n return doc.defaultView || window;\n }\n\n private _getFocusOrigin(focusEventTarget: HTMLElement | null): FocusOrigin {\n if (this._origin) {\n // If the origin was realized via a touch interaction, we need to perform additional checks\n // to determine whether the focus origin should be attributed to touch or program.\n if (this._originFromTouchInteraction) {\n return this._shouldBeAttributedToTouch(focusEventTarget) ? 'touch' : 'program';\n } else {\n return this._origin;\n }\n }\n\n // If the window has just regained focus, we can restore the most recent origin from before the\n // window blurred. Otherwise, we've reached the point where we can't identify the source of the\n // focus. This typically means one of two things happened:\n //\n // 1) The element was programmatically focused, or\n // 2) The element was focused via screen reader navigation (which generally doesn't fire\n // events).\n //\n // Because we can't distinguish between these two cases, we default to setting `program`.\n if (this._windowFocused && this._lastFocusOrigin) {\n return this._lastFocusOrigin;\n }\n\n // If the interaction is coming from an input label, we consider it a mouse interactions.\n // This is a special case where focus moves on `click`, rather than `mousedown` which breaks\n // our detection, because all our assumptions are for `mousedown`. We need to handle this\n // special case, because it's very common for checkboxes and radio buttons.\n if (focusEventTarget && this._isLastInteractionFromInputLabel(focusEventTarget)) {\n return 'mouse';\n }\n\n return 'program';\n }\n\n /**\n * Returns whether the focus event should be attributed to touch. Recall that in IMMEDIATE mode, a\n * touch origin isn't immediately reset at the next tick (see _setOrigin). This means that when we\n * handle a focus event following a touch interaction, we need to determine whether (1) the focus\n * event was directly caused by the touch interaction or (2) the focus event was caused by a\n * subsequent programmatic focus call triggered by the touch interaction.\n * @param focusEventTarget The target of the focus event under examination.\n */\n private _shouldBeAttributedToTouch(focusEventTarget: HTMLElement | null): boolean {\n // Please note that this check is not perfect. Consider the following edge case:\n //\n // <div #parent tabindex=\"0\">\n // <div #child tabindex=\"0\" (click)=\"#parent.focus()\"></div>\n // </div>\n //\n // Suppose there is a FocusMonitor in IMMEDIATE mode attached to #parent. When the user touches\n // #child, #parent is programmatically focused. This code will attribute the focus to touch\n // instead of program. This is a relatively minor edge-case that can be worked around by using\n // focusVia(parent, 'program') to focus #parent.\n return (\n this._detectionMode === FocusMonitorDetectionMode.EVENTUAL ||\n !!focusEventTarget?.contains(this._inputModalityDetector._mostRecentTarget)\n );\n }\n\n /**\n * Sets the focus classes on the element based on the given focus origin.\n * @param element The element to update the classes on.\n * @param origin The focus origin.\n */\n private _setClasses(element: HTMLElement, origin?: FocusOrigin): void {\n element.classList.toggle('cdk-focused', !!origin);\n element.classList.toggle('cdk-touch-focused', origin === 'touch');\n element.classList.toggle('cdk-keyboard-focused', origin === 'keyboard');\n element.classList.toggle('cdk-mouse-focused', origin === 'mouse');\n element.classList.toggle('cdk-program-focused', origin === 'program');\n }\n\n /**\n * Updates the focus origin. If we're using immediate detection mode, we schedule an async\n * function to clear the origin at the end of a timeout. The duration of the timeout depends on\n * the origin being set.\n * @param origin The origin to set.\n * @param isFromInteraction Whether we are setting the origin from an interaction event.\n */\n private _setOrigin(origin: FocusOrigin, isFromInteraction = false): void {\n this._ngZone.runOutsideAngular(() => {\n this._origin = origin;\n this._originFromTouchInteraction = origin === 'touch' && isFromInteraction;\n\n // If we're in IMMEDIATE mode, reset the origin at the next tick (or in `TOUCH_BUFFER_MS` ms\n // for a touch event). We reset the origin at the next tick because Firefox focuses one tick\n // after the interaction event. We wait `TOUCH_BUFFER_MS` ms before resetting the origin for\n // a touch event because when a touch event is fired, the associated focus event isn't yet in\n // the event queue. Before doing so, clear any pending timeouts.\n if (this._detectionMode === FocusMonitorDetectionMode.IMMEDIATE) {\n clearTimeout(this._originTimeoutId);\n const ms = this._originFromTouchInteraction ? TOUCH_BUFFER_MS : 1;\n this._originTimeoutId = setTimeout(() => (this._origin = null), ms);\n }\n });\n }\n\n /**\n * Handles focus events on a registered element.\n * @param event The focus event.\n * @param element The monitored element.\n */\n private _onFocus(event: FocusEvent, element: HTMLElement) {\n // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent\n // focus event affecting the monitored element. If we want to use the origin of the first event\n // instead we should check for the cdk-focused class here and return if the element already has\n // it. (This only matters for elements that have includesChildren = true).\n\n // If we are not counting child-element-focus as focused, make sure that the event target is the\n // monitored element itself.\n const elementInfo = this._elementInfo.get(element);\n const focusEventTarget = _getEventTarget<HTMLElement>(event);\n if (!elementInfo || (!elementInfo.checkChildren && element !== focusEventTarget)) {\n return;\n }\n\n this._originChanged(element, this._getFocusOrigin(focusEventTarget), elementInfo);\n }\n\n /**\n * Handles blur events on a registered element.\n * @param event The blur event.\n * @param element The monitored element.\n */\n _onBlur(event: FocusEvent, element: HTMLElement) {\n // If we are counting child-element-focus as focused, make sure that we aren't just blurring in\n // order to focus another child of the monitored element.\n const elementInfo = this._elementInfo.get(element);\n\n if (\n !elementInfo ||\n (elementInfo.checkChildren &&\n event.relatedTarget instanceof Node &&\n element.contains(event.relatedTarget))\n ) {\n return;\n }\n\n this._setClasses(element);\n this._emitOrigin(elementInfo, null);\n }\n\n private _emitOrigin(info: MonitoredElementInfo, origin: FocusOrigin) {\n if (info.subject.observers.length) {\n this._ngZone.run(() => info.subject.next(origin));\n }\n }\n\n private _registerGlobalListeners(elementInfo: MonitoredElementInfo) {\n if (!this._platform.isBrowser) {\n return;\n }\n\n const rootNode = elementInfo.rootNode;\n const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;\n\n if (!rootNodeFocusListeners) {\n this._ngZone.runOutsideAngular(() => {\n rootNode.addEventListener(\n 'focus',\n this._rootNodeFocusAndBlurListener,\n captureEventListenerOptions,\n );\n rootNode.addEventListener(\n 'blur',\n this._rootNodeFocusAndBlurListener,\n captureEventListenerOptions,\n );\n });\n }\n\n this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1);\n\n // Register global listeners when first element is monitored.\n if (++this._monitoredElementCount === 1) {\n // Note: we listen to events in the capture phase so we\n // can detect them even if the user stops propagation.\n this._ngZone.runOutsideAngular(() => {\n const window = this._getWindow();\n window.addEventListener('focus', this._windowFocusListener);\n });\n\n // The InputModalityDetector is also just a collection of global listeners.\n this._inputModalityDetector.modalityDetected\n .pipe(takeUntil(this._stopInputModalityDetector))\n .subscribe(modality => {\n this._setOrigin(modality, true /* isFromInteraction */);\n });\n }\n }\n\n private _removeGlobalListeners(elementInfo: MonitoredElementInfo) {\n const rootNode = elementInfo.rootNode;\n\n if (this._rootNodeFocusListenerCount.has(rootNode)) {\n const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode)!;\n\n if (rootNodeFocusListeners > 1) {\n this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);\n } else {\n rootNode.removeEventListener(\n 'focus',\n this._rootNodeFocusAndBlurListener,\n captureEventListenerOptions,\n );\n rootNode.removeEventListener(\n 'blur',\n this._rootNodeFocusAndBlurListener,\n captureEventListenerOptions,\n );\n this._rootNodeFocusListenerCount.delete(rootNode);\n }\n }\n\n // Unregister global listeners when last element is unmonitored.\n if (!--this._monitoredElementCount) {\n const window = this._getWindow();\n window.removeEventListener('focus', this._windowFocusListener);\n\n // Equivalently, stop our InputModalityDetector subscription.\n this._stopInputModalityDetector.next();\n\n // Clear timeouts for all potentially pending timeouts to prevent the leaks.\n clearTimeout(this._windowFocusTimeoutId);\n clearTimeout(this._originTimeoutId);\n }\n }\n\n /** Updates all the state on an element once its focus origin has changed. */\n private _originChanged(\n element: HTMLElement,\n origin: FocusOrigin,\n elementInfo: MonitoredElementInfo,\n ) {\n this._setClasses(element, origin);\n this._emitOrigin(elementInfo, origin);\n this._lastFocusOrigin = origin;\n }\n\n /**\n * Collects the `MonitoredElementInfo` of a particular element and\n * all of its ancestors that have enabled `checkChildren`.\n * @param element Element from which to start the search.\n */\n private _getClosestElementsInfo(element: HTMLElement): [HTMLElement, MonitoredElementInfo][] {\n const results: [HTMLElement, MonitoredElementInfo][] = [];\n\n this._elementInfo.forEach((info, currentElement) => {\n if (currentElement === element || (info.checkChildren && currentElement.contains(element))) {\n results.push([currentElement, info]);\n }\n });\n\n return results;\n }\n\n /**\n * Returns whether an interaction is likely to have come from the user clicking the `label` of\n * an `input` or `textarea` in order to focus it.\n * @param focusEventTarget Target currently receiving focus.\n */\n private _isLastInteractionFromInputLabel(focusEventTarget: HTMLElement): boolean {\n const {_mostRecentTarget: mostRecentTarget, mostRecentModality} = this._inputModalityDetector;\n\n // If the last interaction used the mouse on an element contained by one of the labels\n // of an `input`/`textarea` that is currently focused, it is very likely that the\n // user redirected focus using the label.\n if (\n mostRecentModality !== 'mouse' ||\n !mostRecentTarget ||\n mostRecentTarget === focusEventTarget ||\n (focusEventTarget.nodeName !== 'INPUT' && focusEventTarget.nodeName !== 'TEXTAREA') ||\n (focusEventTarget as HTMLInputElement | HTMLTextAreaElement).disabled\n ) {\n return false;\n }\n\n const labels = (focusEventTarget as HTMLInputElement | HTMLTextAreaElement).labels;\n\n if (labels) {\n for (let i = 0; i < labels.length; i++) {\n if (labels[i].contains(mostRecentTarget)) {\n return true;\n }\n }\n }\n\n return false;\n }\n}\n\n/**\n * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or\n * programmatically) and adds corresponding classes to the element.\n *\n * There are two variants of this directive:\n * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is\n * focused.\n * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.\n */\n@Directive({\n selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]',\n exportAs: 'cdkMonitorFocus',\n})\nexport class CdkMonitorFocus implements AfterViewInit, OnDestroy {\n private _monitorSubscription: Subscription;\n private _focusOrigin: FocusOrigin = null;\n\n @Output() readonly cdkFocusChange = new EventEmitter<FocusOrigin>();\n\n constructor(private _elementRef: ElementRef<HTMLElement>, private _focusMonitor: FocusMonitor) {}\n\n get focusOrigin(): FocusOrigin {\n return this._focusOrigin;\n }\n\n ngAfterViewInit() {\n const element = this._elementRef.nativeElement;\n this._monitorSubscription = this._focusMonitor\n .monitor(element, element.nodeType === 1 && element.hasAttribute('cdkMonitorSubtreeFocus'))\n .subscribe(origin => {\n this._focusOrigin = origin;\n this.cdkFocusChange.emit(origin);\n });\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef);\n\n if (this._monitorSubscription) {\n this._monitorSubscription.unsubscribe();\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {inject, Inject, Injectable, OnDestroy} from '@angular/core';\nimport {BreakpointObserver} from '@angular/cdk/layout';\nimport {Platform} from '@angular/cdk/platform';\nimport {DOCUMENT} from '@angular/common';\nimport {Subscription} from 'rxjs';\n\n/** Set of possible high-contrast mode backgrounds. */\nexport const enum HighContrastMode {\n NONE,\n BLACK_ON_WHITE,\n WHITE_ON_BLACK,\n}\n\n/** CSS class applied to the document body when in black-on-white high-contrast mode. */\nexport const BLACK_ON_WHITE_CSS_CLASS = 'cdk-high-contrast-black-on-white';\n\n/** CSS class applied to the document body when in white-on-black high-contrast mode. */\nexport const WHITE_ON_BLACK_CSS_CLASS = 'cdk-high-contrast-white-on-black';\n\n/** CSS class applied to the document body when in high-contrast mode. */\nexport const HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';\n\n/**\n * Service to determine whether the browser is currently in a high-contrast-mode environment.\n *\n * Microsoft Windows supports an accessibility feature called \"High Contrast Mode\". This mode\n * changes the appearance of all applications, including web applications, to dramatically increase\n * contrast.\n *\n * IE, Edge, and Firefox currently support this mode. Chrome does not support Windows High Contrast\n * Mode. This service does not detect high-contrast mode as added by the Chrome \"High Contrast\"\n * browser extension.\n */\n@Injectable({providedIn: 'root'})\nexport class HighContrastModeDetector implements OnDestroy {\n /**\n * Figuring out the high contrast mode and adding the body classes can cause\n * some expensive layouts. This flag is used to ensure that we only do it once.\n */\n private _hasCheckedHighContrastMode: boolean;\n private _document: Document;\n private _breakpointSubscription: Subscription;\n\n constructor(private _platform: Platform, @Inject(DOCUMENT) document: any) {\n this._document = document;\n\n this._breakpointSubscription = inject(BreakpointObserver)\n .observe('(forced-colors: active)')\n .subscribe(() => {\n if (this._hasCheckedHighContrastMode) {\n this._hasCheckedHighContrastMode = false;\n this._applyBodyHighContrastModeCssClasses();\n }\n });\n }\n\n /** Gets the current high-contrast-mode for the page. */\n getHighContrastMode(): HighContrastMode {\n if (!this._platform.isBrowser) {\n return HighContrastMode.NONE;\n }\n\n // Create a test element with an arbitrary background-color that is neither black nor\n // white; high-contrast mode will coerce the color to either black or white. Also ensure that\n // appending the test element to the DOM does not affect layout by absolutely positioning it\n const testElement = this._document.createElement('div');\n testElement.style.backgroundColor = 'rgb(1,2,3)';\n testElement.style.position = 'absolute';\n this._document.body.appendChild(testElement);\n\n // Get the computed style for the background color, collapsing spaces to normalize between\n // browsers. Once we get this color, we no longer need the test element. Access the `window`\n // via the document so we can fake it in tests. Note that we have extra null checks, because\n // this logic will likely run during app bootstrap and throwing can break the entire app.\n const documentWindow = this._document.defaultView || window;\n const computedStyle =\n documentWindow && documentWindow.getComputedStyle\n ? documentWindow.getComputedStyle(testElement)\n : null;\n const computedColor = ((computedStyle && computedStyle.backgroundColor) || '').replace(\n / /g,\n '',\n );\n testElement.remove();\n\n switch (computedColor) {\n // Pre Windows 11 dark theme.\n case 'rgb(0,0,0)':\n // Windows 11 dark themes.\n case 'rgb(45,50,54)':\n case 'rgb(32,32,32)':\n return HighContrastMode.WHITE_ON_BLACK;\n // Pre Windows 11 light theme.\n case 'rgb(255,255,255)':\n // Windows 11 light theme.\n case 'rgb(255,250,239)':\n return HighContrastMode.BLACK_ON_WHITE;\n }\n return HighContrastMode.NONE;\n }\n\n ngOnDestroy(): void {\n this._breakpointSubscription.unsubscribe();\n }\n\n /** Applies CSS classes indicating high-contrast mode to document body (browser-only). */\n _applyBodyHighContrastModeCssClasses(): void {\n if (!this._hasCheckedHighContrastMode && this._platform.isBrowser && this._document.body) {\n const bodyClasses = this._document.body.classList;\n bodyClasses.remove(\n HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS,\n BLACK_ON_WHITE_CSS_CLASS,\n WHITE_ON_BLACK_CSS_CLASS,\n );\n this._hasCheckedHighContrastMode = true;\n\n const mode = this.getHighContrastMode();\n if (mode === HighContrastMode.BLACK_ON_WHITE) {\n bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS, BLACK_ON_WHITE_CSS_CLASS);\n } else if (mode === HighContrastMode.WHITE_ON_BLACK) {\n bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS, WHITE_ON_BLACK_CSS_CLASS);\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ObserversModule} from '@angular/cdk/observers';\nimport {NgModule} from '@angular/core';\nimport {CdkMonitorFocus} from './focus-monitor/focus-monitor';\nimport {CdkTrapFocus} from './focus-trap/focus-trap';\nimport {HighContrastModeDetector} from './high-contrast-mode/high-contrast-mode-detector';\nimport {CdkAriaLive} from './live-announcer/live-announcer';\n\n@NgModule({\n imports: [ObserversModule],\n declarations: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],\n exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],\n})\nexport class A11yModule {\n constructor(highContrastModeDetector: HighContrastModeDetector) {\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {inject, InjectionToken} from '@angular/core';\n\n/**\n * Injection token used to inject the document into Directionality.\n * This is used so that the value can be faked in tests.\n *\n * We can't use the real document in tests because changing the real `dir` causes geometry-based\n * tests in Safari to fail.\n *\n * We also can't re-provide the DOCUMENT token from platform-browser because the unit tests\n * themselves use things like `querySelector` in test code.\n *\n * This token is defined in a separate file from Directionality as a workaround for\n * https://github.com/angular/angular/issues/22559\n *\n * @docs-private\n */\nexport const DIR_DOCUMENT = new InjectionToken<Document>('cdk-dir-doc', {\n providedIn: 'root',\n factory: DIR_DOCUMENT_FACTORY,\n});\n\n/** @docs-private */\nexport function DIR_DOCUMENT_FACTORY(): Document {\n return inject(DOCUMENT);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EventEmitter, Inject, Injectable, Optional, OnDestroy} from '@angular/core';\nimport {DIR_DOCUMENT} from './dir-document-token';\n\nexport type Direction = 'ltr' | 'rtl';\n\n/** Regex that matches locales with an RTL script. Taken from `goog.i18n.bidi.isRtlLanguage`. */\nconst RTL_LOCALE_PATTERN =\n /^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Adlm|Arab|Hebr|Nkoo|Rohg|Thaa))(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)/i;\n\n/** Resolves a string value to a specific direction. */\nexport function _resolveDirectionality(rawValue: string): Direction {\n const value = rawValue?.toLowerCase() || '';\n\n if (value === 'auto' && typeof navigator !== 'undefined' && navigator?.language) {\n return RTL_LOCALE_PATTERN.test(navigator.language) ? 'rtl' : 'ltr';\n }\n\n return value === 'rtl' ? 'rtl' : 'ltr';\n}\n\n/**\n * The directionality (LTR / RTL) context for the application (or a subtree of it).\n * Exposes the current direction and a stream of direction changes.\n */\n@Injectable({providedIn: 'root'})\nexport class Directionality implements OnDestroy {\n /** The current 'ltr' or 'rtl' value. */\n readonly value: Direction = 'ltr';\n\n /** Stream that emits whenever the 'ltr' / 'rtl' state changes. */\n readonly change = new EventEmitter<Direction>();\n\n constructor(@Optional() @Inject(DIR_DOCUMENT) _document?: any) {\n if (_document) {\n const bodyDir = _document.body ? _document.body.dir : null;\n const htmlDir = _document.documentElement ? _document.documentElement.dir : null;\n this.value = _resolveDirectionality(bodyDir || htmlDir || 'ltr');\n }\n }\n\n ngOnDestroy() {\n this.change.complete();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {Dir} from './dir';\n\n@NgModule({\n exports: [Dir],\n declarations: [Dir],\n})\nexport class BidiModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Type describing the allowed values for a boolean input.\n * @docs-private\n */\nexport type BooleanInput = string | boolean | null | undefined;\n\n/** Coerces a data-bound value (typically a string) to a boolean. */\nexport function coerceBooleanProperty(value: any): boolean {\n return value != null && `${value}` !== 'false';\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Type describing the allowed values for a number input\n * @docs-private\n */\nexport type NumberInput = string | number | null | undefined;\n\n/** Coerces a data-bound value (typically a string) to a number. */\nexport function coerceNumberProperty(value: any): number;\nexport function coerceNumberProperty<D>(value: any, fallback: D): number | D;\nexport function coerceNumberProperty(value: any, fallbackValue = 0) {\n return _isNumberValue(value) ? Number(value) : fallbackValue;\n}\n\n/**\n * Whether the provided value is considered a number.\n * @docs-private\n */\nexport function _isNumberValue(value: any): boolean {\n // parseFloat(value) handles most of the cases we're interested in (it treats null, empty string,\n // and other non-number values as NaN, where Number just uses 0) but it considers the string\n // '123hello' to be a valid number. Therefore we also check if Number(value) is NaN.\n return !isNaN(parseFloat(value as any)) && !isNaN(Number(value));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Wraps the provided value in an array, unless the provided value is an array. */\nexport function coerceArray<T>(value: T | T[]): T[];\nexport function coerceArray<T>(value: T | readonly T[]): readonly T[];\nexport function coerceArray<T>(value: T | T[]): T[] {\n return Array.isArray(value) ? value : [value];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Coerces a value to a CSS pixel value. */\nexport function coerceCssPixelValue(value: any): string {\n if (value == null) {\n return '';\n }\n\n return typeof value === 'string' ? value : `${value}px`;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ElementRef} from '@angular/core';\n\n/**\n * Coerces an ElementRef or an Element into an element.\n * Useful for APIs that can accept either a ref or the native element itself.\n */\nexport function coerceElement<T>(elementOrRef: ElementRef<T> | T): T {\n return elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const MAC_ENTER = 3;\nexport const BACKSPACE = 8;\nexport const TAB = 9;\nexport const NUM_CENTER = 12;\nexport const ENTER = 13;\nexport const SHIFT = 16;\nexport const CONTROL = 17;\nexport const ALT = 18;\nexport const PAUSE = 19;\nexport const CAPS_LOCK = 20;\nexport const ESCAPE = 27;\nexport const SPACE = 32;\nexport const PAGE_UP = 33;\nexport const PAGE_DOWN = 34;\nexport const END = 35;\nexport const HOME = 36;\nexport const LEFT_ARROW = 37;\nexport const UP_ARROW = 38;\nexport const RIGHT_ARROW = 39;\nexport const DOWN_ARROW = 40;\nexport const PLUS_SIGN = 43;\nexport const PRINT_SCREEN = 44;\nexport const INSERT = 45;\nexport const DELETE = 46;\nexport const ZERO = 48;\nexport const ONE = 49;\nexport const TWO = 50;\nexport const THREE = 51;\nexport const FOUR = 52;\nexport const FIVE = 53;\nexport const SIX = 54;\nexport const SEVEN = 55;\nexport const EIGHT = 56;\nexport const NINE = 57;\nexport const FF_SEMICOLON = 59; // Firefox (Gecko) fires this for semicolon instead of 186\nexport const FF_EQUALS = 61; // Firefox (Gecko) fires this for equals instead of 187\nexport const QUESTION_MARK = 63;\nexport const AT_SIGN = 64;\nexport const A = 65;\nexport const B = 66;\nexport const C = 67;\nexport const D = 68;\nexport const E = 69;\nexport const F = 70;\nexport const G = 71;\nexport const H = 72;\nexport const I = 73;\nexport const J = 74;\nexport const K = 75;\nexport const L = 76;\nexport const M = 77;\nexport const N = 78;\nexport const O = 79;\nexport const P = 80;\nexport const Q = 81;\nexport const R = 82;\nexport const S = 83;\nexport const T = 84;\nexport const U = 85;\nexport const V = 86;\nexport const W = 87;\nexport const X = 88;\nexport const Y = 89;\nexport const Z = 90;\nexport const META = 91; // WIN_KEY_LEFT\nexport const MAC_WK_CMD_LEFT = 91;\nexport const MAC_WK_CMD_RIGHT = 93;\nexport const CONTEXT_MENU = 93;\nexport const NUMPAD_ZERO = 96;\nexport const NUMPAD_ONE = 97;\nexport const NUMPAD_TWO = 98;\nexport const NUMPAD_THREE = 99;\nexport const NUMPAD_FOUR = 100;\nexport const NUMPAD_FIVE = 101;\nexport const NUMPAD_SIX = 102;\nexport const NUMPAD_SEVEN = 103;\nexport const NUMPAD_EIGHT = 104;\nexport const NUMPAD_NINE = 105;\nexport const NUMPAD_MULTIPLY = 106;\nexport const NUMPAD_PLUS = 107;\nexport const NUMPAD_MINUS = 109;\nexport const NUMPAD_PERIOD = 110;\nexport const NUMPAD_DIVIDE = 111;\nexport const F1 = 112;\nexport const F2 = 113;\nexport const F3 = 114;\nexport const F4 = 115;\nexport const F5 = 116;\nexport const F6 = 117;\nexport const F7 = 118;\nexport const F8 = 119;\nexport const F9 = 120;\nexport const F10 = 121;\nexport const F11 = 122;\nexport const F12 = 123;\nexport const NUM_LOCK = 144;\nexport const SCROLL_LOCK = 145;\nexport const FIRST_MEDIA = 166;\nexport const FF_MINUS = 173;\nexport const MUTE = 173; // Firefox (Gecko) fires 181 for MUTE\nexport const VOLUME_DOWN = 174; // Firefox (Gecko) fires 182 for VOLUME_DOWN\nexport const VOLUME_UP = 175; // Firefox (Gecko) fires 183 for VOLUME_UP\nexport const FF_MUTE = 181;\nexport const FF_VOLUME_DOWN = 182;\nexport const LAST_MEDIA = 183;\nexport const FF_VOLUME_UP = 183;\nexport const SEMICOLON = 186; // Firefox (Gecko) fires 59 for SEMICOLON\nexport const EQUALS = 187; // Firefox (Gecko) fires 61 for EQUALS\nexport const COMMA = 188;\nexport const DASH = 189; // Firefox (Gecko) fires 173 for DASH/MINUS\nexport const PERIOD = 190;\nexport const SLASH = 191;\nexport const APOSTROPHE = 192;\nexport const TILDE = 192;\nexport const OPEN_SQUARE_BRACKET = 219;\nexport const BACKSLASH = 220;\nexport const CLOSE_SQUARE_BRACKET = 221;\nexport const SINGLE_QUOTE = 222;\nexport const MAC_META = 224;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport type ModifierKey = 'altKey' | 'shiftKey' | 'ctrlKey' | 'metaKey';\n\n/**\n * Checks whether a modifier key is pressed.\n * @param event Event to be checked.\n */\nexport function hasModifierKey(event: KeyboardEvent, ...modifiers: ModifierKey[]): boolean {\n if (modifiers.length) {\n return modifiers.some(modifier => event[modifier]);\n }\n\n return event.altKey || event.shiftKey || event.ctrlKey || event.metaKey;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {Injectable} from '@angular/core';\nimport {Platform} from '@angular/cdk/platform';\n\n/** Global registry for all dynamically-created, injected media queries. */\nconst mediaQueriesForWebkitCompatibility: Set<string> = new Set<string>();\n\n/** Style tag that holds all of the dynamically-created media queries. */\nlet mediaQueryStyleNode: HTMLStyleElement | undefined;\n\n/** A utility for calling matchMedia queries. */\n@Injectable({providedIn: 'root'})\nexport class MediaMatcher {\n /** The internal matchMedia method to return back a MediaQueryList like object. */\n private _matchMedia: (query: string) => MediaQueryList;\n\n constructor(private _platform: Platform) {\n this._matchMedia =\n this._platform.isBrowser && window.matchMedia\n ? // matchMedia is bound to the window scope intentionally as it is an illegal invocation to\n // call it from a different scope.\n window.matchMedia.bind(window)\n : noopMatchMedia;\n }\n\n /**\n * Evaluates the given media query and returns the native MediaQueryList from which results\n * can be retrieved.\n * Confirms the layout engine will trigger for the selector query provided and returns the\n * MediaQueryList for the query provided.\n */\n matchMedia(query: string): MediaQueryList {\n if (this._platform.WEBKIT || this._platform.BLINK) {\n createEmptyStyleRule(query);\n }\n return this._matchMedia(query);\n }\n}\n\n/**\n * Creates an empty stylesheet that is used to work around browser inconsistencies related to\n * `matchMedia`. At the time of writing, it handles the following cases:\n * 1. On WebKit browsers, a media query has to have at least one rule in order for `matchMedia`\n * to fire. We work around it by declaring a dummy stylesheet with a `@media` declaration.\n * 2. In some cases Blink browsers will stop firing the `matchMedia` listener if none of the rules\n * inside the `@media` match existing elements on the page. We work around it by having one rule\n * targeting the `body`. See https://github.com/angular/components/issues/23546.\n */\nfunction createEmptyStyleRule(query: string) {\n if (mediaQueriesForWebkitCompatibility.has(query)) {\n return;\n }\n\n try {\n if (!mediaQueryStyleNode) {\n mediaQueryStyleNode = document.createElement('style');\n mediaQueryStyleNode.setAttribute('type', 'text/css');\n document.head!.appendChild(mediaQueryStyleNode);\n }\n\n if (mediaQueryStyleNode.sheet) {\n mediaQueryStyleNode.sheet.insertRule(`@media ${query} {body{ }}`, 0);\n mediaQueriesForWebkitCompatibility.add(query);\n }\n } catch (e) {\n console.error(e);\n }\n}\n\n/** No-op matchMedia replacement for non-browser platforms. */\nfunction noopMatchMedia(query: string): MediaQueryList {\n // Use `as any` here to avoid adding additional necessary properties for\n // the noop matcher.\n return {\n matches: query === 'all' || query === '',\n media: query,\n addListener: () => {},\n removeListener: () => {},\n } as any;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceArray} from '@angular/cdk/coercion';\nimport {Injectable, NgZone, OnDestroy} from '@angular/core';\nimport {combineLatest, concat, Observable, Observer, Subject} from 'rxjs';\nimport {debounceTime, map, skip, startWith, take, takeUntil} from 'rxjs/operators';\nimport {MediaMatcher} from './media-matcher';\n\n/** The current state of a layout breakpoint. */\nexport interface BreakpointState {\n /** Whether the breakpoint is currently matching. */\n matches: boolean;\n /**\n * A key boolean pair for each query provided to the observe method,\n * with its current matched state.\n */\n breakpoints: {\n [key: string]: boolean;\n };\n}\n\n/** The current state of a layout breakpoint. */\ninterface InternalBreakpointState {\n /** Whether the breakpoint is currently matching. */\n matches: boolean;\n /** The media query being to be matched */\n query: string;\n}\n\ninterface Query {\n observable: Observable<InternalBreakpointState>;\n mql: MediaQueryList;\n}\n\n/** Utility for checking the matching state of @media queries. */\n@Injectable({providedIn: 'root'})\nexport class BreakpointObserver implements OnDestroy {\n /** A map of all media queries currently being listened for. */\n private _queries = new Map<string, Query>();\n /** A subject for all other observables to takeUntil based on. */\n private readonly _destroySubject = new Subject<void>();\n\n constructor(private _mediaMatcher: MediaMatcher, private _zone: NgZone) {}\n\n /** Completes the active subject, signalling to all other observables to complete. */\n ngOnDestroy() {\n this._destroySubject.next();\n this._destroySubject.complete();\n }\n\n /**\n * Whether one or more media queries match the current viewport size.\n * @param value One or more media queries to check.\n * @returns Whether any of the media queries match.\n */\n isMatched(value: string | readonly string[]): boolean {\n const queries = splitQueries(coerceArray(value));\n return queries.some(mediaQuery => this._registerQuery(mediaQuery).mql.matches);\n }\n\n /**\n * Gets an observable of results for the given queries that will emit new results for any changes\n * in matching of the given queries.\n * @param value One or more media queries to check.\n * @returns A stream of matches for the given queries.\n */\n observe(value: string | readonly string[]): Observable<BreakpointState> {\n const queries = splitQueries(coerceArray(value));\n const observables = queries.map(query => this._registerQuery(query).observable);\n\n let stateObservable = combineLatest(observables);\n // Emit the first state immediately, and then debounce the subsequent emissions.\n stateObservable = concat(\n stateObservable.pipe(take(1)),\n stateObservable.pipe(skip(1), debounceTime(0)),\n );\n return stateObservable.pipe(\n map(breakpointStates => {\n const response: BreakpointState = {\n matches: false,\n breakpoints: {},\n };\n breakpointStates.forEach(({matches, query}) => {\n response.matches = response.matches || matches;\n response.breakpoints[query] = matches;\n });\n return response;\n }),\n );\n }\n\n /** Registers a specific query to be listened for. */\n private _registerQuery(query: string): Query {\n // Only set up a new MediaQueryList if it is not already being listened for.\n if (this._queries.has(query)) {\n return this._queries.get(query)!;\n }\n\n const mql = this._mediaMatcher.matchMedia(query);\n\n // Create callback for match changes and add it is as a listener.\n const queryObservable = new Observable((observer: Observer<MediaQueryListEvent>) => {\n // Listener callback methods are wrapped to be placed back in ngZone. Callbacks must be placed\n // back into the zone because matchMedia is only included in Zone.js by loading the\n // webapis-media-query.js file alongside the zone.js file. Additionally, some browsers do not\n // have MediaQueryList inherit from EventTarget, which causes inconsistencies in how Zone.js\n // patches it.\n const handler = (e: MediaQueryListEvent): void => this._zone.run(() => observer.next(e));\n mql.addListener(handler);\n\n return () => {\n mql.removeListener(handler);\n };\n }).pipe(\n startWith(mql),\n map(({matches}) => ({query, matches})),\n takeUntil(this._destroySubject),\n );\n\n // Add the MediaQueryList to the set of queries.\n const output = {observable: queryObservable, mql};\n this._queries.set(query, output);\n return output;\n }\n}\n\n/**\n * Split each query string into separate query strings if two queries are provided as comma\n * separated.\n */\nfunction splitQueries(queries: readonly string[]): readonly string[] {\n return queries\n .map(query => query.split(','))\n .reduce((a1, a2) => a1.concat(a2))\n .map(query => query.trim());\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n coerceBooleanProperty,\n coerceNumberProperty,\n coerceElement,\n BooleanInput,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport {\n AfterContentInit,\n Directive,\n ElementRef,\n EventEmitter,\n Injectable,\n Input,\n NgModule,\n NgZone,\n OnDestroy,\n Output,\n} from '@angular/core';\nimport {Observable, Subject, Subscription, Observer} from 'rxjs';\nimport {debounceTime} from 'rxjs/operators';\n\n/**\n * Factory that creates a new MutationObserver and allows us to stub it out in unit tests.\n * @docs-private\n */\n@Injectable({providedIn: 'root'})\nexport class MutationObserverFactory {\n create(callback: MutationCallback): MutationObserver | null {\n return typeof MutationObserver === 'undefined' ? null : new MutationObserver(callback);\n }\n}\n\n/** An injectable service that allows watching elements for changes to their content. */\n@Injectable({providedIn: 'root'})\nexport class ContentObserver implements OnDestroy {\n /** Keeps track of the existing MutationObservers so they can be reused. */\n private _observedElements = new Map<\n Element,\n {\n observer: MutationObserver | null;\n readonly stream: Subject<MutationRecord[]>;\n count: number;\n }\n >();\n\n constructor(private _mutationObserverFactory: MutationObserverFactory) {}\n\n ngOnDestroy() {\n this._observedElements.forEach((_, element) => this._cleanupObserver(element));\n }\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: Element): Observable<MutationRecord[]>;\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: ElementRef<Element>): Observable<MutationRecord[]>;\n\n observe(elementOrRef: Element | ElementRef<Element>): Observable<MutationRecord[]> {\n const element = coerceElement(elementOrRef);\n\n return new Observable((observer: Observer<MutationRecord[]>) => {\n const stream = this._observeElement(element);\n const subscription = stream.subscribe(observer);\n\n return () => {\n subscription.unsubscribe();\n this._unobserveElement(element);\n };\n });\n }\n\n /**\n * Observes the given element by using the existing MutationObserver if available, or creating a\n * new one if not.\n */\n private _observeElement(element: Element): Subject<MutationRecord[]> {\n if (!this._observedElements.has(element)) {\n const stream = new Subject<MutationRecord[]>();\n const observer = this._mutationObserverFactory.create(mutations => stream.next(mutations));\n if (observer) {\n observer.observe(element, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n }\n this._observedElements.set(element, {observer, stream, count: 1});\n } else {\n this._observedElements.get(element)!.count++;\n }\n return this._observedElements.get(element)!.stream;\n }\n\n /**\n * Un-observes the given element and cleans up the underlying MutationObserver if nobody else is\n * observing this element.\n */\n private _unobserveElement(element: Element) {\n if (this._observedElements.has(element)) {\n this._observedElements.get(element)!.count--;\n if (!this._observedElements.get(element)!.count) {\n this._cleanupObserver(element);\n }\n }\n }\n\n /** Clean up the underlying MutationObserver for the specified element. */\n private _cleanupObserver(element: Element) {\n if (this._observedElements.has(element)) {\n const {observer, stream} = this._observedElements.get(element)!;\n if (observer) {\n observer.disconnect();\n }\n stream.complete();\n this._observedElements.delete(element);\n }\n }\n}\n\n/**\n * Directive that triggers a callback whenever the content of\n * its associated element has changed.\n */\n@Directive({\n selector: '[cdkObserveContent]',\n exportAs: 'cdkObserveContent',\n})\nexport class CdkObserveContent implements AfterContentInit, OnDestroy {\n /** Event emitted for each change in the element's content. */\n @Output('cdkObserveContent') readonly event = new EventEmitter<MutationRecord[]>();\n\n /**\n * Whether observing content is disabled. This option can be used\n * to disconnect the underlying MutationObserver until it is needed.\n */\n @Input('cdkObserveContentDisabled')\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value: BooleanInput) {\n this._disabled = coerceBooleanProperty(value);\n this._disabled ? this._unsubscribe() : this._subscribe();\n }\n private _disabled = false;\n\n /** Debounce interval for emitting the changes. */\n @Input()\n get debounce(): number {\n return this._debounce;\n }\n set debounce(value: NumberInput) {\n this._debounce = coerceNumberProperty(value);\n this._subscribe();\n }\n private _debounce: number;\n\n private _currentSubscription: Subscription | null = null;\n\n constructor(\n private _contentObserver: ContentObserver,\n private _elementRef: ElementRef<HTMLElement>,\n private _ngZone: NgZone,\n ) {}\n\n ngAfterContentInit() {\n if (!this._currentSubscription && !this.disabled) {\n this._subscribe();\n }\n }\n\n ngOnDestroy() {\n this._unsubscribe();\n }\n\n private _subscribe() {\n this._unsubscribe();\n const stream = this._contentObserver.observe(this._elementRef);\n\n // TODO(mmalerba): We shouldn't be emitting on this @Output() outside the zone.\n // Consider brining it back inside the zone next time we're making breaking changes.\n // Bringing it back inside can cause things like infinite change detection loops and changed\n // after checked errors if people's code isn't handling it properly.\n this._ngZone.runOutsideAngular(() => {\n this._currentSubscription = (\n this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream\n ).subscribe(this.event);\n });\n }\n\n private _unsubscribe() {\n this._currentSubscription?.unsubscribe();\n }\n}\n\n@NgModule({\n exports: [CdkObserveContent],\n declarations: [CdkObserveContent],\n providers: [MutationObserverFactory],\n})\nexport class ObserversModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ScrollStrategy} from './scroll-strategy';\nimport {ViewportRuler} from '@angular/cdk/scrolling';\nimport {coerceCssPixelValue} from '@angular/cdk/coercion';\nimport {supportsScrollBehavior} from '@angular/cdk/platform';\n\nconst scrollBehaviorSupported = supportsScrollBehavior();\n\n/**\n * Strategy that will prevent the user from scrolling while the overlay is visible.\n */\nexport class BlockScrollStrategy implements ScrollStrategy {\n private _previousHTMLStyles = {top: '', left: ''};\n private _previousScrollPosition: {top: number; left: number};\n private _isEnabled = false;\n private _document: Document;\n\n constructor(private _viewportRuler: ViewportRuler, document: any) {\n this._document = document;\n }\n\n /** Attaches this scroll strategy to an overlay. */\n attach() {}\n\n /** Blocks page-level scroll while the attached overlay is open. */\n enable() {\n if (this._canBeEnabled()) {\n const root = this._document.documentElement!;\n\n this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition();\n\n // Cache the previous inline styles in case the user had set them.\n this._previousHTMLStyles.left = root.style.left || '';\n this._previousHTMLStyles.top = root.style.top || '';\n\n // Note: we're using the `html` node, instead of the `body`, because the `body` may\n // have the user agent margin, whereas the `html` is guaranteed not to have one.\n root.style.left = coerceCssPixelValue(-this._previousScrollPosition.left);\n root.style.top = coerceCssPixelValue(-this._previousScrollPosition.top);\n root.classList.add('cdk-global-scrollblock');\n this._isEnabled = true;\n }\n }\n\n /** Unblocks page-level scroll while the attached overlay is open. */\n disable() {\n if (this._isEnabled) {\n const html = this._document.documentElement!;\n const body = this._document.body!;\n const htmlStyle = html.style;\n const bodyStyle = body.style;\n const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || '';\n const previousBodyScrollBehavior = bodyStyle.scrollBehavior || '';\n\n this._isEnabled = false;\n\n htmlStyle.left = this._previousHTMLStyles.left;\n htmlStyle.top = this._previousHTMLStyles.top;\n html.classList.remove('cdk-global-scrollblock');\n\n // Disable user-defined smooth scrolling temporarily while we restore the scroll position.\n // See https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior\n // Note that we don't mutate the property if the browser doesn't support `scroll-behavior`,\n // because it can throw off feature detections in `supportsScrollBehavior` which\n // checks for `'scrollBehavior' in documentElement.style`.\n if (scrollBehaviorSupported) {\n htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto';\n }\n\n window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top);\n\n if (scrollBehaviorSupported) {\n htmlStyle.scrollBehavior = previousHtmlScrollBehavior;\n bodyStyle.scrollBehavior = previousBodyScrollBehavior;\n }\n }\n }\n\n private _canBeEnabled(): boolean {\n // Since the scroll strategies can't be singletons, we have to use a global CSS class\n // (`cdk-global-scrollblock`) to make sure that we don't try to disable global\n // scrolling multiple times.\n const html = this._document.documentElement!;\n\n if (html.classList.contains('cdk-global-scrollblock') || this._isEnabled) {\n return false;\n }\n\n const body = this._document.body;\n const viewport = this._viewportRuler.getViewportSize();\n return body.scrollHeight > viewport.height || body.scrollWidth > viewport.width;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {NgZone} from '@angular/core';\nimport {ScrollStrategy, getMatScrollStrategyAlreadyAttachedError} from './scroll-strategy';\nimport {OverlayReference} from '../overlay-reference';\nimport {Subscription} from 'rxjs';\nimport {ScrollDispatcher, ViewportRuler} from '@angular/cdk/scrolling';\nimport {filter} from 'rxjs/operators';\n\n/**\n * Config options for the CloseScrollStrategy.\n */\nexport interface CloseScrollStrategyConfig {\n /** Amount of pixels the user has to scroll before the overlay is closed. */\n threshold?: number;\n}\n\n/**\n * Strategy that will close the overlay as soon as the user starts scrolling.\n */\nexport class CloseScrollStrategy implements ScrollStrategy {\n private _scrollSubscription: Subscription | null = null;\n private _overlayRef: OverlayReference;\n private _initialScrollPosition: number;\n\n constructor(\n private _scrollDispatcher: ScrollDispatcher,\n private _ngZone: NgZone,\n private _viewportRuler: ViewportRuler,\n private _config?: CloseScrollStrategyConfig,\n ) {}\n\n /** Attaches this scroll strategy to an overlay. */\n attach(overlayRef: OverlayReference) {\n if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatScrollStrategyAlreadyAttachedError();\n }\n\n this._overlayRef = overlayRef;\n }\n\n /** Enables the closing of the attached overlay on scroll. */\n enable() {\n if (this._scrollSubscription) {\n return;\n }\n\n const stream = this._scrollDispatcher.scrolled(0).pipe(\n filter(scrollable => {\n return (\n !scrollable ||\n !this._overlayRef.overlayElement.contains(scrollable.getElementRef().nativeElement)\n );\n }),\n );\n\n if (this._config && this._config.threshold && this._config.threshold > 1) {\n this._initialScrollPosition = this._viewportRuler.getViewportScrollPosition().top;\n\n this._scrollSubscription = stream.subscribe(() => {\n const scrollPosition = this._viewportRuler.getViewportScrollPosition().top;\n\n if (Math.abs(scrollPosition - this._initialScrollPosition) > this._config!.threshold!) {\n this._detach();\n } else {\n this._overlayRef.updatePosition();\n }\n });\n } else {\n this._scrollSubscription = stream.subscribe(this._detach);\n }\n }\n\n /** Disables the closing the attached overlay on scroll. */\n disable() {\n if (this._scrollSubscription) {\n this._scrollSubscription.unsubscribe();\n this._scrollSubscription = null;\n }\n }\n\n detach() {\n this.disable();\n this._overlayRef = null!;\n }\n\n /** Detaches the overlay ref and disables the scroll strategy. */\n private _detach = () => {\n this.disable();\n\n if (this._overlayRef.hasAttached()) {\n this._ngZone.run(() => this._overlayRef.detach());\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ScrollStrategy} from './scroll-strategy';\n\n/** Scroll strategy that doesn't do anything. */\nexport class NoopScrollStrategy implements ScrollStrategy {\n /** Does nothing, as this scroll strategy is a no-op. */\n enable() {}\n /** Does nothing, as this scroll strategy is a no-op. */\n disable() {}\n /** Does nothing, as this scroll strategy is a no-op. */\n attach() {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// TODO(jelbourn): move this to live with the rest of the scrolling code\n// TODO(jelbourn): someday replace this with IntersectionObservers\n\n/** Equivalent of `ClientRect` without some of the properties we don't care about. */\ntype Dimensions = Omit<ClientRect, 'x' | 'y' | 'toJSON'>;\n\n/**\n * Gets whether an element is scrolled outside of view by any of its parent scrolling containers.\n * @param element Dimensions of the element (from getBoundingClientRect)\n * @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)\n * @returns Whether the element is scrolled out of view\n * @docs-private\n */\nexport function isElementScrolledOutsideView(element: Dimensions, scrollContainers: Dimensions[]) {\n return scrollContainers.some(containerBounds => {\n const outsideAbove = element.bottom < containerBounds.top;\n const outsideBelow = element.top > containerBounds.bottom;\n const outsideLeft = element.right < containerBounds.left;\n const outsideRight = element.left > containerBounds.right;\n\n return outsideAbove || outsideBelow || outsideLeft || outsideRight;\n });\n}\n\n/**\n * Gets whether an element is clipped by any of its scrolling containers.\n * @param element Dimensions of the element (from getBoundingClientRect)\n * @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)\n * @returns Whether the element is clipped\n * @docs-private\n */\nexport function isElementClippedByScrolling(element: Dimensions, scrollContainers: Dimensions[]) {\n return scrollContainers.some(scrollContainerRect => {\n const clippedAbove = element.top < scrollContainerRect.top;\n const clippedBelow = element.bottom > scrollContainerRect.bottom;\n const clippedLeft = element.left < scrollContainerRect.left;\n const clippedRight = element.right > scrollContainerRect.right;\n\n return clippedAbove || clippedBelow || clippedLeft || clippedRight;\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgZone} from '@angular/core';\nimport {Subscription} from 'rxjs';\nimport {ScrollStrategy, getMatScrollStrategyAlreadyAttachedError} from './scroll-strategy';\nimport {OverlayReference} from '../overlay-reference';\nimport {ScrollDispatcher, ViewportRuler} from '@angular/cdk/scrolling';\nimport {isElementScrolledOutsideView} from '../position/scroll-clip';\n\n/**\n * Config options for the RepositionScrollStrategy.\n */\nexport interface RepositionScrollStrategyConfig {\n /** Time in milliseconds to throttle the scroll events. */\n scrollThrottle?: number;\n\n /** Whether to close the overlay once the user has scrolled away completely. */\n autoClose?: boolean;\n}\n\n/**\n * Strategy that will update the element position as the user is scrolling.\n */\nexport class RepositionScrollStrategy implements ScrollStrategy {\n private _scrollSubscription: Subscription | null = null;\n private _overlayRef: OverlayReference;\n\n constructor(\n private _scrollDispatcher: ScrollDispatcher,\n private _viewportRuler: ViewportRuler,\n private _ngZone: NgZone,\n private _config?: RepositionScrollStrategyConfig,\n ) {}\n\n /** Attaches this scroll strategy to an overlay. */\n attach(overlayRef: OverlayReference) {\n if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatScrollStrategyAlreadyAttachedError();\n }\n\n this._overlayRef = overlayRef;\n }\n\n /** Enables repositioning of the attached overlay on scroll. */\n enable() {\n if (!this._scrollSubscription) {\n const throttle = this._config ? this._config.scrollThrottle : 0;\n\n this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe(() => {\n this._overlayRef.updatePosition();\n\n // TODO(crisbeto): make `close` on by default once all components can handle it.\n if (this._config && this._config.autoClose) {\n const overlayRect = this._overlayRef.overlayElement.getBoundingClientRect();\n const {width, height} = this._viewportRuler.getViewportSize();\n\n // TODO(crisbeto): include all ancestor scroll containers here once\n // we have a way of exposing the trigger element to the scroll strategy.\n const parentRects = [{width, height, bottom: height, right: width, top: 0, left: 0}];\n\n if (isElementScrolledOutsideView(overlayRect, parentRects)) {\n this.disable();\n this._ngZone.run(() => this._overlayRef.detach());\n }\n }\n });\n }\n }\n\n /** Disables repositioning of the attached overlay on scroll. */\n disable() {\n if (this._scrollSubscription) {\n this._scrollSubscription.unsubscribe();\n this._scrollSubscription = null;\n }\n }\n\n detach() {\n this.disable();\n this._overlayRef = null!;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ScrollDispatcher, ViewportRuler} from '@angular/cdk/scrolling';\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, NgZone} from '@angular/core';\nimport {BlockScrollStrategy} from './block-scroll-strategy';\nimport {CloseScrollStrategy, CloseScrollStrategyConfig} from './close-scroll-strategy';\nimport {NoopScrollStrategy} from './noop-scroll-strategy';\nimport {\n RepositionScrollStrategy,\n RepositionScrollStrategyConfig,\n} from './reposition-scroll-strategy';\n\n/**\n * Options for how an overlay will handle scrolling.\n *\n * Users can provide a custom value for `ScrollStrategyOptions` to replace the default\n * behaviors. This class primarily acts as a factory for ScrollStrategy instances.\n */\n@Injectable({providedIn: 'root'})\nexport class ScrollStrategyOptions {\n private _document: Document;\n\n constructor(\n private _scrollDispatcher: ScrollDispatcher,\n private _viewportRuler: ViewportRuler,\n private _ngZone: NgZone,\n @Inject(DOCUMENT) document: any,\n ) {\n this._document = document;\n }\n\n /** Do nothing on scroll. */\n noop = () => new NoopScrollStrategy();\n\n /**\n * Close the overlay as soon as the user scrolls.\n * @param config Configuration to be used inside the scroll strategy.\n */\n close = (config?: CloseScrollStrategyConfig) =>\n new CloseScrollStrategy(this._scrollDispatcher, this._ngZone, this._viewportRuler, config);\n\n /** Block scrolling. */\n block = () => new BlockScrollStrategy(this._viewportRuler, this._document);\n\n /**\n * Update the overlay's position on scroll.\n * @param config Configuration to be used inside the scroll strategy.\n * Allows debouncing the reposition calls.\n */\n reposition = (config?: RepositionScrollStrategyConfig) =>\n new RepositionScrollStrategy(this._scrollDispatcher, this._viewportRuler, this._ngZone, config);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {PositionStrategy} from './position/position-strategy';\nimport {Direction, Directionality} from '@angular/cdk/bidi';\nimport {ScrollStrategy, NoopScrollStrategy} from './scroll/index';\n\n/** Initial configuration used when creating an overlay. */\nexport class OverlayConfig {\n /** Strategy with which to position the overlay. */\n positionStrategy?: PositionStrategy;\n\n /** Strategy to be used when handling scroll events while the overlay is open. */\n scrollStrategy?: ScrollStrategy = new NoopScrollStrategy();\n\n /** Custom class to add to the overlay pane. */\n panelClass?: string | string[] = '';\n\n /** Whether the overlay has a backdrop. */\n hasBackdrop?: boolean = false;\n\n /** Custom class to add to the backdrop */\n backdropClass?: string | string[] = 'cdk-overlay-dark-backdrop';\n\n /** The width of the overlay panel. If a number is provided, pixel units are assumed. */\n width?: number | string;\n\n /** The height of the overlay panel. If a number is provided, pixel units are assumed. */\n height?: number | string;\n\n /** The min-width of the overlay panel. If a number is provided, pixel units are assumed. */\n minWidth?: number | string;\n\n /** The min-height of the overlay panel. If a number is provided, pixel units are assumed. */\n minHeight?: number | string;\n\n /** The max-width of the overlay panel. If a number is provided, pixel units are assumed. */\n maxWidth?: number | string;\n\n /** The max-height of the overlay panel. If a number is provided, pixel units are assumed. */\n maxHeight?: number | string;\n\n /**\n * Direction of the text in the overlay panel. If a `Directionality` instance\n * is passed in, the overlay will handle changes to its value automatically.\n */\n direction?: Direction | Directionality;\n\n /**\n * Whether the overlay should be disposed of when the user goes backwards/forwards in history.\n * Note that this usually doesn't include clicking on links (unless the user is using\n * the `HashLocationStrategy`).\n */\n disposeOnNavigation?: boolean = false;\n\n constructor(config?: OverlayConfig) {\n if (config) {\n // Use `Iterable` instead of `Array` because TypeScript, as of 3.6.3,\n // loses the array generic type in the `for of`. But we *also* have to use `Array` because\n // typescript won't iterate over an `Iterable` unless you compile with `--downlevelIteration`\n const configKeys = Object.keys(config) as Iterable<keyof OverlayConfig> &\n (keyof OverlayConfig)[];\n for (const key of configKeys) {\n if (config[key] !== undefined) {\n // TypeScript, as of version 3.5, sees the left-hand-side of this expression\n // as \"I don't know *which* key this is, so the only valid value is the intersection\n // of all the possible values.\" In this case, that happens to be `undefined`. TypeScript\n // is not smart enough to see that the right-hand-side is actually an access of the same\n // exact type with the same exact key, meaning that the value type must be identical.\n // So we use `any` to work around this.\n this[key] = config[key] as any;\n }\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Horizontal dimension of a connection point on the perimeter of the origin or overlay element. */\nexport type HorizontalConnectionPos = 'start' | 'center' | 'end';\n\n/** Vertical dimension of a connection point on the perimeter of the origin or overlay element. */\nexport type VerticalConnectionPos = 'top' | 'center' | 'bottom';\n\n/** A connection point on the origin element. */\nexport interface OriginConnectionPosition {\n originX: HorizontalConnectionPos;\n originY: VerticalConnectionPos;\n}\n\n/** A connection point on the overlay element. */\nexport interface OverlayConnectionPosition {\n overlayX: HorizontalConnectionPos;\n overlayY: VerticalConnectionPos;\n}\n\n/** The points of the origin element and the overlay element to connect. */\nexport class ConnectionPositionPair {\n /** X-axis attachment point for connected overlay origin. Can be 'start', 'end', or 'center'. */\n originX: HorizontalConnectionPos;\n /** Y-axis attachment point for connected overlay origin. Can be 'top', 'bottom', or 'center'. */\n originY: VerticalConnectionPos;\n /** X-axis attachment point for connected overlay. Can be 'start', 'end', or 'center'. */\n overlayX: HorizontalConnectionPos;\n /** Y-axis attachment point for connected overlay. Can be 'top', 'bottom', or 'center'. */\n overlayY: VerticalConnectionPos;\n\n constructor(\n origin: OriginConnectionPosition,\n overlay: OverlayConnectionPosition,\n /** Offset along the X axis. */\n public offsetX?: number,\n /** Offset along the Y axis. */\n public offsetY?: number,\n /** Class(es) to be applied to the panel while this position is active. */\n public panelClass?: string | string[],\n ) {\n this.originX = origin.originX;\n this.originY = origin.originY;\n this.overlayX = overlay.overlayX;\n this.overlayY = overlay.overlayY;\n }\n}\n\n/**\n * Set of properties regarding the position of the origin and overlay relative to the viewport\n * with respect to the containing Scrollable elements.\n *\n * The overlay and origin are clipped if any part of their bounding client rectangle exceeds the\n * bounds of any one of the strategy's Scrollable's bounding client rectangle.\n *\n * The overlay and origin are outside view if there is no overlap between their bounding client\n * rectangle and any one of the strategy's Scrollable's bounding client rectangle.\n *\n * ----------- -----------\n * | outside | | clipped |\n * | view | --------------------------\n * | | | | | |\n * ---------- | ----------- |\n * -------------------------- | |\n * | | | Scrollable |\n * | | | |\n * | | --------------------------\n * | Scrollable |\n * | |\n * --------------------------\n *\n * @docs-private\n */\nexport class ScrollingVisibility {\n isOriginClipped: boolean;\n isOriginOutsideView: boolean;\n isOverlayClipped: boolean;\n isOverlayOutsideView: boolean;\n}\n\n/** The change event emitted by the strategy when a fallback position is used. */\nexport class ConnectedOverlayPositionChange {\n constructor(\n /** The position used as a result of this change. */\n public connectionPair: ConnectionPositionPair,\n /** @docs-private */\n public scrollableViewProperties: ScrollingVisibility,\n ) {}\n}\n\n/**\n * Validates whether a vertical position property matches the expected values.\n * @param property Name of the property being validated.\n * @param value Value of the property being validated.\n * @docs-private\n */\nexport function validateVerticalPosition(property: string, value: VerticalConnectionPos) {\n if (value !== 'top' && value !== 'bottom' && value !== 'center') {\n throw Error(\n `ConnectedPosition: Invalid ${property} \"${value}\". ` +\n `Expected \"top\", \"bottom\" or \"center\".`,\n );\n }\n}\n\n/**\n * Validates whether a horizontal position property matches the expected values.\n * @param property Name of the property being validated.\n * @param value Value of the property being validated.\n * @docs-private\n */\nexport function validateHorizontalPosition(property: string, value: HorizontalConnectionPos) {\n if (value !== 'start' && value !== 'end' && value !== 'center') {\n throw Error(\n `ConnectedPosition: Invalid ${property} \"${value}\". ` +\n `Expected \"start\", \"end\" or \"center\".`,\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, OnDestroy} from '@angular/core';\nimport {OverlayReference} from '../overlay-reference';\n\n/**\n * Service for dispatching events that land on the body to appropriate overlay ref,\n * if any. It maintains a list of attached overlays to determine best suited overlay based\n * on event target and order of overlay opens.\n */\n@Injectable({providedIn: 'root'})\nexport abstract class BaseOverlayDispatcher implements OnDestroy {\n /** Currently attached overlays in the order they were attached. */\n _attachedOverlays: OverlayReference[] = [];\n\n protected _document: Document;\n protected _isAttached: boolean;\n\n constructor(@Inject(DOCUMENT) document: any) {\n this._document = document;\n }\n\n ngOnDestroy(): void {\n this.detach();\n }\n\n /** Add a new overlay to the list of attached overlay refs. */\n add(overlayRef: OverlayReference): void {\n // Ensure that we don't get the same overlay multiple times.\n this.remove(overlayRef);\n this._attachedOverlays.push(overlayRef);\n }\n\n /** Remove an overlay from the list of attached overlay refs. */\n remove(overlayRef: OverlayReference): void {\n const index = this._attachedOverlays.indexOf(overlayRef);\n\n if (index > -1) {\n this._attachedOverlays.splice(index, 1);\n }\n\n // Remove the global listener once there are no more overlays.\n if (this._attachedOverlays.length === 0) {\n this.detach();\n }\n }\n\n /** Detaches the global event listener. */\n protected abstract detach(): void;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, NgZone, Optional} from '@angular/core';\nimport {OverlayReference} from '../overlay-reference';\nimport {BaseOverlayDispatcher} from './base-overlay-dispatcher';\n\n/**\n * Service for dispatching keyboard events that land on the body to appropriate overlay ref,\n * if any. It maintains a list of attached overlays to determine best suited overlay based\n * on event target and order of overlay opens.\n */\n@Injectable({providedIn: 'root'})\nexport class OverlayKeyboardDispatcher extends BaseOverlayDispatcher {\n constructor(\n @Inject(DOCUMENT) document: any,\n /** @breaking-change 14.0.0 _ngZone will be required. */\n @Optional() private _ngZone?: NgZone,\n ) {\n super(document);\n }\n\n /** Add a new overlay to the list of attached overlay refs. */\n override add(overlayRef: OverlayReference): void {\n super.add(overlayRef);\n\n // Lazily start dispatcher once first overlay is added\n if (!this._isAttached) {\n /** @breaking-change 14.0.0 _ngZone will be required. */\n if (this._ngZone) {\n this._ngZone.runOutsideAngular(() =>\n this._document.body.addEventListener('keydown', this._keydownListener),\n );\n } else {\n this._document.body.addEventListener('keydown', this._keydownListener);\n }\n this._isAttached = true;\n }\n }\n\n /** Detaches the global keyboard event listener. */\n protected detach() {\n if (this._isAttached) {\n this._document.body.removeEventListener('keydown', this._keydownListener);\n this._isAttached = false;\n }\n }\n\n /** Keyboard event listener that will be attached to the body. */\n private _keydownListener = (event: KeyboardEvent) => {\n const overlays = this._attachedOverlays;\n\n for (let i = overlays.length - 1; i > -1; i--) {\n // Dispatch the keydown event to the top overlay which has subscribers to its keydown events.\n // We want to target the most recent overlay, rather than trying to match where the event came\n // from, because some components might open an overlay, but keep focus on a trigger element\n // (e.g. for select and autocomplete). We skip overlays without keydown event subscriptions,\n // because we don't want overlays that don't handle keyboard events to block the ones below\n // them that do.\n if (overlays[i]._keydownEvents.observers.length > 0) {\n const keydownEvents = overlays[i]._keydownEvents;\n /** @breaking-change 14.0.0 _ngZone will be required. */\n if (this._ngZone) {\n this._ngZone.run(() => keydownEvents.next(event));\n } else {\n keydownEvents.next(event);\n }\n break;\n }\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, NgZone, Optional} from '@angular/core';\nimport {OverlayReference} from '../overlay-reference';\nimport {Platform, _getEventTarget} from '@angular/cdk/platform';\nimport {BaseOverlayDispatcher} from './base-overlay-dispatcher';\n\n/**\n * Service for dispatching mouse click events that land on the body to appropriate overlay ref,\n * if any. It maintains a list of attached overlays to determine best suited overlay based\n * on event target and order of overlay opens.\n */\n@Injectable({providedIn: 'root'})\nexport class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {\n private _cursorOriginalValue: string;\n private _cursorStyleIsSet = false;\n private _pointerDownEventTarget: EventTarget | null;\n\n constructor(\n @Inject(DOCUMENT) document: any,\n private _platform: Platform,\n /** @breaking-change 14.0.0 _ngZone will be required. */\n @Optional() private _ngZone?: NgZone,\n ) {\n super(document);\n }\n\n /** Add a new overlay to the list of attached overlay refs. */\n override add(overlayRef: OverlayReference): void {\n super.add(overlayRef);\n\n // Safari on iOS does not generate click events for non-interactive\n // elements. However, we want to receive a click for any element outside\n // the overlay. We can force a \"clickable\" state by setting\n // `cursor: pointer` on the document body. See:\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event#Safari_Mobile\n // https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html\n if (!this._isAttached) {\n const body = this._document.body;\n\n /** @breaking-change 14.0.0 _ngZone will be required. */\n if (this._ngZone) {\n this._ngZone.runOutsideAngular(() => this._addEventListeners(body));\n } else {\n this._addEventListeners(body);\n }\n\n // click event is not fired on iOS. To make element \"clickable\" we are\n // setting the cursor to pointer\n if (this._platform.IOS && !this._cursorStyleIsSet) {\n this._cursorOriginalValue = body.style.cursor;\n body.style.cursor = 'pointer';\n this._cursorStyleIsSet = true;\n }\n\n this._isAttached = true;\n }\n }\n\n /** Detaches the global keyboard event listener. */\n protected detach() {\n if (this._isAttached) {\n const body = this._document.body;\n body.removeEventListener('pointerdown', this._pointerDownListener, true);\n body.removeEventListener('click', this._clickListener, true);\n body.removeEventListener('auxclick', this._clickListener, true);\n body.removeEventListener('contextmenu', this._clickListener, true);\n if (this._platform.IOS && this._cursorStyleIsSet) {\n body.style.cursor = this._cursorOriginalValue;\n this._cursorStyleIsSet = false;\n }\n this._isAttached = false;\n }\n }\n\n private _addEventListeners(body: HTMLElement): void {\n body.addEventListener('pointerdown', this._pointerDownListener, true);\n body.addEventListener('click', this._clickListener, true);\n body.addEventListener('auxclick', this._clickListener, true);\n body.addEventListener('contextmenu', this._clickListener, true);\n }\n\n /** Store pointerdown event target to track origin of click. */\n private _pointerDownListener = (event: PointerEvent) => {\n this._pointerDownEventTarget = _getEventTarget(event);\n };\n\n /** Click event listener that will be attached to the body propagate phase. */\n private _clickListener = (event: MouseEvent) => {\n const target = _getEventTarget(event);\n // In case of a click event, we want to check the origin of the click\n // (e.g. in case where a user starts a click inside the overlay and\n // releases the click outside of it).\n // This is done by using the event target of the preceding pointerdown event.\n // Every click event caused by a pointer device has a preceding pointerdown\n // event, unless the click was programmatically triggered (e.g. in a unit test).\n const origin =\n event.type === 'click' && this._pointerDownEventTarget\n ? this._pointerDownEventTarget\n : target;\n // Reset the stored pointerdown event target, to avoid having it interfere\n // in subsequent events.\n this._pointerDownEventTarget = null;\n\n // We copy the array because the original may be modified asynchronously if the\n // outsidePointerEvents listener decides to detach overlays resulting in index errors inside\n // the for loop.\n const overlays = this._attachedOverlays.slice();\n\n // Dispatch the mouse event to the top overlay which has subscribers to its mouse events.\n // We want to target all overlays for which the click could be considered as outside click.\n // As soon as we reach an overlay for which the click is not outside click we break off\n // the loop.\n for (let i = overlays.length - 1; i > -1; i--) {\n const overlayRef = overlays[i];\n if (overlayRef._outsidePointerEvents.observers.length < 1 || !overlayRef.hasAttached()) {\n continue;\n }\n\n // If it's a click inside the overlay, just break - we should do nothing\n // If it's an outside click (both origin and target of the click) dispatch the mouse event,\n // and proceed with the next overlay\n if (\n overlayRef.overlayElement.contains(target as Node) ||\n overlayRef.overlayElement.contains(origin as Node)\n ) {\n break;\n }\n\n const outsidePointerEvents = overlayRef._outsidePointerEvents;\n /** @breaking-change 14.0.0 _ngZone will be required. */\n if (this._ngZone) {\n this._ngZone.run(() => outsidePointerEvents.next(event));\n } else {\n outsidePointerEvents.next(event);\n }\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, OnDestroy} from '@angular/core';\nimport {Platform, _isTestEnvironment} from '@angular/cdk/platform';\n\n/** Container inside which all overlays will render. */\n@Injectable({providedIn: 'root'})\nexport class OverlayContainer implements OnDestroy {\n protected _containerElement: HTMLElement;\n protected _document: Document;\n\n constructor(@Inject(DOCUMENT) document: any, protected _platform: Platform) {\n this._document = document;\n }\n\n ngOnDestroy() {\n this._containerElement?.remove();\n }\n\n /**\n * This method returns the overlay container element. It will lazily\n * create the element the first time it is called to facilitate using\n * the container in non-browser environments.\n * @returns the container element\n */\n getContainerElement(): HTMLElement {\n if (!this._containerElement) {\n this._createContainer();\n }\n\n return this._containerElement;\n }\n\n /**\n * Create the overlay container element, which is simply a div\n * with the 'cdk-overlay-container' class on the document body.\n */\n protected _createContainer(): void {\n const containerClass = 'cdk-overlay-container';\n\n // TODO(crisbeto): remove the testing check once we have an overlay testing\n // module or Angular starts tearing down the testing `NgModule`. See:\n // https://github.com/angular/angular/issues/18831\n if (this._platform.isBrowser || _isTestEnvironment()) {\n const oppositePlatformContainers = this._document.querySelectorAll(\n `.${containerClass}[platform=\"server\"], ` + `.${containerClass}[platform=\"test\"]`,\n );\n\n // Remove any old containers from the opposite platform.\n // This can happen when transitioning from the server to the client.\n for (let i = 0; i < oppositePlatformContainers.length; i++) {\n oppositePlatformContainers[i].remove();\n }\n }\n\n const container = this._document.createElement('div');\n container.classList.add(containerClass);\n\n // A long time ago we kept adding new overlay containers whenever a new app was instantiated,\n // but at some point we added logic which clears the duplicate ones in order to avoid leaks.\n // The new logic was a little too aggressive since it was breaking some legitimate use cases.\n // To mitigate the problem we made it so that only containers from a different platform are\n // cleared, but the side-effect was that people started depending on the overly-aggressive\n // logic to clean up their tests for them. Until we can introduce an overlay-specific testing\n // module which does the cleanup, we try to detect that we're in a test environment and we\n // always clear the container. See #17006.\n // TODO(crisbeto): remove the test environment check once we have an overlay testing module.\n if (_isTestEnvironment()) {\n container.setAttribute('platform', 'test');\n } else if (!this._platform.isBrowser) {\n container.setAttribute('platform', 'server');\n }\n\n this._document.body.appendChild(container);\n this._containerElement = container;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Direction, Directionality} from '@angular/cdk/bidi';\nimport {ComponentPortal, Portal, PortalOutlet, TemplatePortal} from '@angular/cdk/portal';\nimport {ComponentRef, EmbeddedViewRef, NgZone} from '@angular/core';\nimport {Location} from '@angular/common';\nimport {Observable, Subject, merge, SubscriptionLike, Subscription} from 'rxjs';\nimport {take, takeUntil} from 'rxjs/operators';\nimport {OverlayKeyboardDispatcher} from './dispatchers/overlay-keyboard-dispatcher';\nimport {OverlayOutsideClickDispatcher} from './dispatchers/overlay-outside-click-dispatcher';\nimport {OverlayConfig} from './overlay-config';\nimport {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';\nimport {OverlayReference} from './overlay-reference';\nimport {PositionStrategy} from './position/position-strategy';\nimport {ScrollStrategy} from './scroll';\n\n/** An object where all of its properties cannot be written. */\nexport type ImmutableObject<T> = {\n readonly [P in keyof T]: T[P];\n};\n\n/**\n * Reference to an overlay that has been created with the Overlay service.\n * Used to manipulate or dispose of said overlay.\n */\nexport class OverlayRef implements PortalOutlet, OverlayReference {\n private _backdropElement: HTMLElement | null = null;\n private _backdropTimeout: number | undefined;\n private readonly _backdropClick = new Subject<MouseEvent>();\n private readonly _attachments = new Subject<void>();\n private readonly _detachments = new Subject<void>();\n private _positionStrategy: PositionStrategy | undefined;\n private _scrollStrategy: ScrollStrategy | undefined;\n private _locationChanges: SubscriptionLike = Subscription.EMPTY;\n private _backdropClickHandler = (event: MouseEvent) => this._backdropClick.next(event);\n private _backdropTransitionendHandler = (event: TransitionEvent) => {\n this._disposeBackdrop(event.target as HTMLElement | null);\n };\n\n /**\n * Reference to the parent of the `_host` at the time it was detached. Used to restore\n * the `_host` to its original position in the DOM when it gets re-attached.\n */\n private _previousHostParent: HTMLElement;\n\n /** Stream of keydown events dispatched to this overlay. */\n readonly _keydownEvents = new Subject<KeyboardEvent>();\n\n /** Stream of mouse outside events dispatched to this overlay. */\n readonly _outsidePointerEvents = new Subject<MouseEvent>();\n\n constructor(\n private _portalOutlet: PortalOutlet,\n private _host: HTMLElement,\n private _pane: HTMLElement,\n private _config: ImmutableObject<OverlayConfig>,\n private _ngZone: NgZone,\n private _keyboardDispatcher: OverlayKeyboardDispatcher,\n private _document: Document,\n private _location: Location,\n private _outsideClickDispatcher: OverlayOutsideClickDispatcher,\n private _animationsDisabled = false,\n ) {\n if (_config.scrollStrategy) {\n this._scrollStrategy = _config.scrollStrategy;\n this._scrollStrategy.attach(this);\n }\n\n this._positionStrategy = _config.positionStrategy;\n }\n\n /** The overlay's HTML element */\n get overlayElement(): HTMLElement {\n return this._pane;\n }\n\n /** The overlay's backdrop HTML element. */\n get backdropElement(): HTMLElement | null {\n return this._backdropElement;\n }\n\n /**\n * Wrapper around the panel element. Can be used for advanced\n * positioning where a wrapper with specific styling is\n * required around the overlay pane.\n */\n get hostElement(): HTMLElement {\n return this._host;\n }\n\n attach<T>(portal: ComponentPortal<T>): ComponentRef<T>;\n attach<T>(portal: TemplatePortal<T>): EmbeddedViewRef<T>;\n attach(portal: any): any;\n\n /**\n * Attaches content, given via a Portal, to the overlay.\n * If the overlay is configured to have a backdrop, it will be created.\n *\n * @param portal Portal instance to which to attach the overlay.\n * @returns The portal attachment result.\n */\n attach(portal: Portal<any>): any {\n // Insert the host into the DOM before attaching the portal, otherwise\n // the animations module will skip animations on repeat attachments.\n if (!this._host.parentElement && this._previousHostParent) {\n this._previousHostParent.appendChild(this._host);\n }\n\n const attachResult = this._portalOutlet.attach(portal);\n\n if (this._positionStrategy) {\n this._positionStrategy.attach(this);\n }\n\n this._updateStackingOrder();\n this._updateElementSize();\n this._updateElementDirection();\n\n if (this._scrollStrategy) {\n this._scrollStrategy.enable();\n }\n\n // Update the position once the zone is stable so that the overlay will be fully rendered\n // before attempting to position it, as the position may depend on the size of the rendered\n // content.\n this._ngZone.onStable.pipe(take(1)).subscribe(() => {\n // The overlay could've been detached before the zone has stabilized.\n if (this.hasAttached()) {\n this.updatePosition();\n }\n });\n\n // Enable pointer events for the overlay pane element.\n this._togglePointerEvents(true);\n\n if (this._config.hasBackdrop) {\n this._attachBackdrop();\n }\n\n if (this._config.panelClass) {\n this._toggleClasses(this._pane, this._config.panelClass, true);\n }\n\n // Only emit the `attachments` event once all other setup is done.\n this._attachments.next();\n\n // Track this overlay by the keyboard dispatcher\n this._keyboardDispatcher.add(this);\n\n if (this._config.disposeOnNavigation) {\n this._locationChanges = this._location.subscribe(() => this.dispose());\n }\n\n this._outsideClickDispatcher.add(this);\n\n // TODO(crisbeto): the null check is here, because the portal outlet returns `any`.\n // We should be guaranteed for the result to be `ComponentRef | EmbeddedViewRef`, but\n // `instanceof EmbeddedViewRef` doesn't appear to work at the moment.\n if (typeof attachResult?.onDestroy === 'function') {\n // In most cases we control the portal and we know when it is being detached so that\n // we can finish the disposal process. The exception is if the user passes in a custom\n // `ViewContainerRef` that isn't destroyed through the overlay API. Note that we use\n // `detach` here instead of `dispose`, because we don't know if the user intends to\n // reattach the overlay at a later point. It also has the advantage of waiting for animations.\n attachResult.onDestroy(() => {\n if (this.hasAttached()) {\n // We have to delay the `detach` call, because detaching immediately prevents\n // other destroy hooks from running. This is likely a framework bug similar to\n // https://github.com/angular/angular/issues/46119\n this._ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.detach()));\n }\n });\n }\n\n return attachResult;\n }\n\n /**\n * Detaches an overlay from a portal.\n * @returns The portal detachment result.\n */\n detach(): any {\n if (!this.hasAttached()) {\n return;\n }\n\n this.detachBackdrop();\n\n // When the overlay is detached, the pane element should disable pointer events.\n // This is necessary because otherwise the pane element will cover the page and disable\n // pointer events therefore. Depends on the position strategy and the applied pane boundaries.\n this._togglePointerEvents(false);\n\n if (this._positionStrategy && this._positionStrategy.detach) {\n this._positionStrategy.detach();\n }\n\n if (this._scrollStrategy) {\n this._scrollStrategy.disable();\n }\n\n const detachmentResult = this._portalOutlet.detach();\n\n // Only emit after everything is detached.\n this._detachments.next();\n\n // Remove this overlay from keyboard dispatcher tracking.\n this._keyboardDispatcher.remove(this);\n\n // Keeping the host element in the DOM can cause scroll jank, because it still gets\n // rendered, even though it's transparent and unclickable which is why we remove it.\n this._detachContentWhenStable();\n this._locationChanges.unsubscribe();\n this._outsideClickDispatcher.remove(this);\n return detachmentResult;\n }\n\n /** Cleans up the overlay from the DOM. */\n dispose(): void {\n const isAttached = this.hasAttached();\n\n if (this._positionStrategy) {\n this._positionStrategy.dispose();\n }\n\n this._disposeScrollStrategy();\n this._disposeBackdrop(this._backdropElement);\n this._locationChanges.unsubscribe();\n this._keyboardDispatcher.remove(this);\n this._portalOutlet.dispose();\n this._attachments.complete();\n this._backdropClick.complete();\n this._keydownEvents.complete();\n this._outsidePointerEvents.complete();\n this._outsideClickDispatcher.remove(this);\n this._host?.remove();\n\n this._previousHostParent = this._pane = this._host = null!;\n\n if (isAttached) {\n this._detachments.next();\n }\n\n this._detachments.complete();\n }\n\n /** Whether the overlay has attached content. */\n hasAttached(): boolean {\n return this._portalOutlet.hasAttached();\n }\n\n /** Gets an observable that emits when the backdrop has been clicked. */\n backdropClick(): Observable<MouseEvent> {\n return this._backdropClick;\n }\n\n /** Gets an observable that emits when the overlay has been attached. */\n attachments(): Observable<void> {\n return this._attachments;\n }\n\n /** Gets an observable that emits when the overlay has been detached. */\n detachments(): Observable<void> {\n return this._detachments;\n }\n\n /** Gets an observable of keydown events targeted to this overlay. */\n keydownEvents(): Observable<KeyboardEvent> {\n return this._keydownEvents;\n }\n\n /** Gets an observable of pointer events targeted outside this overlay. */\n outsidePointerEvents(): Observable<MouseEvent> {\n return this._outsidePointerEvents;\n }\n\n /** Gets the current overlay configuration, which is immutable. */\n getConfig(): OverlayConfig {\n return this._config;\n }\n\n /** Updates the position of the overlay based on the position strategy. */\n updatePosition(): void {\n if (this._positionStrategy) {\n this._positionStrategy.apply();\n }\n }\n\n /** Switches to a new position strategy and updates the overlay position. */\n updatePositionStrategy(strategy: PositionStrategy): void {\n if (strategy === this._positionStrategy) {\n return;\n }\n\n if (this._positionStrategy) {\n this._positionStrategy.dispose();\n }\n\n this._positionStrategy = strategy;\n\n if (this.hasAttached()) {\n strategy.attach(this);\n this.updatePosition();\n }\n }\n\n /** Update the size properties of the overlay. */\n updateSize(sizeConfig: OverlaySizeConfig): void {\n this._config = {...this._config, ...sizeConfig};\n this._updateElementSize();\n }\n\n /** Sets the LTR/RTL direction for the overlay. */\n setDirection(dir: Direction | Directionality): void {\n this._config = {...this._config, direction: dir};\n this._updateElementDirection();\n }\n\n /** Add a CSS class or an array of classes to the overlay pane. */\n addPanelClass(classes: string | string[]): void {\n if (this._pane) {\n this._toggleClasses(this._pane, classes, true);\n }\n }\n\n /** Remove a CSS class or an array of classes from the overlay pane. */\n removePanelClass(classes: string | string[]): void {\n if (this._pane) {\n this._toggleClasses(this._pane, classes, false);\n }\n }\n\n /**\n * Returns the layout direction of the overlay panel.\n */\n getDirection(): Direction {\n const direction = this._config.direction;\n\n if (!direction) {\n return 'ltr';\n }\n\n return typeof direction === 'string' ? direction : direction.value;\n }\n\n /** Switches to a new scroll strategy. */\n updateScrollStrategy(strategy: ScrollStrategy): void {\n if (strategy === this._scrollStrategy) {\n return;\n }\n\n this._disposeScrollStrategy();\n this._scrollStrategy = strategy;\n\n if (this.hasAttached()) {\n strategy.attach(this);\n strategy.enable();\n }\n }\n\n /** Updates the text direction of the overlay panel. */\n private _updateElementDirection() {\n this._host.setAttribute('dir', this.getDirection());\n }\n\n /** Updates the size of the overlay element based on the overlay config. */\n private _updateElementSize() {\n if (!this._pane) {\n return;\n }\n\n const style = this._pane.style;\n\n style.width = coerceCssPixelValue(this._config.width);\n style.height = coerceCssPixelValue(this._config.height);\n style.minWidth = coerceCssPixelValue(this._config.minWidth);\n style.minHeight = coerceCssPixelValue(this._config.minHeight);\n style.maxWidth = coerceCssPixelValue(this._config.maxWidth);\n style.maxHeight = coerceCssPixelValue(this._config.maxHeight);\n }\n\n /** Toggles the pointer events for the overlay pane element. */\n private _togglePointerEvents(enablePointer: boolean) {\n this._pane.style.pointerEvents = enablePointer ? '' : 'none';\n }\n\n /** Attaches a backdrop for this overlay. */\n private _attachBackdrop() {\n const showingClass = 'cdk-overlay-backdrop-showing';\n\n this._backdropElement = this._document.createElement('div');\n this._backdropElement.classList.add('cdk-overlay-backdrop');\n\n if (this._animationsDisabled) {\n this._backdropElement.classList.add('cdk-overlay-backdrop-noop-animation');\n }\n\n if (this._config.backdropClass) {\n this._toggleClasses(this._backdropElement, this._config.backdropClass, true);\n }\n\n // Insert the backdrop before the pane in the DOM order,\n // in order to handle stacked overlays properly.\n this._host.parentElement!.insertBefore(this._backdropElement, this._host);\n\n // Forward backdrop clicks such that the consumer of the overlay can perform whatever\n // action desired when such a click occurs (usually closing the overlay).\n this._backdropElement.addEventListener('click', this._backdropClickHandler);\n\n // Add class to fade-in the backdrop after one frame.\n if (!this._animationsDisabled && typeof requestAnimationFrame !== 'undefined') {\n this._ngZone.runOutsideAngular(() => {\n requestAnimationFrame(() => {\n if (this._backdropElement) {\n this._backdropElement.classList.add(showingClass);\n }\n });\n });\n } else {\n this._backdropElement.classList.add(showingClass);\n }\n }\n\n /**\n * Updates the stacking order of the element, moving it to the top if necessary.\n * This is required in cases where one overlay was detached, while another one,\n * that should be behind it, was destroyed. The next time both of them are opened,\n * the stacking will be wrong, because the detached element's pane will still be\n * in its original DOM position.\n */\n private _updateStackingOrder() {\n if (this._host.nextSibling) {\n this._host.parentNode!.appendChild(this._host);\n }\n }\n\n /** Detaches the backdrop (if any) associated with the overlay. */\n detachBackdrop(): void {\n const backdropToDetach = this._backdropElement;\n\n if (!backdropToDetach) {\n return;\n }\n\n if (this._animationsDisabled) {\n this._disposeBackdrop(backdropToDetach);\n return;\n }\n\n backdropToDetach.classList.remove('cdk-overlay-backdrop-showing');\n\n this._ngZone.runOutsideAngular(() => {\n backdropToDetach!.addEventListener('transitionend', this._backdropTransitionendHandler);\n });\n\n // If the backdrop doesn't have a transition, the `transitionend` event won't fire.\n // In this case we make it unclickable and we try to remove it after a delay.\n backdropToDetach.style.pointerEvents = 'none';\n\n // Run this outside the Angular zone because there's nothing that Angular cares about.\n // If it were to run inside the Angular zone, every test that used Overlay would have to be\n // either async or fakeAsync.\n this._backdropTimeout = this._ngZone.runOutsideAngular(() =>\n setTimeout(() => {\n this._disposeBackdrop(backdropToDetach);\n }, 500),\n );\n }\n\n /** Toggles a single CSS class or an array of classes on an element. */\n private _toggleClasses(element: HTMLElement, cssClasses: string | string[], isAdd: boolean) {\n const classes = coerceArray(cssClasses || []).filter(c => !!c);\n\n if (classes.length) {\n isAdd ? element.classList.add(...classes) : element.classList.remove(...classes);\n }\n }\n\n /** Detaches the overlay content next time the zone stabilizes. */\n private _detachContentWhenStable() {\n // Normally we wouldn't have to explicitly run this outside the `NgZone`, however\n // if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will\n // be patched to run inside the zone, which will throw us into an infinite loop.\n this._ngZone.runOutsideAngular(() => {\n // We can't remove the host here immediately, because the overlay pane's content\n // might still be animating. This stream helps us avoid interrupting the animation\n // by waiting for the pane to become empty.\n const subscription = this._ngZone.onStable\n .pipe(takeUntil(merge(this._attachments, this._detachments)))\n .subscribe(() => {\n // Needs a couple of checks for the pane and host, because\n // they may have been removed by the time the zone stabilizes.\n if (!this._pane || !this._host || this._pane.children.length === 0) {\n if (this._pane && this._config.panelClass) {\n this._toggleClasses(this._pane, this._config.panelClass, false);\n }\n\n if (this._host && this._host.parentElement) {\n this._previousHostParent = this._host.parentElement;\n this._host.remove();\n }\n\n subscription.unsubscribe();\n }\n });\n });\n }\n\n /** Disposes of a scroll strategy. */\n private _disposeScrollStrategy() {\n const scrollStrategy = this._scrollStrategy;\n\n if (scrollStrategy) {\n scrollStrategy.disable();\n\n if (scrollStrategy.detach) {\n scrollStrategy.detach();\n }\n }\n }\n\n /** Removes a backdrop element from the DOM. */\n private _disposeBackdrop(backdrop: HTMLElement | null) {\n if (backdrop) {\n backdrop.removeEventListener('click', this._backdropClickHandler);\n backdrop.removeEventListener('transitionend', this._backdropTransitionendHandler);\n backdrop.remove();\n\n // It is possible that a new portal has been attached to this overlay since we started\n // removing the backdrop. If that is the case, only clear the backdrop reference if it\n // is still the same instance that we started to remove.\n if (this._backdropElement === backdrop) {\n this._backdropElement = null;\n }\n }\n\n if (this._backdropTimeout) {\n clearTimeout(this._backdropTimeout);\n this._backdropTimeout = undefined;\n }\n }\n}\n\n/** Size properties for an overlay. */\nexport interface OverlaySizeConfig {\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n minHeight?: number | string;\n maxWidth?: number | string;\n maxHeight?: number | string;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {PositionStrategy} from './position-strategy';\nimport {ElementRef} from '@angular/core';\nimport {ViewportRuler, CdkScrollable, ViewportScrollPosition} from '@angular/cdk/scrolling';\nimport {\n ConnectedOverlayPositionChange,\n ConnectionPositionPair,\n ScrollingVisibility,\n validateHorizontalPosition,\n validateVerticalPosition,\n} from './connected-position';\nimport {Observable, Subscription, Subject} from 'rxjs';\nimport {OverlayReference} from '../overlay-reference';\nimport {isElementScrolledOutsideView, isElementClippedByScrolling} from './scroll-clip';\nimport {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';\nimport {Platform} from '@angular/cdk/platform';\nimport {OverlayContainer} from '../overlay-container';\n\n// TODO: refactor clipping detection into a separate thing (part of scrolling module)\n// TODO: doesn't handle both flexible width and height when it has to scroll along both axis.\n\n/** Class to be added to the overlay bounding box. */\nconst boundingBoxClass = 'cdk-overlay-connected-position-bounding-box';\n\n/** Regex used to split a string on its CSS units. */\nconst cssUnitPattern = /([A-Za-z%]+)$/;\n\n/** Possible values that can be set as the origin of a FlexibleConnectedPositionStrategy. */\nexport type FlexibleConnectedPositionStrategyOrigin =\n | ElementRef\n | Element\n | (Point & {\n width?: number;\n height?: number;\n });\n\n/** Equivalent of `ClientRect` without some of the properties we don't care about. */\ntype Dimensions = Omit<ClientRect, 'x' | 'y' | 'toJSON'>;\n\n/**\n * A strategy for positioning overlays. Using this strategy, an overlay is given an\n * implicit position relative some origin element. The relative position is defined in terms of\n * a point on the origin element that is connected to a point on the overlay element. For example,\n * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner\n * of the overlay.\n */\nexport class FlexibleConnectedPositionStrategy implements PositionStrategy {\n /** The overlay to which this strategy is attached. */\n private _overlayRef: OverlayReference;\n\n /** Whether we're performing the very first positioning of the overlay. */\n private _isInitialRender: boolean;\n\n /** Last size used for the bounding box. Used to avoid resizing the overlay after open. */\n private _lastBoundingBoxSize = {width: 0, height: 0};\n\n /** Whether the overlay was pushed in a previous positioning. */\n private _isPushed = false;\n\n /** Whether the overlay can be pushed on-screen on the initial open. */\n private _canPush = true;\n\n /** Whether the overlay can grow via flexible width/height after the initial open. */\n private _growAfterOpen = false;\n\n /** Whether the overlay's width and height can be constrained to fit within the viewport. */\n private _hasFlexibleDimensions = true;\n\n /** Whether the overlay position is locked. */\n private _positionLocked = false;\n\n /** Cached origin dimensions */\n private _originRect: Dimensions;\n\n /** Cached overlay dimensions */\n private _overlayRect: Dimensions;\n\n /** Cached viewport dimensions */\n private _viewportRect: Dimensions;\n\n /** Cached container dimensions */\n private _containerRect: Dimensions;\n\n /** Amount of space that must be maintained between the overlay and the edge of the viewport. */\n private _viewportMargin = 0;\n\n /** The Scrollable containers used to check scrollable view properties on position change. */\n private _scrollables: CdkScrollable[] = [];\n\n /** Ordered list of preferred positions, from most to least desirable. */\n _preferredPositions: ConnectionPositionPair[] = [];\n\n /** The origin element against which the overlay will be positioned. */\n _origin: FlexibleConnectedPositionStrategyOrigin;\n\n /** The overlay pane element. */\n private _pane: HTMLElement;\n\n /** Whether the strategy has been disposed of already. */\n private _isDisposed: boolean;\n\n /**\n * Parent element for the overlay panel used to constrain the overlay panel's size to fit\n * within the viewport.\n */\n private _boundingBox: HTMLElement | null;\n\n /** The last position to have been calculated as the best fit position. */\n private _lastPosition: ConnectedPosition | null;\n\n /** Subject that emits whenever the position changes. */\n private readonly _positionChanges = new Subject<ConnectedOverlayPositionChange>();\n\n /** Subscription to viewport size changes. */\n private _resizeSubscription = Subscription.EMPTY;\n\n /** Default offset for the overlay along the x axis. */\n private _offsetX = 0;\n\n /** Default offset for the overlay along the y axis. */\n private _offsetY = 0;\n\n /** Selector to be used when finding the elements on which to set the transform origin. */\n private _transformOriginSelector: string;\n\n /** Keeps track of the CSS classes that the position strategy has applied on the overlay panel. */\n private _appliedPanelClasses: string[] = [];\n\n /** Amount by which the overlay was pushed in each axis during the last time it was positioned. */\n private _previousPushAmount: {x: number; y: number} | null;\n\n /** Observable sequence of position changes. */\n positionChanges: Observable<ConnectedOverlayPositionChange> = this._positionChanges;\n\n /** Ordered list of preferred positions, from most to least desirable. */\n get positions(): ConnectionPositionPair[] {\n return this._preferredPositions;\n }\n\n constructor(\n connectedTo: FlexibleConnectedPositionStrategyOrigin,\n private _viewportRuler: ViewportRuler,\n private _document: Document,\n private _platform: Platform,\n private _overlayContainer: OverlayContainer,\n ) {\n this.setOrigin(connectedTo);\n }\n\n /** Attaches this position strategy to an overlay. */\n attach(overlayRef: OverlayReference): void {\n if (\n this._overlayRef &&\n overlayRef !== this._overlayRef &&\n (typeof ngDevMode === 'undefined' || ngDevMode)\n ) {\n throw Error('This position strategy is already attached to an overlay');\n }\n\n this._validatePositions();\n\n overlayRef.hostElement.classList.add(boundingBoxClass);\n\n this._overlayRef = overlayRef;\n this._boundingBox = overlayRef.hostElement;\n this._pane = overlayRef.overlayElement;\n this._isDisposed = false;\n this._isInitialRender = true;\n this._lastPosition = null;\n this._resizeSubscription.unsubscribe();\n this._resizeSubscription = this._viewportRuler.change().subscribe(() => {\n // When the window is resized, we want to trigger the next reposition as if it\n // was an initial render, in order for the strategy to pick a new optimal position,\n // otherwise position locking will cause it to stay at the old one.\n this._isInitialRender = true;\n this.apply();\n });\n }\n\n /**\n * Updates the position of the overlay element, using whichever preferred position relative\n * to the origin best fits on-screen.\n *\n * The selection of a position goes as follows:\n * - If any positions fit completely within the viewport as-is,\n * choose the first position that does so.\n * - If flexible dimensions are enabled and at least one satisfies the given minimum width/height,\n * choose the position with the greatest available size modified by the positions' weight.\n * - If pushing is enabled, take the position that went off-screen the least and push it\n * on-screen.\n * - If none of the previous criteria were met, use the position that goes off-screen the least.\n * @docs-private\n */\n apply(): void {\n // We shouldn't do anything if the strategy was disposed or we're on the server.\n if (this._isDisposed || !this._platform.isBrowser) {\n return;\n }\n\n // If the position has been applied already (e.g. when the overlay was opened) and the\n // consumer opted into locking in the position, re-use the old position, in order to\n // prevent the overlay from jumping around.\n if (!this._isInitialRender && this._positionLocked && this._lastPosition) {\n this.reapplyLastPosition();\n return;\n }\n\n this._clearPanelClasses();\n this._resetOverlayElementStyles();\n this._resetBoundingBoxStyles();\n\n // We need the bounding rects for the origin, the overlay and the container to determine how to position\n // the overlay relative to the origin.\n // We use the viewport rect to determine whether a position would go off-screen.\n this._viewportRect = this._getNarrowedViewportRect();\n this._originRect = this._getOriginRect();\n this._overlayRect = this._pane.getBoundingClientRect();\n this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();\n\n const originRect = this._originRect;\n const overlayRect = this._overlayRect;\n const viewportRect = this._viewportRect;\n const containerRect = this._containerRect;\n\n // Positions where the overlay will fit with flexible dimensions.\n const flexibleFits: FlexibleFit[] = [];\n\n // Fallback if none of the preferred positions fit within the viewport.\n let fallback: FallbackPosition | undefined;\n\n // Go through each of the preferred positions looking for a good fit.\n // If a good fit is found, it will be applied immediately.\n for (let pos of this._preferredPositions) {\n // Get the exact (x, y) coordinate for the point-of-origin on the origin element.\n let originPoint = this._getOriginPoint(originRect, containerRect, pos);\n\n // From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the\n // overlay in this position. We use the top-left corner for calculations and later translate\n // this into an appropriate (top, left, bottom, right) style.\n let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);\n\n // Calculate how well the overlay would fit into the viewport with this point.\n let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos);\n\n // If the overlay, without any further work, fits into the viewport, use this position.\n if (overlayFit.isCompletelyWithinViewport) {\n this._isPushed = false;\n this._applyPosition(pos, originPoint);\n return;\n }\n\n // If the overlay has flexible dimensions, we can use this position\n // so long as there's enough space for the minimum dimensions.\n if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) {\n // Save positions where the overlay will fit with flexible dimensions. We will use these\n // if none of the positions fit *without* flexible dimensions.\n flexibleFits.push({\n position: pos,\n origin: originPoint,\n overlayRect,\n boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos),\n });\n\n continue;\n }\n\n // If the current preferred position does not fit on the screen, remember the position\n // if it has more visible area on-screen than we've seen and move onto the next preferred\n // position.\n if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) {\n fallback = {overlayFit, overlayPoint, originPoint, position: pos, overlayRect};\n }\n }\n\n // If there are any positions where the overlay would fit with flexible dimensions, choose the\n // one that has the greatest area available modified by the position's weight\n if (flexibleFits.length) {\n let bestFit: FlexibleFit | null = null;\n let bestScore = -1;\n for (const fit of flexibleFits) {\n const score =\n fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1);\n if (score > bestScore) {\n bestScore = score;\n bestFit = fit;\n }\n }\n\n this._isPushed = false;\n this._applyPosition(bestFit!.position, bestFit!.origin);\n return;\n }\n\n // When none of the preferred positions fit within the viewport, take the position\n // that went off-screen the least and attempt to push it on-screen.\n if (this._canPush) {\n // TODO(jelbourn): after pushing, the opening \"direction\" of the overlay might not make sense.\n this._isPushed = true;\n this._applyPosition(fallback!.position, fallback!.originPoint);\n return;\n }\n\n // All options for getting the overlay within the viewport have been exhausted, so go with the\n // position that went off-screen the least.\n this._applyPosition(fallback!.position, fallback!.originPoint);\n }\n\n detach(): void {\n this._clearPanelClasses();\n this._lastPosition = null;\n this._previousPushAmount = null;\n this._resizeSubscription.unsubscribe();\n }\n\n /** Cleanup after the element gets destroyed. */\n dispose(): void {\n if (this._isDisposed) {\n return;\n }\n\n // We can't use `_resetBoundingBoxStyles` here, because it resets\n // some properties to zero, rather than removing them.\n if (this._boundingBox) {\n extendStyles(this._boundingBox.style, {\n top: '',\n left: '',\n right: '',\n bottom: '',\n height: '',\n width: '',\n alignItems: '',\n justifyContent: '',\n } as CSSStyleDeclaration);\n }\n\n if (this._pane) {\n this._resetOverlayElementStyles();\n }\n\n if (this._overlayRef) {\n this._overlayRef.hostElement.classList.remove(boundingBoxClass);\n }\n\n this.detach();\n this._positionChanges.complete();\n this._overlayRef = this._boundingBox = null!;\n this._isDisposed = true;\n }\n\n /**\n * This re-aligns the overlay element with the trigger in its last calculated position,\n * even if a position higher in the \"preferred positions\" list would now fit. This\n * allows one to re-align the panel without changing the orientation of the panel.\n */\n reapplyLastPosition(): void {\n if (this._isDisposed || !this._platform.isBrowser) {\n return;\n }\n\n const lastPosition = this._lastPosition;\n\n if (lastPosition) {\n this._originRect = this._getOriginRect();\n this._overlayRect = this._pane.getBoundingClientRect();\n this._viewportRect = this._getNarrowedViewportRect();\n this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();\n\n const originPoint = this._getOriginPoint(this._originRect, this._containerRect, lastPosition);\n this._applyPosition(lastPosition, originPoint);\n } else {\n this.apply();\n }\n }\n\n /**\n * Sets the list of Scrollable containers that host the origin element so that\n * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every\n * Scrollable must be an ancestor element of the strategy's origin element.\n */\n withScrollableContainers(scrollables: CdkScrollable[]): this {\n this._scrollables = scrollables;\n return this;\n }\n\n /**\n * Adds new preferred positions.\n * @param positions List of positions options for this overlay.\n */\n withPositions(positions: ConnectedPosition[]): this {\n this._preferredPositions = positions;\n\n // If the last calculated position object isn't part of the positions anymore, clear\n // it in order to avoid it being picked up if the consumer tries to re-apply.\n if (positions.indexOf(this._lastPosition!) === -1) {\n this._lastPosition = null;\n }\n\n this._validatePositions();\n\n return this;\n }\n\n /**\n * Sets a minimum distance the overlay may be positioned to the edge of the viewport.\n * @param margin Required margin between the overlay and the viewport edge in pixels.\n */\n withViewportMargin(margin: number): this {\n this._viewportMargin = margin;\n return this;\n }\n\n /** Sets whether the overlay's width and height can be constrained to fit within the viewport. */\n withFlexibleDimensions(flexibleDimensions = true): this {\n this._hasFlexibleDimensions = flexibleDimensions;\n return this;\n }\n\n /** Sets whether the overlay can grow after the initial open via flexible width/height. */\n withGrowAfterOpen(growAfterOpen = true): this {\n this._growAfterOpen = growAfterOpen;\n return this;\n }\n\n /** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */\n withPush(canPush = true): this {\n this._canPush = canPush;\n return this;\n }\n\n /**\n * Sets whether the overlay's position should be locked in after it is positioned\n * initially. When an overlay is locked in, it won't attempt to reposition itself\n * when the position is re-applied (e.g. when the user scrolls away).\n * @param isLocked Whether the overlay should locked in.\n */\n withLockedPosition(isLocked = true): this {\n this._positionLocked = isLocked;\n return this;\n }\n\n /**\n * Sets the origin, relative to which to position the overlay.\n * Using an element origin is useful for building components that need to be positioned\n * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be\n * used for cases like contextual menus which open relative to the user's pointer.\n * @param origin Reference to the new origin.\n */\n setOrigin(origin: FlexibleConnectedPositionStrategyOrigin): this {\n this._origin = origin;\n return this;\n }\n\n /**\n * Sets the default offset for the overlay's connection point on the x-axis.\n * @param offset New offset in the X axis.\n */\n withDefaultOffsetX(offset: number): this {\n this._offsetX = offset;\n return this;\n }\n\n /**\n * Sets the default offset for the overlay's connection point on the y-axis.\n * @param offset New offset in the Y axis.\n */\n withDefaultOffsetY(offset: number): this {\n this._offsetY = offset;\n return this;\n }\n\n /**\n * Configures that the position strategy should set a `transform-origin` on some elements\n * inside the overlay, depending on the current position that is being applied. This is\n * useful for the cases where the origin of an animation can change depending on the\n * alignment of the overlay.\n * @param selector CSS selector that will be used to find the target\n * elements onto which to set the transform origin.\n */\n withTransformOriginOn(selector: string): this {\n this._transformOriginSelector = selector;\n return this;\n }\n\n /**\n * Gets the (x, y) coordinate of a connection point on the origin based on a relative position.\n */\n private _getOriginPoint(\n originRect: Dimensions,\n containerRect: Dimensions,\n pos: ConnectedPosition,\n ): Point {\n let x: number;\n if (pos.originX == 'center') {\n // Note: when centering we should always use the `left`\n // offset, otherwise the position will be wrong in RTL.\n x = originRect.left + originRect.width / 2;\n } else {\n const startX = this._isRtl() ? originRect.right : originRect.left;\n const endX = this._isRtl() ? originRect.left : originRect.right;\n x = pos.originX == 'start' ? startX : endX;\n }\n\n // When zooming in Safari the container rectangle contains negative values for the position\n // and we need to re-add them to the calculated coordinates.\n if (containerRect.left < 0) {\n x -= containerRect.left;\n }\n\n let y: number;\n if (pos.originY == 'center') {\n y = originRect.top + originRect.height / 2;\n } else {\n y = pos.originY == 'top' ? originRect.top : originRect.bottom;\n }\n\n // Normally the containerRect's top value would be zero, however when the overlay is attached to an input\n // (e.g. in an autocomplete), mobile browsers will shift everything in order to put the input in the middle\n // of the screen and to make space for the virtual keyboard. We need to account for this offset,\n // otherwise our positioning will be thrown off.\n // Additionally, when zooming in Safari this fixes the vertical position.\n if (containerRect.top < 0) {\n y -= containerRect.top;\n }\n\n return {x, y};\n }\n\n /**\n * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and\n * origin point to which the overlay should be connected.\n */\n private _getOverlayPoint(\n originPoint: Point,\n overlayRect: Dimensions,\n pos: ConnectedPosition,\n ): Point {\n // Calculate the (overlayStartX, overlayStartY), the start of the\n // potential overlay position relative to the origin point.\n let overlayStartX: number;\n if (pos.overlayX == 'center') {\n overlayStartX = -overlayRect.width / 2;\n } else if (pos.overlayX === 'start') {\n overlayStartX = this._isRtl() ? -overlayRect.width : 0;\n } else {\n overlayStartX = this._isRtl() ? 0 : -overlayRect.width;\n }\n\n let overlayStartY: number;\n if (pos.overlayY == 'center') {\n overlayStartY = -overlayRect.height / 2;\n } else {\n overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;\n }\n\n // The (x, y) coordinates of the overlay.\n return {\n x: originPoint.x + overlayStartX,\n y: originPoint.y + overlayStartY,\n };\n }\n\n /** Gets how well an overlay at the given point will fit within the viewport. */\n private _getOverlayFit(\n point: Point,\n rawOverlayRect: Dimensions,\n viewport: Dimensions,\n position: ConnectedPosition,\n ): OverlayFit {\n // Round the overlay rect when comparing against the\n // viewport, because the viewport is always rounded.\n const overlay = getRoundedBoundingClientRect(rawOverlayRect);\n let {x, y} = point;\n let offsetX = this._getOffset(position, 'x');\n let offsetY = this._getOffset(position, 'y');\n\n // Account for the offsets since they could push the overlay out of the viewport.\n if (offsetX) {\n x += offsetX;\n }\n\n if (offsetY) {\n y += offsetY;\n }\n\n // How much the overlay would overflow at this position, on each side.\n let leftOverflow = 0 - x;\n let rightOverflow = x + overlay.width - viewport.width;\n let topOverflow = 0 - y;\n let bottomOverflow = y + overlay.height - viewport.height;\n\n // Visible parts of the element on each axis.\n let visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow);\n let visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow);\n let visibleArea = visibleWidth * visibleHeight;\n\n return {\n visibleArea,\n isCompletelyWithinViewport: overlay.width * overlay.height === visibleArea,\n fitsInViewportVertically: visibleHeight === overlay.height,\n fitsInViewportHorizontally: visibleWidth == overlay.width,\n };\n }\n\n /**\n * Whether the overlay can fit within the viewport when it may resize either its width or height.\n * @param fit How well the overlay fits in the viewport at some position.\n * @param point The (x, y) coordinates of the overlay at some position.\n * @param viewport The geometry of the viewport.\n */\n private _canFitWithFlexibleDimensions(fit: OverlayFit, point: Point, viewport: Dimensions) {\n if (this._hasFlexibleDimensions) {\n const availableHeight = viewport.bottom - point.y;\n const availableWidth = viewport.right - point.x;\n const minHeight = getPixelValue(this._overlayRef.getConfig().minHeight);\n const minWidth = getPixelValue(this._overlayRef.getConfig().minWidth);\n\n const verticalFit =\n fit.fitsInViewportVertically || (minHeight != null && minHeight <= availableHeight);\n const horizontalFit =\n fit.fitsInViewportHorizontally || (minWidth != null && minWidth <= availableWidth);\n\n return verticalFit && horizontalFit;\n }\n return false;\n }\n\n /**\n * Gets the point at which the overlay can be \"pushed\" on-screen. If the overlay is larger than\n * the viewport, the top-left corner will be pushed on-screen (with overflow occurring on the\n * right and bottom).\n *\n * @param start Starting point from which the overlay is pushed.\n * @param rawOverlayRect Dimensions of the overlay.\n * @param scrollPosition Current viewport scroll position.\n * @returns The point at which to position the overlay after pushing. This is effectively a new\n * originPoint.\n */\n private _pushOverlayOnScreen(\n start: Point,\n rawOverlayRect: Dimensions,\n scrollPosition: ViewportScrollPosition,\n ): Point {\n // If the position is locked and we've pushed the overlay already, reuse the previous push\n // amount, rather than pushing it again. If we were to continue pushing, the element would\n // remain in the viewport, which goes against the expectations when position locking is enabled.\n if (this._previousPushAmount && this._positionLocked) {\n return {\n x: start.x + this._previousPushAmount.x,\n y: start.y + this._previousPushAmount.y,\n };\n }\n\n // Round the overlay rect when comparing against the\n // viewport, because the viewport is always rounded.\n const overlay = getRoundedBoundingClientRect(rawOverlayRect);\n const viewport = this._viewportRect;\n\n // Determine how much the overlay goes outside the viewport on each\n // side, which we'll use to decide which direction to push it.\n const overflowRight = Math.max(start.x + overlay.width - viewport.width, 0);\n const overflowBottom = Math.max(start.y + overlay.height - viewport.height, 0);\n const overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0);\n const overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0);\n\n // Amount by which to push the overlay in each axis such that it remains on-screen.\n let pushX = 0;\n let pushY = 0;\n\n // If the overlay fits completely within the bounds of the viewport, push it from whichever\n // direction is goes off-screen. Otherwise, push the top-left corner such that its in the\n // viewport and allow for the trailing end of the overlay to go out of bounds.\n if (overlay.width <= viewport.width) {\n pushX = overflowLeft || -overflowRight;\n } else {\n pushX = start.x < this._viewportMargin ? viewport.left - scrollPosition.left - start.x : 0;\n }\n\n if (overlay.height <= viewport.height) {\n pushY = overflowTop || -overflowBottom;\n } else {\n pushY = start.y < this._viewportMargin ? viewport.top - scrollPosition.top - start.y : 0;\n }\n\n this._previousPushAmount = {x: pushX, y: pushY};\n\n return {\n x: start.x + pushX,\n y: start.y + pushY,\n };\n }\n\n /**\n * Applies a computed position to the overlay and emits a position change.\n * @param position The position preference\n * @param originPoint The point on the origin element where the overlay is connected.\n */\n private _applyPosition(position: ConnectedPosition, originPoint: Point) {\n this._setTransformOrigin(position);\n this._setOverlayElementStyles(originPoint, position);\n this._setBoundingBoxStyles(originPoint, position);\n\n if (position.panelClass) {\n this._addPanelClasses(position.panelClass);\n }\n\n // Save the last connected position in case the position needs to be re-calculated.\n this._lastPosition = position;\n\n // Notify that the position has been changed along with its change properties.\n // We only emit if we've got any subscriptions, because the scroll visibility\n // calculations can be somewhat expensive.\n if (this._positionChanges.observers.length) {\n const scrollableViewProperties = this._getScrollVisibility();\n const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);\n this._positionChanges.next(changeEvent);\n }\n\n this._isInitialRender = false;\n }\n\n /** Sets the transform origin based on the configured selector and the passed-in position. */\n private _setTransformOrigin(position: ConnectedPosition) {\n if (!this._transformOriginSelector) {\n return;\n }\n\n const elements: NodeListOf<HTMLElement> = this._boundingBox!.querySelectorAll(\n this._transformOriginSelector,\n );\n let xOrigin: 'left' | 'right' | 'center';\n let yOrigin: 'top' | 'bottom' | 'center' = position.overlayY;\n\n if (position.overlayX === 'center') {\n xOrigin = 'center';\n } else if (this._isRtl()) {\n xOrigin = position.overlayX === 'start' ? 'right' : 'left';\n } else {\n xOrigin = position.overlayX === 'start' ? 'left' : 'right';\n }\n\n for (let i = 0; i < elements.length; i++) {\n elements[i].style.transformOrigin = `${xOrigin} ${yOrigin}`;\n }\n }\n\n /**\n * Gets the position and size of the overlay's sizing container.\n *\n * This method does no measuring and applies no styles so that we can cheaply compute the\n * bounds for all positions and choose the best fit based on these results.\n */\n private _calculateBoundingBoxRect(origin: Point, position: ConnectedPosition): BoundingBoxRect {\n const viewport = this._viewportRect;\n const isRtl = this._isRtl();\n let height: number, top: number, bottom: number;\n\n if (position.overlayY === 'top') {\n // Overlay is opening \"downward\" and thus is bound by the bottom viewport edge.\n top = origin.y;\n height = viewport.height - top + this._viewportMargin;\n } else if (position.overlayY === 'bottom') {\n // Overlay is opening \"upward\" and thus is bound by the top viewport edge. We need to add\n // the viewport margin back in, because the viewport rect is narrowed down to remove the\n // margin, whereas the `origin` position is calculated based on its `ClientRect`.\n bottom = viewport.height - origin.y + this._viewportMargin * 2;\n height = viewport.height - bottom + this._viewportMargin;\n } else {\n // If neither top nor bottom, it means that the overlay is vertically centered on the\n // origin point. Note that we want the position relative to the viewport, rather than\n // the page, which is why we don't use something like `viewport.bottom - origin.y` and\n // `origin.y - viewport.top`.\n const smallestDistanceToViewportEdge = Math.min(\n viewport.bottom - origin.y + viewport.top,\n origin.y,\n );\n\n const previousHeight = this._lastBoundingBoxSize.height;\n\n height = smallestDistanceToViewportEdge * 2;\n top = origin.y - smallestDistanceToViewportEdge;\n\n if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) {\n top = origin.y - previousHeight / 2;\n }\n }\n\n // The overlay is opening 'right-ward' (the content flows to the right).\n const isBoundedByRightViewportEdge =\n (position.overlayX === 'start' && !isRtl) || (position.overlayX === 'end' && isRtl);\n\n // The overlay is opening 'left-ward' (the content flows to the left).\n const isBoundedByLeftViewportEdge =\n (position.overlayX === 'end' && !isRtl) || (position.overlayX === 'start' && isRtl);\n\n let width: number, left: number, right: number;\n\n if (isBoundedByLeftViewportEdge) {\n right = viewport.width - origin.x + this._viewportMargin;\n width = origin.x - this._viewportMargin;\n } else if (isBoundedByRightViewportEdge) {\n left = origin.x;\n width = viewport.right - origin.x;\n } else {\n // If neither start nor end, it means that the overlay is horizontally centered on the\n // origin point. Note that we want the position relative to the viewport, rather than\n // the page, which is why we don't use something like `viewport.right - origin.x` and\n // `origin.x - viewport.left`.\n const smallestDistanceToViewportEdge = Math.min(\n viewport.right - origin.x + viewport.left,\n origin.x,\n );\n const previousWidth = this._lastBoundingBoxSize.width;\n\n width = smallestDistanceToViewportEdge * 2;\n left = origin.x - smallestDistanceToViewportEdge;\n\n if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) {\n left = origin.x - previousWidth / 2;\n }\n }\n\n return {top: top!, left: left!, bottom: bottom!, right: right!, width, height};\n }\n\n /**\n * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the\n * origin's connection point and stretches to the bounds of the viewport.\n *\n * @param origin The point on the origin element where the overlay is connected.\n * @param position The position preference\n */\n private _setBoundingBoxStyles(origin: Point, position: ConnectedPosition): void {\n const boundingBoxRect = this._calculateBoundingBoxRect(origin, position);\n\n // It's weird if the overlay *grows* while scrolling, so we take the last size into account\n // when applying a new size.\n if (!this._isInitialRender && !this._growAfterOpen) {\n boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height);\n boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width);\n }\n\n const styles = {} as CSSStyleDeclaration;\n\n if (this._hasExactPosition()) {\n styles.top = styles.left = '0';\n styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = '';\n styles.width = styles.height = '100%';\n } else {\n const maxHeight = this._overlayRef.getConfig().maxHeight;\n const maxWidth = this._overlayRef.getConfig().maxWidth;\n\n styles.height = coerceCssPixelValue(boundingBoxRect.height);\n styles.top = coerceCssPixelValue(boundingBoxRect.top);\n styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom);\n styles.width = coerceCssPixelValue(boundingBoxRect.width);\n styles.left = coerceCssPixelValue(boundingBoxRect.left);\n styles.right = coerceCssPixelValue(boundingBoxRect.right);\n\n // Push the pane content towards the proper direction.\n if (position.overlayX === 'center') {\n styles.alignItems = 'center';\n } else {\n styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start';\n }\n\n if (position.overlayY === 'center') {\n styles.justifyContent = 'center';\n } else {\n styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start';\n }\n\n if (maxHeight) {\n styles.maxHeight = coerceCssPixelValue(maxHeight);\n }\n\n if (maxWidth) {\n styles.maxWidth = coerceCssPixelValue(maxWidth);\n }\n }\n\n this._lastBoundingBoxSize = boundingBoxRect;\n\n extendStyles(this._boundingBox!.style, styles);\n }\n\n /** Resets the styles for the bounding box so that a new positioning can be computed. */\n private _resetBoundingBoxStyles() {\n extendStyles(this._boundingBox!.style, {\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n height: '',\n width: '',\n alignItems: '',\n justifyContent: '',\n } as CSSStyleDeclaration);\n }\n\n /** Resets the styles for the overlay pane so that a new positioning can be computed. */\n private _resetOverlayElementStyles() {\n extendStyles(this._pane.style, {\n top: '',\n left: '',\n bottom: '',\n right: '',\n position: '',\n transform: '',\n } as CSSStyleDeclaration);\n }\n\n /** Sets positioning styles to the overlay element. */\n private _setOverlayElementStyles(originPoint: Point, position: ConnectedPosition): void {\n const styles = {} as CSSStyleDeclaration;\n const hasExactPosition = this._hasExactPosition();\n const hasFlexibleDimensions = this._hasFlexibleDimensions;\n const config = this._overlayRef.getConfig();\n\n if (hasExactPosition) {\n const scrollPosition = this._viewportRuler.getViewportScrollPosition();\n extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition));\n extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition));\n } else {\n styles.position = 'static';\n }\n\n // Use a transform to apply the offsets. We do this because the `center` positions rely on\n // being in the normal flex flow and setting a `top` / `left` at all will completely throw\n // off the position. We also can't use margins, because they won't have an effect in some\n // cases where the element doesn't have anything to \"push off of\". Finally, this works\n // better both with flexible and non-flexible positioning.\n let transformString = '';\n let offsetX = this._getOffset(position, 'x');\n let offsetY = this._getOffset(position, 'y');\n\n if (offsetX) {\n transformString += `translateX(${offsetX}px) `;\n }\n\n if (offsetY) {\n transformString += `translateY(${offsetY}px)`;\n }\n\n styles.transform = transformString.trim();\n\n // If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because\n // we need these values to both be set to \"100%\" for the automatic flexible sizing to work.\n // The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint.\n // Note that this doesn't apply when we have an exact position, in which case we do want to\n // apply them because they'll be cleared from the bounding box.\n if (config.maxHeight) {\n if (hasExactPosition) {\n styles.maxHeight = coerceCssPixelValue(config.maxHeight);\n } else if (hasFlexibleDimensions) {\n styles.maxHeight = '';\n }\n }\n\n if (config.maxWidth) {\n if (hasExactPosition) {\n styles.maxWidth = coerceCssPixelValue(config.maxWidth);\n } else if (hasFlexibleDimensions) {\n styles.maxWidth = '';\n }\n }\n\n extendStyles(this._pane.style, styles);\n }\n\n /** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */\n private _getExactOverlayY(\n position: ConnectedPosition,\n originPoint: Point,\n scrollPosition: ViewportScrollPosition,\n ) {\n // Reset any existing styles. This is necessary in case the\n // preferred position has changed since the last `apply`.\n let styles = {top: '', bottom: ''} as CSSStyleDeclaration;\n let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);\n\n if (this._isPushed) {\n overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);\n }\n\n // We want to set either `top` or `bottom` based on whether the overlay wants to appear\n // above or below the origin and the direction in which the element will expand.\n if (position.overlayY === 'bottom') {\n // When using `bottom`, we adjust the y position such that it is the distance\n // from the bottom of the viewport rather than the top.\n const documentHeight = this._document.documentElement!.clientHeight;\n styles.bottom = `${documentHeight - (overlayPoint.y + this._overlayRect.height)}px`;\n } else {\n styles.top = coerceCssPixelValue(overlayPoint.y);\n }\n\n return styles;\n }\n\n /** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */\n private _getExactOverlayX(\n position: ConnectedPosition,\n originPoint: Point,\n scrollPosition: ViewportScrollPosition,\n ) {\n // Reset any existing styles. This is necessary in case the preferred position has\n // changed since the last `apply`.\n let styles = {left: '', right: ''} as CSSStyleDeclaration;\n let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);\n\n if (this._isPushed) {\n overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);\n }\n\n // We want to set either `left` or `right` based on whether the overlay wants to appear \"before\"\n // or \"after\" the origin, which determines the direction in which the element will expand.\n // For the horizontal axis, the meaning of \"before\" and \"after\" change based on whether the\n // page is in RTL or LTR.\n let horizontalStyleProperty: 'left' | 'right';\n\n if (this._isRtl()) {\n horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right';\n } else {\n horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left';\n }\n\n // When we're setting `right`, we adjust the x position such that it is the distance\n // from the right edge of the viewport rather than the left edge.\n if (horizontalStyleProperty === 'right') {\n const documentWidth = this._document.documentElement!.clientWidth;\n styles.right = `${documentWidth - (overlayPoint.x + this._overlayRect.width)}px`;\n } else {\n styles.left = coerceCssPixelValue(overlayPoint.x);\n }\n\n return styles;\n }\n\n /**\n * Gets the view properties of the trigger and overlay, including whether they are clipped\n * or completely outside the view of any of the strategy's scrollables.\n */\n private _getScrollVisibility(): ScrollingVisibility {\n // Note: needs fresh rects since the position could've changed.\n const originBounds = this._getOriginRect();\n const overlayBounds = this._pane.getBoundingClientRect();\n\n // TODO(jelbourn): instead of needing all of the client rects for these scrolling containers\n // every time, we should be able to use the scrollTop of the containers if the size of those\n // containers hasn't changed.\n const scrollContainerBounds = this._scrollables.map(scrollable => {\n return scrollable.getElementRef().nativeElement.getBoundingClientRect();\n });\n\n return {\n isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds),\n isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds),\n isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds),\n isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds),\n };\n }\n\n /** Subtracts the amount that an element is overflowing on an axis from its length. */\n private _subtractOverflows(length: number, ...overflows: number[]): number {\n return overflows.reduce((currentValue: number, currentOverflow: number) => {\n return currentValue - Math.max(currentOverflow, 0);\n }, length);\n }\n\n /** Narrows the given viewport rect by the current _viewportMargin. */\n private _getNarrowedViewportRect(): Dimensions {\n // We recalculate the viewport rect here ourselves, rather than using the ViewportRuler,\n // because we want to use the `clientWidth` and `clientHeight` as the base. The difference\n // being that the client properties don't include the scrollbar, as opposed to `innerWidth`\n // and `innerHeight` that do. This is necessary, because the overlay container uses\n // 100% `width` and `height` which don't include the scrollbar either.\n const width = this._document.documentElement!.clientWidth;\n const height = this._document.documentElement!.clientHeight;\n const scrollPosition = this._viewportRuler.getViewportScrollPosition();\n\n return {\n top: scrollPosition.top + this._viewportMargin,\n left: scrollPosition.left + this._viewportMargin,\n right: scrollPosition.left + width - this._viewportMargin,\n bottom: scrollPosition.top + height - this._viewportMargin,\n width: width - 2 * this._viewportMargin,\n height: height - 2 * this._viewportMargin,\n };\n }\n\n /** Whether the we're dealing with an RTL context */\n private _isRtl() {\n return this._overlayRef.getDirection() === 'rtl';\n }\n\n /** Determines whether the overlay uses exact or flexible positioning. */\n private _hasExactPosition() {\n return !this._hasFlexibleDimensions || this._isPushed;\n }\n\n /** Retrieves the offset of a position along the x or y axis. */\n private _getOffset(position: ConnectedPosition, axis: 'x' | 'y') {\n if (axis === 'x') {\n // We don't do something like `position['offset' + axis]` in\n // order to avoid breaking minifiers that rename properties.\n return position.offsetX == null ? this._offsetX : position.offsetX;\n }\n\n return position.offsetY == null ? this._offsetY : position.offsetY;\n }\n\n /** Validates that the current position match the expected values. */\n private _validatePositions(): void {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!this._preferredPositions.length) {\n throw Error('FlexibleConnectedPositionStrategy: At least one position is required.');\n }\n\n // TODO(crisbeto): remove these once Angular's template type\n // checking is advanced enough to catch these cases.\n this._preferredPositions.forEach(pair => {\n validateHorizontalPosition('originX', pair.originX);\n validateVerticalPosition('originY', pair.originY);\n validateHorizontalPosition('overlayX', pair.overlayX);\n validateVerticalPosition('overlayY', pair.overlayY);\n });\n }\n }\n\n /** Adds a single CSS class or an array of classes on the overlay panel. */\n private _addPanelClasses(cssClasses: string | string[]) {\n if (this._pane) {\n coerceArray(cssClasses).forEach(cssClass => {\n if (cssClass !== '' && this._appliedPanelClasses.indexOf(cssClass) === -1) {\n this._appliedPanelClasses.push(cssClass);\n this._pane.classList.add(cssClass);\n }\n });\n }\n }\n\n /** Clears the classes that the position strategy has applied from the overlay panel. */\n private _clearPanelClasses() {\n if (this._pane) {\n this._appliedPanelClasses.forEach(cssClass => {\n this._pane.classList.remove(cssClass);\n });\n this._appliedPanelClasses = [];\n }\n }\n\n /** Returns the ClientRect of the current origin. */\n private _getOriginRect(): Dimensions {\n const origin = this._origin;\n\n if (origin instanceof ElementRef) {\n return origin.nativeElement.getBoundingClientRect();\n }\n\n // Check for Element so SVG elements are also supported.\n if (origin instanceof Element) {\n return origin.getBoundingClientRect();\n }\n\n const width = origin.width || 0;\n const height = origin.height || 0;\n\n // If the origin is a point, return a client rect as if it was a 0x0 element at the point.\n return {\n top: origin.y,\n bottom: origin.y + height,\n left: origin.x,\n right: origin.x + width,\n height,\n width,\n };\n }\n}\n\n/** A simple (x, y) coordinate. */\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Record of measurements for how an overlay (at a given position) fits into the viewport. */\ninterface OverlayFit {\n /** Whether the overlay fits completely in the viewport. */\n isCompletelyWithinViewport: boolean;\n\n /** Whether the overlay fits in the viewport on the y-axis. */\n fitsInViewportVertically: boolean;\n\n /** Whether the overlay fits in the viewport on the x-axis. */\n fitsInViewportHorizontally: boolean;\n\n /** The total visible area (in px^2) of the overlay inside the viewport. */\n visibleArea: number;\n}\n\n/** Record of the measurements determining whether an overlay will fit in a specific position. */\ninterface FallbackPosition {\n position: ConnectedPosition;\n originPoint: Point;\n overlayPoint: Point;\n overlayFit: OverlayFit;\n overlayRect: Dimensions;\n}\n\n/** Position and size of the overlay sizing wrapper for a specific position. */\ninterface BoundingBoxRect {\n top: number;\n left: number;\n bottom: number;\n right: number;\n height: number;\n width: number;\n}\n\n/** Record of measures determining how well a given position will fit with flexible dimensions. */\ninterface FlexibleFit {\n position: ConnectedPosition;\n origin: Point;\n overlayRect: Dimensions;\n boundingBoxRect: BoundingBoxRect;\n}\n\n/** A connected position as specified by the user. */\nexport interface ConnectedPosition {\n originX: 'start' | 'center' | 'end';\n originY: 'top' | 'center' | 'bottom';\n\n overlayX: 'start' | 'center' | 'end';\n overlayY: 'top' | 'center' | 'bottom';\n\n weight?: number;\n offsetX?: number;\n offsetY?: number;\n panelClass?: string | string[];\n}\n\n/** Shallow-extends a stylesheet object with another stylesheet object. */\nfunction extendStyles(\n destination: CSSStyleDeclaration,\n source: CSSStyleDeclaration,\n): CSSStyleDeclaration {\n for (let key in source) {\n if (source.hasOwnProperty(key)) {\n destination[key] = source[key];\n }\n }\n\n return destination;\n}\n\n/**\n * Extracts the pixel value as a number from a value, if it's a number\n * or a CSS pixel string (e.g. `1337px`). Otherwise returns null.\n */\nfunction getPixelValue(input: number | string | null | undefined): number | null {\n if (typeof input !== 'number' && input != null) {\n const [value, units] = input.split(cssUnitPattern);\n return !units || units === 'px' ? parseFloat(value) : null;\n }\n\n return input || null;\n}\n\n/**\n * Gets a version of an element's bounding `ClientRect` where all the values are rounded down to\n * the nearest pixel. This allows us to account for the cases where there may be sub-pixel\n * deviations in the `ClientRect` returned by the browser (e.g. when zoomed in with a percentage\n * size, see #21350).\n */\nfunction getRoundedBoundingClientRect(clientRect: Dimensions): Dimensions {\n return {\n top: Math.floor(clientRect.top),\n right: Math.floor(clientRect.right),\n bottom: Math.floor(clientRect.bottom),\n left: Math.floor(clientRect.left),\n width: Math.floor(clientRect.width),\n height: Math.floor(clientRect.height),\n };\n}\n\nexport const STANDARD_DROPDOWN_BELOW_POSITIONS: ConnectedPosition[] = [\n {originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top'},\n {originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom'},\n {originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top'},\n {originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom'},\n];\n\nexport const STANDARD_DROPDOWN_ADJACENT_POSITIONS: ConnectedPosition[] = [\n {originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top'},\n {originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom'},\n {originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top'},\n {originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom'},\n];\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {PositionStrategy} from './position-strategy';\nimport {OverlayReference} from '../overlay-reference';\n\n/** Class to be added to the overlay pane wrapper. */\nconst wrapperClass = 'cdk-global-overlay-wrapper';\n\n/**\n * A strategy for positioning overlays. Using this strategy, an overlay is given an\n * explicit position relative to the browser's viewport. We use flexbox, instead of\n * transforms, in order to avoid issues with subpixel rendering which can cause the\n * element to become blurry.\n */\nexport class GlobalPositionStrategy implements PositionStrategy {\n /** The overlay to which this strategy is attached. */\n private _overlayRef: OverlayReference;\n private _cssPosition = 'static';\n private _topOffset = '';\n private _bottomOffset = '';\n private _alignItems = '';\n private _xPosition = '';\n private _xOffset = '';\n private _width = '';\n private _height = '';\n private _isDisposed = false;\n\n attach(overlayRef: OverlayReference): void {\n const config = overlayRef.getConfig();\n\n this._overlayRef = overlayRef;\n\n if (this._width && !config.width) {\n overlayRef.updateSize({width: this._width});\n }\n\n if (this._height && !config.height) {\n overlayRef.updateSize({height: this._height});\n }\n\n overlayRef.hostElement.classList.add(wrapperClass);\n this._isDisposed = false;\n }\n\n /**\n * Sets the top position of the overlay. Clears any previously set vertical position.\n * @param value New top offset.\n */\n top(value: string = ''): this {\n this._bottomOffset = '';\n this._topOffset = value;\n this._alignItems = 'flex-start';\n return this;\n }\n\n /**\n * Sets the left position of the overlay. Clears any previously set horizontal position.\n * @param value New left offset.\n */\n left(value: string = ''): this {\n this._xOffset = value;\n this._xPosition = 'left';\n return this;\n }\n\n /**\n * Sets the bottom position of the overlay. Clears any previously set vertical position.\n * @param value New bottom offset.\n */\n bottom(value: string = ''): this {\n this._topOffset = '';\n this._bottomOffset = value;\n this._alignItems = 'flex-end';\n return this;\n }\n\n /**\n * Sets the right position of the overlay. Clears any previously set horizontal position.\n * @param value New right offset.\n */\n right(value: string = ''): this {\n this._xOffset = value;\n this._xPosition = 'right';\n return this;\n }\n\n /**\n * Sets the overlay to the start of the viewport, depending on the overlay direction.\n * This will be to the left in LTR layouts and to the right in RTL.\n * @param offset Offset from the edge of the screen.\n */\n start(value: string = ''): this {\n this._xOffset = value;\n this._xPosition = 'start';\n return this;\n }\n\n /**\n * Sets the overlay to the end of the viewport, depending on the overlay direction.\n * This will be to the right in LTR layouts and to the left in RTL.\n * @param offset Offset from the edge of the screen.\n */\n end(value: string = ''): this {\n this._xOffset = value;\n this._xPosition = 'end';\n return this;\n }\n\n /**\n * Sets the overlay width and clears any previously set width.\n * @param value New width for the overlay\n * @deprecated Pass the `width` through the `OverlayConfig`.\n * @breaking-change 8.0.0\n */\n width(value: string = ''): this {\n if (this._overlayRef) {\n this._overlayRef.updateSize({width: value});\n } else {\n this._width = value;\n }\n\n return this;\n }\n\n /**\n * Sets the overlay height and clears any previously set height.\n * @param value New height for the overlay\n * @deprecated Pass the `height` through the `OverlayConfig`.\n * @breaking-change 8.0.0\n */\n height(value: string = ''): this {\n if (this._overlayRef) {\n this._overlayRef.updateSize({height: value});\n } else {\n this._height = value;\n }\n\n return this;\n }\n\n /**\n * Centers the overlay horizontally with an optional offset.\n * Clears any previously set horizontal position.\n *\n * @param offset Overlay offset from the horizontal center.\n */\n centerHorizontally(offset: string = ''): this {\n this.left(offset);\n this._xPosition = 'center';\n return this;\n }\n\n /**\n * Centers the overlay vertically with an optional offset.\n * Clears any previously set vertical position.\n *\n * @param offset Overlay offset from the vertical center.\n */\n centerVertically(offset: string = ''): this {\n this.top(offset);\n this._alignItems = 'center';\n return this;\n }\n\n /**\n * Apply the position to the element.\n * @docs-private\n */\n apply(): void {\n // Since the overlay ref applies the strategy asynchronously, it could\n // have been disposed before it ends up being applied. If that is the\n // case, we shouldn't do anything.\n if (!this._overlayRef || !this._overlayRef.hasAttached()) {\n return;\n }\n\n const styles = this._overlayRef.overlayElement.style;\n const parentStyles = this._overlayRef.hostElement.style;\n const config = this._overlayRef.getConfig();\n const {width, height, maxWidth, maxHeight} = config;\n const shouldBeFlushHorizontally =\n (width === '100%' || width === '100vw') &&\n (!maxWidth || maxWidth === '100%' || maxWidth === '100vw');\n const shouldBeFlushVertically =\n (height === '100%' || height === '100vh') &&\n (!maxHeight || maxHeight === '100%' || maxHeight === '100vh');\n const xPosition = this._xPosition;\n const xOffset = this._xOffset;\n const isRtl = this._overlayRef.getConfig().direction === 'rtl';\n let marginLeft = '';\n let marginRight = '';\n let justifyContent = '';\n\n if (shouldBeFlushHorizontally) {\n justifyContent = 'flex-start';\n } else if (xPosition === 'center') {\n justifyContent = 'center';\n\n if (isRtl) {\n marginRight = xOffset;\n } else {\n marginLeft = xOffset;\n }\n } else if (isRtl) {\n if (xPosition === 'left' || xPosition === 'end') {\n justifyContent = 'flex-end';\n marginLeft = xOffset;\n } else if (xPosition === 'right' || xPosition === 'start') {\n justifyContent = 'flex-start';\n marginRight = xOffset;\n }\n } else if (xPosition === 'left' || xPosition === 'start') {\n justifyContent = 'flex-start';\n marginLeft = xOffset;\n } else if (xPosition === 'right' || xPosition === 'end') {\n justifyContent = 'flex-end';\n marginRight = xOffset;\n }\n\n styles.position = this._cssPosition;\n styles.marginLeft = shouldBeFlushHorizontally ? '0' : marginLeft;\n styles.marginTop = shouldBeFlushVertically ? '0' : this._topOffset;\n styles.marginBottom = this._bottomOffset;\n styles.marginRight = shouldBeFlushHorizontally ? '0' : marginRight;\n parentStyles.justifyContent = justifyContent;\n parentStyles.alignItems = shouldBeFlushVertically ? 'flex-start' : this._alignItems;\n }\n\n /**\n * Cleans up the DOM changes from the position strategy.\n * @docs-private\n */\n dispose(): void {\n if (this._isDisposed || !this._overlayRef) {\n return;\n }\n\n const styles = this._overlayRef.overlayElement.style;\n const parent = this._overlayRef.hostElement;\n const parentStyles = parent.style;\n\n parent.classList.remove(wrapperClass);\n parentStyles.justifyContent =\n parentStyles.alignItems =\n styles.marginTop =\n styles.marginBottom =\n styles.marginLeft =\n styles.marginRight =\n styles.position =\n '';\n\n this._overlayRef = null!;\n this._isDisposed = true;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Platform} from '@angular/cdk/platform';\nimport {ViewportRuler} from '@angular/cdk/scrolling';\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable} from '@angular/core';\nimport {OverlayContainer} from '../overlay-container';\nimport {\n FlexibleConnectedPositionStrategy,\n FlexibleConnectedPositionStrategyOrigin,\n} from './flexible-connected-position-strategy';\nimport {GlobalPositionStrategy} from './global-position-strategy';\n\n/** Builder for overlay position strategy. */\n@Injectable({providedIn: 'root'})\nexport class OverlayPositionBuilder {\n constructor(\n private _viewportRuler: ViewportRuler,\n @Inject(DOCUMENT) private _document: any,\n private _platform: Platform,\n private _overlayContainer: OverlayContainer,\n ) {}\n\n /**\n * Creates a global position strategy.\n */\n global(): GlobalPositionStrategy {\n return new GlobalPositionStrategy();\n }\n\n /**\n * Creates a flexible position strategy.\n * @param origin Origin relative to which to position the overlay.\n */\n flexibleConnectedTo(\n origin: FlexibleConnectedPositionStrategyOrigin,\n ): FlexibleConnectedPositionStrategy {\n return new FlexibleConnectedPositionStrategy(\n origin,\n this._viewportRuler,\n this._document,\n this._platform,\n this._overlayContainer,\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directionality} from '@angular/cdk/bidi';\nimport {DomPortalOutlet} from '@angular/cdk/portal';\nimport {DOCUMENT, Location} from '@angular/common';\nimport {\n ApplicationRef,\n ComponentFactoryResolver,\n Inject,\n Injectable,\n Injector,\n NgZone,\n ANIMATION_MODULE_TYPE,\n Optional,\n} from '@angular/core';\nimport {OverlayKeyboardDispatcher} from './dispatchers/overlay-keyboard-dispatcher';\nimport {OverlayOutsideClickDispatcher} from './dispatchers/overlay-outside-click-dispatcher';\nimport {OverlayConfig} from './overlay-config';\nimport {OverlayContainer} from './overlay-container';\nimport {OverlayRef} from './overlay-ref';\nimport {OverlayPositionBuilder} from './position/overlay-position-builder';\nimport {ScrollStrategyOptions} from './scroll/index';\n\n/** Next overlay unique ID. */\nlet nextUniqueId = 0;\n\n// Note that Overlay is *not* scoped to the app root because of the ComponentFactoryResolver\n// which needs to be different depending on where OverlayModule is imported.\n\n/**\n * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be\n * used as a low-level building block for other components. Dialogs, tooltips, menus,\n * selects, etc. can all be built using overlays. The service should primarily be used by authors\n * of re-usable components rather than developers building end-user applications.\n *\n * An overlay *is* a PortalOutlet, so any kind of Portal can be loaded into one.\n */\n@Injectable({providedIn: 'root'})\nexport class Overlay {\n private _appRef: ApplicationRef;\n\n constructor(\n /** Scrolling strategies that can be used when creating an overlay. */\n public scrollStrategies: ScrollStrategyOptions,\n private _overlayContainer: OverlayContainer,\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _positionBuilder: OverlayPositionBuilder,\n private _keyboardDispatcher: OverlayKeyboardDispatcher,\n private _injector: Injector,\n private _ngZone: NgZone,\n @Inject(DOCUMENT) private _document: any,\n private _directionality: Directionality,\n private _location: Location,\n private _outsideClickDispatcher: OverlayOutsideClickDispatcher,\n @Inject(ANIMATION_MODULE_TYPE) @Optional() private _animationsModuleType?: string,\n ) {}\n\n /**\n * Creates an overlay.\n * @param config Configuration applied to the overlay.\n * @returns Reference to the created overlay.\n */\n create(config?: OverlayConfig): OverlayRef {\n const host = this._createHostElement();\n const pane = this._createPaneElement(host);\n const portalOutlet = this._createPortalOutlet(pane);\n const overlayConfig = new OverlayConfig(config);\n\n overlayConfig.direction = overlayConfig.direction || this._directionality.value;\n\n return new OverlayRef(\n portalOutlet,\n host,\n pane,\n overlayConfig,\n this._ngZone,\n this._keyboardDispatcher,\n this._document,\n this._location,\n this._outsideClickDispatcher,\n this._animationsModuleType === 'NoopAnimations',\n );\n }\n\n /**\n * Gets a position builder that can be used, via fluent API,\n * to construct and configure a position strategy.\n * @returns An overlay position builder.\n */\n position(): OverlayPositionBuilder {\n return this._positionBuilder;\n }\n\n /**\n * Creates the DOM element for an overlay and appends it to the overlay container.\n * @returns Newly-created pane element\n */\n private _createPaneElement(host: HTMLElement): HTMLElement {\n const pane = this._document.createElement('div');\n\n pane.id = `cdk-overlay-${nextUniqueId++}`;\n pane.classList.add('cdk-overlay-pane');\n host.appendChild(pane);\n\n return pane;\n }\n\n /**\n * Creates the host element that wraps around an overlay\n * and can be used for advanced positioning.\n * @returns Newly-create host element.\n */\n private _createHostElement(): HTMLElement {\n const host = this._document.createElement('div');\n this._overlayContainer.getContainerElement().appendChild(host);\n return host;\n }\n\n /**\n * Create a DomPortalOutlet into which the overlay content can be loaded.\n * @param pane The DOM element to turn into a portal outlet.\n * @returns A portal outlet for the given DOM element.\n */\n private _createPortalOutlet(pane: HTMLElement): DomPortalOutlet {\n // We have to resolve the ApplicationRef later in order to allow people\n // to use overlay-based providers during app initialization.\n if (!this._appRef) {\n this._appRef = this._injector.get<ApplicationRef>(ApplicationRef);\n }\n\n return new DomPortalOutlet(\n pane,\n this._componentFactoryResolver,\n this._appRef,\n this._injector,\n this._document,\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Direction, Directionality} from '@angular/cdk/bidi';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {ESCAPE, hasModifierKey} from '@angular/cdk/keycodes';\nimport {TemplatePortal} from '@angular/cdk/portal';\nimport {\n Directive,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Input,\n OnChanges,\n OnDestroy,\n Optional,\n Output,\n SimpleChanges,\n TemplateRef,\n ViewContainerRef,\n} from '@angular/core';\nimport {Subscription} from 'rxjs';\nimport {takeWhile} from 'rxjs/operators';\nimport {Overlay} from './overlay';\nimport {OverlayConfig} from './overlay-config';\nimport {OverlayRef} from './overlay-ref';\nimport {ConnectedOverlayPositionChange} from './position/connected-position';\nimport {\n ConnectedPosition,\n FlexibleConnectedPositionStrategy,\n FlexibleConnectedPositionStrategyOrigin,\n} from './position/flexible-connected-position-strategy';\nimport {RepositionScrollStrategy, ScrollStrategy} from './scroll/index';\n\n/** Default set of positions for the overlay. Follows the behavior of a dropdown. */\nconst defaultPositionList: ConnectedPosition[] = [\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n },\n {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n },\n];\n\n/** Injection token that determines the scroll handling while the connected overlay is open. */\nexport const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'cdk-connected-overlay-scroll-strategy',\n);\n\n/**\n * Directive applied to an element to make it usable as an origin for an Overlay using a\n * ConnectedPositionStrategy.\n */\n@Directive({\n selector: '[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]',\n exportAs: 'cdkOverlayOrigin',\n standalone: true,\n})\nexport class CdkOverlayOrigin {\n constructor(\n /** Reference to the element on which the directive is applied. */\n public elementRef: ElementRef,\n ) {}\n}\n\n/**\n * Directive to facilitate declarative creation of an\n * Overlay using a FlexibleConnectedPositionStrategy.\n */\n@Directive({\n selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]',\n exportAs: 'cdkConnectedOverlay',\n standalone: true,\n})\nexport class CdkConnectedOverlay implements OnDestroy, OnChanges {\n private _overlayRef: OverlayRef;\n private _templatePortal: TemplatePortal;\n private _hasBackdrop = false;\n private _lockPosition = false;\n private _growAfterOpen = false;\n private _flexibleDimensions = false;\n private _push = false;\n private _backdropSubscription = Subscription.EMPTY;\n private _attachSubscription = Subscription.EMPTY;\n private _detachSubscription = Subscription.EMPTY;\n private _positionSubscription = Subscription.EMPTY;\n private _offsetX: number;\n private _offsetY: number;\n private _position: FlexibleConnectedPositionStrategy;\n private _scrollStrategyFactory: () => ScrollStrategy;\n\n /** Origin for the connected overlay. */\n @Input('cdkConnectedOverlayOrigin')\n origin: CdkOverlayOrigin | FlexibleConnectedPositionStrategyOrigin;\n\n /** Registered connected position pairs. */\n @Input('cdkConnectedOverlayPositions') positions: ConnectedPosition[];\n\n /**\n * This input overrides the positions input if specified. It lets users pass\n * in arbitrary positioning strategies.\n */\n @Input('cdkConnectedOverlayPositionStrategy') positionStrategy: FlexibleConnectedPositionStrategy;\n\n /** The offset in pixels for the overlay connection point on the x-axis */\n @Input('cdkConnectedOverlayOffsetX')\n get offsetX(): number {\n return this._offsetX;\n }\n set offsetX(offsetX: number) {\n this._offsetX = offsetX;\n\n if (this._position) {\n this._updatePositionStrategy(this._position);\n }\n }\n\n /** The offset in pixels for the overlay connection point on the y-axis */\n @Input('cdkConnectedOverlayOffsetY')\n get offsetY() {\n return this._offsetY;\n }\n set offsetY(offsetY: number) {\n this._offsetY = offsetY;\n\n if (this._position) {\n this._updatePositionStrategy(this._position);\n }\n }\n\n /** The width of the overlay panel. */\n @Input('cdkConnectedOverlayWidth') width: number | string;\n\n /** The height of the overlay panel. */\n @Input('cdkConnectedOverlayHeight') height: number | string;\n\n /** The min width of the overlay panel. */\n @Input('cdkConnectedOverlayMinWidth') minWidth: number | string;\n\n /** The min height of the overlay panel. */\n @Input('cdkConnectedOverlayMinHeight') minHeight: number | string;\n\n /** The custom class to be set on the backdrop element. */\n @Input('cdkConnectedOverlayBackdropClass') backdropClass: string | string[];\n\n /** The custom class to add to the overlay pane element. */\n @Input('cdkConnectedOverlayPanelClass') panelClass: string | string[];\n\n /** Margin between the overlay and the viewport edges. */\n @Input('cdkConnectedOverlayViewportMargin') viewportMargin: number = 0;\n\n /** Strategy to be used when handling scroll events while the overlay is open. */\n @Input('cdkConnectedOverlayScrollStrategy') scrollStrategy: ScrollStrategy;\n\n /** Whether the overlay is open. */\n @Input('cdkConnectedOverlayOpen') open: boolean = false;\n\n /** Whether the overlay can be closed by user interaction. */\n @Input('cdkConnectedOverlayDisableClose') disableClose: boolean = false;\n\n /** CSS selector which to set the transform origin. */\n @Input('cdkConnectedOverlayTransformOriginOn') transformOriginSelector: string;\n\n /** Whether or not the overlay should attach a backdrop. */\n @Input('cdkConnectedOverlayHasBackdrop')\n get hasBackdrop(): boolean {\n return this._hasBackdrop;\n }\n set hasBackdrop(value: BooleanInput) {\n this._hasBackdrop = coerceBooleanProperty(value);\n }\n\n /** Whether or not the overlay should be locked when scrolling. */\n @Input('cdkConnectedOverlayLockPosition')\n get lockPosition(): boolean {\n return this._lockPosition;\n }\n set lockPosition(value: BooleanInput) {\n this._lockPosition = coerceBooleanProperty(value);\n }\n\n /** Whether the overlay's width and height can be constrained to fit within the viewport. */\n @Input('cdkConnectedOverlayFlexibleDimensions')\n get flexibleDimensions(): boolean {\n return this._flexibleDimensions;\n }\n set flexibleDimensions(value: BooleanInput) {\n this._flexibleDimensions = coerceBooleanProperty(value);\n }\n\n /** Whether the overlay can grow after the initial open when flexible positioning is turned on. */\n @Input('cdkConnectedOverlayGrowAfterOpen')\n get growAfterOpen(): boolean {\n return this._growAfterOpen;\n }\n set growAfterOpen(value: BooleanInput) {\n this._growAfterOpen = coerceBooleanProperty(value);\n }\n\n /** Whether the overlay can be pushed on-screen if none of the provided positions fit. */\n @Input('cdkConnectedOverlayPush')\n get push(): boolean {\n return this._push;\n }\n set push(value: BooleanInput) {\n this._push = coerceBooleanProperty(value);\n }\n\n /** Event emitted when the backdrop is clicked. */\n @Output() readonly backdropClick = new EventEmitter<MouseEvent>();\n\n /** Event emitted when the position has changed. */\n @Output() readonly positionChange = new EventEmitter<ConnectedOverlayPositionChange>();\n\n /** Event emitted when the overlay has been attached. */\n @Output() readonly attach = new EventEmitter<void>();\n\n /** Event emitted when the overlay has been detached. */\n @Output() readonly detach = new EventEmitter<void>();\n\n /** Emits when there are keyboard events that are targeted at the overlay. */\n @Output() readonly overlayKeydown = new EventEmitter<KeyboardEvent>();\n\n /** Emits when there are mouse outside click events that are targeted at the overlay. */\n @Output() readonly overlayOutsideClick = new EventEmitter<MouseEvent>();\n\n // TODO(jelbourn): inputs for size, scroll behavior, animation, etc.\n\n constructor(\n private _overlay: Overlay,\n templateRef: TemplateRef<any>,\n viewContainerRef: ViewContainerRef,\n @Inject(CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY) scrollStrategyFactory: any,\n @Optional() private _dir: Directionality,\n ) {\n this._templatePortal = new TemplatePortal(templateRef, viewContainerRef);\n this._scrollStrategyFactory = scrollStrategyFactory;\n this.scrollStrategy = this._scrollStrategyFactory();\n }\n\n /** The associated overlay reference. */\n get overlayRef(): OverlayRef {\n return this._overlayRef;\n }\n\n /** The element's layout direction. */\n get dir(): Direction {\n return this._dir ? this._dir.value : 'ltr';\n }\n\n ngOnDestroy() {\n this._attachSubscription.unsubscribe();\n this._detachSubscription.unsubscribe();\n this._backdropSubscription.unsubscribe();\n this._positionSubscription.unsubscribe();\n\n if (this._overlayRef) {\n this._overlayRef.dispose();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n if (this._position) {\n this._updatePositionStrategy(this._position);\n this._overlayRef.updateSize({\n width: this.width,\n minWidth: this.minWidth,\n height: this.height,\n minHeight: this.minHeight,\n });\n\n if (changes['origin'] && this.open) {\n this._position.apply();\n }\n }\n\n if (changes['open']) {\n this.open ? this._attachOverlay() : this._detachOverlay();\n }\n }\n\n /** Creates an overlay */\n private _createOverlay() {\n if (!this.positions || !this.positions.length) {\n this.positions = defaultPositionList;\n }\n\n const overlayRef = (this._overlayRef = this._overlay.create(this._buildConfig()));\n this._attachSubscription = overlayRef.attachments().subscribe(() => this.attach.emit());\n this._detachSubscription = overlayRef.detachments().subscribe(() => this.detach.emit());\n overlayRef.keydownEvents().subscribe((event: KeyboardEvent) => {\n this.overlayKeydown.next(event);\n\n if (event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)) {\n event.preventDefault();\n this._detachOverlay();\n }\n });\n\n this._overlayRef.outsidePointerEvents().subscribe((event: MouseEvent) => {\n this.overlayOutsideClick.next(event);\n });\n }\n\n /** Builds the overlay config based on the directive's inputs */\n private _buildConfig(): OverlayConfig {\n const positionStrategy = (this._position =\n this.positionStrategy || this._createPositionStrategy());\n const overlayConfig = new OverlayConfig({\n direction: this._dir,\n positionStrategy,\n scrollStrategy: this.scrollStrategy,\n hasBackdrop: this.hasBackdrop,\n });\n\n if (this.width || this.width === 0) {\n overlayConfig.width = this.width;\n }\n\n if (this.height || this.height === 0) {\n overlayConfig.height = this.height;\n }\n\n if (this.minWidth || this.minWidth === 0) {\n overlayConfig.minWidth = this.minWidth;\n }\n\n if (this.minHeight || this.minHeight === 0) {\n overlayConfig.minHeight = this.minHeight;\n }\n\n if (this.backdropClass) {\n overlayConfig.backdropClass = this.backdropClass;\n }\n\n if (this.panelClass) {\n overlayConfig.panelClass = this.panelClass;\n }\n\n return overlayConfig;\n }\n\n /** Updates the state of a position strategy, based on the values of the directive inputs. */\n private _updatePositionStrategy(positionStrategy: FlexibleConnectedPositionStrategy) {\n const positions: ConnectedPosition[] = this.positions.map(currentPosition => ({\n originX: currentPosition.originX,\n originY: currentPosition.originY,\n overlayX: currentPosition.overlayX,\n overlayY: currentPosition.overlayY,\n offsetX: currentPosition.offsetX || this.offsetX,\n offsetY: currentPosition.offsetY || this.offsetY,\n panelClass: currentPosition.panelClass || undefined,\n }));\n\n return positionStrategy\n .setOrigin(this._getFlexibleConnectedPositionStrategyOrigin())\n .withPositions(positions)\n .withFlexibleDimensions(this.flexibleDimensions)\n .withPush(this.push)\n .withGrowAfterOpen(this.growAfterOpen)\n .withViewportMargin(this.viewportMargin)\n .withLockedPosition(this.lockPosition)\n .withTransformOriginOn(this.transformOriginSelector);\n }\n\n /** Returns the position strategy of the overlay to be set on the overlay config */\n private _createPositionStrategy(): FlexibleConnectedPositionStrategy {\n const strategy = this._overlay\n .position()\n .flexibleConnectedTo(this._getFlexibleConnectedPositionStrategyOrigin());\n this._updatePositionStrategy(strategy);\n return strategy;\n }\n\n private _getFlexibleConnectedPositionStrategyOrigin(): FlexibleConnectedPositionStrategyOrigin {\n if (this.origin instanceof CdkOverlayOrigin) {\n return this.origin.elementRef;\n } else {\n return this.origin;\n }\n }\n\n /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */\n private _attachOverlay() {\n if (!this._overlayRef) {\n this._createOverlay();\n } else {\n // Update the overlay size, in case the directive's inputs have changed\n this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop;\n }\n\n if (!this._overlayRef.hasAttached()) {\n this._overlayRef.attach(this._templatePortal);\n }\n\n if (this.hasBackdrop) {\n this._backdropSubscription = this._overlayRef.backdropClick().subscribe(event => {\n this.backdropClick.emit(event);\n });\n } else {\n this._backdropSubscription.unsubscribe();\n }\n\n this._positionSubscription.unsubscribe();\n\n // Only subscribe to `positionChanges` if requested, because putting\n // together all the information for it can be expensive.\n if (this.positionChange.observers.length > 0) {\n this._positionSubscription = this._position.positionChanges\n .pipe(takeWhile(() => this.positionChange.observers.length > 0))\n .subscribe(position => {\n this.positionChange.emit(position);\n\n if (this.positionChange.observers.length === 0) {\n this._positionSubscription.unsubscribe();\n }\n });\n }\n }\n\n /** Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists */\n private _detachOverlay() {\n if (this._overlayRef) {\n this._overlayRef.detach();\n }\n\n this._backdropSubscription.unsubscribe();\n this._positionSubscription.unsubscribe();\n }\n}\n\n/** @docs-private */\nexport function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(\n overlay: Overlay,\n): () => RepositionScrollStrategy {\n return () => overlay.scrollStrategies.reposition();\n}\n\n/** @docs-private */\nexport const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = {\n provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY,\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BidiModule} from '@angular/cdk/bidi';\nimport {PortalModule} from '@angular/cdk/portal';\nimport {ScrollingModule} from '@angular/cdk/scrolling';\nimport {NgModule} from '@angular/core';\nimport {Overlay} from './overlay';\nimport {\n CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER,\n CdkConnectedOverlay,\n CdkOverlayOrigin,\n} from './overlay-directives';\n\n@NgModule({\n imports: [BidiModule, PortalModule, ScrollingModule, CdkConnectedOverlay, CdkOverlayOrigin],\n exports: [CdkConnectedOverlay, CdkOverlayOrigin, ScrollingModule],\n providers: [Overlay, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER],\n})\nexport class OverlayModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, Injectable, PLATFORM_ID} from '@angular/core';\nimport {isPlatformBrowser} from '@angular/common';\n\n// Whether the current platform supports the V8 Break Iterator. The V8 check\n// is necessary to detect all Blink based browsers.\nlet hasV8BreakIterator: boolean;\n\n// We need a try/catch around the reference to `Intl`, because accessing it in some cases can\n// cause IE to throw. These cases are tied to particular versions of Windows and can happen if\n// the consumer is providing a polyfilled `Map`. See:\n// https://github.com/Microsoft/ChakraCore/issues/3189\n// https://github.com/angular/components/issues/15687\ntry {\n hasV8BreakIterator = typeof Intl !== 'undefined' && (Intl as any).v8BreakIterator;\n} catch {\n hasV8BreakIterator = false;\n}\n\n/**\n * Service to detect the current platform by comparing the userAgent strings and\n * checking browser-specific global properties.\n */\n@Injectable({providedIn: 'root'})\nexport class Platform {\n // We want to use the Angular platform check because if the Document is shimmed\n // without the navigator, the following checks will fail. This is preferred because\n // sometimes the Document may be shimmed without the user's knowledge or intention\n /** Whether the Angular application is being rendered in the browser. */\n isBrowser: boolean = this._platformId\n ? isPlatformBrowser(this._platformId)\n : typeof document === 'object' && !!document;\n\n /** Whether the current browser is Microsoft Edge. */\n EDGE: boolean = this.isBrowser && /(edge)/i.test(navigator.userAgent);\n\n /** Whether the current rendering engine is Microsoft Trident. */\n TRIDENT: boolean = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);\n\n // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check.\n /** Whether the current rendering engine is Blink. */\n BLINK: boolean =\n this.isBrowser &&\n !!((window as any).chrome || hasV8BreakIterator) &&\n typeof CSS !== 'undefined' &&\n !this.EDGE &&\n !this.TRIDENT;\n\n // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to\n // ensure that Webkit runs standalone and is not used as another engine's base.\n /** Whether the current rendering engine is WebKit. */\n WEBKIT: boolean =\n this.isBrowser &&\n /AppleWebKit/i.test(navigator.userAgent) &&\n !this.BLINK &&\n !this.EDGE &&\n !this.TRIDENT;\n\n /** Whether the current platform is Apple iOS. */\n IOS: boolean =\n this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window);\n\n // It's difficult to detect the plain Gecko engine, because most of the browsers identify\n // them self as Gecko-like browsers and modify the userAgent's according to that.\n // Since we only cover one explicit Firefox case, we can simply check for Firefox\n // instead of having an unstable check for Gecko.\n /** Whether the current browser is Firefox. */\n FIREFOX: boolean = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);\n\n /** Whether the current platform is Android. */\n // Trident on mobile adds the android platform to the userAgent to trick detections.\n ANDROID: boolean = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT;\n\n // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake\n // this and just place the Safari keyword in the userAgent. To be more safe about Safari every\n // Safari browser should also use Webkit as its layout engine.\n /** Whether the current browser is Safari. */\n SAFARI: boolean = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;\n\n constructor(@Inject(PLATFORM_ID) private _platformId: Object) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Cached result of whether the user's browser supports passive event listeners. */\nlet supportsPassiveEvents: boolean;\n\n/**\n * Checks whether the user's browser supports passive event listeners.\n * See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n */\nexport function supportsPassiveEventListeners(): boolean {\n if (supportsPassiveEvents == null && typeof window !== 'undefined') {\n try {\n window.addEventListener(\n 'test',\n null!,\n Object.defineProperty({}, 'passive', {\n get: () => (supportsPassiveEvents = true),\n }),\n );\n } finally {\n supportsPassiveEvents = supportsPassiveEvents || false;\n }\n }\n\n return supportsPassiveEvents;\n}\n\n/**\n * Normalizes an `AddEventListener` object to something that can be passed\n * to `addEventListener` on any browser, no matter whether it supports the\n * `options` parameter.\n * @param options Object to be normalized.\n */\nexport function normalizePassiveListenerOptions(\n options: AddEventListenerOptions,\n): AddEventListenerOptions | boolean {\n return supportsPassiveEventListeners() ? options : !!options.capture;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** The possible ways the browser may handle the horizontal scroll axis in RTL languages. */\nexport const enum RtlScrollAxisType {\n /**\n * scrollLeft is 0 when scrolled all the way left and (scrollWidth - clientWidth) when scrolled\n * all the way right.\n */\n NORMAL,\n /**\n * scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled\n * all the way right.\n */\n NEGATED,\n /**\n * scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled\n * all the way right.\n */\n INVERTED,\n}\n\n/** Cached result of the way the browser handles the horizontal scroll axis in RTL mode. */\nlet rtlScrollAxisType: RtlScrollAxisType | undefined;\n\n/** Cached result of the check that indicates whether the browser supports scroll behaviors. */\nlet scrollBehaviorSupported: boolean | undefined;\n\n/** Check whether the browser supports scroll behaviors. */\nexport function supportsScrollBehavior(): boolean {\n if (scrollBehaviorSupported == null) {\n // If we're not in the browser, it can't be supported. Also check for `Element`, because\n // some projects stub out the global `document` during SSR which can throw us off.\n if (typeof document !== 'object' || !document || typeof Element !== 'function' || !Element) {\n scrollBehaviorSupported = false;\n return scrollBehaviorSupported;\n }\n\n // If the element can have a `scrollBehavior` style, we can be sure that it's supported.\n if ('scrollBehavior' in document.documentElement!.style) {\n scrollBehaviorSupported = true;\n } else {\n // At this point we have 3 possibilities: `scrollTo` isn't supported at all, it's\n // supported but it doesn't handle scroll behavior, or it has been polyfilled.\n const scrollToFunction: Function | undefined = Element.prototype.scrollTo;\n\n if (scrollToFunction) {\n // We can detect if the function has been polyfilled by calling `toString` on it. Native\n // functions are obfuscated using `[native code]`, whereas if it was overwritten we'd get\n // the actual function source. Via https://davidwalsh.name/detect-native-function. Consider\n // polyfilled functions as supporting scroll behavior.\n scrollBehaviorSupported = !/\\{\\s*\\[native code\\]\\s*\\}/.test(scrollToFunction.toString());\n } else {\n scrollBehaviorSupported = false;\n }\n }\n }\n\n return scrollBehaviorSupported;\n}\n\n/**\n * Checks the type of RTL scroll axis used by this browser. As of time of writing, Chrome is NORMAL,\n * Firefox & Safari are NEGATED, and IE & Edge are INVERTED.\n */\nexport function getRtlScrollAxisType(): RtlScrollAxisType {\n // We can't check unless we're on the browser. Just assume 'normal' if we're not.\n if (typeof document !== 'object' || !document) {\n return RtlScrollAxisType.NORMAL;\n }\n\n if (rtlScrollAxisType == null) {\n // Create a 1px wide scrolling container and a 2px wide content element.\n const scrollContainer = document.createElement('div');\n const containerStyle = scrollContainer.style;\n scrollContainer.dir = 'rtl';\n containerStyle.width = '1px';\n containerStyle.overflow = 'auto';\n containerStyle.visibility = 'hidden';\n containerStyle.pointerEvents = 'none';\n containerStyle.position = 'absolute';\n\n const content = document.createElement('div');\n const contentStyle = content.style;\n contentStyle.width = '2px';\n contentStyle.height = '1px';\n\n scrollContainer.appendChild(content);\n document.body.appendChild(scrollContainer);\n\n rtlScrollAxisType = RtlScrollAxisType.NORMAL;\n\n // The viewport starts scrolled all the way to the right in RTL mode. If we are in a NORMAL\n // browser this would mean that the scrollLeft should be 1. If it's zero instead we know we're\n // dealing with one of the other two types of browsers.\n if (scrollContainer.scrollLeft === 0) {\n // In a NEGATED browser the scrollLeft is always somewhere in [-maxScrollAmount, 0]. For an\n // INVERTED browser it is always somewhere in [0, maxScrollAmount]. We can determine which by\n // setting to the scrollLeft to 1. This is past the max for a NEGATED browser, so it will\n // return 0 when we read it again.\n scrollContainer.scrollLeft = 1;\n rtlScrollAxisType =\n scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED;\n }\n\n scrollContainer.remove();\n }\n return rtlScrollAxisType;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nlet shadowDomIsSupported: boolean;\n\n/** Checks whether the user's browser support Shadow DOM. */\nexport function _supportsShadowDom(): boolean {\n if (shadowDomIsSupported == null) {\n const head = typeof document !== 'undefined' ? document.head : null;\n shadowDomIsSupported = !!(head && ((head as any).createShadowRoot || head.attachShadow));\n }\n\n return shadowDomIsSupported;\n}\n\n/** Gets the shadow root of an element, if supported and the element is inside the Shadow DOM. */\nexport function _getShadowRoot(element: HTMLElement): ShadowRoot | null {\n if (_supportsShadowDom()) {\n const rootNode = element.getRootNode ? element.getRootNode() : null;\n\n // Note that this should be caught by `_supportsShadowDom`, but some\n // teams have been able to hit this code path on unsupported browsers.\n if (typeof ShadowRoot !== 'undefined' && ShadowRoot && rootNode instanceof ShadowRoot) {\n return rootNode;\n }\n }\n\n return null;\n}\n\n/**\n * Gets the currently-focused element on the page while\n * also piercing through Shadow DOM boundaries.\n */\nexport function _getFocusedElementPierceShadowDom(): HTMLElement | null {\n let activeElement =\n typeof document !== 'undefined' && document\n ? (document.activeElement as HTMLElement | null)\n : null;\n\n while (activeElement && activeElement.shadowRoot) {\n const newActiveElement = activeElement.shadowRoot.activeElement as HTMLElement | null;\n if (newActiveElement === activeElement) {\n break;\n } else {\n activeElement = newActiveElement;\n }\n }\n\n return activeElement;\n}\n\n/** Gets the target of an event while accounting for Shadow DOM. */\nexport function _getEventTarget<T extends EventTarget>(event: Event): T | null {\n // If an event is bound outside the Shadow DOM, the `event.target` will\n // point to the shadow root so we have to use `composedPath` instead.\n return (event.composedPath ? event.composedPath()[0] : event.target) as T | null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Gets whether the code is currently running in a test environment. */\nexport function _isTestEnvironment(): boolean {\n // We can't use `declare const` because it causes conflicts inside Google with the real typings\n // for these symbols and we can't read them off the global object, because they don't appear to\n // be attached there for some runners like Jest.\n // (see: https://github.com/angular/components/issues/23365#issuecomment-938146643)\n return (\n // @ts-ignore\n (typeof __karma__ !== 'undefined' && !!__karma__) ||\n // @ts-ignore\n (typeof jasmine !== 'undefined' && !!jasmine) ||\n // @ts-ignore\n (typeof jest !== 'undefined' && !!jest) ||\n // @ts-ignore\n (typeof Mocha !== 'undefined' && !!Mocha)\n );\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n TemplateRef,\n ViewContainerRef,\n ElementRef,\n ComponentRef,\n EmbeddedViewRef,\n Injector,\n ComponentFactoryResolver,\n} from '@angular/core';\nimport {\n throwNullPortalOutletError,\n throwPortalAlreadyAttachedError,\n throwNoPortalAttachedError,\n throwNullPortalError,\n throwPortalOutletAlreadyDisposedError,\n throwUnknownPortalTypeError,\n} from './portal-errors';\n\n/** Interface that can be used to generically type a class. */\nexport interface ComponentType<T> {\n new (...args: any[]): T;\n}\n\n/**\n * A `Portal` is something that you want to render somewhere else.\n * It can be attach to / detached from a `PortalOutlet`.\n */\nexport abstract class Portal<T> {\n private _attachedHost: PortalOutlet | null;\n\n /** Attach this portal to a host. */\n attach(host: PortalOutlet): T {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (host == null) {\n throwNullPortalOutletError();\n }\n\n if (host.hasAttached()) {\n throwPortalAlreadyAttachedError();\n }\n }\n\n this._attachedHost = host;\n return <T>host.attach(this);\n }\n\n /** Detach this portal from its host */\n detach(): void {\n let host = this._attachedHost;\n\n if (host != null) {\n this._attachedHost = null;\n host.detach();\n } else if (typeof ngDevMode === 'undefined' || ngDevMode) {\n throwNoPortalAttachedError();\n }\n }\n\n /** Whether this portal is attached to a host. */\n get isAttached(): boolean {\n return this._attachedHost != null;\n }\n\n /**\n * Sets the PortalOutlet reference without performing `attach()`. This is used directly by\n * the PortalOutlet when it is performing an `attach()` or `detach()`.\n */\n setAttachedHost(host: PortalOutlet | null) {\n this._attachedHost = host;\n }\n}\n\n/**\n * A `ComponentPortal` is a portal that instantiates some Component upon attachment.\n */\nexport class ComponentPortal<T> extends Portal<ComponentRef<T>> {\n /** The type of the component that will be instantiated for attachment. */\n component: ComponentType<T>;\n\n /**\n * Where the attached component should live in Angular's *logical* component tree.\n * This is different from where the component *renders*, which is determined by the PortalOutlet.\n * The origin is necessary when the host is outside of the Angular application context.\n */\n viewContainerRef?: ViewContainerRef | null;\n\n /** Injector used for the instantiation of the component. */\n injector?: Injector | null;\n\n /**\n * Alternate `ComponentFactoryResolver` to use when resolving the associated component.\n * Defaults to using the resolver from the outlet that the portal is attached to.\n */\n componentFactoryResolver?: ComponentFactoryResolver | null;\n\n /**\n * List of DOM nodes that should be projected through `<ng-content>` of the attached component.\n */\n projectableNodes?: Node[][] | null;\n\n constructor(\n component: ComponentType<T>,\n viewContainerRef?: ViewContainerRef | null,\n injector?: Injector | null,\n componentFactoryResolver?: ComponentFactoryResolver | null,\n projectableNodes?: Node[][] | null,\n ) {\n super();\n this.component = component;\n this.viewContainerRef = viewContainerRef;\n this.injector = injector;\n this.componentFactoryResolver = componentFactoryResolver;\n this.projectableNodes = projectableNodes;\n }\n}\n\n/**\n * A `TemplatePortal` is a portal that represents some embedded template (TemplateRef).\n */\nexport class TemplatePortal<C = any> extends Portal<EmbeddedViewRef<C>> {\n constructor(\n /** The embedded template that will be used to instantiate an embedded View in the host. */\n public templateRef: TemplateRef<C>,\n /** Reference to the ViewContainer into which the template will be stamped out. */\n public viewContainerRef: ViewContainerRef,\n /** Contextual data to be passed in to the embedded view. */\n public context?: C,\n /** The injector to use for the embedded view. */\n public injector?: Injector,\n ) {\n super();\n }\n\n get origin(): ElementRef {\n return this.templateRef.elementRef;\n }\n\n /**\n * Attach the portal to the provided `PortalOutlet`.\n * When a context is provided it will override the `context` property of the `TemplatePortal`\n * instance.\n */\n override attach(host: PortalOutlet, context: C | undefined = this.context): EmbeddedViewRef<C> {\n this.context = context;\n return super.attach(host);\n }\n\n override detach(): void {\n this.context = undefined;\n return super.detach();\n }\n}\n\n/**\n * A `DomPortal` is a portal whose DOM element will be taken from its current position\n * in the DOM and moved into a portal outlet, when it is attached. On detach, the content\n * will be restored to its original position.\n */\nexport class DomPortal<T = HTMLElement> extends Portal<T> {\n /** DOM node hosting the portal's content. */\n readonly element: T;\n\n constructor(element: T | ElementRef<T>) {\n super();\n this.element = element instanceof ElementRef ? element.nativeElement : element;\n }\n}\n\n/** A `PortalOutlet` is an space that can contain a single `Portal`. */\nexport interface PortalOutlet {\n /** Attaches a portal to this outlet. */\n attach(portal: Portal<any>): any;\n\n /** Detaches the currently attached portal from this outlet. */\n detach(): any;\n\n /** Performs cleanup before the outlet is destroyed. */\n dispose(): void;\n\n /** Whether there is currently a portal attached to this outlet. */\n hasAttached(): boolean;\n}\n\n/**\n * @deprecated Use `PortalOutlet` instead.\n * @breaking-change 9.0.0\n */\nexport type PortalHost = PortalOutlet;\n\n/**\n * Partial implementation of PortalOutlet that handles attaching\n * ComponentPortal and TemplatePortal.\n */\nexport abstract class BasePortalOutlet implements PortalOutlet {\n /** The portal currently attached to the host. */\n protected _attachedPortal: Portal<any> | null;\n\n /** A function that will permanently dispose this host. */\n private _disposeFn: (() => void) | null;\n\n /** Whether this host has already been permanently disposed. */\n private _isDisposed: boolean = false;\n\n /** Whether this host has an attached portal. */\n hasAttached(): boolean {\n return !!this._attachedPortal;\n }\n\n attach<T>(portal: ComponentPortal<T>): ComponentRef<T>;\n attach<T>(portal: TemplatePortal<T>): EmbeddedViewRef<T>;\n attach(portal: any): any;\n\n /** Attaches a portal. */\n attach(portal: Portal<any>): any {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!portal) {\n throwNullPortalError();\n }\n\n if (this.hasAttached()) {\n throwPortalAlreadyAttachedError();\n }\n\n if (this._isDisposed) {\n throwPortalOutletAlreadyDisposedError();\n }\n }\n\n if (portal instanceof ComponentPortal) {\n this._attachedPortal = portal;\n return this.attachComponentPortal(portal);\n } else if (portal instanceof TemplatePortal) {\n this._attachedPortal = portal;\n return this.attachTemplatePortal(portal);\n // @breaking-change 10.0.0 remove null check for `this.attachDomPortal`.\n } else if (this.attachDomPortal && portal instanceof DomPortal) {\n this._attachedPortal = portal;\n return this.attachDomPortal(portal);\n }\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n throwUnknownPortalTypeError();\n }\n }\n\n abstract attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T>;\n\n abstract attachTemplatePortal<C>(portal: TemplatePortal<C>): EmbeddedViewRef<C>;\n\n // @breaking-change 10.0.0 `attachDomPortal` to become a required abstract method.\n readonly attachDomPortal: null | ((portal: DomPortal) => any) = null;\n\n /** Detaches a previously attached portal. */\n detach(): void {\n if (this._attachedPortal) {\n this._attachedPortal.setAttachedHost(null);\n this._attachedPortal = null;\n }\n\n this._invokeDisposeFn();\n }\n\n /** Permanently dispose of this portal host. */\n dispose(): void {\n if (this.hasAttached()) {\n this.detach();\n }\n\n this._invokeDisposeFn();\n this._isDisposed = true;\n }\n\n /** @docs-private */\n setDisposeFn(fn: () => void) {\n this._disposeFn = fn;\n }\n\n private _invokeDisposeFn() {\n if (this._disposeFn) {\n this._disposeFn();\n this._disposeFn = null;\n }\n }\n}\n\n/**\n * @deprecated Use `BasePortalOutlet` instead.\n * @breaking-change 9.0.0\n */\nexport abstract class BasePortalHost extends BasePortalOutlet {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n EmbeddedViewRef,\n Injector,\n} from '@angular/core';\nimport {BasePortalOutlet, ComponentPortal, DomPortal, TemplatePortal} from './portal';\n\n/**\n * A PortalOutlet for attaching portals to an arbitrary DOM element outside of the Angular\n * application context.\n */\nexport class DomPortalOutlet extends BasePortalOutlet {\n private _document: Document;\n\n /**\n * @param outletElement Element into which the content is projected.\n * @param _componentFactoryResolver Used to resolve the component factory.\n * Only required when attaching component portals.\n * @param _appRef Reference to the application. Only used in component portals when there\n * is no `ViewContainerRef` available.\n * @param _defaultInjector Injector to use as a fallback when the portal being attached doesn't\n * have one. Only used for component portals.\n * @param _document Reference to the document. Used when attaching a DOM portal. Will eventually\n * become a required parameter.\n */\n constructor(\n /** Element into which the content is projected. */\n public outletElement: Element,\n private _componentFactoryResolver?: ComponentFactoryResolver,\n private _appRef?: ApplicationRef,\n private _defaultInjector?: Injector,\n\n /**\n * @deprecated `_document` Parameter to be made required.\n * @breaking-change 10.0.0\n */\n _document?: any,\n ) {\n super();\n this._document = _document;\n }\n\n /**\n * Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver.\n * @param portal Portal to be attached\n * @returns Reference to the created component.\n */\n attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {\n const resolver = (portal.componentFactoryResolver || this._componentFactoryResolver)!;\n\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && !resolver) {\n throw Error('Cannot attach component portal to outlet without a ComponentFactoryResolver.');\n }\n\n const componentFactory = resolver.resolveComponentFactory(portal.component);\n let componentRef: ComponentRef<T>;\n\n // If the portal specifies a ViewContainerRef, we will use that as the attachment point\n // for the component (in terms of Angular's component tree, not rendering).\n // When the ViewContainerRef is missing, we use the factory to create the component directly\n // and then manually attach the view to the application.\n if (portal.viewContainerRef) {\n componentRef = portal.viewContainerRef.createComponent(\n componentFactory,\n portal.viewContainerRef.length,\n portal.injector || portal.viewContainerRef.injector,\n portal.projectableNodes || undefined,\n );\n\n this.setDisposeFn(() => componentRef.destroy());\n } else {\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && !this._appRef) {\n throw Error('Cannot attach component portal to outlet without an ApplicationRef.');\n }\n\n componentRef = componentFactory.create(\n portal.injector || this._defaultInjector || Injector.NULL,\n );\n this._appRef!.attachView(componentRef.hostView);\n this.setDisposeFn(() => {\n // Verify that the ApplicationRef has registered views before trying to detach a host view.\n // This check also protects the `detachView` from being called on a destroyed ApplicationRef.\n if (this._appRef!.viewCount > 0) {\n this._appRef!.detachView(componentRef.hostView);\n }\n componentRef.destroy();\n });\n }\n // At this point the component has been instantiated, so we move it to the location in the DOM\n // where we want it to be rendered.\n this.outletElement.appendChild(this._getComponentRootNode(componentRef));\n this._attachedPortal = portal;\n\n return componentRef;\n }\n\n /**\n * Attaches a template portal to the DOM as an embedded view.\n * @param portal Portal to be attached.\n * @returns Reference to the created embedded view.\n */\n attachTemplatePortal<C>(portal: TemplatePortal<C>): EmbeddedViewRef<C> {\n let viewContainer = portal.viewContainerRef;\n let viewRef = viewContainer.createEmbeddedView(portal.templateRef, portal.context, {\n injector: portal.injector,\n });\n\n // The method `createEmbeddedView` will add the view as a child of the viewContainer.\n // But for the DomPortalOutlet the view can be added everywhere in the DOM\n // (e.g Overlay Container) To move the view to the specified host element. We just\n // re-append the existing root nodes.\n viewRef.rootNodes.forEach(rootNode => this.outletElement.appendChild(rootNode));\n\n // Note that we want to detect changes after the nodes have been moved so that\n // any directives inside the portal that are looking at the DOM inside a lifecycle\n // hook won't be invoked too early.\n viewRef.detectChanges();\n\n this.setDisposeFn(() => {\n let index = viewContainer.indexOf(viewRef);\n if (index !== -1) {\n viewContainer.remove(index);\n }\n });\n\n this._attachedPortal = portal;\n\n // TODO(jelbourn): Return locals from view.\n return viewRef;\n }\n\n /**\n * Attaches a DOM portal by transferring its content into the outlet.\n * @param portal Portal to be attached.\n * @deprecated To be turned into a method.\n * @breaking-change 10.0.0\n */\n override attachDomPortal = (portal: DomPortal) => {\n // @breaking-change 10.0.0 Remove check and error once the\n // `_document` constructor parameter is required.\n if (!this._document && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('Cannot attach DOM portal without _document constructor parameter');\n }\n\n const element = portal.element;\n if (!element.parentNode && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('DOM portal content must be attached to a parent node.');\n }\n\n // Anchor used to save the element's previous position so\n // that we can restore it when the portal is detached.\n const anchorNode = this._document.createComment('dom-portal');\n\n element.parentNode!.insertBefore(anchorNode, element);\n this.outletElement.appendChild(element);\n this._attachedPortal = portal;\n\n super.setDisposeFn(() => {\n // We can't use `replaceWith` here because IE doesn't support it.\n if (anchorNode.parentNode) {\n anchorNode.parentNode.replaceChild(element, anchorNode);\n }\n });\n };\n\n /**\n * Clears out a portal from the DOM.\n */\n override dispose(): void {\n super.dispose();\n this.outletElement.remove();\n }\n\n /** Gets the root HTMLElement for an instantiated component. */\n private _getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {\n return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;\n }\n}\n\n/**\n * @deprecated Use `DomPortalOutlet` instead.\n * @breaking-change 9.0.0\n */\nexport class DomPortalHost extends DomPortalOutlet {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ComponentFactoryResolver,\n ComponentRef,\n Directive,\n EmbeddedViewRef,\n EventEmitter,\n NgModule,\n OnDestroy,\n OnInit,\n Output,\n TemplateRef,\n ViewContainerRef,\n Inject,\n} from '@angular/core';\nimport {DOCUMENT} from '@angular/common';\nimport {BasePortalOutlet, ComponentPortal, Portal, TemplatePortal, DomPortal} from './portal';\n\n/**\n * Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal,\n * the directive instance itself can be attached to a host, enabling declarative use of portals.\n */\n@Directive({\n selector: '[cdkPortal]',\n exportAs: 'cdkPortal',\n})\nexport class CdkPortal extends TemplatePortal {\n constructor(templateRef: TemplateRef<any>, viewContainerRef: ViewContainerRef) {\n super(templateRef, viewContainerRef);\n }\n}\n\n/**\n * @deprecated Use `CdkPortal` instead.\n * @breaking-change 9.0.0\n */\n@Directive({\n selector: '[cdk-portal], [portal]',\n exportAs: 'cdkPortal',\n providers: [\n {\n provide: CdkPortal,\n useExisting: TemplatePortalDirective,\n },\n ],\n})\nexport class TemplatePortalDirective extends CdkPortal {}\n\n/**\n * Possible attached references to the CdkPortalOutlet.\n */\nexport type CdkPortalOutletAttachedRef = ComponentRef<any> | EmbeddedViewRef<any> | null;\n\n/**\n * Directive version of a PortalOutlet. Because the directive *is* a PortalOutlet, portals can be\n * directly attached to it, enabling declarative use.\n *\n * Usage:\n * `<ng-template [cdkPortalOutlet]=\"greeting\"></ng-template>`\n */\n@Directive({\n selector: '[cdkPortalOutlet]',\n exportAs: 'cdkPortalOutlet',\n inputs: ['portal: cdkPortalOutlet'],\n})\nexport class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestroy {\n private _document: Document;\n\n /** Whether the portal component is initialized. */\n private _isInitialized = false;\n\n /** Reference to the currently-attached component/view ref. */\n private _attachedRef: CdkPortalOutletAttachedRef;\n\n constructor(\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _viewContainerRef: ViewContainerRef,\n\n /**\n * @deprecated `_document` parameter to be made required.\n * @breaking-change 9.0.0\n */\n @Inject(DOCUMENT) _document?: any,\n ) {\n super();\n this._document = _document;\n }\n\n /** Portal associated with the Portal outlet. */\n get portal(): Portal<any> | null {\n return this._attachedPortal;\n }\n\n set portal(portal: Portal<any> | null | undefined | '') {\n // Ignore the cases where the `portal` is set to a falsy value before the lifecycle hooks have\n // run. This handles the cases where the user might do something like `<div cdkPortalOutlet>`\n // and attach a portal programmatically in the parent component. When Angular does the first CD\n // round, it will fire the setter with empty string, causing the user's content to be cleared.\n if (this.hasAttached() && !portal && !this._isInitialized) {\n return;\n }\n\n if (this.hasAttached()) {\n super.detach();\n }\n\n if (portal) {\n super.attach(portal);\n }\n\n this._attachedPortal = portal || null;\n }\n\n /** Emits when a portal is attached to the outlet. */\n @Output() readonly attached: EventEmitter<CdkPortalOutletAttachedRef> =\n new EventEmitter<CdkPortalOutletAttachedRef>();\n\n /** Component or view reference that is attached to the portal. */\n get attachedRef(): CdkPortalOutletAttachedRef {\n return this._attachedRef;\n }\n\n ngOnInit() {\n this._isInitialized = true;\n }\n\n ngOnDestroy() {\n super.dispose();\n this._attachedRef = this._attachedPortal = null;\n }\n\n /**\n * Attach the given ComponentPortal to this PortalOutlet using the ComponentFactoryResolver.\n *\n * @param portal Portal to be attached to the portal outlet.\n * @returns Reference to the created component.\n */\n attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {\n portal.setAttachedHost(this);\n\n // If the portal specifies an origin, use that as the logical location of the component\n // in the application tree. Otherwise use the location of this PortalOutlet.\n const viewContainerRef =\n portal.viewContainerRef != null ? portal.viewContainerRef : this._viewContainerRef;\n\n const resolver = portal.componentFactoryResolver || this._componentFactoryResolver;\n const componentFactory = resolver.resolveComponentFactory(portal.component);\n const ref = viewContainerRef.createComponent(\n componentFactory,\n viewContainerRef.length,\n portal.injector || viewContainerRef.injector,\n portal.projectableNodes || undefined,\n );\n\n // If we're using a view container that's different from the injected one (e.g. when the portal\n // specifies its own) we need to move the component into the outlet, otherwise it'll be rendered\n // inside of the alternate view container.\n if (viewContainerRef !== this._viewContainerRef) {\n this._getRootNode().appendChild((ref.hostView as EmbeddedViewRef<any>).rootNodes[0]);\n }\n\n super.setDisposeFn(() => ref.destroy());\n this._attachedPortal = portal;\n this._attachedRef = ref;\n this.attached.emit(ref);\n\n return ref;\n }\n\n /**\n * Attach the given TemplatePortal to this PortalHost as an embedded View.\n * @param portal Portal to be attached.\n * @returns Reference to the created embedded view.\n */\n attachTemplatePortal<C>(portal: TemplatePortal<C>): EmbeddedViewRef<C> {\n portal.setAttachedHost(this);\n const viewRef = this._viewContainerRef.createEmbeddedView(portal.templateRef, portal.context, {\n injector: portal.injector,\n });\n super.setDisposeFn(() => this._viewContainerRef.clear());\n\n this._attachedPortal = portal;\n this._attachedRef = viewRef;\n this.attached.emit(viewRef);\n\n return viewRef;\n }\n\n /**\n * Attaches the given DomPortal to this PortalHost by moving all of the portal content into it.\n * @param portal Portal to be attached.\n * @deprecated To be turned into a method.\n * @breaking-change 10.0.0\n */\n override attachDomPortal = (portal: DomPortal) => {\n // @breaking-change 9.0.0 Remove check and error once the\n // `_document` constructor parameter is required.\n if (!this._document && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('Cannot attach DOM portal without _document constructor parameter');\n }\n\n const element = portal.element;\n if (!element.parentNode && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('DOM portal content must be attached to a parent node.');\n }\n\n // Anchor used to save the element's previous position so\n // that we can restore it when the portal is detached.\n const anchorNode = this._document.createComment('dom-portal');\n\n portal.setAttachedHost(this);\n element.parentNode!.insertBefore(anchorNode, element);\n this._getRootNode().appendChild(element);\n this._attachedPortal = portal;\n\n super.setDisposeFn(() => {\n if (anchorNode.parentNode) {\n anchorNode.parentNode!.replaceChild(element, anchorNode);\n }\n });\n };\n\n /** Gets the root node of the portal outlet. */\n private _getRootNode(): HTMLElement {\n const nativeElement: Node = this._viewContainerRef.element.nativeElement;\n\n // The directive could be set on a template which will result in a comment\n // node being the root. Use the comment's parent node if that is the case.\n return (\n nativeElement.nodeType === nativeElement.ELEMENT_NODE\n ? nativeElement\n : nativeElement.parentNode!\n ) as HTMLElement;\n }\n}\n\n/**\n * @deprecated Use `CdkPortalOutlet` instead.\n * @breaking-change 9.0.0\n */\n@Directive({\n selector: '[cdkPortalHost], [portalHost]',\n exportAs: 'cdkPortalHost',\n inputs: ['portal: cdkPortalHost'],\n providers: [\n {\n provide: CdkPortalOutlet,\n useExisting: PortalHostDirective,\n },\n ],\n})\nexport class PortalHostDirective extends CdkPortalOutlet {}\n\n@NgModule({\n exports: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective],\n declarations: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective],\n})\nexport class PortalModule {}\n","import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n","import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * <span class=\"informal\">Perform task when `window.requestAnimationFrame` would fire</span>\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html: <div style=\"background: #0ff;\"></div>\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction<any>): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n","import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction<T> extends AsyncAction<T> {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n","import { asyncScheduler } from '../scheduler/async';\nimport { audit } from './audit';\nimport { timer } from '../observable/timer';\nimport { MonoTypeOperatorFunction, SchedulerLike } from '../types';\n\n/**\n * Ignores source values for `duration` milliseconds, then emits the most recent\n * value from the source Observable, then repeats this process.\n *\n * <span class=\"informal\">When it sees a source value, it ignores that plus\n * the next ones for `duration` milliseconds, and then it emits the most recent\n * value from the source.</span>\n *\n * ![](auditTime.png)\n *\n * `auditTime` is similar to `throttleTime`, but emits the last value from the\n * silenced time window, instead of the first value. `auditTime` emits the most\n * recent value from the source Observable on the output Observable as soon as\n * its internal timer becomes disabled, and ignores source values while the\n * timer is enabled. Initially, the timer is disabled. As soon as the first\n * source value arrives, the timer is enabled. After `duration` milliseconds (or\n * the time unit determined internally by the optional `scheduler`) has passed,\n * the timer is disabled, then the most recent source value is emitted on the\n * output Observable, and this process repeats for the next source value.\n * Optionally takes a {@link SchedulerLike} for managing timers.\n *\n * ## Example\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, auditTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(auditTime(1000));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link debounceTime}\n * @see {@link delay}\n * @see {@link sampleTime}\n * @see {@link throttleTime}\n *\n * @param {number} duration Time to wait before emitting the most recent source\n * value, measured in milliseconds or the time unit determined internally\n * by the optional `scheduler`.\n * @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for\n * managing the timers that handle the rate-limiting behavior.\n * @return A function that returns an Observable that performs rate-limiting of\n * emissions from the source Observable.\n */\nexport function auditTime<T>(duration: number, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n return audit(() => timer(duration, scheduler));\n}\n","import { Subscriber } from '../Subscriber';\nimport { MonoTypeOperatorFunction, ObservableInput } from '../types';\n\nimport { operate } from '../util/lift';\nimport { innerFrom } from '../observable/innerFrom';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Ignores source values for a duration determined by another Observable, then\n * emits the most recent value from the source Observable, then repeats this\n * process.\n *\n * <span class=\"informal\">It's like {@link auditTime}, but the silencing\n * duration is determined by a second Observable.</span>\n *\n * ![](audit.svg)\n *\n * `audit` is similar to `throttle`, but emits the last value from the silenced\n * time window, instead of the first value. `audit` emits the most recent value\n * from the source Observable on the output Observable as soon as its internal\n * timer becomes disabled, and ignores source values while the timer is enabled.\n * Initially, the timer is disabled. As soon as the first source value arrives,\n * the timer is enabled by calling the `durationSelector` function with the\n * source value, which returns the \"duration\" Observable. When the duration\n * Observable emits a value, the timer is disabled, then the most\n * recent source value is emitted on the output Observable, and this process\n * repeats for the next source value.\n *\n * ## Example\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, audit, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(audit(ev => interval(1000)));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link auditTime}\n * @see {@link debounce}\n * @see {@link delayWhen}\n * @see {@link sample}\n * @see {@link throttle}\n *\n * @param durationSelector A function\n * that receives a value from the source Observable, for computing the silencing\n * duration, returned as an Observable or a Promise.\n * @return A function that returns an Observable that performs rate-limiting of\n * emissions from the source Observable.\n */\nexport function audit<T>(durationSelector: (value: T) => ObservableInput<any>): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n let hasValue = false;\n let lastValue: T | null = null;\n let durationSubscriber: Subscriber<any> | null = null;\n let isComplete = false;\n\n const endDuration = () => {\n durationSubscriber?.unsubscribe();\n durationSubscriber = null;\n if (hasValue) {\n hasValue = false;\n const value = lastValue!;\n lastValue = null;\n subscriber.next(value);\n }\n isComplete && subscriber.complete();\n };\n\n const cleanupDuration = () => {\n durationSubscriber = null;\n isComplete && subscriber.complete();\n };\n\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n hasValue = true;\n lastValue = value;\n if (!durationSubscriber) {\n innerFrom(durationSelector(value)).subscribe(\n (durationSubscriber = createOperatorSubscriber(subscriber, endDuration, cleanupDuration))\n );\n }\n },\n () => {\n isComplete = true;\n (!hasValue || !durationSubscriber || durationSubscriber.closed) && subscriber.complete();\n }\n )\n );\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\nimport {Observable} from 'rxjs';\nimport {CdkVirtualScrollViewport} from './virtual-scroll-viewport';\n\n/** The injection token used to specify the virtual scrolling strategy. */\nexport const VIRTUAL_SCROLL_STRATEGY = new InjectionToken<VirtualScrollStrategy>(\n 'VIRTUAL_SCROLL_STRATEGY',\n);\n\n/** A strategy that dictates which items should be rendered in the viewport. */\nexport interface VirtualScrollStrategy {\n /** Emits when the index of the first element visible in the viewport changes. */\n scrolledIndexChange: Observable<number>;\n\n /**\n * Attaches this scroll strategy to a viewport.\n * @param viewport The viewport to attach this strategy to.\n */\n attach(viewport: CdkVirtualScrollViewport): void;\n\n /** Detaches this scroll strategy from the currently attached viewport. */\n detach(): void;\n\n /** Called when the viewport is scrolled (debounced using requestAnimationFrame). */\n onContentScrolled(): void;\n\n /** Called when the length of the data changes. */\n onDataLengthChanged(): void;\n\n /** Called when the range of items rendered in the DOM has changed. */\n onContentRendered(): void;\n\n /** Called when the offset of the rendered items changed. */\n onRenderedOffsetChanged(): void;\n\n /**\n * Scroll to the offset for the given index.\n * @param index The index of the element to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling.\n */\n scrollToIndex(index: number, behavior: ScrollBehavior): void;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {Platform} from '@angular/cdk/platform';\nimport {ElementRef, Injectable, NgZone, OnDestroy, Optional, Inject} from '@angular/core';\nimport {fromEvent, of as observableOf, Subject, Subscription, Observable, Observer} from 'rxjs';\nimport {auditTime, filter} from 'rxjs/operators';\nimport {CdkScrollable} from './scrollable';\nimport {DOCUMENT} from '@angular/common';\n\n/** Time in ms to throttle the scrolling events by default. */\nexport const DEFAULT_SCROLL_TIME = 20;\n\n/**\n * Service contained all registered Scrollable references and emits an event when any one of the\n * Scrollable references emit a scrolled event.\n */\n@Injectable({providedIn: 'root'})\nexport class ScrollDispatcher implements OnDestroy {\n /** Used to reference correct document/window */\n protected _document: Document;\n\n constructor(\n private _ngZone: NgZone,\n private _platform: Platform,\n @Optional() @Inject(DOCUMENT) document: any,\n ) {\n this._document = document;\n }\n\n /** Subject for notifying that a registered scrollable reference element has been scrolled. */\n private readonly _scrolled = new Subject<CdkScrollable | void>();\n\n /** Keeps track of the global `scroll` and `resize` subscriptions. */\n _globalSubscription: Subscription | null = null;\n\n /** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */\n private _scrolledCount = 0;\n\n /**\n * Map of all the scrollable references that are registered with the service and their\n * scroll event subscriptions.\n */\n scrollContainers: Map<CdkScrollable, Subscription> = new Map();\n\n /**\n * Registers a scrollable instance with the service and listens for its scrolled events. When the\n * scrollable is scrolled, the service emits the event to its scrolled observable.\n * @param scrollable Scrollable instance to be registered.\n */\n register(scrollable: CdkScrollable): void {\n if (!this.scrollContainers.has(scrollable)) {\n this.scrollContainers.set(\n scrollable,\n scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable)),\n );\n }\n }\n\n /**\n * De-registers a Scrollable reference and unsubscribes from its scroll event observable.\n * @param scrollable Scrollable instance to be deregistered.\n */\n deregister(scrollable: CdkScrollable): void {\n const scrollableReference = this.scrollContainers.get(scrollable);\n\n if (scrollableReference) {\n scrollableReference.unsubscribe();\n this.scrollContainers.delete(scrollable);\n }\n }\n\n /**\n * Returns an observable that emits an event whenever any of the registered Scrollable\n * references (or window, document, or body) fire a scrolled event. Can provide a time in ms\n * to override the default \"throttle\" time.\n *\n * **Note:** in order to avoid hitting change detection for every scroll event,\n * all of the events emitted from this stream will be run outside the Angular zone.\n * If you need to update any data bindings as a result of a scroll event, you have\n * to run the callback using `NgZone.run`.\n */\n scrolled(auditTimeInMs: number = DEFAULT_SCROLL_TIME): Observable<CdkScrollable | void> {\n if (!this._platform.isBrowser) {\n return observableOf<void>();\n }\n\n return new Observable((observer: Observer<CdkScrollable | void>) => {\n if (!this._globalSubscription) {\n this._addGlobalListener();\n }\n\n // In the case of a 0ms delay, use an observable without auditTime\n // since it does add a perceptible delay in processing overhead.\n const subscription =\n auditTimeInMs > 0\n ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer)\n : this._scrolled.subscribe(observer);\n\n this._scrolledCount++;\n\n return () => {\n subscription.unsubscribe();\n this._scrolledCount--;\n\n if (!this._scrolledCount) {\n this._removeGlobalListener();\n }\n };\n });\n }\n\n ngOnDestroy() {\n this._removeGlobalListener();\n this.scrollContainers.forEach((_, container) => this.deregister(container));\n this._scrolled.complete();\n }\n\n /**\n * Returns an observable that emits whenever any of the\n * scrollable ancestors of an element are scrolled.\n * @param elementOrElementRef Element whose ancestors to listen for.\n * @param auditTimeInMs Time to throttle the scroll events.\n */\n ancestorScrolled(\n elementOrElementRef: ElementRef | HTMLElement,\n auditTimeInMs?: number,\n ): Observable<CdkScrollable | void> {\n const ancestors = this.getAncestorScrollContainers(elementOrElementRef);\n\n return this.scrolled(auditTimeInMs).pipe(\n filter(target => {\n return !target || ancestors.indexOf(target) > -1;\n }),\n );\n }\n\n /** Returns all registered Scrollables that contain the provided element. */\n getAncestorScrollContainers(elementOrElementRef: ElementRef | HTMLElement): CdkScrollable[] {\n const scrollingContainers: CdkScrollable[] = [];\n\n this.scrollContainers.forEach((_subscription: Subscription, scrollable: CdkScrollable) => {\n if (this._scrollableContainsElement(scrollable, elementOrElementRef)) {\n scrollingContainers.push(scrollable);\n }\n });\n\n return scrollingContainers;\n }\n\n /** Use defaultView of injected document if available or fallback to global window reference */\n private _getWindow(): Window {\n return this._document.defaultView || window;\n }\n\n /** Returns true if the element is contained within the provided Scrollable. */\n private _scrollableContainsElement(\n scrollable: CdkScrollable,\n elementOrElementRef: ElementRef | HTMLElement,\n ): boolean {\n let element: HTMLElement | null = coerceElement(elementOrElementRef);\n let scrollableElement = scrollable.getElementRef().nativeElement;\n\n // Traverse through the element parents until we reach null, checking if any of the elements\n // are the scrollable's element.\n do {\n if (element == scrollableElement) {\n return true;\n }\n } while ((element = element!.parentElement));\n\n return false;\n }\n\n /** Sets up the global scroll listeners. */\n private _addGlobalListener() {\n this._globalSubscription = this._ngZone.runOutsideAngular(() => {\n const window = this._getWindow();\n return fromEvent(window.document, 'scroll').subscribe(() => this._scrolled.next());\n });\n }\n\n /** Cleans up the global scroll listener. */\n private _removeGlobalListener() {\n if (this._globalSubscription) {\n this._globalSubscription.unsubscribe();\n this._globalSubscription = null;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directionality} from '@angular/cdk/bidi';\nimport {\n getRtlScrollAxisType,\n RtlScrollAxisType,\n supportsScrollBehavior,\n} from '@angular/cdk/platform';\nimport {Directive, ElementRef, NgZone, OnDestroy, OnInit, Optional} from '@angular/core';\nimport {fromEvent, Observable, Subject, Observer} from 'rxjs';\nimport {takeUntil} from 'rxjs/operators';\nimport {ScrollDispatcher} from './scroll-dispatcher';\n\nexport type _Without<T> = {[P in keyof T]?: never};\nexport type _XOR<T, U> = (_Without<T> & U) | (_Without<U> & T);\nexport type _Top = {top?: number};\nexport type _Bottom = {bottom?: number};\nexport type _Left = {left?: number};\nexport type _Right = {right?: number};\nexport type _Start = {start?: number};\nexport type _End = {end?: number};\nexport type _XAxis = _XOR<_XOR<_Left, _Right>, _XOR<_Start, _End>>;\nexport type _YAxis = _XOR<_Top, _Bottom>;\n\n/**\n * An extended version of ScrollToOptions that allows expressing scroll offsets relative to the\n * top, bottom, left, right, start, or end of the viewport rather than just the top and left.\n * Please note: the top and bottom properties are mutually exclusive, as are the left, right,\n * start, and end properties.\n */\nexport type ExtendedScrollToOptions = _XAxis & _YAxis & ScrollOptions;\n\n/**\n * Sends an event when the directive's element is scrolled. Registers itself with the\n * ScrollDispatcher service to include itself as part of its collection of scrolling events that it\n * can be listened to through the service.\n */\n@Directive({\n selector: '[cdk-scrollable], [cdkScrollable]',\n standalone: true,\n})\nexport class CdkScrollable implements OnInit, OnDestroy {\n protected readonly _destroyed = new Subject<void>();\n\n protected _elementScrolled: Observable<Event> = new Observable((observer: Observer<Event>) =>\n this.ngZone.runOutsideAngular(() =>\n fromEvent(this.elementRef.nativeElement, 'scroll')\n .pipe(takeUntil(this._destroyed))\n .subscribe(observer),\n ),\n );\n\n constructor(\n protected elementRef: ElementRef<HTMLElement>,\n protected scrollDispatcher: ScrollDispatcher,\n protected ngZone: NgZone,\n @Optional() protected dir?: Directionality,\n ) {}\n\n ngOnInit() {\n this.scrollDispatcher.register(this);\n }\n\n ngOnDestroy() {\n this.scrollDispatcher.deregister(this);\n this._destroyed.next();\n this._destroyed.complete();\n }\n\n /** Returns observable that emits when a scroll event is fired on the host element. */\n elementScrolled(): Observable<Event> {\n return this._elementScrolled;\n }\n\n /** Gets the ElementRef for the viewport. */\n getElementRef(): ElementRef<HTMLElement> {\n return this.elementRef;\n }\n\n /**\n * Scrolls to the specified offsets. This is a normalized version of the browser's native scrollTo\n * method, since browsers are not consistent about what scrollLeft means in RTL. For this method\n * left and right always refer to the left and right side of the scrolling container irrespective\n * of the layout direction. start and end refer to left and right in an LTR context and vice-versa\n * in an RTL context.\n * @param options specified the offsets to scroll to.\n */\n scrollTo(options: ExtendedScrollToOptions): void {\n const el = this.elementRef.nativeElement;\n const isRtl = this.dir && this.dir.value == 'rtl';\n\n // Rewrite start & end offsets as right or left offsets.\n if (options.left == null) {\n options.left = isRtl ? options.end : options.start;\n }\n\n if (options.right == null) {\n options.right = isRtl ? options.start : options.end;\n }\n\n // Rewrite the bottom offset as a top offset.\n if (options.bottom != null) {\n (options as _Without<_Bottom> & _Top).top =\n el.scrollHeight - el.clientHeight - options.bottom;\n }\n\n // Rewrite the right offset as a left offset.\n if (isRtl && getRtlScrollAxisType() != RtlScrollAxisType.NORMAL) {\n if (options.left != null) {\n (options as _Without<_Left> & _Right).right =\n el.scrollWidth - el.clientWidth - options.left;\n }\n\n if (getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {\n options.left = options.right;\n } else if (getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {\n options.left = options.right ? -options.right : options.right;\n }\n } else {\n if (options.right != null) {\n (options as _Without<_Right> & _Left).left =\n el.scrollWidth - el.clientWidth - options.right;\n }\n }\n\n this._applyScrollToOptions(options);\n }\n\n private _applyScrollToOptions(options: ScrollToOptions): void {\n const el = this.elementRef.nativeElement;\n\n if (supportsScrollBehavior()) {\n el.scrollTo(options);\n } else {\n if (options.top != null) {\n el.scrollTop = options.top;\n }\n if (options.left != null) {\n el.scrollLeft = options.left;\n }\n }\n }\n\n /**\n * Measures the scroll offset relative to the specified edge of the viewport. This method can be\n * used instead of directly checking scrollLeft or scrollTop, since browsers are not consistent\n * about what scrollLeft means in RTL. The values returned by this method are normalized such that\n * left and right always refer to the left and right side of the scrolling container irrespective\n * of the layout direction. start and end refer to left and right in an LTR context and vice-versa\n * in an RTL context.\n * @param from The edge to measure from.\n */\n measureScrollOffset(from: 'top' | 'left' | 'right' | 'bottom' | 'start' | 'end'): number {\n const LEFT = 'left';\n const RIGHT = 'right';\n const el = this.elementRef.nativeElement;\n if (from == 'top') {\n return el.scrollTop;\n }\n if (from == 'bottom') {\n return el.scrollHeight - el.clientHeight - el.scrollTop;\n }\n\n // Rewrite start & end as left or right offsets.\n const isRtl = this.dir && this.dir.value == 'rtl';\n if (from == 'start') {\n from = isRtl ? RIGHT : LEFT;\n } else if (from == 'end') {\n from = isRtl ? LEFT : RIGHT;\n }\n\n if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {\n // For INVERTED, scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and\n // 0 when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollWidth - el.clientWidth - el.scrollLeft;\n } else {\n return el.scrollLeft;\n }\n } else if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {\n // For NEGATED, scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and\n // 0 when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollLeft + el.scrollWidth - el.clientWidth;\n } else {\n return -el.scrollLeft;\n }\n } else {\n // For NORMAL, as well as non-RTL contexts, scrollLeft is 0 when scrolled all the way left and\n // (scrollWidth - clientWidth) when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollLeft;\n } else {\n return el.scrollWidth - el.clientWidth - el.scrollLeft;\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Platform} from '@angular/cdk/platform';\nimport {Injectable, NgZone, OnDestroy, Optional, Inject} from '@angular/core';\nimport {Observable, Subject} from 'rxjs';\nimport {auditTime} from 'rxjs/operators';\nimport {DOCUMENT} from '@angular/common';\n\n/** Time in ms to throttle the resize events by default. */\nexport const DEFAULT_RESIZE_TIME = 20;\n\n/** Object that holds the scroll position of the viewport in each direction. */\nexport interface ViewportScrollPosition {\n top: number;\n left: number;\n}\n\n/**\n * Simple utility for getting the bounds of the browser viewport.\n * @docs-private\n */\n@Injectable({providedIn: 'root'})\nexport class ViewportRuler implements OnDestroy {\n /** Cached viewport dimensions. */\n private _viewportSize: {width: number; height: number} | null;\n\n /** Stream of viewport change events. */\n private readonly _change = new Subject<Event>();\n\n /** Event listener that will be used to handle the viewport change events. */\n private _changeListener = (event: Event) => {\n this._change.next(event);\n };\n\n /** Used to reference correct document/window */\n protected _document: Document;\n\n constructor(\n private _platform: Platform,\n ngZone: NgZone,\n @Optional() @Inject(DOCUMENT) document: any,\n ) {\n this._document = document;\n\n ngZone.runOutsideAngular(() => {\n if (_platform.isBrowser) {\n const window = this._getWindow();\n\n // Note that bind the events ourselves, rather than going through something like RxJS's\n // `fromEvent` so that we can ensure that they're bound outside of the NgZone.\n window.addEventListener('resize', this._changeListener);\n window.addEventListener('orientationchange', this._changeListener);\n }\n\n // Clear the cached position so that the viewport is re-measured next time it is required.\n // We don't need to keep track of the subscription, because it is completed on destroy.\n this.change().subscribe(() => (this._viewportSize = null));\n });\n }\n\n ngOnDestroy() {\n if (this._platform.isBrowser) {\n const window = this._getWindow();\n window.removeEventListener('resize', this._changeListener);\n window.removeEventListener('orientationchange', this._changeListener);\n }\n\n this._change.complete();\n }\n\n /** Returns the viewport's width and height. */\n getViewportSize(): Readonly<{width: number; height: number}> {\n if (!this._viewportSize) {\n this._updateViewportSize();\n }\n\n const output = {width: this._viewportSize!.width, height: this._viewportSize!.height};\n\n // If we're not on a browser, don't cache the size since it'll be mocked out anyway.\n if (!this._platform.isBrowser) {\n this._viewportSize = null!;\n }\n\n return output;\n }\n\n /** Gets a ClientRect for the viewport's bounds. */\n getViewportRect() {\n // Use the document element's bounding rect rather than the window scroll properties\n // (e.g. pageYOffset, scrollY) due to in issue in Chrome and IE where window scroll\n // properties and client coordinates (boundingClientRect, clientX/Y, etc.) are in different\n // conceptual viewports. Under most circumstances these viewports are equivalent, but they\n // can disagree when the page is pinch-zoomed (on devices that support touch).\n // See https://bugs.chromium.org/p/chromium/issues/detail?id=489206#c4\n // We use the documentElement instead of the body because, by default (without a css reset)\n // browsers typically give the document body an 8px margin, which is not included in\n // getBoundingClientRect().\n const scrollPosition = this.getViewportScrollPosition();\n const {width, height} = this.getViewportSize();\n\n return {\n top: scrollPosition.top,\n left: scrollPosition.left,\n bottom: scrollPosition.top + height,\n right: scrollPosition.left + width,\n height,\n width,\n };\n }\n\n /** Gets the (top, left) scroll position of the viewport. */\n getViewportScrollPosition(): ViewportScrollPosition {\n // While we can get a reference to the fake document\n // during SSR, it doesn't have getBoundingClientRect.\n if (!this._platform.isBrowser) {\n return {top: 0, left: 0};\n }\n\n // The top-left-corner of the viewport is determined by the scroll position of the document\n // body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about\n // whether `document.body` or `document.documentElement` is the scrolled element, so reading\n // `scrollTop` and `scrollLeft` is inconsistent. However, using the bounding rect of\n // `document.documentElement` works consistently, where the `top` and `left` values will\n // equal negative the scroll position.\n const document = this._document;\n const window = this._getWindow();\n const documentElement = document.documentElement!;\n const documentRect = documentElement.getBoundingClientRect();\n\n const top =\n -documentRect.top ||\n document.body.scrollTop ||\n window.scrollY ||\n documentElement.scrollTop ||\n 0;\n\n const left =\n -documentRect.left ||\n document.body.scrollLeft ||\n window.scrollX ||\n documentElement.scrollLeft ||\n 0;\n\n return {top, left};\n }\n\n /**\n * Returns a stream that emits whenever the size of the viewport changes.\n * This stream emits outside of the Angular zone.\n * @param throttleTime Time in milliseconds to throttle the stream.\n */\n change(throttleTime: number = DEFAULT_RESIZE_TIME): Observable<Event> {\n return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change;\n }\n\n /** Use defaultView of injected document if available or fallback to global window reference */\n private _getWindow(): Window {\n return this._document.defaultView || window;\n }\n\n /** Updates the cached viewport size. */\n private _updateViewportSize() {\n const window = this._getWindow();\n this._viewportSize = this._platform.isBrowser\n ? {width: window.innerWidth, height: window.innerHeight}\n : {width: 0, height: 0};\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directionality} from '@angular/cdk/bidi';\nimport {Directive, ElementRef, InjectionToken, NgZone, Optional} from '@angular/core';\nimport {ScrollDispatcher} from './scroll-dispatcher';\nimport {CdkScrollable} from './scrollable';\n\nexport const VIRTUAL_SCROLLABLE = new InjectionToken<CdkVirtualScrollable>('VIRTUAL_SCROLLABLE');\n\n/**\n * Extending the {@link CdkScrollable} to be used as scrolling container for virtual scrolling.\n */\n@Directive()\nexport abstract class CdkVirtualScrollable extends CdkScrollable {\n constructor(\n elementRef: ElementRef<HTMLElement>,\n scrollDispatcher: ScrollDispatcher,\n ngZone: NgZone,\n @Optional() dir?: Directionality,\n ) {\n super(elementRef, scrollDispatcher, ngZone, dir);\n }\n\n /**\n * Measure the viewport size for the provided orientation.\n *\n * @param orientation The orientation to measure the size from.\n */\n measureViewportSize(orientation: 'horizontal' | 'vertical') {\n const viewportEl = this.elementRef.nativeElement;\n return orientation === 'horizontal' ? viewportEl.clientWidth : viewportEl.clientHeight;\n }\n\n /**\n * Measure the bounding ClientRect size including the scroll offset.\n *\n * @param from The edge to measure from.\n */\n abstract measureBoundingClientRectWithScrollOffset(\n from: 'left' | 'top' | 'right' | 'bottom',\n ): number;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directionality} from '@angular/cdk/bidi';\nimport {ListRange} from '@angular/cdk/collections';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n inject,\n Inject,\n Input,\n NgZone,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport {Platform} from '@angular/cdk/platform';\nimport {\n animationFrameScheduler,\n asapScheduler,\n Observable,\n Subject,\n Observer,\n Subscription,\n} from 'rxjs';\nimport {auditTime, startWith, takeUntil} from 'rxjs/operators';\nimport {ScrollDispatcher} from './scroll-dispatcher';\nimport {CdkScrollable, ExtendedScrollToOptions} from './scrollable';\nimport {VIRTUAL_SCROLL_STRATEGY, VirtualScrollStrategy} from './virtual-scroll-strategy';\nimport {ViewportRuler} from './viewport-ruler';\nimport {CdkVirtualScrollRepeater} from './virtual-scroll-repeater';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {CdkVirtualScrollable, VIRTUAL_SCROLLABLE} from './virtual-scrollable';\n\n/** Checks if the given ranges are equal. */\nfunction rangesEqual(r1: ListRange, r2: ListRange): boolean {\n return r1.start == r2.start && r1.end == r2.end;\n}\n\n/**\n * Scheduler to be used for scroll events. Needs to fall back to\n * something that doesn't rely on requestAnimationFrame on environments\n * that don't support it (e.g. server-side rendering).\n */\nconst SCROLL_SCHEDULER =\n typeof requestAnimationFrame !== 'undefined' ? animationFrameScheduler : asapScheduler;\n\n/** A viewport that virtualizes its scrolling with the help of `CdkVirtualForOf`. */\n@Component({\n selector: 'cdk-virtual-scroll-viewport',\n templateUrl: 'virtual-scroll-viewport.html',\n styleUrls: ['virtual-scroll-viewport.css'],\n host: {\n 'class': 'cdk-virtual-scroll-viewport',\n '[class.cdk-virtual-scroll-orientation-horizontal]': 'orientation === \"horizontal\"',\n '[class.cdk-virtual-scroll-orientation-vertical]': 'orientation !== \"horizontal\"',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n providers: [\n {\n provide: CdkScrollable,\n useFactory: (\n virtualScrollable: CdkVirtualScrollable | null,\n viewport: CdkVirtualScrollViewport,\n ) => virtualScrollable || viewport,\n deps: [[new Optional(), new Inject(VIRTUAL_SCROLLABLE)], CdkVirtualScrollViewport],\n },\n ],\n})\nexport class CdkVirtualScrollViewport extends CdkVirtualScrollable implements OnInit, OnDestroy {\n private _platform = inject(Platform);\n\n /** Emits when the viewport is detached from a CdkVirtualForOf. */\n private readonly _detachedSubject = new Subject<void>();\n\n /** Emits when the rendered range changes. */\n private readonly _renderedRangeSubject = new Subject<ListRange>();\n\n /** The direction the viewport scrolls. */\n @Input()\n get orientation() {\n return this._orientation;\n }\n\n set orientation(orientation: 'horizontal' | 'vertical') {\n if (this._orientation !== orientation) {\n this._orientation = orientation;\n this._calculateSpacerSize();\n }\n }\n private _orientation: 'horizontal' | 'vertical' = 'vertical';\n\n /**\n * Whether rendered items should persist in the DOM after scrolling out of view. By default, items\n * will be removed.\n */\n @Input()\n get appendOnly(): boolean {\n return this._appendOnly;\n }\n set appendOnly(value: BooleanInput) {\n this._appendOnly = coerceBooleanProperty(value);\n }\n private _appendOnly = false;\n\n // Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll\n // strategy lazily (i.e. only if the user is actually listening to the events). We do this because\n // depending on how the strategy calculates the scrolled index, it may come at a cost to\n // performance.\n /** Emits when the index of the first element visible in the viewport changes. */\n @Output()\n readonly scrolledIndexChange: Observable<number> = new Observable((observer: Observer<number>) =>\n this._scrollStrategy.scrolledIndexChange.subscribe(index =>\n Promise.resolve().then(() => this.ngZone.run(() => observer.next(index))),\n ),\n );\n\n /** The element that wraps the rendered content. */\n @ViewChild('contentWrapper', {static: true}) _contentWrapper: ElementRef<HTMLElement>;\n\n /** A stream that emits whenever the rendered range changes. */\n readonly renderedRangeStream: Observable<ListRange> = this._renderedRangeSubject;\n\n /**\n * The total size of all content (in pixels), including content that is not currently rendered.\n */\n private _totalContentSize = 0;\n\n /** A string representing the `style.width` property value to be used for the spacer element. */\n _totalContentWidth = '';\n\n /** A string representing the `style.height` property value to be used for the spacer element. */\n _totalContentHeight = '';\n\n /**\n * The CSS transform applied to the rendered subset of items so that they appear within the bounds\n * of the visible viewport.\n */\n private _renderedContentTransform: string;\n\n /** The currently rendered range of indices. */\n private _renderedRange: ListRange = {start: 0, end: 0};\n\n /** The length of the data bound to this viewport (in number of items). */\n private _dataLength = 0;\n\n /** The size of the viewport (in pixels). */\n private _viewportSize = 0;\n\n /** the currently attached CdkVirtualScrollRepeater. */\n private _forOf: CdkVirtualScrollRepeater<any> | null;\n\n /** The last rendered content offset that was set. */\n private _renderedContentOffset = 0;\n\n /**\n * Whether the last rendered content offset was to the end of the content (and therefore needs to\n * be rewritten as an offset to the start of the content).\n */\n private _renderedContentOffsetNeedsRewrite = false;\n\n /** Whether there is a pending change detection cycle. */\n private _isChangeDetectionPending = false;\n\n /** A list of functions to run after the next change detection cycle. */\n private _runAfterChangeDetection: Function[] = [];\n\n /** Subscription to changes in the viewport size. */\n private _viewportChanges = Subscription.EMPTY;\n\n constructor(\n public override elementRef: ElementRef<HTMLElement>,\n private _changeDetectorRef: ChangeDetectorRef,\n ngZone: NgZone,\n @Optional()\n @Inject(VIRTUAL_SCROLL_STRATEGY)\n private _scrollStrategy: VirtualScrollStrategy,\n @Optional() dir: Directionality,\n scrollDispatcher: ScrollDispatcher,\n viewportRuler: ViewportRuler,\n @Optional() @Inject(VIRTUAL_SCROLLABLE) public scrollable: CdkVirtualScrollable,\n ) {\n super(elementRef, scrollDispatcher, ngZone, dir);\n\n if (!_scrollStrategy && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('Error: cdk-virtual-scroll-viewport requires the \"itemSize\" property to be set.');\n }\n\n this._viewportChanges = viewportRuler.change().subscribe(() => {\n this.checkViewportSize();\n });\n\n if (!this.scrollable) {\n // No scrollable is provided, so the virtual-scroll-viewport needs to become a scrollable\n this.elementRef.nativeElement.classList.add('cdk-virtual-scrollable');\n this.scrollable = this;\n }\n }\n\n override ngOnInit() {\n // Scrolling depends on the element dimensions which we can't get during SSR.\n if (!this._platform.isBrowser) {\n return;\n }\n\n if (this.scrollable === this) {\n super.ngOnInit();\n }\n // It's still too early to measure the viewport at this point. Deferring with a promise allows\n // the Viewport to be rendered with the correct size before we measure. We run this outside the\n // zone to avoid causing more change detection cycles. We handle the change detection loop\n // ourselves instead.\n this.ngZone.runOutsideAngular(() =>\n Promise.resolve().then(() => {\n this._measureViewportSize();\n this._scrollStrategy.attach(this);\n\n this.scrollable\n .elementScrolled()\n .pipe(\n // Start off with a fake scroll event so we properly detect our initial position.\n startWith(null),\n // Collect multiple events into one until the next animation frame. This way if\n // there are multiple scroll events in the same frame we only need to recheck\n // our layout once.\n auditTime(0, SCROLL_SCHEDULER),\n )\n .subscribe(() => this._scrollStrategy.onContentScrolled());\n\n this._markChangeDetectionNeeded();\n }),\n );\n }\n\n override ngOnDestroy() {\n this.detach();\n this._scrollStrategy.detach();\n\n // Complete all subjects\n this._renderedRangeSubject.complete();\n this._detachedSubject.complete();\n this._viewportChanges.unsubscribe();\n\n super.ngOnDestroy();\n }\n\n /** Attaches a `CdkVirtualScrollRepeater` to this viewport. */\n attach(forOf: CdkVirtualScrollRepeater<any>) {\n if (this._forOf && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('CdkVirtualScrollViewport is already attached.');\n }\n\n // Subscribe to the data stream of the CdkVirtualForOf to keep track of when the data length\n // changes. Run outside the zone to avoid triggering change detection, since we're managing the\n // change detection loop ourselves.\n this.ngZone.runOutsideAngular(() => {\n this._forOf = forOf;\n this._forOf.dataStream.pipe(takeUntil(this._detachedSubject)).subscribe(data => {\n const newLength = data.length;\n if (newLength !== this._dataLength) {\n this._dataLength = newLength;\n this._scrollStrategy.onDataLengthChanged();\n }\n this._doChangeDetection();\n });\n });\n }\n\n /** Detaches the current `CdkVirtualForOf`. */\n detach() {\n this._forOf = null;\n this._detachedSubject.next();\n }\n\n /** Gets the length of the data bound to this viewport (in number of items). */\n getDataLength(): number {\n return this._dataLength;\n }\n\n /** Gets the size of the viewport (in pixels). */\n getViewportSize(): number {\n return this._viewportSize;\n }\n\n // TODO(mmalerba): This is technically out of sync with what's really rendered until a render\n // cycle happens. I'm being careful to only call it after the render cycle is complete and before\n // setting it to something else, but its error prone and should probably be split into\n // `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM.\n\n /** Get the current rendered range of items. */\n getRenderedRange(): ListRange {\n return this._renderedRange;\n }\n\n measureBoundingClientRectWithScrollOffset(from: 'left' | 'top' | 'right' | 'bottom'): number {\n return this.getElementRef().nativeElement.getBoundingClientRect()[from];\n }\n\n /**\n * Sets the total size of all content (in pixels), including content that is not currently\n * rendered.\n */\n setTotalContentSize(size: number) {\n if (this._totalContentSize !== size) {\n this._totalContentSize = size;\n this._calculateSpacerSize();\n this._markChangeDetectionNeeded();\n }\n }\n\n /** Sets the currently rendered range of indices. */\n setRenderedRange(range: ListRange) {\n if (!rangesEqual(this._renderedRange, range)) {\n if (this.appendOnly) {\n range = {start: 0, end: Math.max(this._renderedRange.end, range.end)};\n }\n this._renderedRangeSubject.next((this._renderedRange = range));\n this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered());\n }\n }\n\n /**\n * Gets the offset from the start of the viewport to the start of the rendered data (in pixels).\n */\n getOffsetToRenderedContentStart(): number | null {\n return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset;\n }\n\n /**\n * Sets the offset from the start of the viewport to either the start or end of the rendered data\n * (in pixels).\n */\n setRenderedContentOffset(offset: number, to: 'to-start' | 'to-end' = 'to-start') {\n // In appendOnly, we always start from the top\n offset = this.appendOnly && to === 'to-start' ? 0 : offset;\n\n // For a horizontal viewport in a right-to-left language we need to translate along the x-axis\n // in the negative direction.\n const isRtl = this.dir && this.dir.value == 'rtl';\n const isHorizontal = this.orientation == 'horizontal';\n const axis = isHorizontal ? 'X' : 'Y';\n const axisDirection = isHorizontal && isRtl ? -1 : 1;\n let transform = `translate${axis}(${Number(axisDirection * offset)}px)`;\n this._renderedContentOffset = offset;\n if (to === 'to-end') {\n transform += ` translate${axis}(-100%)`;\n // The viewport should rewrite this as a `to-start` offset on the next render cycle. Otherwise\n // elements will appear to expand in the wrong direction (e.g. `mat-expansion-panel` would\n // expand upward).\n this._renderedContentOffsetNeedsRewrite = true;\n }\n if (this._renderedContentTransform != transform) {\n // We know this value is safe because we parse `offset` with `Number()` before passing it\n // into the string.\n this._renderedContentTransform = transform;\n this._markChangeDetectionNeeded(() => {\n if (this._renderedContentOffsetNeedsRewrite) {\n this._renderedContentOffset -= this.measureRenderedContentSize();\n this._renderedContentOffsetNeedsRewrite = false;\n this.setRenderedContentOffset(this._renderedContentOffset);\n } else {\n this._scrollStrategy.onRenderedOffsetChanged();\n }\n });\n }\n }\n\n /**\n * Scrolls to the given offset from the start of the viewport. Please note that this is not always\n * the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left\n * direction, this would be the equivalent of setting a fictional `scrollRight` property.\n * @param offset The offset to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.\n */\n scrollToOffset(offset: number, behavior: ScrollBehavior = 'auto') {\n const options: ExtendedScrollToOptions = {behavior};\n if (this.orientation === 'horizontal') {\n options.start = offset;\n } else {\n options.top = offset;\n }\n this.scrollable.scrollTo(options);\n }\n\n /**\n * Scrolls to the offset for the given index.\n * @param index The index of the element to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.\n */\n scrollToIndex(index: number, behavior: ScrollBehavior = 'auto') {\n this._scrollStrategy.scrollToIndex(index, behavior);\n }\n\n /**\n * Gets the current scroll offset from the start of the scrollable (in pixels).\n * @param from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start'\n * in horizontal mode.\n */\n override measureScrollOffset(\n from?: 'top' | 'left' | 'right' | 'bottom' | 'start' | 'end',\n ): number {\n // This is to break the call cycle\n let measureScrollOffset: InstanceType<typeof CdkVirtualScrollable>['measureScrollOffset'];\n if (this.scrollable == this) {\n measureScrollOffset = (_from: NonNullable<typeof from>) => super.measureScrollOffset(_from);\n } else {\n measureScrollOffset = (_from: NonNullable<typeof from>) =>\n this.scrollable.measureScrollOffset(_from);\n }\n\n return Math.max(\n 0,\n measureScrollOffset(from ?? (this.orientation === 'horizontal' ? 'start' : 'top')) -\n this.measureViewportOffset(),\n );\n }\n\n /**\n * Measures the offset of the viewport from the scrolling container\n * @param from The edge to measure from.\n */\n measureViewportOffset(from?: 'top' | 'left' | 'right' | 'bottom' | 'start' | 'end') {\n let fromRect: 'left' | 'top' | 'right' | 'bottom';\n const LEFT = 'left';\n const RIGHT = 'right';\n const isRtl = this.dir?.value == 'rtl';\n if (from == 'start') {\n fromRect = isRtl ? RIGHT : LEFT;\n } else if (from == 'end') {\n fromRect = isRtl ? LEFT : RIGHT;\n } else if (from) {\n fromRect = from;\n } else {\n fromRect = this.orientation === 'horizontal' ? 'left' : 'top';\n }\n\n const scrollerClientRect = this.scrollable.measureBoundingClientRectWithScrollOffset(fromRect);\n const viewportClientRect = this.elementRef.nativeElement.getBoundingClientRect()[fromRect];\n\n return viewportClientRect - scrollerClientRect;\n }\n\n /** Measure the combined size of all of the rendered items. */\n measureRenderedContentSize(): number {\n const contentEl = this._contentWrapper.nativeElement;\n return this.orientation === 'horizontal' ? contentEl.offsetWidth : contentEl.offsetHeight;\n }\n\n /**\n * Measure the total combined size of the given range. Throws if the range includes items that are\n * not rendered.\n */\n measureRangeSize(range: ListRange): number {\n if (!this._forOf) {\n return 0;\n }\n return this._forOf.measureRangeSize(range, this.orientation);\n }\n\n /** Update the viewport dimensions and re-render. */\n checkViewportSize() {\n // TODO: Cleanup later when add logic for handling content resize\n this._measureViewportSize();\n this._scrollStrategy.onDataLengthChanged();\n }\n\n /** Measure the viewport size. */\n private _measureViewportSize() {\n this._viewportSize = this.scrollable.measureViewportSize(this.orientation);\n }\n\n /** Queue up change detection to run. */\n private _markChangeDetectionNeeded(runAfter?: Function) {\n if (runAfter) {\n this._runAfterChangeDetection.push(runAfter);\n }\n\n // Use a Promise to batch together calls to `_doChangeDetection`. This way if we set a bunch of\n // properties sequentially we only have to run `_doChangeDetection` once at the end.\n if (!this._isChangeDetectionPending) {\n this._isChangeDetectionPending = true;\n this.ngZone.runOutsideAngular(() =>\n Promise.resolve().then(() => {\n this._doChangeDetection();\n }),\n );\n }\n }\n\n /** Run change detection. */\n private _doChangeDetection() {\n this._isChangeDetectionPending = false;\n\n // Apply the content transform. The transform can't be set via an Angular binding because\n // bypassSecurityTrustStyle is banned in Google. However the value is safe, it's composed of\n // string literals, a variable that can only be 'X' or 'Y', and user input that is run through\n // the `Number` function first to coerce it to a numeric value.\n this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;\n // Apply changes to Angular bindings. Note: We must call `markForCheck` to run change detection\n // from the root, since the repeated items are content projected in. Calling `detectChanges`\n // instead does not properly check the projected content.\n this.ngZone.run(() => this._changeDetectorRef.markForCheck());\n\n const runAfterChangeDetection = this._runAfterChangeDetection;\n this._runAfterChangeDetection = [];\n for (const fn of runAfterChangeDetection) {\n fn();\n }\n }\n\n /** Calculates the `style.width` and `style.height` for the spacer element. */\n private _calculateSpacerSize() {\n this._totalContentHeight =\n this.orientation === 'horizontal' ? '' : `${this._totalContentSize}px`;\n this._totalContentWidth =\n this.orientation === 'horizontal' ? `${this._totalContentSize}px` : '';\n }\n}\n","<!--\n Wrap the rendered content in an element that will be used to offset it based on the scroll\n position.\n-->\n<div #contentWrapper class=\"cdk-virtual-scroll-content-wrapper\">\n <ng-content></ng-content>\n</div>\n<!--\n Spacer used to force the scrolling container to the correct size for the *total* number of items\n so that the scrollbar captures the size of the entire data set.\n-->\n<div class=\"cdk-virtual-scroll-spacer\"\n [style.width]=\"_totalContentWidth\" [style.height]=\"_totalContentHeight\"></div>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BidiModule} from '@angular/cdk/bidi';\nimport {NgModule} from '@angular/core';\nimport {CdkFixedSizeVirtualScroll} from './fixed-size-virtual-scroll';\nimport {CdkScrollable} from './scrollable';\nimport {CdkVirtualForOf} from './virtual-for-of';\nimport {CdkVirtualScrollViewport} from './virtual-scroll-viewport';\nimport {CdkVirtualScrollableElement} from './virtual-scrollable-element';\nimport {CdkVirtualScrollableWindow} from './virtual-scrollable-window';\n\n@NgModule({\n exports: [CdkScrollable],\n imports: [CdkScrollable],\n})\nexport class CdkScrollableModule {}\n\n/**\n * @docs-primary-export\n */\n@NgModule({\n imports: [\n BidiModule,\n CdkScrollableModule,\n CdkVirtualScrollViewport,\n CdkFixedSizeVirtualScroll,\n CdkVirtualForOf,\n CdkVirtualScrollableWindow,\n CdkVirtualScrollableElement,\n ],\n exports: [\n BidiModule,\n CdkScrollableModule,\n CdkFixedSizeVirtualScroll,\n CdkVirtualForOf,\n CdkVirtualScrollViewport,\n CdkVirtualScrollableWindow,\n CdkVirtualScrollableElement,\n ],\n})\nexport class ScrollingModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nlet _DOM: DomAdapter = null!;\n\nexport function getDOM(): DomAdapter {\n return _DOM;\n}\n\nexport function setRootDomAdapter(adapter: DomAdapter) {\n if (!_DOM) {\n _DOM = adapter;\n }\n}\n\n/* tslint:disable:requireParameterType */\n/**\n * Provides DOM operations in an environment-agnostic way.\n *\n * @security Tread carefully! Interacting with the DOM directly is dangerous and\n * can introduce XSS risks.\n */\nexport abstract class DomAdapter {\n // Needs Domino-friendly test utility\n abstract dispatchEvent(el: any, evt: any): any;\n abstract readonly supportsDOMEvents: boolean;\n\n // Used by Meta\n abstract remove(el: any): void;\n abstract createElement(tagName: any, doc?: any): HTMLElement;\n abstract createHtmlDocument(): Document;\n abstract getDefaultDocument(): Document;\n\n // Used by By.css\n abstract isElementNode(node: any): boolean;\n\n // Used by Testability\n abstract isShadowRoot(node: any): boolean;\n\n // Used by KeyEventsPlugin\n abstract onAndCancel(el: any, evt: any, listener: any): Function;\n\n // Used by PlatformLocation and ServerEventManagerPlugin\n abstract getGlobalEventTarget(doc: Document, target: string): any;\n\n // Used by PlatformLocation\n abstract getBaseHref(doc: Document): string|null;\n abstract resetBaseElement(): void;\n\n // TODO: remove dependency in DefaultValueAccessor\n abstract getUserAgent(): string;\n\n // Used in the legacy @angular/http package which has some usage in g3.\n abstract getCookie(name: string): string|null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\n\n/**\n * A DI Token representing the main rendering context.\n * In a browser and SSR this is the DOM Document.\n * When using SSR, that document is created by [Domino](https://github.com/angular/domino).\n *\n * @publicApi\n */\nexport const DOCUMENT = new InjectionToken<Document>('DocumentToken');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, Injectable, InjectionToken, ɵɵinject} from '@angular/core';\n\nimport {getDOM} from '../dom_adapter';\nimport {DOCUMENT} from '../dom_tokens';\n\n/**\n * This class should not be used directly by an application developer. Instead, use\n * {@link Location}.\n *\n * `PlatformLocation` encapsulates all calls to DOM APIs, which allows the Router to be\n * platform-agnostic.\n * This means that we can have different implementation of `PlatformLocation` for the different\n * platforms that Angular supports. For example, `@angular/platform-browser` provides an\n * implementation specific to the browser environment, while `@angular/platform-server` provides\n * one suitable for use with server-side rendering.\n *\n * The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}\n * when they need to interact with the DOM APIs like pushState, popState, etc.\n *\n * {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly\n * by the {@link Router} in order to navigate between routes. Since all interactions between {@link\n * Router} /\n * {@link Location} / {@link LocationStrategy} and DOM APIs flow through the `PlatformLocation`\n * class, they are all platform-agnostic.\n *\n * @publicApi\n */\n@Injectable({\n providedIn: 'platform',\n // See #23917\n useFactory: useBrowserPlatformLocation\n})\nexport abstract class PlatformLocation {\n abstract getBaseHrefFromDOM(): string;\n abstract getState(): unknown;\n /**\n * Returns a function that, when executed, removes the `popstate` event handler.\n */\n abstract onPopState(fn: LocationChangeListener): VoidFunction;\n /**\n * Returns a function that, when executed, removes the `hashchange` event handler.\n */\n abstract onHashChange(fn: LocationChangeListener): VoidFunction;\n\n abstract get href(): string;\n abstract get protocol(): string;\n abstract get hostname(): string;\n abstract get port(): string;\n abstract get pathname(): string;\n abstract get search(): string;\n abstract get hash(): string;\n\n abstract replaceState(state: any, title: string, url: string): void;\n\n abstract pushState(state: any, title: string, url: string): void;\n\n abstract forward(): void;\n\n abstract back(): void;\n\n historyGo?(relativePosition: number): void {\n throw new Error('Not implemented');\n }\n}\n\nexport function useBrowserPlatformLocation() {\n return ɵɵinject(BrowserPlatformLocation);\n}\n\n/**\n * @description\n * Indicates when a location is initialized.\n *\n * @publicApi\n */\nexport const LOCATION_INITIALIZED = new InjectionToken<Promise<any>>('Location Initialized');\n\n/**\n * @description\n * A serializable version of the event from `onPopState` or `onHashChange`\n *\n * @publicApi\n */\nexport interface LocationChangeEvent {\n type: string;\n state: any;\n}\n\n/**\n * @publicApi\n */\nexport interface LocationChangeListener {\n (event: LocationChangeEvent): any;\n}\n\n\n\n/**\n * `PlatformLocation` encapsulates all of the direct calls to platform APIs.\n * This class should not be used directly by an application developer. Instead, use\n * {@link Location}.\n *\n * @publicApi\n */\n@Injectable({\n providedIn: 'platform',\n // See #23917\n useFactory: createBrowserPlatformLocation,\n})\nexport class BrowserPlatformLocation extends PlatformLocation {\n private _location: Location;\n private _history: History;\n\n constructor(@Inject(DOCUMENT) private _doc: any) {\n super();\n this._location = window.location;\n this._history = window.history;\n }\n\n override getBaseHrefFromDOM(): string {\n return getDOM().getBaseHref(this._doc)!;\n }\n\n override onPopState(fn: LocationChangeListener): VoidFunction {\n const window = getDOM().getGlobalEventTarget(this._doc, 'window');\n window.addEventListener('popstate', fn, false);\n return () => window.removeEventListener('popstate', fn);\n }\n\n override onHashChange(fn: LocationChangeListener): VoidFunction {\n const window = getDOM().getGlobalEventTarget(this._doc, 'window');\n window.addEventListener('hashchange', fn, false);\n return () => window.removeEventListener('hashchange', fn);\n }\n\n override get href(): string {\n return this._location.href;\n }\n override get protocol(): string {\n return this._location.protocol;\n }\n override get hostname(): string {\n return this._location.hostname;\n }\n override get port(): string {\n return this._location.port;\n }\n override get pathname(): string {\n return this._location.pathname;\n }\n override get search(): string {\n return this._location.search;\n }\n override get hash(): string {\n return this._location.hash;\n }\n override set pathname(newPath: string) {\n this._location.pathname = newPath;\n }\n\n override pushState(state: any, title: string, url: string): void {\n if (supportsState()) {\n this._history.pushState(state, title, url);\n } else {\n this._location.hash = url;\n }\n }\n\n override replaceState(state: any, title: string, url: string): void {\n if (supportsState()) {\n this._history.replaceState(state, title, url);\n } else {\n this._location.hash = url;\n }\n }\n\n override forward(): void {\n this._history.forward();\n }\n\n override back(): void {\n this._history.back();\n }\n\n override historyGo(relativePosition: number = 0): void {\n this._history.go(relativePosition);\n }\n\n override getState(): unknown {\n return this._history.state;\n }\n}\n\nexport function supportsState(): boolean {\n return !!window.history.pushState;\n}\nexport function createBrowserPlatformLocation() {\n return new BrowserPlatformLocation(ɵɵinject(DOCUMENT));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\n/**\n * Joins two parts of a URL with a slash if needed.\n *\n * @param start URL string\n * @param end URL string\n *\n *\n * @returns The joined URL string.\n */\nexport function joinWithSlash(start: string, end: string): string {\n if (start.length == 0) {\n return end;\n }\n if (end.length == 0) {\n return start;\n }\n let slashes = 0;\n if (start.endsWith('/')) {\n slashes++;\n }\n if (end.startsWith('/')) {\n slashes++;\n }\n if (slashes == 2) {\n return start + end.substring(1);\n }\n if (slashes == 1) {\n return start + end;\n }\n return start + '/' + end;\n}\n\n/**\n * Removes a trailing slash from a URL string if needed.\n * Looks for the first occurrence of either `#`, `?`, or the end of the\n * line as `/` characters and removes the trailing slash if one exists.\n *\n * @param url URL string.\n *\n * @returns The URL string, modified if needed.\n */\nexport function stripTrailingSlash(url: string): string {\n const match = url.match(/#|\\?|$/);\n const pathEndIdx = match && match.index || url.length;\n const droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0);\n return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx);\n}\n\n/**\n * Normalizes URL parameters by prepending with `?` if needed.\n *\n * @param params String of URL parameters.\n *\n * @returns The normalized URL parameters string.\n */\nexport function normalizeQueryParams(params: string): string {\n return params && params[0] !== '?' ? '?' + params : params;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, inject, Injectable, InjectionToken, OnDestroy, Optional} from '@angular/core';\n\nimport {DOCUMENT} from '../dom_tokens';\n\nimport {LocationChangeListener, PlatformLocation} from './platform_location';\nimport {joinWithSlash, normalizeQueryParams} from './util';\n\n/**\n * Enables the `Location` service to read route state from the browser's URL.\n * Angular provides two strategies:\n * `HashLocationStrategy` and `PathLocationStrategy`.\n *\n * Applications should use the `Router` or `Location` services to\n * interact with application route state.\n *\n * For instance, `HashLocationStrategy` produces URLs like\n * <code class=\"no-auto-link\">http://example.com#/foo</code>,\n * and `PathLocationStrategy` produces\n * <code class=\"no-auto-link\">http://example.com/foo</code> as an equivalent URL.\n *\n * See these two classes for more.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: () => inject(PathLocationStrategy)})\nexport abstract class LocationStrategy {\n abstract path(includeHash?: boolean): string;\n abstract prepareExternalUrl(internal: string): string;\n abstract getState(): unknown;\n abstract pushState(state: any, title: string, url: string, queryParams: string): void;\n abstract replaceState(state: any, title: string, url: string, queryParams: string): void;\n abstract forward(): void;\n abstract back(): void;\n historyGo?(relativePosition: number): void {\n throw new Error('Not implemented');\n }\n abstract onPopState(fn: LocationChangeListener): void;\n abstract getBaseHref(): string;\n}\n\n/**\n * A predefined [DI token](guide/glossary#di-token) for the base href\n * to be used with the `PathLocationStrategy`.\n * The base href is the URL prefix that should be preserved when generating\n * and recognizing URLs.\n *\n * @usageNotes\n *\n * The following example shows how to use this token to configure the root app injector\n * with a base href value, so that the DI framework can supply the dependency anywhere in the app.\n *\n * ```typescript\n * import {Component, NgModule} from '@angular/core';\n * import {APP_BASE_HREF} from '@angular/common';\n *\n * @NgModule({\n * providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]\n * })\n * class AppModule {}\n * ```\n *\n * @publicApi\n */\nexport const APP_BASE_HREF = new InjectionToken<string>('appBaseHref');\n\n/**\n * @description\n * A {@link LocationStrategy} used to configure the {@link Location} service to\n * represent its state in the\n * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the\n * browser's URL.\n *\n * If you're using `PathLocationStrategy`, you may provide a {@link APP_BASE_HREF}\n * or add a `<base href>` element to the document to override the default.\n *\n * For instance, if you provide an `APP_BASE_HREF` of `'/my/app/'` and call\n * `location.go('/foo')`, the browser's URL will become\n * `example.com/my/app/foo`. To ensure all relative URIs resolve correctly,\n * the `<base href>` and/or `APP_BASE_HREF` should end with a `/`.\n *\n * Similarly, if you add `<base href='/my/app/'/>` to the document and call\n * `location.go('/foo')`, the browser's URL will become\n * `example.com/my/app/foo`.\n *\n * Note that when using `PathLocationStrategy`, neither the query nor\n * the fragment in the `<base href>` will be preserved, as outlined\n * by the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2).\n *\n * @usageNotes\n *\n * ### Example\n *\n * {@example common/location/ts/path_location_component.ts region='LocationComponent'}\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class PathLocationStrategy extends LocationStrategy implements OnDestroy {\n private _baseHref: string;\n private _removeListenerFns: (() => void)[] = [];\n\n constructor(\n private _platformLocation: PlatformLocation,\n @Optional() @Inject(APP_BASE_HREF) href?: string) {\n super();\n\n this._baseHref = href ?? this._platformLocation.getBaseHrefFromDOM() ??\n inject(DOCUMENT).location?.origin ?? '';\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n while (this._removeListenerFns.length) {\n this._removeListenerFns.pop()!();\n }\n }\n\n override onPopState(fn: LocationChangeListener): void {\n this._removeListenerFns.push(\n this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));\n }\n\n override getBaseHref(): string {\n return this._baseHref;\n }\n\n override prepareExternalUrl(internal: string): string {\n return joinWithSlash(this._baseHref, internal);\n }\n\n override path(includeHash: boolean = false): string {\n const pathname =\n this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search);\n const hash = this._platformLocation.hash;\n return hash && includeHash ? `${pathname}${hash}` : pathname;\n }\n\n override pushState(state: any, title: string, url: string, queryParams: string) {\n const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));\n this._platformLocation.pushState(state, title, externalUrl);\n }\n\n override replaceState(state: any, title: string, url: string, queryParams: string) {\n const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));\n this._platformLocation.replaceState(state, title, externalUrl);\n }\n\n override forward(): void {\n this._platformLocation.forward();\n }\n\n override back(): void {\n this._platformLocation.back();\n }\n\n override getState(): unknown {\n return this._platformLocation.getState();\n }\n\n override historyGo(relativePosition: number = 0): void {\n this._platformLocation.historyGo?.(relativePosition);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, Injectable, OnDestroy, Optional} from '@angular/core';\n\nimport {APP_BASE_HREF, LocationStrategy} from './location_strategy';\nimport {LocationChangeListener, PlatformLocation} from './platform_location';\nimport {joinWithSlash, normalizeQueryParams} from './util';\n\n\n\n/**\n * @description\n * A {@link LocationStrategy} used to configure the {@link Location} service to\n * represent its state in the\n * [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax)\n * of the browser's URL.\n *\n * For instance, if you call `location.go('/foo')`, the browser's URL will become\n * `example.com#/foo`.\n *\n * @usageNotes\n *\n * ### Example\n *\n * {@example common/location/ts/hash_location_component.ts region='LocationComponent'}\n *\n * @publicApi\n */\n@Injectable()\nexport class HashLocationStrategy extends LocationStrategy implements OnDestroy {\n private _baseHref: string = '';\n private _removeListenerFns: (() => void)[] = [];\n\n constructor(\n private _platformLocation: PlatformLocation,\n @Optional() @Inject(APP_BASE_HREF) _baseHref?: string) {\n super();\n if (_baseHref != null) {\n this._baseHref = _baseHref;\n }\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n while (this._removeListenerFns.length) {\n this._removeListenerFns.pop()!();\n }\n }\n\n override onPopState(fn: LocationChangeListener): void {\n this._removeListenerFns.push(\n this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));\n }\n\n override getBaseHref(): string {\n return this._baseHref;\n }\n\n override path(includeHash: boolean = false): string {\n // the hash value is always prefixed with a `#`\n // and if it is empty then it will stay empty\n let path = this._platformLocation.hash;\n if (path == null) path = '#';\n\n return path.length > 0 ? path.substring(1) : path;\n }\n\n override prepareExternalUrl(internal: string): string {\n const url = joinWithSlash(this._baseHref, internal);\n return url.length > 0 ? ('#' + url) : url;\n }\n\n override pushState(state: any, title: string, path: string, queryParams: string) {\n let url: string|null = this.prepareExternalUrl(path + normalizeQueryParams(queryParams));\n if (url.length == 0) {\n url = this._platformLocation.pathname;\n }\n this._platformLocation.pushState(state, title, url);\n }\n\n override replaceState(state: any, title: string, path: string, queryParams: string) {\n let url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams));\n if (url.length == 0) {\n url = this._platformLocation.pathname;\n }\n this._platformLocation.replaceState(state, title, url);\n }\n\n override forward(): void {\n this._platformLocation.forward();\n }\n\n override back(): void {\n this._platformLocation.back();\n }\n\n override getState(): unknown {\n return this._platformLocation.getState();\n }\n\n override historyGo(relativePosition: number = 0): void {\n this._platformLocation.historyGo?.(relativePosition);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EventEmitter, Injectable, OnDestroy, ɵɵinject} from '@angular/core';\nimport {SubscriptionLike} from 'rxjs';\n\nimport {LocationStrategy} from './location_strategy';\nimport {joinWithSlash, normalizeQueryParams, stripTrailingSlash} from './util';\n\n/** @publicApi */\nexport interface PopStateEvent {\n pop?: boolean;\n state?: any;\n type?: string;\n url?: string;\n}\n\n/**\n * @description\n *\n * A service that applications can use to interact with a browser's URL.\n *\n * Depending on the `LocationStrategy` used, `Location` persists\n * to the URL's path or the URL's hash segment.\n *\n * @usageNotes\n *\n * It's better to use the `Router.navigate()` service to trigger route changes. Use\n * `Location` only if you need to interact with or create normalized URLs outside of\n * routing.\n *\n * `Location` is responsible for normalizing the URL against the application's base href.\n * A normalized URL is absolute from the URL host, includes the application's base href, and has no\n * trailing slash:\n * - `/my/app/user/123` is normalized\n * - `my/app/user/123` **is not** normalized\n * - `/my/app/user/123/` **is not** normalized\n *\n * ### Example\n *\n * <code-example path='common/location/ts/path_location_component.ts'\n * region='LocationComponent'></code-example>\n *\n * @publicApi\n */\n@Injectable({\n providedIn: 'root',\n // See #23917\n useFactory: createLocation,\n})\nexport class Location implements OnDestroy {\n /** @internal */\n _subject: EventEmitter<any> = new EventEmitter();\n /** @internal */\n _basePath: string;\n /** @internal */\n _locationStrategy: LocationStrategy;\n /** @internal */\n _urlChangeListeners: ((url: string, state: unknown) => void)[] = [];\n /** @internal */\n _urlChangeSubscription: SubscriptionLike|null = null;\n\n constructor(locationStrategy: LocationStrategy) {\n this._locationStrategy = locationStrategy;\n const baseHref = this._locationStrategy.getBaseHref();\n // Note: This class's interaction with base HREF does not fully follow the rules\n // outlined in the spec https://www.freesoft.org/CIE/RFC/1808/18.htm.\n // Instead of trying to fix individual bugs with more and more code, we should\n // investigate using the URL constructor and providing the base as a second\n // argument.\n // https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#parameters\n this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));\n this._locationStrategy.onPopState((ev) => {\n this._subject.emit({\n 'url': this.path(true),\n 'pop': true,\n 'state': ev.state,\n 'type': ev.type,\n });\n });\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n this._urlChangeSubscription?.unsubscribe();\n this._urlChangeListeners = [];\n }\n\n /**\n * Normalizes the URL path for this location.\n *\n * @param includeHash True to include an anchor fragment in the path.\n *\n * @returns The normalized URL path.\n */\n // TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is\n // removed.\n path(includeHash: boolean = false): string {\n return this.normalize(this._locationStrategy.path(includeHash));\n }\n\n /**\n * Reports the current state of the location history.\n * @returns The current value of the `history.state` object.\n */\n getState(): unknown {\n return this._locationStrategy.getState();\n }\n\n /**\n * Normalizes the given path and compares to the current normalized path.\n *\n * @param path The given URL path.\n * @param query Query parameters.\n *\n * @returns True if the given URL path is equal to the current normalized path, false\n * otherwise.\n */\n isCurrentPathEqualTo(path: string, query: string = ''): boolean {\n return this.path() == this.normalize(path + normalizeQueryParams(query));\n }\n\n /**\n * Normalizes a URL path by stripping any trailing slashes.\n *\n * @param url String representing a URL.\n *\n * @returns The normalized URL string.\n */\n normalize(url: string): string {\n return Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));\n }\n\n /**\n * Normalizes an external URL path.\n * If the given URL doesn't begin with a leading slash (`'/'`), adds one\n * before normalizing. Adds a hash if `HashLocationStrategy` is\n * in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.\n *\n * @param url String representing a URL.\n *\n * @returns A normalized platform-specific URL.\n */\n prepareExternalUrl(url: string): string {\n if (url && url[0] !== '/') {\n url = '/' + url;\n }\n return this._locationStrategy.prepareExternalUrl(url);\n }\n\n // TODO: rename this method to pushState\n /**\n * Changes the browser's URL to a normalized version of a given URL, and pushes a\n * new item onto the platform's history.\n *\n * @param path URL path to normalize.\n * @param query Query parameters.\n * @param state Location history state.\n *\n */\n go(path: string, query: string = '', state: any = null): void {\n this._locationStrategy.pushState(state, '', path, query);\n this._notifyUrlChangeListeners(\n this.prepareExternalUrl(path + normalizeQueryParams(query)), state);\n }\n\n /**\n * Changes the browser's URL to a normalized version of the given URL, and replaces\n * the top item on the platform's history stack.\n *\n * @param path URL path to normalize.\n * @param query Query parameters.\n * @param state Location history state.\n */\n replaceState(path: string, query: string = '', state: any = null): void {\n this._locationStrategy.replaceState(state, '', path, query);\n this._notifyUrlChangeListeners(\n this.prepareExternalUrl(path + normalizeQueryParams(query)), state);\n }\n\n /**\n * Navigates forward in the platform's history.\n */\n forward(): void {\n this._locationStrategy.forward();\n }\n\n /**\n * Navigates back in the platform's history.\n */\n back(): void {\n this._locationStrategy.back();\n }\n\n /**\n * Navigate to a specific page from session history, identified by its relative position to the\n * current page.\n *\n * @param relativePosition Position of the target page in the history relative to the current\n * page.\n * A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)`\n * moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go\n * beyond what's stored in the history session, we stay in the current page. Same behaviour occurs\n * when `relativePosition` equals 0.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history\n */\n historyGo(relativePosition: number = 0): void {\n this._locationStrategy.historyGo?.(relativePosition);\n }\n\n /**\n * Registers a URL change listener. Use to catch updates performed by the Angular\n * framework that are not detectible through \"popstate\" or \"hashchange\" events.\n *\n * @param fn The change handler function, which take a URL and a location history state.\n * @returns A function that, when executed, unregisters a URL change listener.\n */\n onUrlChange(fn: (url: string, state: unknown) => void): VoidFunction {\n this._urlChangeListeners.push(fn);\n\n if (!this._urlChangeSubscription) {\n this._urlChangeSubscription = this.subscribe(v => {\n this._notifyUrlChangeListeners(v.url, v.state);\n });\n }\n\n return () => {\n const fnIndex = this._urlChangeListeners.indexOf(fn);\n this._urlChangeListeners.splice(fnIndex, 1);\n\n if (this._urlChangeListeners.length === 0) {\n this._urlChangeSubscription?.unsubscribe();\n this._urlChangeSubscription = null;\n }\n };\n }\n\n /** @internal */\n _notifyUrlChangeListeners(url: string = '', state: unknown) {\n this._urlChangeListeners.forEach(fn => fn(url, state));\n }\n\n /**\n * Subscribes to the platform's `popState` events.\n *\n * Note: `Location.go()` does not trigger the `popState` event in the browser. Use\n * `Location.onUrlChange()` to subscribe to URL changes instead.\n *\n * @param value Event that is triggered when the state history changes.\n * @param exception The exception to throw.\n *\n * @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate)\n *\n * @returns Subscribed events.\n */\n subscribe(\n onNext: (value: PopStateEvent) => void, onThrow?: ((exception: any) => void)|null,\n onReturn?: (() => void)|null): SubscriptionLike {\n return this._subject.subscribe({next: onNext, error: onThrow, complete: onReturn});\n }\n\n /**\n * Normalizes URL parameters by prepending with `?` if needed.\n *\n * @param params String of URL parameters.\n *\n * @returns The normalized URL parameters string.\n */\n public static normalizeQueryParams: (params: string) => string = normalizeQueryParams;\n\n /**\n * Joins two parts of a URL with a slash if needed.\n *\n * @param start URL string\n * @param end URL string\n *\n *\n * @returns The joined URL string.\n */\n public static joinWithSlash: (start: string, end: string) => string = joinWithSlash;\n\n /**\n * Removes a trailing slash from a URL string if needed.\n * Looks for the first occurrence of either `#`, `?`, or the end of the\n * line as `/` characters and removes the trailing slash if one exists.\n *\n * @param url URL string.\n *\n * @returns The URL string, modified if needed.\n */\n public static stripTrailingSlash: (url: string) => string = stripTrailingSlash;\n}\n\nexport function createLocation() {\n return new Location(ɵɵinject(LocationStrategy as any));\n}\n\nfunction _stripBasePath(basePath: string, url: string): string {\n if (!basePath || !url.startsWith(basePath)) {\n return url;\n }\n const strippedUrl = url.substring(basePath.length);\n if (strippedUrl === '' || ['/', ';', '?', '#'].includes(strippedUrl[0])) {\n return strippedUrl;\n }\n return url;\n}\n\nfunction _stripIndexHtml(url: string): string {\n return url.replace(/\\/index.html$/, '');\n}\n\nfunction _stripOrigin(baseHref: string): string {\n // DO NOT REFACTOR! Previously, this check looked like this:\n // `/^(https?:)?\\/\\//.test(baseHref)`, but that resulted in\n // syntactically incorrect code after Closure Compiler minification.\n // This was likely caused by a bug in Closure Compiler, but\n // for now, the check is rewritten to use `new RegExp` instead.\n const isAbsoluteUrl = (new RegExp('^(https?:)?//')).test(baseHref);\n if (isAbsoluteUrl) {\n const [, pathname] = baseHref.split(/\\/\\/[^\\/]+/);\n return pathname;\n }\n return baseHref;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵCurrencyIndex, ɵExtraLocaleDataIndex, ɵfindLocaleData, ɵgetLocaleCurrencyCode, ɵgetLocalePluralCase, ɵLocaleDataIndex} from '@angular/core';\n\nimport {CURRENCIES_EN, CurrenciesSymbols} from './currencies';\n\n\n/**\n * Format styles that can be used to represent numbers.\n * @see `getLocaleNumberFormat()`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport enum NumberFormatStyle {\n Decimal,\n Percent,\n Currency,\n Scientific\n}\n\n/**\n * Plurality cases used for translating plurals to different languages.\n *\n * @see `NgPlural`\n * @see `NgPluralCase`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport enum Plural {\n Zero = 0,\n One = 1,\n Two = 2,\n Few = 3,\n Many = 4,\n Other = 5,\n}\n\n/**\n * Context-dependant translation forms for strings.\n * Typically the standalone version is for the nominative form of the word,\n * and the format version is used for the genitive case.\n * @see [CLDR website](http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles)\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport enum FormStyle {\n Format,\n Standalone\n}\n\n/**\n * String widths available for translations.\n * The specific character widths are locale-specific.\n * Examples are given for the word \"Sunday\" in English.\n *\n * @publicApi\n */\nexport enum TranslationWidth {\n /** 1 character for `en-US`. For example: 'S' */\n Narrow,\n /** 3 characters for `en-US`. For example: 'Sun' */\n Abbreviated,\n /** Full length for `en-US`. For example: \"Sunday\" */\n Wide,\n /** 2 characters for `en-US`, For example: \"Su\" */\n Short\n}\n\n/**\n * String widths available for date-time formats.\n * The specific character widths are locale-specific.\n * Examples are given for `en-US`.\n *\n * @see `getLocaleDateFormat()`\n * @see `getLocaleTimeFormat()`\n * @see `getLocaleDateTimeFormat()`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n * @publicApi\n */\nexport enum FormatWidth {\n /**\n * For `en-US`, 'M/d/yy, h:mm a'`\n * (Example: `6/15/15, 9:03 AM`)\n */\n Short,\n /**\n * For `en-US`, `'MMM d, y, h:mm:ss a'`\n * (Example: `Jun 15, 2015, 9:03:01 AM`)\n */\n Medium,\n /**\n * For `en-US`, `'MMMM d, y, h:mm:ss a z'`\n * (Example: `June 15, 2015 at 9:03:01 AM GMT+1`)\n */\n Long,\n /**\n * For `en-US`, `'EEEE, MMMM d, y, h:mm:ss a zzzz'`\n * (Example: `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00`)\n */\n Full\n}\n\n/**\n * Symbols that can be used to replace placeholders in number patterns.\n * Examples are based on `en-US` values.\n *\n * @see `getLocaleNumberSymbol()`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport enum NumberSymbol {\n /**\n * Decimal separator.\n * For `en-US`, the dot character.\n * Example: 2,345`.`67\n */\n Decimal,\n /**\n * Grouping separator, typically for thousands.\n * For `en-US`, the comma character.\n * Example: 2`,`345.67\n */\n Group,\n /**\n * List-item separator.\n * Example: \"one, two, and three\"\n */\n List,\n /**\n * Sign for percentage (out of 100).\n * Example: 23.4%\n */\n PercentSign,\n /**\n * Sign for positive numbers.\n * Example: +23\n */\n PlusSign,\n /**\n * Sign for negative numbers.\n * Example: -23\n */\n MinusSign,\n /**\n * Computer notation for exponential value (n times a power of 10).\n * Example: 1.2E3\n */\n Exponential,\n /**\n * Human-readable format of exponential.\n * Example: 1.2x103\n */\n SuperscriptingExponent,\n /**\n * Sign for permille (out of 1000).\n * Example: 23.4‰\n */\n PerMille,\n /**\n * Infinity, can be used with plus and minus.\n * Example: ∞, +∞, -∞\n */\n Infinity,\n /**\n * Not a number.\n * Example: NaN\n */\n NaN,\n /**\n * Symbol used between time units.\n * Example: 10:52\n */\n TimeSeparator,\n /**\n * Decimal separator for currency values (fallback to `Decimal`).\n * Example: $2,345.67\n */\n CurrencyDecimal,\n /**\n * Group separator for currency values (fallback to `Group`).\n * Example: $2,345.67\n */\n CurrencyGroup\n}\n\n/**\n * The value for each day of the week, based on the `en-US` locale\n *\n * @publicApi\n */\nexport enum WeekDay {\n Sunday = 0,\n Monday,\n Tuesday,\n Wednesday,\n Thursday,\n Friday,\n Saturday\n}\n\n/**\n * Retrieves the locale ID from the currently loaded locale.\n * The loaded locale could be, for example, a global one rather than a regional one.\n * @param locale A locale code, such as `fr-FR`.\n * @returns The locale code. For example, `fr`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleId(locale: string): string {\n return ɵfindLocaleData(locale)[ɵLocaleDataIndex.LocaleId];\n}\n\n/**\n * Retrieves day period strings for the given locale.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param formStyle The required grammatical form.\n * @param width The required character width.\n * @returns An array of localized period strings. For example, `[AM, PM]` for `en-US`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleDayPeriods(\n locale: string, formStyle: FormStyle, width: TranslationWidth): Readonly<[string, string]> {\n const data = ɵfindLocaleData(locale);\n const amPmData = <[string, string][][]>[\n data[ɵLocaleDataIndex.DayPeriodsFormat], data[ɵLocaleDataIndex.DayPeriodsStandalone]\n ];\n const amPm = getLastDefinedValue(amPmData, formStyle);\n return getLastDefinedValue(amPm, width);\n}\n\n/**\n * Retrieves days of the week for the given locale, using the Gregorian calendar.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param formStyle The required grammatical form.\n * @param width The required character width.\n * @returns An array of localized name strings.\n * For example,`[Sunday, Monday, ... Saturday]` for `en-US`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleDayNames(\n locale: string, formStyle: FormStyle, width: TranslationWidth): ReadonlyArray<string> {\n const data = ɵfindLocaleData(locale);\n const daysData =\n <string[][][]>[data[ɵLocaleDataIndex.DaysFormat], data[ɵLocaleDataIndex.DaysStandalone]];\n const days = getLastDefinedValue(daysData, formStyle);\n return getLastDefinedValue(days, width);\n}\n\n/**\n * Retrieves months of the year for the given locale, using the Gregorian calendar.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param formStyle The required grammatical form.\n * @param width The required character width.\n * @returns An array of localized name strings.\n * For example, `[January, February, ...]` for `en-US`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleMonthNames(\n locale: string, formStyle: FormStyle, width: TranslationWidth): ReadonlyArray<string> {\n const data = ɵfindLocaleData(locale);\n const monthsData =\n <string[][][]>[data[ɵLocaleDataIndex.MonthsFormat], data[ɵLocaleDataIndex.MonthsStandalone]];\n const months = getLastDefinedValue(monthsData, formStyle);\n return getLastDefinedValue(months, width);\n}\n\n/**\n * Retrieves Gregorian-calendar eras for the given locale.\n * @param locale A locale code for the locale format rules to use.\n * @param width The required character width.\n\n * @returns An array of localized era strings.\n * For example, `[AD, BC]` for `en-US`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleEraNames(\n locale: string, width: TranslationWidth): Readonly<[string, string]> {\n const data = ɵfindLocaleData(locale);\n const erasData = <[string, string][]>data[ɵLocaleDataIndex.Eras];\n return getLastDefinedValue(erasData, width);\n}\n\n/**\n * Retrieves the first day of the week for the given locale.\n *\n * @param locale A locale code for the locale format rules to use.\n * @returns A day index number, using the 0-based week-day index for `en-US`\n * (Sunday = 0, Monday = 1, ...).\n * For example, for `fr-FR`, returns 1 to indicate that the first day is Monday.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleFirstDayOfWeek(locale: string): WeekDay {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.FirstDayOfWeek];\n}\n\n/**\n * Range of week days that are considered the week-end for the given locale.\n *\n * @param locale A locale code for the locale format rules to use.\n * @returns The range of day values, `[startDay, endDay]`.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleWeekEndRange(locale: string): [WeekDay, WeekDay] {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.WeekendRange];\n}\n\n/**\n * Retrieves a localized date-value formatting string.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param width The format type.\n * @returns The localized formatting string.\n * @see `FormatWidth`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleDateFormat(locale: string, width: FormatWidth): string {\n const data = ɵfindLocaleData(locale);\n return getLastDefinedValue(data[ɵLocaleDataIndex.DateFormat], width);\n}\n\n/**\n * Retrieves a localized time-value formatting string.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param width The format type.\n * @returns The localized formatting string.\n * @see `FormatWidth`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n\n * @publicApi\n */\nexport function getLocaleTimeFormat(locale: string, width: FormatWidth): string {\n const data = ɵfindLocaleData(locale);\n return getLastDefinedValue(data[ɵLocaleDataIndex.TimeFormat], width);\n}\n\n/**\n * Retrieves a localized date-time formatting string.\n *\n * @param locale A locale code for the locale format rules to use.\n * @param width The format type.\n * @returns The localized formatting string.\n * @see `FormatWidth`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleDateTimeFormat(locale: string, width: FormatWidth): string {\n const data = ɵfindLocaleData(locale);\n const dateTimeFormatData = <string[]>data[ɵLocaleDataIndex.DateTimeFormat];\n return getLastDefinedValue(dateTimeFormatData, width);\n}\n\n/**\n * Retrieves a localized number symbol that can be used to replace placeholders in number formats.\n * @param locale The locale code.\n * @param symbol The symbol to localize.\n * @returns The character for the localized symbol.\n * @see `NumberSymbol`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleNumberSymbol(locale: string, symbol: NumberSymbol): string {\n const data = ɵfindLocaleData(locale);\n const res = data[ɵLocaleDataIndex.NumberSymbols][symbol];\n if (typeof res === 'undefined') {\n if (symbol === NumberSymbol.CurrencyDecimal) {\n return data[ɵLocaleDataIndex.NumberSymbols][NumberSymbol.Decimal];\n } else if (symbol === NumberSymbol.CurrencyGroup) {\n return data[ɵLocaleDataIndex.NumberSymbols][NumberSymbol.Group];\n }\n }\n return res;\n}\n\n/**\n * Retrieves a number format for a given locale.\n *\n * Numbers are formatted using patterns, like `#,###.00`. For example, the pattern `#,###.00`\n * when used to format the number 12345.678 could result in \"12'345,678\". That would happen if the\n * grouping separator for your language is an apostrophe, and the decimal separator is a comma.\n *\n * <b>Important:</b> The characters `.` `,` `0` `#` (and others below) are special placeholders\n * that stand for the decimal separator, and so on, and are NOT real characters.\n * You must NOT \"translate\" the placeholders. For example, don't change `.` to `,` even though in\n * your language the decimal point is written with a comma. The symbols should be replaced by the\n * local equivalents, using the appropriate `NumberSymbol` for your language.\n *\n * Here are the special characters used in number patterns:\n *\n * | Symbol | Meaning |\n * |--------|---------|\n * | . | Replaced automatically by the character used for the decimal point. |\n * | , | Replaced by the \"grouping\" (thousands) separator. |\n * | 0 | Replaced by a digit (or zero if there aren't enough digits). |\n * | # | Replaced by a digit (or nothing if there aren't enough). |\n * | ¤ | Replaced by a currency symbol, such as $ or USD. |\n * | % | Marks a percent format. The % symbol may change position, but must be retained. |\n * | E | Marks a scientific format. The E symbol may change position, but must be retained. |\n * | ' | Special characters used as literal characters are quoted with ASCII single quotes. |\n *\n * @param locale A locale code for the locale format rules to use.\n * @param type The type of numeric value to be formatted (such as `Decimal` or `Currency`.)\n * @returns The localized format string.\n * @see `NumberFormatStyle`\n * @see [CLDR website](http://cldr.unicode.org/translation/number-patterns)\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleNumberFormat(locale: string, type: NumberFormatStyle): string {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.NumberFormats][type];\n}\n\n/**\n * Retrieves the symbol used to represent the currency for the main country\n * corresponding to a given locale. For example, '$' for `en-US`.\n *\n * @param locale A locale code for the locale format rules to use.\n * @returns The localized symbol character,\n * or `null` if the main country cannot be determined.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleCurrencySymbol(locale: string): string|null {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.CurrencySymbol] || null;\n}\n\n/**\n * Retrieves the name of the currency for the main country corresponding\n * to a given locale. For example, 'US Dollar' for `en-US`.\n * @param locale A locale code for the locale format rules to use.\n * @returns The currency name,\n * or `null` if the main country cannot be determined.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleCurrencyName(locale: string): string|null {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.CurrencyName] || null;\n}\n\n/**\n * Retrieves the default currency code for the given locale.\n *\n * The default is defined as the first currency which is still in use.\n *\n * @param locale The code of the locale whose currency code we want.\n * @returns The code of the default currency for the given locale.\n *\n * @publicApi\n */\nexport function getLocaleCurrencyCode(locale: string): string|null {\n return ɵgetLocaleCurrencyCode(locale);\n}\n\n/**\n * Retrieves the currency values for a given locale.\n * @param locale A locale code for the locale format rules to use.\n * @returns The currency values.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n */\nfunction getLocaleCurrencies(locale: string): {[code: string]: CurrenciesSymbols} {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.Currencies];\n}\n\n/**\n * @alias core/ɵgetLocalePluralCase\n * @publicApi\n */\nexport const getLocalePluralCase: (locale: string) => ((value: number) => Plural) =\n ɵgetLocalePluralCase;\n\nfunction checkFullData(data: any) {\n if (!data[ɵLocaleDataIndex.ExtraData]) {\n throw new Error(`Missing extra locale data for the locale \"${\n data[ɵLocaleDataIndex\n .LocaleId]}\". Use \"registerLocaleData\" to load new data. See the \"I18n guide\" on angular.io to know more.`);\n }\n}\n\n/**\n * Retrieves locale-specific rules used to determine which day period to use\n * when more than one period is defined for a locale.\n *\n * There is a rule for each defined day period. The\n * first rule is applied to the first day period and so on.\n * Fall back to AM/PM when no rules are available.\n *\n * A rule can specify a period as time range, or as a single time value.\n *\n * This functionality is only available when you have loaded the full locale data.\n * See the [\"I18n guide\"](guide/i18n-common-format-data-locale).\n *\n * @param locale A locale code for the locale format rules to use.\n * @returns The rules for the locale, a single time value or array of *from-time, to-time*,\n * or null if no periods are available.\n *\n * @see `getLocaleExtraDayPeriods()`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleExtraDayPeriodRules(locale: string): (Time|[Time, Time])[] {\n const data = ɵfindLocaleData(locale);\n checkFullData(data);\n const rules = data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodsRules] || [];\n return rules.map((rule: string|[string, string]) => {\n if (typeof rule === 'string') {\n return extractTime(rule);\n }\n return [extractTime(rule[0]), extractTime(rule[1])];\n });\n}\n\n/**\n * Retrieves locale-specific day periods, which indicate roughly how a day is broken up\n * in different languages.\n * For example, for `en-US`, periods are morning, noon, afternoon, evening, and midnight.\n *\n * This functionality is only available when you have loaded the full locale data.\n * See the [\"I18n guide\"](guide/i18n-common-format-data-locale).\n *\n * @param locale A locale code for the locale format rules to use.\n * @param formStyle The required grammatical form.\n * @param width The required character width.\n * @returns The translated day-period strings.\n * @see `getLocaleExtraDayPeriodRules()`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getLocaleExtraDayPeriods(\n locale: string, formStyle: FormStyle, width: TranslationWidth): string[] {\n const data = ɵfindLocaleData(locale);\n checkFullData(data);\n const dayPeriodsData = <string[][][]>[\n data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodFormats],\n data[ɵLocaleDataIndex.ExtraData][ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone]\n ];\n const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];\n return getLastDefinedValue(dayPeriods, width) || [];\n}\n\n/**\n * Retrieves the writing direction of a specified locale\n * @param locale A locale code for the locale format rules to use.\n * @publicApi\n * @returns 'rtl' or 'ltr'\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n */\nexport function getLocaleDirection(locale: string): 'ltr'|'rtl' {\n const data = ɵfindLocaleData(locale);\n return data[ɵLocaleDataIndex.Directionality];\n}\n\n/**\n * Retrieves the first value that is defined in an array, going backwards from an index position.\n *\n * To avoid repeating the same data (as when the \"format\" and \"standalone\" forms are the same)\n * add the first value to the locale data arrays, and add other values only if they are different.\n *\n * @param data The data array to retrieve from.\n * @param index A 0-based index into the array to start from.\n * @returns The value immediately before the given index position.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nfunction getLastDefinedValue<T>(data: T[], index: number): T {\n for (let i = index; i > -1; i--) {\n if (typeof data[i] !== 'undefined') {\n return data[i];\n }\n }\n throw new Error('Locale data API: locale data undefined');\n}\n\n/**\n * Represents a time value with hours and minutes.\n *\n * @publicApi\n */\nexport type Time = {\n hours: number,\n minutes: number\n};\n\n/**\n * Extracts the hours and minutes from a string like \"15:45\"\n */\nfunction extractTime(time: string): Time {\n const [h, m] = time.split(':');\n return {hours: +h, minutes: +m};\n}\n\n\n\n/**\n * Retrieves the currency symbol for a given currency code.\n *\n * For example, for the default `en-US` locale, the code `USD` can\n * be represented by the narrow symbol `$` or the wide symbol `US$`.\n *\n * @param code The currency code.\n * @param format The format, `wide` or `narrow`.\n * @param locale A locale code for the locale format rules to use.\n *\n * @returns The symbol, or the currency code if no symbol is available.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getCurrencySymbol(code: string, format: 'wide'|'narrow', locale = 'en'): string {\n const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];\n const symbolNarrow = currency[ɵCurrencyIndex.SymbolNarrow];\n\n if (format === 'narrow' && typeof symbolNarrow === 'string') {\n return symbolNarrow;\n }\n\n return currency[ɵCurrencyIndex.Symbol] || code;\n}\n\n// Most currencies have cents, that's why the default is 2\nconst DEFAULT_NB_OF_CURRENCY_DIGITS = 2;\n\n/**\n * Reports the number of decimal digits for a given currency.\n * The value depends upon the presence of cents in that particular currency.\n *\n * @param code The currency code.\n * @returns The number of decimal digits, typically 0 or 2.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function getNumberOfCurrencyDigits(code: string): number {\n let digits;\n const currency = CURRENCIES_EN[code];\n if (currency) {\n digits = currency[ɵCurrencyIndex.NbOfDigits];\n }\n return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {FormatWidth, FormStyle, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleDayNames, getLocaleDayPeriods, getLocaleEraNames, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocaleId, getLocaleMonthNames, getLocaleNumberSymbol, getLocaleTimeFormat, NumberSymbol, Time, TranslationWidth} from './locale_data_api';\n\nexport const ISO8601_DATE_REGEX =\n /^(\\d{4,})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n// 1 2 3 4 5 6 7 8 9 10 11\nconst NAMED_FORMATS: {[localeId: string]: {[format: string]: string}} = {};\nconst DATE_FORMATS_SPLIT =\n /((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\\s\\S]*)/;\n\nenum ZoneWidth {\n Short,\n ShortGMT,\n Long,\n Extended\n}\n\nenum DateType {\n FullYear,\n Month,\n Date,\n Hours,\n Minutes,\n Seconds,\n FractionalSeconds,\n Day\n}\n\nenum TranslationType {\n DayPeriods,\n Days,\n Months,\n Eras\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a date according to locale rules.\n *\n * @param value The date to format, as a Date, or a number (milliseconds since UTC epoch)\n * or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime).\n * @param format The date-time components to include. See `DatePipe` for details.\n * @param locale A locale code for the locale format rules to use.\n * @param timezone The time zone. A time zone offset from GMT (such as `'+0430'`),\n * or a standard UTC/GMT or continental US time zone abbreviation.\n * If not specified, uses host system settings.\n *\n * @returns The formatted date string.\n *\n * @see `DatePipe`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function formatDate(\n value: string|number|Date, format: string, locale: string, timezone?: string): string {\n let date = toDate(value);\n const namedFormat = getNamedFormat(locale, format);\n format = namedFormat || format;\n\n let parts: string[] = [];\n let match;\n while (format) {\n match = DATE_FORMATS_SPLIT.exec(format);\n if (match) {\n parts = parts.concat(match.slice(1));\n const part = parts.pop();\n if (!part) {\n break;\n }\n format = part;\n } else {\n parts.push(format);\n break;\n }\n }\n\n let dateTimezoneOffset = date.getTimezoneOffset();\n if (timezone) {\n dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n date = convertTimezoneToLocal(date, timezone, true);\n }\n\n let text = '';\n parts.forEach(value => {\n const dateFormatter = getDateFormatter(value);\n text += dateFormatter ? dateFormatter(date, locale, dateTimezoneOffset) :\n value === '\\'\\'' ? '\\'' :\n value.replace(/(^'|'$)/g, '').replace(/''/g, '\\'');\n });\n\n return text;\n}\n\n/**\n * Create a new Date object with the given date value, and the time set to midnight.\n *\n * We cannot use `new Date(year, month, date)` because it maps years between 0 and 99 to 1900-1999.\n * See: https://github.com/angular/angular/issues/40377\n *\n * Note that this function returns a Date object whose time is midnight in the current locale's\n * timezone. In the future we might want to change this to be midnight in UTC, but this would be a\n * considerable breaking change.\n */\nfunction createDate(year: number, month: number, date: number): Date {\n // The `newDate` is set to midnight (UTC) on January 1st 1970.\n // - In PST this will be December 31st 1969 at 4pm.\n // - In GMT this will be January 1st 1970 at 1am.\n // Note that they even have different years, dates and months!\n const newDate = new Date(0);\n\n // `setFullYear()` allows years like 0001 to be set correctly. This function does not\n // change the internal time of the date.\n // Consider calling `setFullYear(2019, 8, 20)` (September 20, 2019).\n // - In PST this will now be September 20, 2019 at 4pm\n // - In GMT this will now be September 20, 2019 at 1am\n\n newDate.setFullYear(year, month, date);\n // We want the final date to be at local midnight, so we reset the time.\n // - In PST this will now be September 20, 2019 at 12am\n // - In GMT this will now be September 20, 2019 at 12am\n newDate.setHours(0, 0, 0);\n\n return newDate;\n}\n\nfunction getNamedFormat(locale: string, format: string): string {\n const localeId = getLocaleId(locale);\n NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {};\n\n if (NAMED_FORMATS[localeId][format]) {\n return NAMED_FORMATS[localeId][format];\n }\n\n let formatValue = '';\n switch (format) {\n case 'shortDate':\n formatValue = getLocaleDateFormat(locale, FormatWidth.Short);\n break;\n case 'mediumDate':\n formatValue = getLocaleDateFormat(locale, FormatWidth.Medium);\n break;\n case 'longDate':\n formatValue = getLocaleDateFormat(locale, FormatWidth.Long);\n break;\n case 'fullDate':\n formatValue = getLocaleDateFormat(locale, FormatWidth.Full);\n break;\n case 'shortTime':\n formatValue = getLocaleTimeFormat(locale, FormatWidth.Short);\n break;\n case 'mediumTime':\n formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium);\n break;\n case 'longTime':\n formatValue = getLocaleTimeFormat(locale, FormatWidth.Long);\n break;\n case 'fullTime':\n formatValue = getLocaleTimeFormat(locale, FormatWidth.Full);\n break;\n case 'short':\n const shortTime = getNamedFormat(locale, 'shortTime');\n const shortDate = getNamedFormat(locale, 'shortDate');\n formatValue = formatDateTime(\n getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]);\n break;\n case 'medium':\n const mediumTime = getNamedFormat(locale, 'mediumTime');\n const mediumDate = getNamedFormat(locale, 'mediumDate');\n formatValue = formatDateTime(\n getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]);\n break;\n case 'long':\n const longTime = getNamedFormat(locale, 'longTime');\n const longDate = getNamedFormat(locale, 'longDate');\n formatValue =\n formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]);\n break;\n case 'full':\n const fullTime = getNamedFormat(locale, 'fullTime');\n const fullDate = getNamedFormat(locale, 'fullDate');\n formatValue =\n formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]);\n break;\n }\n if (formatValue) {\n NAMED_FORMATS[localeId][format] = formatValue;\n }\n return formatValue;\n}\n\nfunction formatDateTime(str: string, opt_values: string[]) {\n if (opt_values) {\n str = str.replace(/\\{([^}]+)}/g, function(match, key) {\n return (opt_values != null && key in opt_values) ? opt_values[key] : match;\n });\n }\n return str;\n}\n\nfunction padNumber(\n num: number, digits: number, minusSign = '-', trim?: boolean, negWrap?: boolean): string {\n let neg = '';\n if (num < 0 || (negWrap && num <= 0)) {\n if (negWrap) {\n num = -num + 1;\n } else {\n num = -num;\n neg = minusSign;\n }\n }\n let strNum = String(num);\n while (strNum.length < digits) {\n strNum = '0' + strNum;\n }\n if (trim) {\n strNum = strNum.slice(strNum.length - digits);\n }\n return neg + strNum;\n}\n\nfunction formatFractionalSeconds(milliseconds: number, digits: number): string {\n const strMs = padNumber(milliseconds, 3);\n return strMs.substring(0, digits);\n}\n\n/**\n * Returns a date formatter that transforms a date into its locale digit representation\n */\nfunction dateGetter(\n name: DateType, size: number, offset: number = 0, trim = false,\n negWrap = false): DateFormatter {\n return function(date: Date, locale: string): string {\n let part = getDatePart(name, date);\n if (offset > 0 || part > -offset) {\n part += offset;\n }\n\n if (name === DateType.Hours) {\n if (part === 0 && offset === -12) {\n part = 12;\n }\n } else if (name === DateType.FractionalSeconds) {\n return formatFractionalSeconds(part, size);\n }\n\n const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);\n return padNumber(part, size, localeMinus, trim, negWrap);\n };\n}\n\nfunction getDatePart(part: DateType, date: Date): number {\n switch (part) {\n case DateType.FullYear:\n return date.getFullYear();\n case DateType.Month:\n return date.getMonth();\n case DateType.Date:\n return date.getDate();\n case DateType.Hours:\n return date.getHours();\n case DateType.Minutes:\n return date.getMinutes();\n case DateType.Seconds:\n return date.getSeconds();\n case DateType.FractionalSeconds:\n return date.getMilliseconds();\n case DateType.Day:\n return date.getDay();\n default:\n throw new Error(`Unknown DateType value \"${part}\".`);\n }\n}\n\n/**\n * Returns a date formatter that transforms a date into its locale string representation\n */\nfunction dateStrGetter(\n name: TranslationType, width: TranslationWidth, form: FormStyle = FormStyle.Format,\n extended = false): DateFormatter {\n return function(date: Date, locale: string): string {\n return getDateTranslation(date, locale, name, width, form, extended);\n };\n}\n\n/**\n * Returns the locale translation of a date for a given form, type and width\n */\nfunction getDateTranslation(\n date: Date, locale: string, name: TranslationType, width: TranslationWidth, form: FormStyle,\n extended: boolean) {\n switch (name) {\n case TranslationType.Months:\n return getLocaleMonthNames(locale, form, width)[date.getMonth()];\n case TranslationType.Days:\n return getLocaleDayNames(locale, form, width)[date.getDay()];\n case TranslationType.DayPeriods:\n const currentHours = date.getHours();\n const currentMinutes = date.getMinutes();\n if (extended) {\n const rules = getLocaleExtraDayPeriodRules(locale);\n const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);\n const index = rules.findIndex(rule => {\n if (Array.isArray(rule)) {\n // morning, afternoon, evening, night\n const [from, to] = rule;\n const afterFrom = currentHours >= from.hours && currentMinutes >= from.minutes;\n const beforeTo =\n (currentHours < to.hours ||\n (currentHours === to.hours && currentMinutes < to.minutes));\n // We must account for normal rules that span a period during the day (e.g. 6am-9am)\n // where `from` is less (earlier) than `to`. But also rules that span midnight (e.g.\n // 10pm - 5am) where `from` is greater (later!) than `to`.\n //\n // In the first case the current time must be BOTH after `from` AND before `to`\n // (e.g. 8am is after 6am AND before 10am).\n //\n // In the second case the current time must be EITHER after `from` OR before `to`\n // (e.g. 4am is before 5am but not after 10pm; and 11pm is not before 5am but it is\n // after 10pm).\n if (from.hours < to.hours) {\n if (afterFrom && beforeTo) {\n return true;\n }\n } else if (afterFrom || beforeTo) {\n return true;\n }\n } else { // noon or midnight\n if (rule.hours === currentHours && rule.minutes === currentMinutes) {\n return true;\n }\n }\n return false;\n });\n if (index !== -1) {\n return dayPeriods[index];\n }\n }\n // if no rules for the day periods, we use am/pm by default\n return getLocaleDayPeriods(locale, form, <TranslationWidth>width)[currentHours < 12 ? 0 : 1];\n case TranslationType.Eras:\n return getLocaleEraNames(locale, <TranslationWidth>width)[date.getFullYear() <= 0 ? 0 : 1];\n default:\n // This default case is not needed by TypeScript compiler, as the switch is exhaustive.\n // However Closure Compiler does not understand that and reports an error in typed mode.\n // The `throw new Error` below works around the problem, and the unexpected: never variable\n // makes sure tsc still checks this code is unreachable.\n const unexpected: never = name;\n throw new Error(`unexpected translation type ${unexpected}`);\n }\n}\n\n/**\n * Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or\n * GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30,\n * extended = +04:30)\n */\nfunction timeZoneGetter(width: ZoneWidth): DateFormatter {\n return function(date: Date, locale: string, offset: number) {\n const zone = -1 * offset;\n const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);\n const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60);\n switch (width) {\n case ZoneWidth.Short:\n return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) +\n padNumber(Math.abs(zone % 60), 2, minusSign);\n case ZoneWidth.ShortGMT:\n return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 1, minusSign);\n case ZoneWidth.Long:\n return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +\n padNumber(Math.abs(zone % 60), 2, minusSign);\n case ZoneWidth.Extended:\n if (offset === 0) {\n return 'Z';\n } else {\n return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +\n padNumber(Math.abs(zone % 60), 2, minusSign);\n }\n default:\n throw new Error(`Unknown zone width \"${width}\"`);\n }\n };\n}\n\nconst JANUARY = 0;\nconst THURSDAY = 4;\nfunction getFirstThursdayOfYear(year: number) {\n const firstDayOfYear = createDate(year, JANUARY, 1).getDay();\n return createDate(\n year, 0, 1 + ((firstDayOfYear <= THURSDAY) ? THURSDAY : THURSDAY + 7) - firstDayOfYear);\n}\n\nfunction getThursdayThisWeek(datetime: Date) {\n return createDate(\n datetime.getFullYear(), datetime.getMonth(),\n datetime.getDate() + (THURSDAY - datetime.getDay()));\n}\n\nfunction weekGetter(size: number, monthBased = false): DateFormatter {\n return function(date: Date, locale: string) {\n let result;\n if (monthBased) {\n const nbDaysBefore1stDayOfMonth =\n new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1;\n const today = date.getDate();\n result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7);\n } else {\n const thisThurs = getThursdayThisWeek(date);\n // Some days of a year are part of next year according to ISO 8601.\n // Compute the firstThurs from the year of this week's Thursday\n const firstThurs = getFirstThursdayOfYear(thisThurs.getFullYear());\n const diff = thisThurs.getTime() - firstThurs.getTime();\n result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n }\n\n return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));\n };\n}\n\n/**\n * Returns a date formatter that provides the week-numbering year for the input date.\n */\nfunction weekNumberingYearGetter(size: number, trim = false): DateFormatter {\n return function(date: Date, locale: string) {\n const thisThurs = getThursdayThisWeek(date);\n const weekNumberingYear = thisThurs.getFullYear();\n return padNumber(\n weekNumberingYear, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign), trim);\n };\n}\n\ntype DateFormatter = (date: Date, locale: string, offset: number) => string;\n\nconst DATE_FORMATS: {[format: string]: DateFormatter} = {};\n\n// Based on CLDR formats:\n// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table\n// See also explanations: http://cldr.unicode.org/translation/date-time\n// TODO(ocombe): support all missing cldr formats: U, Q, D, F, e, j, J, C, A, v, V, X, x\nfunction getDateFormatter(format: string): DateFormatter|null {\n if (DATE_FORMATS[format]) {\n return DATE_FORMATS[format];\n }\n let formatter;\n switch (format) {\n // Era name (AD/BC)\n case 'G':\n case 'GG':\n case 'GGG':\n formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated);\n break;\n case 'GGGG':\n formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide);\n break;\n case 'GGGGG':\n formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow);\n break;\n\n // 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199)\n case 'y':\n formatter = dateGetter(DateType.FullYear, 1, 0, false, true);\n break;\n // 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n case 'yy':\n formatter = dateGetter(DateType.FullYear, 2, 0, true, true);\n break;\n // 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10)\n case 'yyy':\n formatter = dateGetter(DateType.FullYear, 3, 0, false, true);\n break;\n // 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010)\n case 'yyyy':\n formatter = dateGetter(DateType.FullYear, 4, 0, false, true);\n break;\n\n // 1 digit representation of the week-numbering year, e.g. (AD 1 => 1, AD 199 => 199)\n case 'Y':\n formatter = weekNumberingYearGetter(1);\n break;\n // 2 digit representation of the week-numbering year, padded (00-99). (e.g. AD 2001 => 01, AD\n // 2010 => 10)\n case 'YY':\n formatter = weekNumberingYearGetter(2, true);\n break;\n // 3 digit representation of the week-numbering year, padded (000-999). (e.g. AD 1 => 001, AD\n // 2010 => 2010)\n case 'YYY':\n formatter = weekNumberingYearGetter(3);\n break;\n // 4 digit representation of the week-numbering year (e.g. AD 1 => 0001, AD 2010 => 2010)\n case 'YYYY':\n formatter = weekNumberingYearGetter(4);\n break;\n\n // Month of the year (1-12), numeric\n case 'M':\n case 'L':\n formatter = dateGetter(DateType.Month, 1, 1);\n break;\n case 'MM':\n case 'LL':\n formatter = dateGetter(DateType.Month, 2, 1);\n break;\n\n // Month of the year (January, ...), string, format\n case 'MMM':\n formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated);\n break;\n case 'MMMM':\n formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide);\n break;\n case 'MMMMM':\n formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow);\n break;\n\n // Month of the year (January, ...), string, standalone\n case 'LLL':\n formatter =\n dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone);\n break;\n case 'LLLL':\n formatter =\n dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone);\n break;\n case 'LLLLL':\n formatter =\n dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone);\n break;\n\n // Week of the year (1, ... 52)\n case 'w':\n formatter = weekGetter(1);\n break;\n case 'ww':\n formatter = weekGetter(2);\n break;\n\n // Week of the month (1, ...)\n case 'W':\n formatter = weekGetter(1, true);\n break;\n\n // Day of the month (1-31)\n case 'd':\n formatter = dateGetter(DateType.Date, 1);\n break;\n case 'dd':\n formatter = dateGetter(DateType.Date, 2);\n break;\n\n // Day of the Week StandAlone (1, 1, Mon, Monday, M, Mo)\n case 'c':\n case 'cc':\n formatter = dateGetter(DateType.Day, 1);\n break;\n case 'ccc':\n formatter =\n dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated, FormStyle.Standalone);\n break;\n case 'cccc':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide, FormStyle.Standalone);\n break;\n case 'ccccc':\n formatter =\n dateStrGetter(TranslationType.Days, TranslationWidth.Narrow, FormStyle.Standalone);\n break;\n case 'cccccc':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short, FormStyle.Standalone);\n break;\n\n // Day of the Week\n case 'E':\n case 'EE':\n case 'EEE':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated);\n break;\n case 'EEEE':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide);\n break;\n case 'EEEEE':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow);\n break;\n case 'EEEEEE':\n formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short);\n break;\n\n // Generic period of the day (am-pm)\n case 'a':\n case 'aa':\n case 'aaa':\n formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated);\n break;\n case 'aaaa':\n formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide);\n break;\n case 'aaaaa':\n formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow);\n break;\n\n // Extended period of the day (midnight, at night, ...), standalone\n case 'b':\n case 'bb':\n case 'bbb':\n formatter = dateStrGetter(\n TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true);\n break;\n case 'bbbb':\n formatter = dateStrGetter(\n TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true);\n break;\n case 'bbbbb':\n formatter = dateStrGetter(\n TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true);\n break;\n\n // Extended period of the day (midnight, night, ...), standalone\n case 'B':\n case 'BB':\n case 'BBB':\n formatter = dateStrGetter(\n TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true);\n break;\n case 'BBBB':\n formatter =\n dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true);\n break;\n case 'BBBBB':\n formatter = dateStrGetter(\n TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true);\n break;\n\n // Hour in AM/PM, (1-12)\n case 'h':\n formatter = dateGetter(DateType.Hours, 1, -12);\n break;\n case 'hh':\n formatter = dateGetter(DateType.Hours, 2, -12);\n break;\n\n // Hour of the day (0-23)\n case 'H':\n formatter = dateGetter(DateType.Hours, 1);\n break;\n // Hour in day, padded (00-23)\n case 'HH':\n formatter = dateGetter(DateType.Hours, 2);\n break;\n\n // Minute of the hour (0-59)\n case 'm':\n formatter = dateGetter(DateType.Minutes, 1);\n break;\n case 'mm':\n formatter = dateGetter(DateType.Minutes, 2);\n break;\n\n // Second of the minute (0-59)\n case 's':\n formatter = dateGetter(DateType.Seconds, 1);\n break;\n case 'ss':\n formatter = dateGetter(DateType.Seconds, 2);\n break;\n\n // Fractional second\n case 'S':\n formatter = dateGetter(DateType.FractionalSeconds, 1);\n break;\n case 'SS':\n formatter = dateGetter(DateType.FractionalSeconds, 2);\n break;\n case 'SSS':\n formatter = dateGetter(DateType.FractionalSeconds, 3);\n break;\n\n\n // Timezone ISO8601 short format (-0430)\n case 'Z':\n case 'ZZ':\n case 'ZZZ':\n formatter = timeZoneGetter(ZoneWidth.Short);\n break;\n // Timezone ISO8601 extended format (-04:30)\n case 'ZZZZZ':\n formatter = timeZoneGetter(ZoneWidth.Extended);\n break;\n\n // Timezone GMT short format (GMT+4)\n case 'O':\n case 'OO':\n case 'OOO':\n // Should be location, but fallback to format O instead because we don't have the data yet\n case 'z':\n case 'zz':\n case 'zzz':\n formatter = timeZoneGetter(ZoneWidth.ShortGMT);\n break;\n // Timezone GMT long format (GMT+0430)\n case 'OOOO':\n case 'ZZZZ':\n // Should be location, but fallback to format O instead because we don't have the data yet\n case 'zzzz':\n formatter = timeZoneGetter(ZoneWidth.Long);\n break;\n default:\n return null;\n }\n DATE_FORMATS[format] = formatter;\n return formatter;\n}\n\nfunction timezoneToOffset(timezone: string, fallback: number): number {\n // Support: IE 11 only, Edge 13-15+\n // IE/Edge do not \"understand\" colon (`:`) in timezone\n timezone = timezone.replace(/:/g, '');\n const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;\n return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;\n}\n\nfunction addDateMinutes(date: Date, minutes: number) {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + minutes);\n return date;\n}\n\nfunction convertTimezoneToLocal(date: Date, timezone: string, reverse: boolean): Date {\n const reverseValue = reverse ? -1 : 1;\n const dateTimezoneOffset = date.getTimezoneOffset();\n const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);\n return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset));\n}\n\n/**\n * Converts a value to date.\n *\n * Supported input formats:\n * - `Date`\n * - number: timestamp\n * - string: numeric (e.g. \"1234\"), ISO and date strings in a format supported by\n * [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).\n * Note: ISO strings without time return a date without timeoffset.\n *\n * Throws if unable to convert to a date.\n */\nexport function toDate(value: string|number|Date): Date {\n if (isDate(value)) {\n return value;\n }\n\n if (typeof value === 'number' && !isNaN(value)) {\n return new Date(value);\n }\n\n if (typeof value === 'string') {\n value = value.trim();\n\n if (/^(\\d{4}(-\\d{1,2}(-\\d{1,2})?)?)$/.test(value)) {\n /* For ISO Strings without time the day, month and year must be extracted from the ISO String\n before Date creation to avoid time offset and errors in the new Date.\n If we only replace '-' with ',' in the ISO String (\"2015,01,01\"), and try to create a new\n date, some browsers (e.g. IE 9) will throw an invalid Date error.\n If we leave the '-' (\"2015-01-01\") and try to create a new Date(\"2015-01-01\") the timeoffset\n is applied.\n Note: ISO months are 0 for January, 1 for February, ... */\n const [y, m = 1, d = 1] = value.split('-').map((val: string) => +val);\n return createDate(y, m - 1, d);\n }\n\n const parsedNb = parseFloat(value);\n\n // any string that only contains numbers, like \"1234\" but not like \"1234hello\"\n if (!isNaN(value as any - parsedNb)) {\n return new Date(parsedNb);\n }\n\n let match: RegExpMatchArray|null;\n if (match = value.match(ISO8601_DATE_REGEX)) {\n return isoStringToDate(match);\n }\n }\n\n const date = new Date(value as any);\n if (!isDate(date)) {\n throw new Error(`Unable to convert \"${value}\" into a date`);\n }\n return date;\n}\n\n/**\n * Converts a date in ISO8601 to a Date.\n * Used instead of `Date.parse` because of browser discrepancies.\n */\nexport function isoStringToDate(match: RegExpMatchArray): Date {\n const date = new Date(0);\n let tzHour = 0;\n let tzMin = 0;\n\n // match[8] means that the string contains \"Z\" (UTC) or a timezone like \"+01:00\" or \"+0100\"\n const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;\n const timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n // if there is a timezone defined like \"+01:00\" or \"+0100\"\n if (match[9]) {\n tzHour = Number(match[9] + match[10]);\n tzMin = Number(match[9] + match[11]);\n }\n dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n const h = Number(match[4] || 0) - tzHour;\n const m = Number(match[5] || 0) - tzMin;\n const s = Number(match[6] || 0);\n // The ECMAScript specification (https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11)\n // defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms`\n // becomes `999ms`.\n const ms = Math.floor(parseFloat('0.' + (match[7] || 0)) * 1000);\n timeSetter.call(date, h, m, s, ms);\n return date;\n}\n\nexport function isDate(value: any): value is Date {\n return value instanceof Date && !isNaN(value.valueOf());\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {getLocaleNumberFormat, getLocaleNumberSymbol, getNumberOfCurrencyDigits, NumberFormatStyle, NumberSymbol} from './locale_data_api';\n\nexport const NUMBER_FORMAT_REGEXP = /^(\\d+)?\\.((\\d+)(-(\\d+))?)?$/;\nconst MAX_DIGITS = 22;\nconst DECIMAL_SEP = '.';\nconst ZERO_CHAR = '0';\nconst PATTERN_SEP = ';';\nconst GROUP_SEP = ',';\nconst DIGIT_CHAR = '#';\nconst CURRENCY_CHAR = '¤';\nconst PERCENT_CHAR = '%';\n\n/**\n * Transforms a number to a locale string based on a style and a format.\n */\nfunction formatNumberToLocaleString(\n value: number, pattern: ParsedNumberFormat, locale: string, groupSymbol: NumberSymbol,\n decimalSymbol: NumberSymbol, digitsInfo?: string, isPercent = false): string {\n let formattedText = '';\n let isZero = false;\n\n if (!isFinite(value)) {\n formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity);\n } else {\n let parsedNumber = parseNumber(value);\n\n if (isPercent) {\n parsedNumber = toPercent(parsedNumber);\n }\n\n let minInt = pattern.minInt;\n let minFraction = pattern.minFrac;\n let maxFraction = pattern.maxFrac;\n\n if (digitsInfo) {\n const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);\n if (parts === null) {\n throw new Error(`${digitsInfo} is not a valid digit info`);\n }\n const minIntPart = parts[1];\n const minFractionPart = parts[3];\n const maxFractionPart = parts[5];\n if (minIntPart != null) {\n minInt = parseIntAutoRadix(minIntPart);\n }\n if (minFractionPart != null) {\n minFraction = parseIntAutoRadix(minFractionPart);\n }\n if (maxFractionPart != null) {\n maxFraction = parseIntAutoRadix(maxFractionPart);\n } else if (minFractionPart != null && minFraction > maxFraction) {\n maxFraction = minFraction;\n }\n }\n\n roundNumber(parsedNumber, minFraction, maxFraction);\n\n let digits = parsedNumber.digits;\n let integerLen = parsedNumber.integerLen;\n const exponent = parsedNumber.exponent;\n let decimals = [];\n isZero = digits.every(d => !d);\n\n // pad zeros for small numbers\n for (; integerLen < minInt; integerLen++) {\n digits.unshift(0);\n }\n\n // pad zeros for small numbers\n for (; integerLen < 0; integerLen++) {\n digits.unshift(0);\n }\n\n // extract decimals digits\n if (integerLen > 0) {\n decimals = digits.splice(integerLen, digits.length);\n } else {\n decimals = digits;\n digits = [0];\n }\n\n // format the integer digits with grouping separators\n const groups = [];\n if (digits.length >= pattern.lgSize) {\n groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));\n }\n\n while (digits.length > pattern.gSize) {\n groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));\n }\n\n if (digits.length) {\n groups.unshift(digits.join(''));\n }\n\n formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));\n\n // append the decimal digits\n if (decimals.length) {\n formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join('');\n }\n\n if (exponent) {\n formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + '+' + exponent;\n }\n }\n\n if (value < 0 && !isZero) {\n formattedText = pattern.negPre + formattedText + pattern.negSuf;\n } else {\n formattedText = pattern.posPre + formattedText + pattern.posSuf;\n }\n\n return formattedText;\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a number as currency using locale rules.\n *\n * @param value The number to format.\n * @param locale A locale code for the locale format rules to use.\n * @param currency A string containing the currency symbol or its name,\n * such as \"$\" or \"Canadian Dollar\". Used in output string, but does not affect the operation\n * of the function.\n * @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)\n * currency code, such as `USD` for the US dollar and `EUR` for the euro.\n * Used to determine the number of digits in the decimal part.\n * @param digitsInfo Decimal representation options, specified by a string in the following format:\n * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.\n *\n * @returns The formatted currency value.\n *\n * @see `formatNumber()`\n * @see `DecimalPipe`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function formatCurrency(\n value: number, locale: string, currency: string, currencyCode?: string,\n digitsInfo?: string): string {\n const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency);\n const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));\n\n pattern.minFrac = getNumberOfCurrencyDigits(currencyCode!);\n pattern.maxFrac = pattern.minFrac;\n\n const res = formatNumberToLocaleString(\n value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo);\n return res\n .replace(CURRENCY_CHAR, currency)\n // if we have 2 time the currency character, the second one is ignored\n .replace(CURRENCY_CHAR, '')\n // If there is a spacing between currency character and the value and\n // the currency character is suppressed by passing an empty string, the\n // spacing character would remain as part of the string. Then we\n // should remove it.\n .trim();\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a number as a percentage according to locale rules.\n *\n * @param value The number to format.\n * @param locale A locale code for the locale format rules to use.\n * @param digitsInfo Decimal representation options, specified by a string in the following format:\n * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.\n *\n * @returns The formatted percentage value.\n *\n * @see `formatNumber()`\n * @see `DecimalPipe`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n * @publicApi\n *\n */\nexport function formatPercent(value: number, locale: string, digitsInfo?: string): string {\n const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent);\n const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));\n const res = formatNumberToLocaleString(\n value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true);\n return res.replace(\n new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a number as text, with group sizing, separator, and other\n * parameters based on the locale.\n *\n * @param value The number to format.\n * @param locale A locale code for the locale format rules to use.\n * @param digitsInfo Decimal representation options, specified by a string in the following format:\n * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.\n *\n * @returns The formatted text string.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n *\n * @publicApi\n */\nexport function formatNumber(value: number, locale: string, digitsInfo?: string): string {\n const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal);\n const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));\n return formatNumberToLocaleString(\n value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo);\n}\n\ninterface ParsedNumberFormat {\n minInt: number;\n // the minimum number of digits required in the fraction part of the number\n minFrac: number;\n // the maximum number of digits required in the fraction part of the number\n maxFrac: number;\n // the prefix for a positive number\n posPre: string;\n // the suffix for a positive number\n posSuf: string;\n // the prefix for a negative number (e.g. `-` or `(`))\n negPre: string;\n // the suffix for a negative number (e.g. `)`)\n negSuf: string;\n // number of digits in each group of separated digits\n gSize: number;\n // number of digits in the last group of digits before the decimal separator\n lgSize: number;\n}\n\nfunction parseNumberFormat(format: string, minusSign = '-'): ParsedNumberFormat {\n const p = {\n minInt: 1,\n minFrac: 0,\n maxFrac: 0,\n posPre: '',\n posSuf: '',\n negPre: '',\n negSuf: '',\n gSize: 0,\n lgSize: 0\n };\n\n const patternParts = format.split(PATTERN_SEP);\n const positive = patternParts[0];\n const negative = patternParts[1];\n\n const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ?\n positive.split(DECIMAL_SEP) :\n [\n positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1),\n positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1)\n ],\n integer = positiveParts[0], fraction = positiveParts[1] || '';\n\n p.posPre = integer.substring(0, integer.indexOf(DIGIT_CHAR));\n\n for (let i = 0; i < fraction.length; i++) {\n const ch = fraction.charAt(i);\n if (ch === ZERO_CHAR) {\n p.minFrac = p.maxFrac = i + 1;\n } else if (ch === DIGIT_CHAR) {\n p.maxFrac = i + 1;\n } else {\n p.posSuf += ch;\n }\n }\n\n const groups = integer.split(GROUP_SEP);\n p.gSize = groups[1] ? groups[1].length : 0;\n p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;\n\n if (negative) {\n const trunkLen = positive.length - p.posPre.length - p.posSuf.length,\n pos = negative.indexOf(DIGIT_CHAR);\n\n p.negPre = negative.substring(0, pos).replace(/'/g, '');\n p.negSuf = negative.slice(pos + trunkLen).replace(/'/g, '');\n } else {\n p.negPre = minusSign + p.posPre;\n p.negSuf = p.posSuf;\n }\n\n return p;\n}\n\ninterface ParsedNumber {\n // an array of digits containing leading zeros as necessary\n digits: number[];\n // the exponent for numbers that would need more than `MAX_DIGITS` digits in `d`\n exponent: number;\n // the number of the digits in `d` that are to the left of the decimal point\n integerLen: number;\n}\n\n// Transforms a parsed number into a percentage by multiplying it by 100\nfunction toPercent(parsedNumber: ParsedNumber): ParsedNumber {\n // if the number is 0, don't do anything\n if (parsedNumber.digits[0] === 0) {\n return parsedNumber;\n }\n\n // Getting the current number of decimals\n const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen;\n if (parsedNumber.exponent) {\n parsedNumber.exponent += 2;\n } else {\n if (fractionLen === 0) {\n parsedNumber.digits.push(0, 0);\n } else if (fractionLen === 1) {\n parsedNumber.digits.push(0);\n }\n parsedNumber.integerLen += 2;\n }\n\n return parsedNumber;\n}\n\n/**\n * Parses a number.\n * Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/\n */\nfunction parseNumber(num: number): ParsedNumber {\n let numStr = Math.abs(num) + '';\n let exponent = 0, digits, integerLen;\n let i, j, zeros;\n\n // Decimal point?\n if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) {\n numStr = numStr.replace(DECIMAL_SEP, '');\n }\n\n // Exponential form?\n if ((i = numStr.search(/e/i)) > 0) {\n // Work out the exponent.\n if (integerLen < 0) integerLen = i;\n integerLen += +numStr.slice(i + 1);\n numStr = numStr.substring(0, i);\n } else if (integerLen < 0) {\n // There was no decimal point or exponent so it is an integer.\n integerLen = numStr.length;\n }\n\n // Count the number of leading zeros.\n for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */\n }\n\n if (i === (zeros = numStr.length)) {\n // The digits are all zero.\n digits = [0];\n integerLen = 1;\n } else {\n // Count the number of trailing zeros\n zeros--;\n while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;\n\n // Trailing zeros are insignificant so ignore them\n integerLen -= i;\n digits = [];\n // Convert string to array of digits without leading/trailing zeros.\n for (j = 0; i <= zeros; i++, j++) {\n digits[j] = Number(numStr.charAt(i));\n }\n }\n\n // If the number overflows the maximum allowed digits then use an exponent.\n if (integerLen > MAX_DIGITS) {\n digits = digits.splice(0, MAX_DIGITS - 1);\n exponent = integerLen - 1;\n integerLen = 1;\n }\n\n return {digits, exponent, integerLen};\n}\n\n/**\n * Round the parsed number to the specified number of decimal places\n * This function changes the parsedNumber in-place\n */\nfunction roundNumber(parsedNumber: ParsedNumber, minFrac: number, maxFrac: number) {\n if (minFrac > maxFrac) {\n throw new Error(`The minimum number of digits after fraction (${\n minFrac}) is higher than the maximum (${maxFrac}).`);\n }\n\n let digits = parsedNumber.digits;\n let fractionLen = digits.length - parsedNumber.integerLen;\n const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac);\n\n // The index of the digit to where rounding is to occur\n let roundAt = fractionSize + parsedNumber.integerLen;\n let digit = digits[roundAt];\n\n if (roundAt > 0) {\n // Drop fractional digits beyond `roundAt`\n digits.splice(Math.max(parsedNumber.integerLen, roundAt));\n\n // Set non-fractional digits beyond `roundAt` to 0\n for (let j = roundAt; j < digits.length; j++) {\n digits[j] = 0;\n }\n } else {\n // We rounded to zero so reset the parsedNumber\n fractionLen = Math.max(0, fractionLen);\n parsedNumber.integerLen = 1;\n digits.length = Math.max(1, roundAt = fractionSize + 1);\n digits[0] = 0;\n for (let i = 1; i < roundAt; i++) digits[i] = 0;\n }\n\n if (digit >= 5) {\n if (roundAt - 1 < 0) {\n for (let k = 0; k > roundAt; k--) {\n digits.unshift(0);\n parsedNumber.integerLen++;\n }\n digits.unshift(1);\n parsedNumber.integerLen++;\n } else {\n digits[roundAt - 1]++;\n }\n }\n\n // Pad out with zeros to get the required fraction length\n for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);\n\n let dropTrailingZeros = fractionSize !== 0;\n // Minimal length = nb of decimals required + current nb of integers\n // Any number besides that is optional and can be removed if it's a trailing 0\n const minLen = minFrac + parsedNumber.integerLen;\n // Do any carrying, e.g. a digit was rounded up to 10\n const carry = digits.reduceRight(function(carry, d, i, digits) {\n d = d + carry;\n digits[i] = d < 10 ? d : d - 10; // d % 10\n if (dropTrailingZeros) {\n // Do not keep meaningless fractional trailing zeros (e.g. 15.52000 --> 15.52)\n if (digits[i] === 0 && i >= minLen) {\n digits.pop();\n } else {\n dropTrailingZeros = false;\n }\n }\n return d >= 10 ? 1 : 0; // Math.floor(d / 10);\n }, 0);\n if (carry) {\n digits.unshift(carry);\n parsedNumber.integerLen++;\n }\n}\n\nexport function parseIntAutoRadix(text: string): number {\n const result: number = parseInt(text);\n if (isNaN(result)) {\n throw new Error('Invalid integer literal when parsing ' + text);\n }\n return result;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function parseCookieValue(cookieStr: string, name: string): string|null {\n name = encodeURIComponent(name);\n for (const cookie of cookieStr.split(';')) {\n const eqIndex = cookie.indexOf('=');\n const [cookieName, cookieValue]: string[] =\n eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];\n if (cookieName.trim() === name) {\n return decodeURIComponent(cookieValue);\n }\n }\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {Directive, DoCheck, ElementRef, Input, IterableDiffers, KeyValueDiffers, Renderer2, ɵstringify as stringify} from '@angular/core';\n\ntype NgClassSupportedTypes = string[]|Set<string>|{[klass: string]: any}|null|undefined;\n\nconst WS_REGEXP = /\\s+/;\n\nconst EMPTY_ARRAY: string[] = [];\n\n/**\n * Represents internal object used to track state of each CSS class. There are 3 different (boolean)\n * flags that, combined together, indicate state of a given CSS class:\n * - enabled: indicates if a class should be present in the DOM (true) or not (false);\n * - changed: tracks if a class was toggled (added or removed) during the custom dirty-checking\n * process; changed classes must be synchronized with the DOM;\n * - touched: tracks if a class is present in the current object bound to the class / ngClass input;\n * classes that are not present any more can be removed from the internal data structures;\n */\ninterface CssClassState {\n // PERF: could use a bit mask to represent state as all fields are boolean flags\n enabled: boolean;\n changed: boolean;\n touched: boolean;\n}\n\n/**\n * @ngModule CommonModule\n *\n * @usageNotes\n * ```\n * <some-element [ngClass]=\"'first second'\">...</some-element>\n *\n * <some-element [ngClass]=\"['first', 'second']\">...</some-element>\n *\n * <some-element [ngClass]=\"{'first': true, 'second': true, 'third': false}\">...</some-element>\n *\n * <some-element [ngClass]=\"stringExp|arrayExp|objExp\">...</some-element>\n *\n * <some-element [ngClass]=\"{'class1 class2 class3' : true}\">...</some-element>\n * ```\n *\n * @description\n *\n * Adds and removes CSS classes on an HTML element.\n *\n * The CSS classes are updated as follows, depending on the type of the expression evaluation:\n * - `string` - the CSS classes listed in the string (space delimited) are added,\n * - `Array` - the CSS classes declared as Array elements are added,\n * - `Object` - keys are CSS classes that get added when the expression given in the value\n * evaluates to a truthy value, otherwise they are removed.\n *\n * @publicApi\n */\n@Directive({\n selector: '[ngClass]',\n standalone: true,\n})\nexport class NgClass implements DoCheck {\n private initialClasses = EMPTY_ARRAY;\n private rawClass: NgClassSupportedTypes;\n\n private stateMap = new Map<string, CssClassState>();\n\n constructor(\n // leaving references to differs in place since flex layout is extending NgClass...\n private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,\n private _ngEl: ElementRef, private _renderer: Renderer2) {}\n\n @Input('class')\n set klass(value: string) {\n this.initialClasses = value != null ? value.trim().split(WS_REGEXP) : EMPTY_ARRAY;\n }\n\n @Input('ngClass')\n set ngClass(value: string|string[]|Set<string>|{[klass: string]: any}|null|undefined) {\n this.rawClass = typeof value === 'string' ? value.trim().split(WS_REGEXP) : value;\n }\n\n /*\n The NgClass directive uses the custom change detection algorithm for its inputs. The custom\n algorithm is necessary since inputs are represented as complex object or arrays that need to be\n deeply-compared.\n\n This algorithm is perf-sensitive since NgClass is used very frequently and its poor performance\n might negatively impact runtime performance of the entire change detection cycle. The design of\n this algorithm is making sure that:\n - there is no unnecessary DOM manipulation (CSS classes are added / removed from the DOM only when\n needed), even if references to bound objects change;\n - there is no memory allocation if nothing changes (even relatively modest memory allocation\n during the change detection cycle can result in GC pauses for some of the CD cycles).\n\n The algorithm works by iterating over the set of bound classes, staring with [class] binding and\n then going over [ngClass] binding. For each CSS class name:\n - check if it was seen before (this information is tracked in the state map) and if its value\n changed;\n - mark it as \"touched\" - names that are not marked are not present in the latest set of binding\n and we can remove such class name from the internal data structures;\n\n After iteration over all the CSS class names we've got data structure with all the information\n necessary to synchronize changes to the DOM - it is enough to iterate over the state map, flush\n changes to the DOM and reset internal data structures so those are ready for the next change\n detection cycle.\n */\n ngDoCheck(): void {\n // classes from the [class] binding\n for (const klass of this.initialClasses) {\n this._updateState(klass, true);\n }\n\n // classes from the [ngClass] binding\n const rawClass = this.rawClass;\n if (Array.isArray(rawClass) || rawClass instanceof Set) {\n for (const klass of rawClass) {\n this._updateState(klass, true);\n }\n } else if (rawClass != null) {\n for (const klass of Object.keys(rawClass)) {\n this._updateState(klass, Boolean(rawClass[klass]));\n }\n }\n\n this._applyStateDiff();\n }\n\n private _updateState(klass: string, nextEnabled: boolean) {\n const state = this.stateMap.get(klass);\n if (state !== undefined) {\n if (state.enabled !== nextEnabled) {\n state.changed = true;\n state.enabled = nextEnabled;\n }\n state.touched = true;\n } else {\n this.stateMap.set(klass, {enabled: nextEnabled, changed: true, touched: true});\n }\n }\n\n private _applyStateDiff() {\n for (const stateEntry of this.stateMap) {\n const klass = stateEntry[0];\n const state = stateEntry[1];\n\n if (state.changed) {\n this._toggleClass(klass, state.enabled);\n state.changed = false;\n } else if (!state.touched) {\n // A class that was previously active got removed from the new collection of classes -\n // remove from the DOM as well.\n if (state.enabled) {\n this._toggleClass(klass, false);\n }\n this.stateMap.delete(klass);\n }\n\n state.touched = false;\n }\n }\n\n private _toggleClass(klass: string, enabled: boolean): void {\n if (ngDevMode) {\n if (typeof klass !== 'string') {\n throw new Error(\n `NgClass can only toggle CSS classes expressed as strings, got ${stringify(klass)}`);\n }\n }\n klass = klass.trim();\n if (klass.length > 0) {\n klass.split(WS_REGEXP).forEach(klass => {\n if (enabled) {\n this._renderer.addClass(this._ngEl.nativeElement, klass);\n } else {\n this._renderer.removeClass(this._ngEl.nativeElement, klass);\n }\n });\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, DoCheck, EmbeddedViewRef, Input, IterableChangeRecord, IterableChanges, IterableDiffer, IterableDiffers, NgIterable, TemplateRef, TrackByFunction, ViewContainerRef, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * @publicApi\n */\nexport class NgForOfContext<T, U extends NgIterable<T> = NgIterable<T>> {\n constructor(public $implicit: T, public ngForOf: U, public index: number, public count: number) {}\n\n get first(): boolean {\n return this.index === 0;\n }\n\n get last(): boolean {\n return this.index === this.count - 1;\n }\n\n get even(): boolean {\n return this.index % 2 === 0;\n }\n\n get odd(): boolean {\n return !this.even;\n }\n}\n\n/**\n * A [structural directive](guide/structural-directives) that renders\n * a template for each item in a collection.\n * The directive is placed on an element, which becomes the parent\n * of the cloned templates.\n *\n * The `ngForOf` directive is generally used in the\n * [shorthand form](guide/structural-directives#asterisk) `*ngFor`.\n * In this form, the template to be rendered for each iteration is the content\n * of an anchor element containing the directive.\n *\n * The following example shows the shorthand syntax with some options,\n * contained in an `<li>` element.\n *\n * ```\n * <li *ngFor=\"let item of items; index as i; trackBy: trackByFn\">...</li>\n * ```\n *\n * The shorthand form expands into a long form that uses the `ngForOf` selector\n * on an `<ng-template>` element.\n * The content of the `<ng-template>` element is the `<li>` element that held the\n * short-form directive.\n *\n * Here is the expanded version of the short-form example.\n *\n * ```\n * <ng-template ngFor let-item [ngForOf]=\"items\" let-i=\"index\" [ngForTrackBy]=\"trackByFn\">\n * <li>...</li>\n * </ng-template>\n * ```\n *\n * Angular automatically expands the shorthand syntax as it compiles the template.\n * The context for each embedded view is logically merged to the current component\n * context according to its lexical position.\n *\n * When using the shorthand syntax, Angular allows only [one structural directive\n * on an element](guide/structural-directives#one-per-element).\n * If you want to iterate conditionally, for example,\n * put the `*ngIf` on a container element that wraps the `*ngFor` element.\n * For further discussion, see\n * [Structural Directives](guide/structural-directives#one-per-element).\n *\n * @usageNotes\n *\n * ### Local variables\n *\n * `NgForOf` provides exported values that can be aliased to local variables.\n * For example:\n *\n * ```\n * <li *ngFor=\"let user of users; index as i; first as isFirst\">\n * {{i}}/{{users.length}}. {{user}} <span *ngIf=\"isFirst\">default</span>\n * </li>\n * ```\n *\n * The following exported values can be aliased to local variables:\n *\n * - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).\n * - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is\n * more complex then a property access, for example when using the async pipe (`userStreams |\n * async`).\n * - `index: number`: The index of the current item in the iterable.\n * - `count: number`: The length of the iterable.\n * - `first: boolean`: True when the item is the first item in the iterable.\n * - `last: boolean`: True when the item is the last item in the iterable.\n * - `even: boolean`: True when the item has an even index in the iterable.\n * - `odd: boolean`: True when the item has an odd index in the iterable.\n *\n * ### Change propagation\n *\n * When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:\n *\n * * When an item is added, a new instance of the template is added to the DOM.\n * * When an item is removed, its template instance is removed from the DOM.\n * * When items are reordered, their respective templates are reordered in the DOM.\n *\n * Angular uses object identity to track insertions and deletions within the iterator and reproduce\n * those changes in the DOM. This has important implications for animations and any stateful\n * controls that are present, such as `<input>` elements that accept user input. Inserted rows can\n * be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state\n * such as user input.\n * For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).\n *\n * The identities of elements in the iterator can change while the data does not.\n * This can happen, for example, if the iterator is produced from an RPC to the server, and that\n * RPC is re-run. Even if the data hasn't changed, the second response produces objects with\n * different identities, and Angular must tear down the entire DOM and rebuild it (as if all old\n * elements were deleted and all new elements inserted).\n *\n * To avoid this expensive operation, you can customize the default tracking algorithm.\n * by supplying the `trackBy` option to `NgForOf`.\n * `trackBy` takes a function that has two arguments: `index` and `item`.\n * If `trackBy` is given, Angular tracks changes by the return value of the function.\n *\n * @see [Structural Directives](guide/structural-directives)\n * @ngModule CommonModule\n * @publicApi\n */\n@Directive({\n selector: '[ngFor][ngForOf]',\n standalone: true,\n})\nexport class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCheck {\n /**\n * The value of the iterable expression, which can be used as a\n * [template input variable](guide/structural-directives#shorthand).\n */\n @Input()\n set ngForOf(ngForOf: U&NgIterable<T>|undefined|null) {\n this._ngForOf = ngForOf;\n this._ngForOfDirty = true;\n }\n /**\n * Specifies a custom `TrackByFunction` to compute the identity of items in an iterable.\n *\n * If a custom `TrackByFunction` is not provided, `NgForOf` will use the item's [object\n * identity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)\n * as the key.\n *\n * `NgForOf` uses the computed key to associate items in an iterable with DOM elements\n * it produces for these items.\n *\n * A custom `TrackByFunction` is useful to provide good user experience in cases when items in an\n * iterable rendered using `NgForOf` have a natural identifier (for example, custom ID or a\n * primary key), and this iterable could be updated with new object instances that still\n * represent the same underlying entity (for example, when data is re-fetched from the server,\n * and the iterable is recreated and re-rendered, but most of the data is still the same).\n *\n * @see `TrackByFunction`\n */\n @Input()\n set ngForTrackBy(fn: TrackByFunction<T>) {\n if (NG_DEV_MODE && fn != null && typeof fn !== 'function') {\n console.warn(\n `trackBy must be a function, but received ${JSON.stringify(fn)}. ` +\n `See https://angular.io/api/common/NgForOf#change-propagation for more information.`);\n }\n this._trackByFn = fn;\n }\n\n get ngForTrackBy(): TrackByFunction<T> {\n return this._trackByFn;\n }\n\n private _ngForOf: U|undefined|null = null;\n private _ngForOfDirty: boolean = true;\n private _differ: IterableDiffer<T>|null = null;\n // TODO(issue/24571): remove '!'\n // waiting for microsoft/typescript#43662 to allow the return type `TrackByFunction|undefined` for\n // the getter\n private _trackByFn!: TrackByFunction<T>;\n\n constructor(\n private _viewContainer: ViewContainerRef,\n private _template: TemplateRef<NgForOfContext<T, U>>, private _differs: IterableDiffers) {}\n\n /**\n * A reference to the template that is stamped out for each item in the iterable.\n * @see [template reference variable](guide/template-reference-variables)\n */\n @Input()\n set ngForTemplate(value: TemplateRef<NgForOfContext<T, U>>) {\n // TODO(TS2.1): make TemplateRef<Partial<NgForRowOf<T>>> once we move to TS v2.1\n // The current type is too restrictive; a template that just uses index, for example,\n // should be acceptable.\n if (value) {\n this._template = value;\n }\n }\n\n /**\n * Applies the changes when needed.\n * @nodoc\n */\n ngDoCheck(): void {\n if (this._ngForOfDirty) {\n this._ngForOfDirty = false;\n // React on ngForOf changes only once all inputs have been initialized\n const value = this._ngForOf;\n if (!this._differ && value) {\n if (NG_DEV_MODE) {\n try {\n // CAUTION: this logic is duplicated for production mode below, as the try-catch\n // is only present in development builds.\n this._differ = this._differs.find(value).create(this.ngForTrackBy);\n } catch {\n let errorMessage = `Cannot find a differ supporting object '${value}' of type '` +\n `${getTypeName(value)}'. NgFor only supports binding to Iterables, such as Arrays.`;\n if (typeof value === 'object') {\n errorMessage += ' Did you mean to use the keyvalue pipe?';\n }\n throw new RuntimeError(RuntimeErrorCode.NG_FOR_MISSING_DIFFER, errorMessage);\n }\n } else {\n // CAUTION: this logic is duplicated for development mode above, as the try-catch\n // is only present in development builds.\n this._differ = this._differs.find(value).create(this.ngForTrackBy);\n }\n }\n }\n if (this._differ) {\n const changes = this._differ.diff(this._ngForOf);\n if (changes) this._applyChanges(changes);\n }\n }\n\n private _applyChanges(changes: IterableChanges<T>) {\n const viewContainer = this._viewContainer;\n changes.forEachOperation(\n (item: IterableChangeRecord<T>, adjustedPreviousIndex: number|null,\n currentIndex: number|null) => {\n if (item.previousIndex == null) {\n // NgForOf is never \"null\" or \"undefined\" here because the differ detected\n // that a new item needs to be inserted from the iterable. This implies that\n // there is an iterable value for \"_ngForOf\".\n viewContainer.createEmbeddedView(\n this._template, new NgForOfContext<T, U>(item.item, this._ngForOf!, -1, -1),\n currentIndex === null ? undefined : currentIndex);\n } else if (currentIndex == null) {\n viewContainer.remove(\n adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex);\n } else if (adjustedPreviousIndex !== null) {\n const view = viewContainer.get(adjustedPreviousIndex)!;\n viewContainer.move(view, currentIndex);\n applyViewChange(view as EmbeddedViewRef<NgForOfContext<T, U>>, item);\n }\n });\n\n for (let i = 0, ilen = viewContainer.length; i < ilen; i++) {\n const viewRef = <EmbeddedViewRef<NgForOfContext<T, U>>>viewContainer.get(i);\n const context = viewRef.context;\n context.index = i;\n context.count = ilen;\n context.ngForOf = this._ngForOf!;\n }\n\n changes.forEachIdentityChange((record: any) => {\n const viewRef = <EmbeddedViewRef<NgForOfContext<T, U>>>viewContainer.get(record.currentIndex);\n applyViewChange(viewRef, record);\n });\n }\n\n /**\n * Asserts the correct type of the context for the template that `NgForOf` will render.\n *\n * The presence of this method is a signal to the Ivy template type-check compiler that the\n * `NgForOf` structural directive renders its template with a specific context type.\n */\n static ngTemplateContextGuard<T, U extends NgIterable<T>>(dir: NgForOf<T, U>, ctx: any):\n ctx is NgForOfContext<T, U> {\n return true;\n }\n}\n\n// Also export the `NgForOf` class as `NgFor` to improve the DX for\n// cases when the directive is used as standalone, so the class name\n// matches the CSS selector (*ngFor).\nexport {NgForOf as NgFor};\n\nfunction applyViewChange<T>(\n view: EmbeddedViewRef<NgForOfContext<T>>, record: IterableChangeRecord<T>) {\n view.context.$implicit = record.item;\n}\n\nfunction getTypeName(type: any): string {\n return type['name'] || typeof type;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef, ɵstringify as stringify} from '@angular/core';\n\n\n/**\n * A structural directive that conditionally includes a template based on the value of\n * an expression coerced to Boolean.\n * When the expression evaluates to true, Angular renders the template\n * provided in a `then` clause, and when false or null,\n * Angular renders the template provided in an optional `else` clause. The default\n * template for the `else` clause is blank.\n *\n * A [shorthand form](guide/structural-directives#asterisk) of the directive,\n * `*ngIf=\"condition\"`, is generally used, provided\n * as an attribute of the anchor element for the inserted template.\n * Angular expands this into a more explicit version, in which the anchor element\n * is contained in an `<ng-template>` element.\n *\n * Simple form with shorthand syntax:\n *\n * ```\n * <div *ngIf=\"condition\">Content to render when condition is true.</div>\n * ```\n *\n * Simple form with expanded syntax:\n *\n * ```\n * <ng-template [ngIf]=\"condition\"><div>Content to render when condition is\n * true.</div></ng-template>\n * ```\n *\n * Form with an \"else\" block:\n *\n * ```\n * <div *ngIf=\"condition; else elseBlock\">Content to render when condition is true.</div>\n * <ng-template #elseBlock>Content to render when condition is false.</ng-template>\n * ```\n *\n * Shorthand form with \"then\" and \"else\" blocks:\n *\n * ```\n * <div *ngIf=\"condition; then thenBlock else elseBlock\"></div>\n * <ng-template #thenBlock>Content to render when condition is true.</ng-template>\n * <ng-template #elseBlock>Content to render when condition is false.</ng-template>\n * ```\n *\n * Form with storing the value locally:\n *\n * ```\n * <div *ngIf=\"condition as value; else elseBlock\">{{value}}</div>\n * <ng-template #elseBlock>Content to render when value is null.</ng-template>\n * ```\n *\n * @usageNotes\n *\n * The `*ngIf` directive is most commonly used to conditionally show an inline template,\n * as seen in the following example.\n * The default `else` template is blank.\n *\n * {@example common/ngIf/ts/module.ts region='NgIfSimple'}\n *\n * ### Showing an alternative template using `else`\n *\n * To display a template when `expression` evaluates to false, use an `else` template\n * binding as shown in the following example.\n * The `else` binding points to an `<ng-template>` element labeled `#elseBlock`.\n * The template can be defined anywhere in the component view, but is typically placed right after\n * `ngIf` for readability.\n *\n * {@example common/ngIf/ts/module.ts region='NgIfElse'}\n *\n * ### Using an external `then` template\n *\n * In the previous example, the then-clause template is specified inline, as the content of the\n * tag that contains the `ngIf` directive. You can also specify a template that is defined\n * externally, by referencing a labeled `<ng-template>` element. When you do this, you can\n * change which template to use at runtime, as shown in the following example.\n *\n * {@example common/ngIf/ts/module.ts region='NgIfThenElse'}\n *\n * ### Storing a conditional result in a variable\n *\n * You might want to show a set of properties from the same object. If you are waiting\n * for asynchronous data, the object can be undefined.\n * In this case, you can use `ngIf` and store the result of the condition in a local\n * variable as shown in the following example.\n *\n * {@example common/ngIf/ts/module.ts region='NgIfAs'}\n *\n * This code uses only one `AsyncPipe`, so only one subscription is created.\n * The conditional statement stores the result of `userStream|async` in the local variable `user`.\n * You can then bind the local `user` repeatedly.\n *\n * The conditional displays the data only if `userStream` returns a value,\n * so you don't need to use the\n * safe-navigation-operator (`?.`)\n * to guard against null values when accessing properties.\n * You can display an alternative template while waiting for the data.\n *\n * ### Shorthand syntax\n *\n * The shorthand syntax `*ngIf` expands into two separate template specifications\n * for the \"then\" and \"else\" clauses. For example, consider the following shorthand statement,\n * that is meant to show a loading page while waiting for data to be loaded.\n *\n * ```\n * <div class=\"hero-list\" *ngIf=\"heroes else loading\">\n * ...\n * </div>\n *\n * <ng-template #loading>\n * <div>Loading...</div>\n * </ng-template>\n * ```\n *\n * You can see that the \"else\" clause references the `<ng-template>`\n * with the `#loading` label, and the template for the \"then\" clause\n * is provided as the content of the anchor element.\n *\n * However, when Angular expands the shorthand syntax, it creates\n * another `<ng-template>` tag, with `ngIf` and `ngIfElse` directives.\n * The anchor element containing the template for the \"then\" clause becomes\n * the content of this unlabeled `<ng-template>` tag.\n *\n * ```\n * <ng-template [ngIf]=\"heroes\" [ngIfElse]=\"loading\">\n * <div class=\"hero-list\">\n * ...\n * </div>\n * </ng-template>\n *\n * <ng-template #loading>\n * <div>Loading...</div>\n * </ng-template>\n * ```\n *\n * The presence of the implicit template object has implications for the nesting of\n * structural directives. For more on this subject, see\n * [Structural Directives](guide/structural-directives#one-per-element).\n *\n * @ngModule CommonModule\n * @publicApi\n */\n@Directive({\n selector: '[ngIf]',\n standalone: true,\n})\nexport class NgIf<T = unknown> {\n private _context: NgIfContext<T> = new NgIfContext<T>();\n private _thenTemplateRef: TemplateRef<NgIfContext<T>>|null = null;\n private _elseTemplateRef: TemplateRef<NgIfContext<T>>|null = null;\n private _thenViewRef: EmbeddedViewRef<NgIfContext<T>>|null = null;\n private _elseViewRef: EmbeddedViewRef<NgIfContext<T>>|null = null;\n\n constructor(private _viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext<T>>) {\n this._thenTemplateRef = templateRef;\n }\n\n /**\n * The Boolean expression to evaluate as the condition for showing a template.\n */\n @Input()\n set ngIf(condition: T) {\n this._context.$implicit = this._context.ngIf = condition;\n this._updateView();\n }\n\n /**\n * A template to show if the condition expression evaluates to true.\n */\n @Input()\n set ngIfThen(templateRef: TemplateRef<NgIfContext<T>>|null) {\n assertTemplate('ngIfThen', templateRef);\n this._thenTemplateRef = templateRef;\n this._thenViewRef = null; // clear previous view if any.\n this._updateView();\n }\n\n /**\n * A template to show if the condition expression evaluates to false.\n */\n @Input()\n set ngIfElse(templateRef: TemplateRef<NgIfContext<T>>|null) {\n assertTemplate('ngIfElse', templateRef);\n this._elseTemplateRef = templateRef;\n this._elseViewRef = null; // clear previous view if any.\n this._updateView();\n }\n\n private _updateView() {\n if (this._context.$implicit) {\n if (!this._thenViewRef) {\n this._viewContainer.clear();\n this._elseViewRef = null;\n if (this._thenTemplateRef) {\n this._thenViewRef =\n this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);\n }\n }\n } else {\n if (!this._elseViewRef) {\n this._viewContainer.clear();\n this._thenViewRef = null;\n if (this._elseTemplateRef) {\n this._elseViewRef =\n this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);\n }\n }\n }\n }\n\n /** @internal */\n public static ngIfUseIfTypeGuard: void;\n\n /**\n * Assert the correct type of the expression bound to the `ngIf` input within the template.\n *\n * The presence of this static field is a signal to the Ivy template type check compiler that\n * when the `NgIf` structural directive renders its template, the type of the expression bound\n * to `ngIf` should be narrowed in some way. For `NgIf`, the binding expression itself is used to\n * narrow its type, which allows the strictNullChecks feature of TypeScript to work with `NgIf`.\n */\n static ngTemplateGuard_ngIf: 'binding';\n\n /**\n * Asserts the correct type of the context for the template that `NgIf` will render.\n *\n * The presence of this method is a signal to the Ivy template type-check compiler that the\n * `NgIf` structural directive renders its template with a specific context type.\n */\n static ngTemplateContextGuard<T>(dir: NgIf<T>, ctx: any):\n ctx is NgIfContext<Exclude<T, false|0|''|null|undefined>> {\n return true;\n }\n}\n\n/**\n * @publicApi\n */\nexport class NgIfContext<T = unknown> {\n public $implicit: T = null!;\n public ngIf: T = null!;\n}\n\nfunction assertTemplate(property: string, templateRef: TemplateRef<any>|null): void {\n const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView);\n if (!isTemplateRefOrNull) {\n throw new Error(`${property} must be a TemplateRef, but received '${stringify(templateRef)}'.`);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Attribute, Directive, Host, Input, TemplateRef, ViewContainerRef} from '@angular/core';\n\nimport {getPluralCategory, NgLocalization} from '../i18n/localization';\n\nimport {SwitchView} from './ng_switch';\n\n/**\n * @ngModule CommonModule\n *\n * @usageNotes\n * ```\n * <some-element [ngPlural]=\"value\">\n * <ng-template ngPluralCase=\"=0\">there is nothing</ng-template>\n * <ng-template ngPluralCase=\"=1\">there is one</ng-template>\n * <ng-template ngPluralCase=\"few\">there are a few</ng-template>\n * </some-element>\n * ```\n *\n * @description\n *\n * Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization.\n *\n * Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees\n * that match the switch expression's pluralization category.\n *\n * To use this directive you must provide a container element that sets the `[ngPlural]` attribute\n * to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their\n * expression:\n * - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value\n * matches the switch expression exactly,\n * - otherwise, the view will be treated as a \"category match\", and will only display if exact\n * value matches aren't found and the value maps to its category for the defined locale.\n *\n * See http://cldr.unicode.org/index/cldr-spec/plural-rules\n *\n * @publicApi\n */\n@Directive({\n selector: '[ngPlural]',\n standalone: true,\n})\nexport class NgPlural {\n private _activeView?: SwitchView;\n private _caseViews: {[k: string]: SwitchView} = {};\n\n constructor(private _localization: NgLocalization) {}\n\n @Input()\n set ngPlural(value: number) {\n this._updateView(value);\n }\n\n addCase(value: string, switchView: SwitchView): void {\n this._caseViews[value] = switchView;\n }\n\n private _updateView(switchValue: number): void {\n this._clearViews();\n\n const cases = Object.keys(this._caseViews);\n const key = getPluralCategory(switchValue, cases, this._localization);\n this._activateView(this._caseViews[key]);\n }\n\n private _clearViews() {\n if (this._activeView) this._activeView.destroy();\n }\n\n private _activateView(view: SwitchView) {\n if (view) {\n this._activeView = view;\n this._activeView.create();\n }\n }\n}\n\n/**\n * @ngModule CommonModule\n *\n * @description\n *\n * Creates a view that will be added/removed from the parent {@link NgPlural} when the\n * given expression matches the plural expression according to CLDR rules.\n *\n * @usageNotes\n * ```\n * <some-element [ngPlural]=\"value\">\n * <ng-template ngPluralCase=\"=0\">...</ng-template>\n * <ng-template ngPluralCase=\"other\">...</ng-template>\n * </some-element>\n *```\n *\n * See {@link NgPlural} for more details and example.\n *\n * @publicApi\n */\n@Directive({\n selector: '[ngPluralCase]',\n standalone: true,\n})\nexport class NgPluralCase {\n constructor(\n @Attribute('ngPluralCase') public value: string, template: TemplateRef<Object>,\n viewContainer: ViewContainerRef, @Host() ngPlural: NgPlural) {\n const isANumber: boolean = !isNaN(Number(value));\n ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {Directive, DoCheck, ElementRef, Input, KeyValueChanges, KeyValueDiffer, KeyValueDiffers, Renderer2, RendererStyleFlags2} from '@angular/core';\n\n\n/**\n * @ngModule CommonModule\n *\n * @usageNotes\n *\n * Set the font of the containing element to the result of an expression.\n *\n * ```\n * <some-element [ngStyle]=\"{'font-style': styleExp}\">...</some-element>\n * ```\n *\n * Set the width of the containing element to a pixel value returned by an expression.\n *\n * ```\n * <some-element [ngStyle]=\"{'max-width.px': widthExp}\">...</some-element>\n * ```\n *\n * Set a collection of style values using an expression that returns key-value pairs.\n *\n * ```\n * <some-element [ngStyle]=\"objExp\">...</some-element>\n * ```\n *\n * @description\n *\n * An attribute directive that updates styles for the containing HTML element.\n * Sets one or more style properties, specified as colon-separated key-value pairs.\n * The key is a style name, with an optional `.<unit>` suffix\n * (such as 'top.px', 'font-style.em').\n * The value is an expression to be evaluated.\n * The resulting non-null value, expressed in the given unit,\n * is assigned to the given style property.\n * If the result of evaluation is null, the corresponding style is removed.\n *\n * @publicApi\n */\n@Directive({\n selector: '[ngStyle]',\n standalone: true,\n})\nexport class NgStyle implements DoCheck {\n private _ngStyle: {[key: string]: string}|null|undefined = null;\n private _differ: KeyValueDiffer<string, string|number>|null = null;\n\n constructor(\n private _ngEl: ElementRef, private _differs: KeyValueDiffers, private _renderer: Renderer2) {}\n\n @Input('ngStyle')\n set ngStyle(values: {[klass: string]: any}|null|undefined) {\n this._ngStyle = values;\n if (!this._differ && values) {\n this._differ = this._differs.find(values).create();\n }\n }\n\n ngDoCheck() {\n if (this._differ) {\n const changes = this._differ.diff(this._ngStyle!);\n if (changes) {\n this._applyChanges(changes);\n }\n }\n }\n\n private _setStyle(nameAndUnit: string, value: string|number|null|undefined): void {\n const [name, unit] = nameAndUnit.split('.');\n const flags = name.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase as number;\n\n if (value != null) {\n this._renderer.setStyle(\n this._ngEl.nativeElement, name, unit ? `${value}${unit}` : value, flags);\n } else {\n this._renderer.removeStyle(this._ngEl.nativeElement, name, flags);\n }\n }\n\n private _applyChanges(changes: KeyValueChanges<string, string|number>): void {\n changes.forEachRemovedItem((record) => this._setStyle(record.key, null));\n changes.forEachAddedItem((record) => this._setStyle(record.key, record.currentValue));\n changes.forEachChangedItem((record) => this._setStyle(record.key, record.currentValue));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, EmbeddedViewRef, Injector, Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef} from '@angular/core';\n\n/**\n * @ngModule CommonModule\n *\n * @description\n *\n * Inserts an embedded view from a prepared `TemplateRef`.\n *\n * You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.\n * `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding\n * by the local template `let` declarations.\n *\n * @usageNotes\n * ```\n * <ng-container *ngTemplateOutlet=\"templateRefExp; context: contextExp\"></ng-container>\n * ```\n *\n * Using the key `$implicit` in the context object will set its value as default.\n *\n * ### Example\n *\n * {@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'}\n *\n * @publicApi\n */\n@Directive({\n selector: '[ngTemplateOutlet]',\n standalone: true,\n})\nexport class NgTemplateOutlet implements OnChanges {\n private _viewRef: EmbeddedViewRef<any>|null = null;\n\n /**\n * A context object to attach to the {@link EmbeddedViewRef}. This should be an\n * object, the object's keys will be available for binding by the local template `let`\n * declarations.\n * Using the key `$implicit` in the context object will set its value as default.\n */\n @Input() public ngTemplateOutletContext: Object|null = null;\n\n /**\n * A string defining the template reference and optionally the context object for the template.\n */\n @Input() public ngTemplateOutlet: TemplateRef<any>|null = null;\n\n /** Injector to be used within the embedded view. */\n @Input() public ngTemplateOutletInjector: Injector|null = null;\n\n constructor(private _viewContainerRef: ViewContainerRef) {}\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges) {\n if (changes['ngTemplateOutlet'] || changes['ngTemplateOutletInjector']) {\n const viewContainerRef = this._viewContainerRef;\n\n if (this._viewRef) {\n viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));\n }\n\n if (this.ngTemplateOutlet) {\n const {\n ngTemplateOutlet: template,\n ngTemplateOutletContext: context,\n ngTemplateOutletInjector: injector\n } = this;\n this._viewRef = viewContainerRef.createEmbeddedView(\n template, context, injector ? {injector} : undefined);\n } else {\n this._viewRef = null;\n }\n } else if (\n this._viewRef && changes['ngTemplateOutletContext'] && this.ngTemplateOutletContext) {\n this._viewRef.context = this.ngTemplateOutletContext;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type, ɵRuntimeError as RuntimeError, ɵstringify as stringify} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\n\nexport function invalidPipeArgumentError(type: Type<any>, value: Object) {\n return new RuntimeError(\n RuntimeErrorCode.INVALID_PIPE_ARGUMENT,\n ngDevMode && `InvalidPipeArgument: '${value}' for pipe '${stringify(type)}'`);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef, EventEmitter, OnDestroy, Pipe, PipeTransform, ɵisPromise, ɵisSubscribable} from '@angular/core';\nimport {Observable, Subscribable, Unsubscribable} from 'rxjs';\n\nimport {invalidPipeArgumentError} from './invalid_pipe_argument_error';\n\ninterface SubscriptionStrategy {\n createSubscription(async: Subscribable<any>|Promise<any>, updateLatestValue: any): Unsubscribable\n |Promise<any>;\n dispose(subscription: Unsubscribable|Promise<any>): void;\n}\n\nclass SubscribableStrategy implements SubscriptionStrategy {\n createSubscription(async: Subscribable<any>, updateLatestValue: any): Unsubscribable {\n return async.subscribe({\n next: updateLatestValue,\n error: (e: any) => {\n throw e;\n }\n });\n }\n\n dispose(subscription: Unsubscribable): void {\n subscription.unsubscribe();\n }\n}\n\nclass PromiseStrategy implements SubscriptionStrategy {\n createSubscription(async: Promise<any>, updateLatestValue: (v: any) => any): Promise<any> {\n return async.then(updateLatestValue, e => {\n throw e;\n });\n }\n\n dispose(subscription: Promise<any>): void {}\n}\n\nconst _promiseStrategy = new PromiseStrategy();\nconst _subscribableStrategy = new SubscribableStrategy();\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Unwraps a value from an asynchronous primitive.\n *\n * The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has\n * emitted. When a new value is emitted, the `async` pipe marks the component to be checked for\n * changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid\n * potential memory leaks. When the reference of the expression changes, the `async` pipe\n * automatically unsubscribes from the old `Observable` or `Promise` and subscribes to the new one.\n *\n * @usageNotes\n *\n * ### Examples\n *\n * This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the\n * promise.\n *\n * {@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'}\n *\n * It's also possible to use `async` with Observables. The example below binds the `time` Observable\n * to the view. The Observable continuously updates the view with the current time.\n *\n * {@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'}\n *\n * @publicApi\n */\n@Pipe({\n name: 'async',\n pure: false,\n standalone: true,\n})\nexport class AsyncPipe implements OnDestroy, PipeTransform {\n private _ref: ChangeDetectorRef|null;\n private _latestValue: any = null;\n\n private _subscription: Unsubscribable|Promise<any>|null = null;\n private _obj: Subscribable<any>|Promise<any>|EventEmitter<any>|null = null;\n private _strategy: SubscriptionStrategy|null = null;\n\n constructor(ref: ChangeDetectorRef) {\n // Assign `ref` into `this._ref` manually instead of declaring `_ref` in the constructor\n // parameter list, as the type of `this._ref` includes `null` unlike the type of `ref`.\n this._ref = ref;\n }\n\n ngOnDestroy(): void {\n if (this._subscription) {\n this._dispose();\n }\n // Clear the `ChangeDetectorRef` and its association with the view data, to mitigate\n // potential memory leaks in Observables that could otherwise cause the view data to\n // be retained.\n // https://github.com/angular/angular/issues/17624\n this._ref = null;\n }\n\n // NOTE(@benlesh): Because Observable has deprecated a few call patterns for `subscribe`,\n // TypeScript has a hard time matching Observable to Subscribable, for more information\n // see https://github.com/microsoft/TypeScript/issues/43643\n\n transform<T>(obj: Observable<T>|Subscribable<T>|Promise<T>): T|null;\n transform<T>(obj: null|undefined): null;\n transform<T>(obj: Observable<T>|Subscribable<T>|Promise<T>|null|undefined): T|null;\n transform<T>(obj: Observable<T>|Subscribable<T>|Promise<T>|null|undefined): T|null {\n if (!this._obj) {\n if (obj) {\n this._subscribe(obj);\n }\n return this._latestValue;\n }\n\n if (obj !== this._obj) {\n this._dispose();\n return this.transform(obj);\n }\n\n return this._latestValue;\n }\n\n private _subscribe(obj: Subscribable<any>|Promise<any>|EventEmitter<any>): void {\n this._obj = obj;\n this._strategy = this._selectStrategy(obj);\n this._subscription = this._strategy.createSubscription(\n obj, (value: Object) => this._updateLatestValue(obj, value));\n }\n\n private _selectStrategy(obj: Subscribable<any>|Promise<any>|\n EventEmitter<any>): SubscriptionStrategy {\n if (ɵisPromise(obj)) {\n return _promiseStrategy;\n }\n\n if (ɵisSubscribable(obj)) {\n return _subscribableStrategy;\n }\n\n throw invalidPipeArgumentError(AsyncPipe, obj);\n }\n\n private _dispose(): void {\n // Note: `dispose` is only called if a subscription has been initialized before, indicating\n // that `this._strategy` is also available.\n this._strategy!.dispose(this._subscription!);\n this._latestValue = null;\n this._subscription = null;\n this._obj = null;\n }\n\n private _updateLatestValue(async: any, value: Object): void {\n if (async === this._obj) {\n this._latestValue = value;\n // Note: `this._ref` is only cleared in `ngOnDestroy` so is known to be available when a\n // value is being updated.\n this._ref!.markForCheck();\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Pipe, PipeTransform} from '@angular/core';\n\nimport {invalidPipeArgumentError} from './invalid_pipe_argument_error';\n\n/**\n * Transforms text to all lower case.\n *\n * @see `UpperCasePipe`\n * @see `TitleCasePipe`\n * @usageNotes\n *\n * The following example defines a view that allows the user to enter\n * text, and then uses the pipe to convert the input text to all lower case.\n *\n * <code-example path=\"common/pipes/ts/lowerupper_pipe.ts\" region='LowerUpperPipe'></code-example>\n *\n * @ngModule CommonModule\n * @publicApi\n */\n@Pipe({\n name: 'lowercase',\n standalone: true,\n})\nexport class LowerCasePipe implements PipeTransform {\n /**\n * @param value The string to transform to lower case.\n */\n transform(value: string): string;\n transform(value: null|undefined): null;\n transform(value: string|null|undefined): string|null;\n transform(value: string|null|undefined): string|null {\n if (value == null) return null;\n if (typeof value !== 'string') {\n throw invalidPipeArgumentError(LowerCasePipe, value);\n }\n return value.toLowerCase();\n }\n}\n\n//\n// Regex below matches any Unicode word and number compatible with ES5. In ES2018 the same result\n// can be achieved by using /[0-9\\p{L}]\\S*/gu and also known as Unicode Property Escapes\n// (https://2ality.com/2017/07/regexp-unicode-property-escapes.html). Since there is no\n// transpilation of this functionality down to ES5 without external tool, the only solution is\n// to use already transpiled form. Example can be found here -\n// https://mothereff.in/regexpu#input=var+regex+%3D+%2F%5B0-9%5Cp%7BL%7D%5D%5CS*%2Fgu%3B%0A%0A&unicodePropertyEscape=1\n//\n\nconst unicodeWordMatch =\n /(?:[0-9A-Za-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u0870-\\u0887\\u0889-\\u088E\\u08A0-\\u08C9\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C5D\\u0C60\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D04-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u1711\\u171F-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4C\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C88\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF3\\u1CF5\\u1CF6\\u1CFA\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BF\\u31F0-\\u31FF\\u3400-\\u4DBF\\u4E00-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7CA\\uA7D0\\uA7D1\\uA7D3\\uA7D5-\\uA7D9\\uA7F2-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB69\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]|\\uD800[\\uDC00-\\uDC0B\\uDC0D-\\uDC26\\uDC28-\\uDC3A\\uDC3C\\uDC3D\\uDC3F-\\uDC4D\\uDC50-\\uDC5D\\uDC80-\\uDCFA\\uDE80-\\uDE9C\\uDEA0-\\uDED0\\uDF00-\\uDF1F\\uDF2D-\\uDF40\\uDF42-\\uDF49\\uDF50-\\uDF75\\uDF80-\\uDF9D\\uDFA0-\\uDFC3\\uDFC8-\\uDFCF]|\\uD801[\\uDC00-\\uDC9D\\uDCB0-\\uDCD3\\uDCD8-\\uDCFB\\uDD00-\\uDD27\\uDD30-\\uDD63\\uDD70-\\uDD7A\\uDD7C-\\uDD8A\\uDD8C-\\uDD92\\uDD94\\uDD95\\uDD97-\\uDDA1\\uDDA3-\\uDDB1\\uDDB3-\\uDDB9\\uDDBB\\uDDBC\\uDE00-\\uDF36\\uDF40-\\uDF55\\uDF60-\\uDF67\\uDF80-\\uDF85\\uDF87-\\uDFB0\\uDFB2-\\uDFBA]|\\uD802[\\uDC00-\\uDC05\\uDC08\\uDC0A-\\uDC35\\uDC37\\uDC38\\uDC3C\\uDC3F-\\uDC55\\uDC60-\\uDC76\\uDC80-\\uDC9E\\uDCE0-\\uDCF2\\uDCF4\\uDCF5\\uDD00-\\uDD15\\uDD20-\\uDD39\\uDD80-\\uDDB7\\uDDBE\\uDDBF\\uDE00\\uDE10-\\uDE13\\uDE15-\\uDE17\\uDE19-\\uDE35\\uDE60-\\uDE7C\\uDE80-\\uDE9C\\uDEC0-\\uDEC7\\uDEC9-\\uDEE4\\uDF00-\\uDF35\\uDF40-\\uDF55\\uDF60-\\uDF72\\uDF80-\\uDF91]|\\uD803[\\uDC00-\\uDC48\\uDC80-\\uDCB2\\uDCC0-\\uDCF2\\uDD00-\\uDD23\\uDE80-\\uDEA9\\uDEB0\\uDEB1\\uDF00-\\uDF1C\\uDF27\\uDF30-\\uDF45\\uDF70-\\uDF81\\uDFB0-\\uDFC4\\uDFE0-\\uDFF6]|\\uD804[\\uDC03-\\uDC37\\uDC71\\uDC72\\uDC75\\uDC83-\\uDCAF\\uDCD0-\\uDCE8\\uDD03-\\uDD26\\uDD44\\uDD47\\uDD50-\\uDD72\\uDD76\\uDD83-\\uDDB2\\uDDC1-\\uDDC4\\uDDDA\\uDDDC\\uDE00-\\uDE11\\uDE13-\\uDE2B\\uDE80-\\uDE86\\uDE88\\uDE8A-\\uDE8D\\uDE8F-\\uDE9D\\uDE9F-\\uDEA8\\uDEB0-\\uDEDE\\uDF05-\\uDF0C\\uDF0F\\uDF10\\uDF13-\\uDF28\\uDF2A-\\uDF30\\uDF32\\uDF33\\uDF35-\\uDF39\\uDF3D\\uDF50\\uDF5D-\\uDF61]|\\uD805[\\uDC00-\\uDC34\\uDC47-\\uDC4A\\uDC5F-\\uDC61\\uDC80-\\uDCAF\\uDCC4\\uDCC5\\uDCC7\\uDD80-\\uDDAE\\uDDD8-\\uDDDB\\uDE00-\\uDE2F\\uDE44\\uDE80-\\uDEAA\\uDEB8\\uDF00-\\uDF1A\\uDF40-\\uDF46]|\\uD806[\\uDC00-\\uDC2B\\uDCA0-\\uDCDF\\uDCFF-\\uDD06\\uDD09\\uDD0C-\\uDD13\\uDD15\\uDD16\\uDD18-\\uDD2F\\uDD3F\\uDD41\\uDDA0-\\uDDA7\\uDDAA-\\uDDD0\\uDDE1\\uDDE3\\uDE00\\uDE0B-\\uDE32\\uDE3A\\uDE50\\uDE5C-\\uDE89\\uDE9D\\uDEB0-\\uDEF8]|\\uD807[\\uDC00-\\uDC08\\uDC0A-\\uDC2E\\uDC40\\uDC72-\\uDC8F\\uDD00-\\uDD06\\uDD08\\uDD09\\uDD0B-\\uDD30\\uDD46\\uDD60-\\uDD65\\uDD67\\uDD68\\uDD6A-\\uDD89\\uDD98\\uDEE0-\\uDEF2\\uDFB0]|\\uD808[\\uDC00-\\uDF99]|\\uD809[\\uDC80-\\uDD43]|\\uD80B[\\uDF90-\\uDFF0]|[\\uD80C\\uD81C-\\uD820\\uD822\\uD840-\\uD868\\uD86A-\\uD86C\\uD86F-\\uD872\\uD874-\\uD879\\uD880-\\uD883][\\uDC00-\\uDFFF]|\\uD80D[\\uDC00-\\uDC2E]|\\uD811[\\uDC00-\\uDE46]|\\uD81A[\\uDC00-\\uDE38\\uDE40-\\uDE5E\\uDE70-\\uDEBE\\uDED0-\\uDEED\\uDF00-\\uDF2F\\uDF40-\\uDF43\\uDF63-\\uDF77\\uDF7D-\\uDF8F]|\\uD81B[\\uDE40-\\uDE7F\\uDF00-\\uDF4A\\uDF50\\uDF93-\\uDF9F\\uDFE0\\uDFE1\\uDFE3]|\\uD821[\\uDC00-\\uDFF7]|\\uD823[\\uDC00-\\uDCD5\\uDD00-\\uDD08]|\\uD82B[\\uDFF0-\\uDFF3\\uDFF5-\\uDFFB\\uDFFD\\uDFFE]|\\uD82C[\\uDC00-\\uDD22\\uDD50-\\uDD52\\uDD64-\\uDD67\\uDD70-\\uDEFB]|\\uD82F[\\uDC00-\\uDC6A\\uDC70-\\uDC7C\\uDC80-\\uDC88\\uDC90-\\uDC99]|\\uD835[\\uDC00-\\uDC54\\uDC56-\\uDC9C\\uDC9E\\uDC9F\\uDCA2\\uDCA5\\uDCA6\\uDCA9-\\uDCAC\\uDCAE-\\uDCB9\\uDCBB\\uDCBD-\\uDCC3\\uDCC5-\\uDD05\\uDD07-\\uDD0A\\uDD0D-\\uDD14\\uDD16-\\uDD1C\\uDD1E-\\uDD39\\uDD3B-\\uDD3E\\uDD40-\\uDD44\\uDD46\\uDD4A-\\uDD50\\uDD52-\\uDEA5\\uDEA8-\\uDEC0\\uDEC2-\\uDEDA\\uDEDC-\\uDEFA\\uDEFC-\\uDF14\\uDF16-\\uDF34\\uDF36-\\uDF4E\\uDF50-\\uDF6E\\uDF70-\\uDF88\\uDF8A-\\uDFA8\\uDFAA-\\uDFC2\\uDFC4-\\uDFCB]|\\uD837[\\uDF00-\\uDF1E]|\\uD838[\\uDD00-\\uDD2C\\uDD37-\\uDD3D\\uDD4E\\uDE90-\\uDEAD\\uDEC0-\\uDEEB]|\\uD839[\\uDFE0-\\uDFE6\\uDFE8-\\uDFEB\\uDFED\\uDFEE\\uDFF0-\\uDFFE]|\\uD83A[\\uDC00-\\uDCC4\\uDD00-\\uDD43\\uDD4B]|\\uD83B[\\uDE00-\\uDE03\\uDE05-\\uDE1F\\uDE21\\uDE22\\uDE24\\uDE27\\uDE29-\\uDE32\\uDE34-\\uDE37\\uDE39\\uDE3B\\uDE42\\uDE47\\uDE49\\uDE4B\\uDE4D-\\uDE4F\\uDE51\\uDE52\\uDE54\\uDE57\\uDE59\\uDE5B\\uDE5D\\uDE5F\\uDE61\\uDE62\\uDE64\\uDE67-\\uDE6A\\uDE6C-\\uDE72\\uDE74-\\uDE77\\uDE79-\\uDE7C\\uDE7E\\uDE80-\\uDE89\\uDE8B-\\uDE9B\\uDEA1-\\uDEA3\\uDEA5-\\uDEA9\\uDEAB-\\uDEBB]|\\uD869[\\uDC00-\\uDEDF\\uDF00-\\uDFFF]|\\uD86D[\\uDC00-\\uDF38\\uDF40-\\uDFFF]|\\uD86E[\\uDC00-\\uDC1D\\uDC20-\\uDFFF]|\\uD873[\\uDC00-\\uDEA1\\uDEB0-\\uDFFF]|\\uD87A[\\uDC00-\\uDFE0]|\\uD87E[\\uDC00-\\uDE1D]|\\uD884[\\uDC00-\\uDF4A])\\S*/g;\n\n/**\n * Transforms text to title case.\n * Capitalizes the first letter of each word and transforms the\n * rest of the word to lower case.\n * Words are delimited by any whitespace character, such as a space, tab, or line-feed character.\n *\n * @see `LowerCasePipe`\n * @see `UpperCasePipe`\n *\n * @usageNotes\n * The following example shows the result of transforming various strings into title case.\n *\n * <code-example path=\"common/pipes/ts/titlecase_pipe.ts\" region='TitleCasePipe'></code-example>\n *\n * @ngModule CommonModule\n * @publicApi\n */\n@Pipe({\n name: 'titlecase',\n standalone: true,\n})\nexport class TitleCasePipe implements PipeTransform {\n /**\n * @param value The string to transform to title case.\n */\n transform(value: string): string;\n transform(value: null|undefined): null;\n transform(value: string|null|undefined): string|null;\n transform(value: string|null|undefined): string|null {\n if (value == null) return null;\n if (typeof value !== 'string') {\n throw invalidPipeArgumentError(TitleCasePipe, value);\n }\n\n return value.replace(\n unicodeWordMatch, (txt => txt[0].toUpperCase() + txt.slice(1).toLowerCase()));\n }\n}\n\n/**\n * Transforms text to all upper case.\n * @see `LowerCasePipe`\n * @see `TitleCasePipe`\n *\n * @ngModule CommonModule\n * @publicApi\n */\n@Pipe({\n name: 'uppercase',\n standalone: true,\n})\nexport class UpperCasePipe implements PipeTransform {\n /**\n * @param value The string to transform to upper case.\n */\n transform(value: string): string;\n transform(value: null|undefined): null;\n transform(value: string|null|undefined): string|null;\n transform(value: string|null|undefined): string|null {\n if (value == null) return null;\n if (typeof value !== 'string') {\n throw invalidPipeArgumentError(UpperCasePipe, value);\n }\n return value.toUpperCase();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * An interface that describes the date pipe configuration, which can be provided using the\n * `DATE_PIPE_DEFAULT_OPTIONS` token.\n *\n * @see `DATE_PIPE_DEFAULT_OPTIONS`\n *\n * @publicApi\n */\nexport interface DatePipeConfig {\n dateFormat: string;\n timezone: string;\n}\n\n/**\n * The default date format of Angular date pipe, which corresponds to the following format:\n * `'MMM d,y'` (e.g. `Jun 15, 2015`)\n */\nexport const DEFAULT_DATE_FORMAT = 'mediumDate';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, InjectionToken, LOCALE_ID, Optional, Pipe, PipeTransform} from '@angular/core';\n\nimport {formatDate} from '../i18n/format_date';\n\nimport {DatePipeConfig, DEFAULT_DATE_FORMAT} from './date_pipe_config';\nimport {invalidPipeArgumentError} from './invalid_pipe_argument_error';\n\n/**\n * Optionally-provided default timezone to use for all instances of `DatePipe` (such as `'+0430'`).\n * If the value isn't provided, the `DatePipe` will use the end-user's local system timezone.\n *\n * @deprecated use DATE_PIPE_DEFAULT_OPTIONS token to configure DatePipe\n */\nexport const DATE_PIPE_DEFAULT_TIMEZONE = new InjectionToken<string>('DATE_PIPE_DEFAULT_TIMEZONE');\n\n/**\n * DI token that allows to provide default configuration for the `DatePipe` instances in an\n * application. The value is an object which can include the following fields:\n * - `dateFormat`: configures the default date format. If not provided, the `DatePipe`\n * will use the 'mediumDate' as a value.\n * - `timezone`: configures the default timezone. If not provided, the `DatePipe` will\n * use the end-user's local system timezone.\n *\n * @see `DatePipeConfig`\n *\n * @usageNotes\n *\n * Various date pipe default values can be overwritten by providing this token with\n * the value that has this interface.\n *\n * For example:\n *\n * Override the default date format by providing a value using the token:\n * ```typescript\n * providers: [\n * {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {dateFormat: 'shortDate'}}\n * ]\n * ```\n *\n * Override the default timezone by providing a value using the token:\n * ```typescript\n * providers: [\n * {provide: DATE_PIPE_DEFAULT_OPTIONS, useValue: {timezone: '-1200'}}\n * ]\n * ```\n */\nexport const DATE_PIPE_DEFAULT_OPTIONS =\n new InjectionToken<DatePipeConfig>('DATE_PIPE_DEFAULT_OPTIONS');\n\n// clang-format off\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a date value according to locale rules.\n *\n * `DatePipe` is executed only when it detects a pure change to the input value.\n * A pure change is either a change to a primitive input value\n * (such as `String`, `Number`, `Boolean`, or `Symbol`),\n * or a changed object reference (such as `Date`, `Array`, `Function`, or `Object`).\n *\n * Note that mutating a `Date` object does not cause the pipe to be rendered again.\n * To ensure that the pipe is executed, you must create a new `Date` object.\n *\n * Only the `en-US` locale data comes with Angular. To localize dates\n * in another language, you must import the corresponding locale data.\n * See the [I18n guide](guide/i18n-common-format-data-locale) for more information.\n *\n * The time zone of the formatted value can be specified either by passing it in as the second\n * parameter of the pipe, or by setting the default through the `DATE_PIPE_DEFAULT_OPTIONS`\n * injection token. The value that is passed in as the second parameter takes precedence over\n * the one defined using the injection token.\n *\n * @see `formatDate()`\n *\n *\n * @usageNotes\n *\n * The result of this pipe is not reevaluated when the input is mutated. To avoid the need to\n * reformat the date on every change-detection cycle, treat the date as an immutable object\n * and change the reference when the pipe needs to run again.\n *\n * ### Pre-defined format options\n *\n * | Option | Equivalent to | Examples (given in `en-US` locale) |\n * |---------------|-------------------------------------|-------------------------------------------------|\n * | `'short'` | `'M/d/yy, h:mm a'` | `6/15/15, 9:03 AM` |\n * | `'medium'` | `'MMM d, y, h:mm:ss a'` | `Jun 15, 2015, 9:03:01 AM` |\n * | `'long'` | `'MMMM d, y, h:mm:ss a z'` | `June 15, 2015 at 9:03:01 AM GMT+1` |\n * | `'full'` | `'EEEE, MMMM d, y, h:mm:ss a zzzz'` | `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00` |\n * | `'shortDate'` | `'M/d/yy'` | `6/15/15` |\n * | `'mediumDate'`| `'MMM d, y'` | `Jun 15, 2015` |\n * | `'longDate'` | `'MMMM d, y'` | `June 15, 2015` |\n * | `'fullDate'` | `'EEEE, MMMM d, y'` | `Monday, June 15, 2015` |\n * | `'shortTime'` | `'h:mm a'` | `9:03 AM` |\n * | `'mediumTime'`| `'h:mm:ss a'` | `9:03:01 AM` |\n * | `'longTime'` | `'h:mm:ss a z'` | `9:03:01 AM GMT+1` |\n * | `'fullTime'` | `'h:mm:ss a zzzz'` | `9:03:01 AM GMT+01:00` |\n *\n * ### Custom format options\n *\n * You can construct a format string using symbols to specify the components\n * of a date-time value, as described in the following table.\n * Format details depend on the locale.\n * Fields marked with (*) are only available in the extra data set for the given locale.\n *\n * | Field type | Format | Description | Example Value |\n * |-------------------- |-------------|---------------------------------------------------------------|------------------------------------------------------------|\n * | Era | G, GG & GGG | Abbreviated | AD |\n * | | GGGG | Wide | Anno Domini |\n * | | GGGGG | Narrow | A |\n * | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 |\n * | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |\n * | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |\n * | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |\n * | Week-numbering year | Y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 |\n * | | YY | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |\n * | | YYY | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |\n * | | YYYY | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |\n * | Month | M | Numeric: 1 digit | 9, 12 |\n * | | MM | Numeric: 2 digits + zero padded | 09, 12 |\n * | | MMM | Abbreviated | Sep |\n * | | MMMM | Wide | September |\n * | | MMMMM | Narrow | S |\n * | Month standalone | L | Numeric: 1 digit | 9, 12 |\n * | | LL | Numeric: 2 digits + zero padded | 09, 12 |\n * | | LLL | Abbreviated | Sep |\n * | | LLLL | Wide | September |\n * | | LLLLL | Narrow | S |\n * | Week of year | w | Numeric: minimum digits | 1... 53 |\n * | | ww | Numeric: 2 digits + zero padded | 01... 53 |\n * | Week of month | W | Numeric: 1 digit | 1... 5 |\n * | Day of month | d | Numeric: minimum digits | 1 |\n * | | dd | Numeric: 2 digits + zero padded | 01 |\n * | Week day | E, EE & EEE | Abbreviated | Tue |\n * | | EEEE | Wide | Tuesday |\n * | | EEEEE | Narrow | T |\n * | | EEEEEE | Short | Tu |\n * | Week day standalone | c, cc | Numeric: 1 digit | 2 |\n * | | ccc | Abbreviated | Tue |\n * | | cccc | Wide | Tuesday |\n * | | ccccc | Narrow | T |\n * | | cccccc | Short | Tu |\n * | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM |\n * | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem |\n * | | aaaaa | Narrow | a/p |\n * | Period* | B, BB & BBB | Abbreviated | mid. |\n * | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |\n * | | BBBBB | Narrow | md |\n * | Period standalone* | b, bb & bbb | Abbreviated | mid. |\n * | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |\n * | | bbbbb | Narrow | md |\n * | Hour 1-12 | h | Numeric: minimum digits | 1, 12 |\n * | | hh | Numeric: 2 digits + zero padded | 01, 12 |\n * | Hour 0-23 | H | Numeric: minimum digits | 0, 23 |\n * | | HH | Numeric: 2 digits + zero padded | 00, 23 |\n * | Minute | m | Numeric: minimum digits | 8, 59 |\n * | | mm | Numeric: 2 digits + zero padded | 08, 59 |\n * | Second | s | Numeric: minimum digits | 0... 59 |\n * | | ss | Numeric: 2 digits + zero padded | 00... 59 |\n * | Fractional seconds | S | Numeric: 1 digit | 0... 9 |\n * | | SS | Numeric: 2 digits + zero padded | 00... 99 |\n * | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 |\n * | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 |\n * | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 |\n * | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 |\n * | | ZZZZ | Long localized GMT format | GMT-8:00 |\n * | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 |\n * | | O, OO & OOO | Short localized GMT format | GMT-8 |\n * | | OOOO | Long localized GMT format | GMT-08:00 |\n *\n *\n * ### Format examples\n *\n * These examples transform a date into various formats,\n * assuming that `dateObj` is a JavaScript `Date` object for\n * year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11,\n * given in the local time for the `en-US` locale.\n *\n * ```\n * {{ dateObj | date }} // output is 'Jun 15, 2015'\n * {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM'\n * {{ dateObj | date:'shortTime' }} // output is '9:43 PM'\n * {{ dateObj | date:'mm:ss' }} // output is '43:11'\n * ```\n *\n * ### Usage example\n *\n * The following component uses a date pipe to display the current date in different formats.\n *\n * ```\n * @Component({\n * selector: 'date-pipe',\n * template: `<div>\n * <p>Today is {{today | date}}</p>\n * <p>Or if you prefer, {{today | date:'fullDate'}}</p>\n * <p>The time is {{today | date:'h:mm a z'}}</p>\n * </div>`\n * })\n * // Get the current date and time as a date-time value.\n * export class DatePipeComponent {\n * today: number = Date.now();\n * }\n * ```\n *\n * @publicApi\n */\n// clang-format on\n@Pipe({\n name: 'date',\n pure: true,\n standalone: true,\n})\nexport class DatePipe implements PipeTransform {\n constructor(\n @Inject(LOCALE_ID) private locale: string,\n @Inject(DATE_PIPE_DEFAULT_TIMEZONE) @Optional() private defaultTimezone?: string|null,\n @Inject(DATE_PIPE_DEFAULT_OPTIONS) @Optional() private defaultOptions?: DatePipeConfig|null,\n ) {}\n\n /**\n * @param value The date expression: a `Date` object, a number\n * (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).\n * @param format The date/time components to include, using predefined options or a\n * custom format string. When not provided, the `DatePipe` looks for the value using the\n * `DATE_PIPE_DEFAULT_OPTIONS` injection token (and reads the `dateFormat` property).\n * If the token is not configured, the `mediumDate` is used as a value.\n * @param timezone A timezone offset (such as `'+0430'`), or a standard UTC/GMT, or continental US\n * timezone abbreviation. When not provided, the `DatePipe` looks for the value using the\n * `DATE_PIPE_DEFAULT_OPTIONS` injection token (and reads the `timezone` property). If the token\n * is not configured, the end-user's local system timezone is used as a value.\n * @param locale A locale code for the locale format rules to use.\n * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.\n * See [Setting your app locale](guide/i18n-common-locale-id).\n *\n * @see `DATE_PIPE_DEFAULT_OPTIONS`\n *\n * @returns A date string in the desired format.\n */\n transform(value: Date|string|number, format?: string, timezone?: string, locale?: string): string\n |null;\n transform(value: null|undefined, format?: string, timezone?: string, locale?: string): null;\n transform(\n value: Date|string|number|null|undefined, format?: string, timezone?: string,\n locale?: string): string|null;\n transform(\n value: Date|string|number|null|undefined, format?: string, timezone?: string,\n locale?: string): string|null {\n if (value == null || value === '' || value !== value) return null;\n\n try {\n const _format = format ?? this.defaultOptions?.dateFormat ?? DEFAULT_DATE_FORMAT;\n const _timezone =\n timezone ?? this.defaultOptions?.timezone ?? this.defaultTimezone ?? undefined;\n return formatDate(value, _format, locale || this.locale, _timezone);\n } catch (error) {\n throw invalidPipeArgumentError(DatePipe, (error as Error).message);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Pipe, PipeTransform} from '@angular/core';\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Converts a value into its JSON-format representation. Useful for debugging.\n *\n * @usageNotes\n *\n * The following component uses a JSON pipe to convert an object\n * to JSON format, and displays the string in both formats for comparison.\n *\n * {@example common/pipes/ts/json_pipe.ts region='JsonPipe'}\n *\n * @publicApi\n */\n@Pipe({\n name: 'json',\n pure: false,\n standalone: true,\n})\nexport class JsonPipe implements PipeTransform {\n /**\n * @param value A value of any type to convert into a JSON-format string.\n */\n transform(value: any): string {\n return JSON.stringify(value, null, 2);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {KeyValueChangeRecord, KeyValueChanges, KeyValueDiffer, KeyValueDiffers, Pipe, PipeTransform} from '@angular/core';\n\nfunction makeKeyValuePair<K, V>(key: K, value: V): KeyValue<K, V> {\n return {key: key, value: value};\n}\n\n/**\n * A key value pair.\n * Usually used to represent the key value pairs from a Map or Object.\n *\n * @publicApi\n */\nexport interface KeyValue<K, V> {\n key: K;\n value: V;\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Transforms Object or Map into an array of key value pairs.\n *\n * The output array will be ordered by keys.\n * By default the comparator will be by Unicode point value.\n * You can optionally pass a compareFn if your keys are complex types.\n *\n * @usageNotes\n * ### Examples\n *\n * This examples show how an Object or a Map can be iterated by ngFor with the use of this\n * keyvalue pipe.\n *\n * {@example common/pipes/ts/keyvalue_pipe.ts region='KeyValuePipe'}\n *\n * @publicApi\n */\n@Pipe({\n name: 'keyvalue',\n pure: false,\n standalone: true,\n})\nexport class KeyValuePipe implements PipeTransform {\n constructor(private readonly differs: KeyValueDiffers) {}\n\n private differ!: KeyValueDiffer<any, any>;\n private keyValues: Array<KeyValue<any, any>> = [];\n private compareFn: (a: KeyValue<any, any>, b: KeyValue<any, any>) => number = defaultComparator;\n\n /*\n * NOTE: when the `input` value is a simple Record<K, V> object, the keys are extracted with\n * Object.keys(). This means that even if the `input` type is Record<number, V> the keys are\n * compared/returned as `string`s.\n */\n transform<K, V>(\n input: ReadonlyMap<K, V>,\n compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>;\n transform<K extends number, V>(\n input: Record<K, V>, compareFn?: (a: KeyValue<string, V>, b: KeyValue<string, V>) => number):\n Array<KeyValue<string, V>>;\n transform<K extends string, V>(\n input: Record<K, V>|ReadonlyMap<K, V>,\n compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>;\n transform(\n input: null|undefined,\n compareFn?: (a: KeyValue<unknown, unknown>, b: KeyValue<unknown, unknown>) => number): null;\n transform<K, V>(\n input: ReadonlyMap<K, V>|null|undefined,\n compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>|null;\n transform<K extends number, V>(\n input: Record<K, V>|null|undefined,\n compareFn?: (a: KeyValue<string, V>, b: KeyValue<string, V>) => number):\n Array<KeyValue<string, V>>|null;\n transform<K extends string, V>(\n input: Record<K, V>|ReadonlyMap<K, V>|null|undefined,\n compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>|null;\n transform<K, V>(\n input: undefined|null|{[key: string]: V, [key: number]: V}|ReadonlyMap<K, V>,\n compareFn: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number = defaultComparator):\n Array<KeyValue<K, V>>|null {\n if (!input || (!(input instanceof Map) && typeof input !== 'object')) {\n return null;\n }\n\n if (!this.differ) {\n // make a differ for whatever type we've been passed in\n this.differ = this.differs.find(input).create();\n }\n\n const differChanges: KeyValueChanges<K, V>|null = this.differ.diff(input as any);\n const compareFnChanged = compareFn !== this.compareFn;\n\n if (differChanges) {\n this.keyValues = [];\n differChanges.forEachItem((r: KeyValueChangeRecord<K, V>) => {\n this.keyValues.push(makeKeyValuePair(r.key, r.currentValue!));\n });\n }\n if (differChanges || compareFnChanged) {\n this.keyValues.sort(compareFn);\n this.compareFn = compareFn;\n }\n return this.keyValues;\n }\n}\n\nexport function defaultComparator<K, V>(\n keyValueA: KeyValue<K, V>, keyValueB: KeyValue<K, V>): number {\n const a = keyValueA.key;\n const b = keyValueB.key;\n // if same exit with 0;\n if (a === b) return 0;\n // make sure that undefined are at the end of the sort.\n if (a === undefined) return 1;\n if (b === undefined) return -1;\n // make sure that nulls are at the end of the sort.\n if (a === null) return 1;\n if (b === null) return -1;\n if (typeof a == 'string' && typeof b == 'string') {\n return a < b ? -1 : 1;\n }\n if (typeof a == 'number' && typeof b == 'number') {\n return a - b;\n }\n if (typeof a == 'boolean' && typeof b == 'boolean') {\n return a < b ? -1 : 1;\n }\n // `a` and `b` are of different types. Compare their string values.\n const aString = String(a);\n const bString = String(b);\n return aString == bString ? 0 : aString < bString ? -1 : 1;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DEFAULT_CURRENCY_CODE, Inject, LOCALE_ID, Pipe, PipeTransform} from '@angular/core';\n\nimport {formatCurrency, formatNumber, formatPercent} from '../i18n/format_number';\nimport {getCurrencySymbol} from '../i18n/locale_data_api';\n\nimport {invalidPipeArgumentError} from './invalid_pipe_argument_error';\n\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Formats a value according to digit options and locale rules.\n * Locale determines group sizing and separator,\n * decimal point character, and other locale-specific configurations.\n *\n * @see `formatNumber()`\n *\n * @usageNotes\n *\n * ### digitsInfo\n *\n * The value's decimal representation is specified by the `digitsInfo`\n * parameter, written in the following format:<br>\n *\n * ```\n * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}\n * ```\n *\n * - `minIntegerDigits`:\n * The minimum number of integer digits before the decimal point.\n * Default is 1.\n *\n * - `minFractionDigits`:\n * The minimum number of digits after the decimal point.\n * Default is 0.\n *\n * - `maxFractionDigits`:\n * The maximum number of digits after the decimal point.\n * Default is 3.\n *\n * If the formatted value is truncated it will be rounded using the \"to-nearest\" method:\n *\n * ```\n * {{3.6 | number: '1.0-0'}}\n * <!--will output '4'-->\n *\n * {{-3.6 | number:'1.0-0'}}\n * <!--will output '-4'-->\n * ```\n *\n * ### locale\n *\n * `locale` will format a value according to locale rules.\n * Locale determines group sizing and separator,\n * decimal point character, and other locale-specific configurations.\n *\n * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.\n *\n * See [Setting your app locale](guide/i18n-common-locale-id).\n *\n * ### Example\n *\n * The following code shows how the pipe transforms values\n * according to various format specifications,\n * where the caller's default locale is `en-US`.\n *\n * <code-example path=\"common/pipes/ts/number_pipe.ts\" region='NumberPipe'></code-example>\n *\n * @publicApi\n */\n@Pipe({\n name: 'number',\n standalone: true,\n})\nexport class DecimalPipe implements PipeTransform {\n constructor(@Inject(LOCALE_ID) private _locale: string) {}\n\n transform(value: number|string, digitsInfo?: string, locale?: string): string|null;\n transform(value: null|undefined, digitsInfo?: string, locale?: string): null;\n transform(value: number|string|null|undefined, digitsInfo?: string, locale?: string): string|null;\n /**\n * @param value The value to be formatted.\n * @param digitsInfo Sets digit and decimal representation.\n * [See more](#digitsinfo).\n * @param locale Specifies what locale format rules to use.\n * [See more](#locale).\n */\n transform(value: number|string|null|undefined, digitsInfo?: string, locale?: string): string\n |null {\n if (!isValue(value)) return null;\n\n locale = locale || this._locale;\n\n try {\n const num = strToNumber(value);\n return formatNumber(num, locale, digitsInfo);\n } catch (error) {\n throw invalidPipeArgumentError(DecimalPipe, (error as Error).message);\n }\n }\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Transforms a number to a percentage\n * string, formatted according to locale rules that determine group sizing and\n * separator, decimal-point character, and other locale-specific\n * configurations.\n *\n * @see `formatPercent()`\n *\n * @usageNotes\n * The following code shows how the pipe transforms numbers\n * into text strings, according to various format specifications,\n * where the caller's default locale is `en-US`.\n *\n * <code-example path=\"common/pipes/ts/percent_pipe.ts\" region='PercentPipe'></code-example>\n *\n * @publicApi\n */\n@Pipe({\n name: 'percent',\n standalone: true,\n})\nexport class PercentPipe implements PipeTransform {\n constructor(@Inject(LOCALE_ID) private _locale: string) {}\n\n transform(value: number|string, digitsInfo?: string, locale?: string): string|null;\n transform(value: null|undefined, digitsInfo?: string, locale?: string): null;\n transform(value: number|string|null|undefined, digitsInfo?: string, locale?: string): string|null;\n /**\n *\n * @param value The number to be formatted as a percentage.\n * @param digitsInfo Decimal representation options, specified by a string\n * in the following format:<br>\n * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>.\n * - `minIntegerDigits`: The minimum number of integer digits before the decimal point.\n * Default is `1`.\n * - `minFractionDigits`: The minimum number of digits after the decimal point.\n * Default is `0`.\n * - `maxFractionDigits`: The maximum number of digits after the decimal point.\n * Default is `0`.\n * @param locale A locale code for the locale format rules to use.\n * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.\n * See [Setting your app locale](guide/i18n-common-locale-id).\n */\n transform(value: number|string|null|undefined, digitsInfo?: string, locale?: string): string\n |null {\n if (!isValue(value)) return null;\n locale = locale || this._locale;\n try {\n const num = strToNumber(value);\n return formatPercent(num, locale, digitsInfo);\n } catch (error) {\n throw invalidPipeArgumentError(PercentPipe, (error as Error).message);\n }\n }\n}\n\n/**\n * @ngModule CommonModule\n * @description\n *\n * Transforms a number to a currency string, formatted according to locale rules\n * that determine group sizing and separator, decimal-point character,\n * and other locale-specific configurations.\n *\n *\n * @see `getCurrencySymbol()`\n * @see `formatCurrency()`\n *\n * @usageNotes\n * The following code shows how the pipe transforms numbers\n * into text strings, according to various format specifications,\n * where the caller's default locale is `en-US`.\n *\n * <code-example path=\"common/pipes/ts/currency_pipe.ts\" region='CurrencyPipe'></code-example>\n *\n * @publicApi\n */\n@Pipe({\n name: 'currency',\n standalone: true,\n})\nexport class CurrencyPipe implements PipeTransform {\n constructor(\n @Inject(LOCALE_ID) private _locale: string,\n @Inject(DEFAULT_CURRENCY_CODE) private _defaultCurrencyCode: string = 'USD') {}\n\n transform(\n value: number|string, currencyCode?: string,\n display?: 'code'|'symbol'|'symbol-narrow'|string|boolean, digitsInfo?: string,\n locale?: string): string|null;\n transform(\n value: null|undefined, currencyCode?: string,\n display?: 'code'|'symbol'|'symbol-narrow'|string|boolean, digitsInfo?: string,\n locale?: string): null;\n transform(\n value: number|string|null|undefined, currencyCode?: string,\n display?: 'code'|'symbol'|'symbol-narrow'|string|boolean, digitsInfo?: string,\n locale?: string): string|null;\n /**\n *\n * @param value The number to be formatted as currency.\n * @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code,\n * such as `USD` for the US dollar and `EUR` for the euro. The default currency code can be\n * configured using the `DEFAULT_CURRENCY_CODE` injection token.\n * @param display The format for the currency indicator. One of the following:\n * - `code`: Show the code (such as `USD`).\n * - `symbol`(default): Show the symbol (such as `$`).\n * - `symbol-narrow`: Use the narrow symbol for locales that have two symbols for their\n * currency.\n * For example, the Canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`. If the\n * locale has no narrow symbol, uses the standard symbol for the locale.\n * - String: Use the given string value instead of a code or a symbol.\n * For example, an empty string will suppress the currency & symbol.\n * - Boolean (marked deprecated in v5): `true` for symbol and false for `code`.\n *\n * @param digitsInfo Decimal representation options, specified by a string\n * in the following format:<br>\n * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>.\n * - `minIntegerDigits`: The minimum number of integer digits before the decimal point.\n * Default is `1`.\n * - `minFractionDigits`: The minimum number of digits after the decimal point.\n * Default is `2`.\n * - `maxFractionDigits`: The maximum number of digits after the decimal point.\n * Default is `2`.\n * If not provided, the number will be formatted with the proper amount of digits,\n * depending on what the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) specifies.\n * For example, the Canadian dollar has 2 digits, whereas the Chilean peso has none.\n * @param locale A locale code for the locale format rules to use.\n * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.\n * See [Setting your app locale](guide/i18n-common-locale-id).\n */\n transform(\n value: number|string|null|undefined, currencyCode: string = this._defaultCurrencyCode,\n display: 'code'|'symbol'|'symbol-narrow'|string|boolean = 'symbol', digitsInfo?: string,\n locale?: string): string|null {\n if (!isValue(value)) return null;\n\n locale = locale || this._locale;\n\n if (typeof display === 'boolean') {\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && <any>console && <any>console.warn) {\n console.warn(\n `Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are \"code\", \"symbol\" or \"symbol-narrow\".`);\n }\n display = display ? 'symbol' : 'code';\n }\n\n let currency: string = currencyCode || this._defaultCurrencyCode;\n if (display !== 'code') {\n if (display === 'symbol' || display === 'symbol-narrow') {\n currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale);\n } else {\n currency = display;\n }\n }\n\n try {\n const num = strToNumber(value);\n return formatCurrency(num, locale, currency, currencyCode, digitsInfo);\n } catch (error) {\n throw invalidPipeArgumentError(CurrencyPipe, (error as Error).message);\n }\n }\n}\n\nfunction isValue(value: number|string|null|undefined): value is number|string {\n return !(value == null || value === '' || value !== value);\n}\n\n/**\n * Transforms a string into a number (if needed).\n */\nfunction strToNumber(value: number|string): number {\n // Convert strings to numbers\n if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) {\n return Number(value);\n }\n if (typeof value !== 'number') {\n throw new Error(`${value} is not a number`);\n }\n return value;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\n\nimport {COMMON_DIRECTIVES} from './directives/index';\nimport {COMMON_PIPES} from './pipes/index';\n\n\n\n// Note: This does not contain the location providers,\n// as they need some platform specific implementations to work.\n/**\n * Exports all the basic Angular directives and pipes,\n * such as `NgIf`, `NgForOf`, `DecimalPipe`, and so on.\n * Re-exported by `BrowserModule`, which is included automatically in the root\n * `AppModule` when you create a new app with the CLI `new` command.\n *\n * @publicApi\n */\n@NgModule({\n imports: [COMMON_DIRECTIVES, COMMON_PIPES],\n exports: [COMMON_DIRECTIVES, COMMON_PIPES],\n})\nexport class CommonModule {\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const PLATFORM_BROWSER_ID = 'browser';\nexport const PLATFORM_SERVER_ID = 'server';\nexport const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';\nexport const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';\n\n/**\n * Returns whether a platform id represents a browser platform.\n * @publicApi\n */\nexport function isPlatformBrowser(platformId: Object): boolean {\n return platformId === PLATFORM_BROWSER_ID;\n}\n\n/**\n * Returns whether a platform id represents a server platform.\n * @publicApi\n */\nexport function isPlatformServer(platformId: Object): boolean {\n return platformId === PLATFORM_SERVER_ID;\n}\n\n/**\n * Returns whether a platform id represents a web worker app platform.\n * @publicApi\n */\nexport function isPlatformWorkerApp(platformId: Object): boolean {\n return platformId === PLATFORM_WORKER_APP_ID;\n}\n\n/**\n * Returns whether a platform id represents a web worker UI platform.\n * @publicApi\n */\nexport function isPlatformWorkerUi(platformId: Object): boolean {\n return platformId === PLATFORM_WORKER_UI_ID;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵɵdefineInjectable, ɵɵinject} from '@angular/core';\n\nimport {DOCUMENT} from './dom_tokens';\n\n\n\n/**\n * Defines a scroll position manager. Implemented by `BrowserViewportScroller`.\n *\n * @publicApi\n */\nexport abstract class ViewportScroller {\n // De-sugared tree-shakable injection\n // See #23917\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable({\n token: ViewportScroller,\n providedIn: 'root',\n factory: () => new BrowserViewportScroller(ɵɵinject(DOCUMENT), window)\n });\n\n /**\n * Configures the top offset used when scrolling to an anchor.\n * @param offset A position in screen coordinates (a tuple with x and y values)\n * or a function that returns the top offset position.\n *\n */\n abstract setOffset(offset: [number, number]|(() => [number, number])): void;\n\n /**\n * Retrieves the current scroll position.\n * @returns A position in screen coordinates (a tuple with x and y values).\n */\n abstract getScrollPosition(): [number, number];\n\n /**\n * Scrolls to a specified position.\n * @param position A position in screen coordinates (a tuple with x and y values).\n */\n abstract scrollToPosition(position: [number, number]): void;\n\n /**\n * Scrolls to an anchor element.\n * @param anchor The ID of the anchor element.\n */\n abstract scrollToAnchor(anchor: string): void;\n\n /**\n * Disables automatic scroll restoration provided by the browser.\n * See also [window.history.scrollRestoration\n * info](https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration).\n */\n abstract setHistoryScrollRestoration(scrollRestoration: 'auto'|'manual'): void;\n}\n\n/**\n * Manages the scroll position for a browser window.\n */\nexport class BrowserViewportScroller implements ViewportScroller {\n private offset: () => [number, number] = () => [0, 0];\n\n constructor(private document: Document, private window: Window) {}\n\n /**\n * Configures the top offset used when scrolling to an anchor.\n * @param offset A position in screen coordinates (a tuple with x and y values)\n * or a function that returns the top offset position.\n *\n */\n setOffset(offset: [number, number]|(() => [number, number])): void {\n if (Array.isArray(offset)) {\n this.offset = () => offset;\n } else {\n this.offset = offset;\n }\n }\n\n /**\n * Retrieves the current scroll position.\n * @returns The position in screen coordinates.\n */\n getScrollPosition(): [number, number] {\n if (this.supportsScrolling()) {\n return [this.window.pageXOffset, this.window.pageYOffset];\n } else {\n return [0, 0];\n }\n }\n\n /**\n * Sets the scroll position.\n * @param position The new position in screen coordinates.\n */\n scrollToPosition(position: [number, number]): void {\n if (this.supportsScrolling()) {\n this.window.scrollTo(position[0], position[1]);\n }\n }\n\n /**\n * Scrolls to an element and attempts to focus the element.\n *\n * Note that the function name here is misleading in that the target string may be an ID for a\n * non-anchor element.\n *\n * @param target The ID of an element or name of the anchor.\n *\n * @see https://html.spec.whatwg.org/#the-indicated-part-of-the-document\n * @see https://html.spec.whatwg.org/#scroll-to-fragid\n */\n scrollToAnchor(target: string): void {\n if (!this.supportsScrolling()) {\n return;\n }\n\n const elSelected = findAnchorFromDocument(this.document, target);\n\n if (elSelected) {\n this.scrollToElement(elSelected);\n // After scrolling to the element, the spec dictates that we follow the focus steps for the\n // target. Rather than following the robust steps, simply attempt focus.\n //\n // @see https://html.spec.whatwg.org/#get-the-focusable-area\n // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus\n // @see https://html.spec.whatwg.org/#focusable-area\n elSelected.focus();\n }\n }\n\n /**\n * Disables automatic scroll restoration provided by the browser.\n */\n setHistoryScrollRestoration(scrollRestoration: 'auto'|'manual'): void {\n if (this.supportScrollRestoration()) {\n const history = this.window.history;\n if (history && history.scrollRestoration) {\n history.scrollRestoration = scrollRestoration;\n }\n }\n }\n\n /**\n * Scrolls to an element using the native offset and the specified offset set on this scroller.\n *\n * The offset can be used when we know that there is a floating header and scrolling naively to an\n * element (ex: `scrollIntoView`) leaves the element hidden behind the floating header.\n */\n private scrollToElement(el: HTMLElement): void {\n const rect = el.getBoundingClientRect();\n const left = rect.left + this.window.pageXOffset;\n const top = rect.top + this.window.pageYOffset;\n const offset = this.offset();\n this.window.scrollTo(left - offset[0], top - offset[1]);\n }\n\n /**\n * We only support scroll restoration when we can get a hold of window.\n * This means that we do not support this behavior when running in a web worker.\n *\n * Lifting this restriction right now would require more changes in the dom adapter.\n * Since webworkers aren't widely used, we will lift it once RouterScroller is\n * battle-tested.\n */\n private supportScrollRestoration(): boolean {\n try {\n if (!this.supportsScrolling()) {\n return false;\n }\n // The `scrollRestoration` property could be on the `history` instance or its prototype.\n const scrollRestorationDescriptor = getScrollRestorationProperty(this.window.history) ||\n getScrollRestorationProperty(Object.getPrototypeOf(this.window.history));\n // We can write to the `scrollRestoration` property if it is a writable data field or it has a\n // setter function.\n return !!scrollRestorationDescriptor &&\n !!(scrollRestorationDescriptor.writable || scrollRestorationDescriptor.set);\n } catch {\n return false;\n }\n }\n\n private supportsScrolling(): boolean {\n try {\n return !!this.window && !!this.window.scrollTo && 'pageXOffset' in this.window;\n } catch {\n return false;\n }\n }\n}\n\nfunction getScrollRestorationProperty(obj: any): PropertyDescriptor|undefined {\n return Object.getOwnPropertyDescriptor(obj, 'scrollRestoration');\n}\n\nfunction findAnchorFromDocument(document: Document, target: string): HTMLElement|null {\n const documentResult = document.getElementById(target) || document.getElementsByName(target)[0];\n\n if (documentResult) {\n return documentResult;\n }\n\n // `getElementById` and `getElementsByName` won't pierce through the shadow DOM so we\n // have to traverse the DOM manually and do the lookup through the shadow roots.\n if (typeof document.createTreeWalker === 'function' && document.body &&\n ((document.body as any).createShadowRoot || document.body.attachShadow)) {\n const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);\n let currentNode = treeWalker.currentNode as HTMLElement | null;\n\n while (currentNode) {\n const shadowRoot = currentNode.shadowRoot;\n\n if (shadowRoot) {\n // Note that `ShadowRoot` doesn't support `getElementsByName`\n // so we have to fall back to `querySelector`.\n const result =\n shadowRoot.getElementById(target) || shadowRoot.querySelector(`[name=\"${target}\"]`);\n if (result) {\n return result;\n }\n }\n\n currentNode = treeWalker.nextNode() as HTMLElement | null;\n }\n }\n\n return null;\n}\n\n/**\n * Provides an empty implementation of the viewport scroller.\n */\nexport class NullViewportScroller implements ViewportScroller {\n /**\n * Empty implementation\n */\n setOffset(offset: [number, number]|(() => [number, number])): void {}\n\n /**\n * Empty implementation\n */\n getScrollPosition(): [number, number] {\n return [0, 0];\n }\n\n /**\n * Empty implementation\n */\n scrollToPosition(position: [number, number]): void {}\n\n /**\n * Empty implementation\n */\n scrollToAnchor(anchor: string): void {}\n\n /**\n * Empty implementation\n */\n setHistoryScrollRestoration(scrollRestoration: 'auto'|'manual'): void {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * A wrapper around the `XMLHttpRequest` constructor.\n *\n * @publicApi\n */\nexport abstract class XhrFactory {\n abstract build(): XMLHttpRequest;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Observable} from 'rxjs';\n\nimport {HttpRequest} from './request';\nimport {HttpEvent} from './response';\n\n/**\n * Transforms an `HttpRequest` into a stream of `HttpEvent`s, one of which will likely be a\n * `HttpResponse`.\n *\n * `HttpHandler` is injectable. When injected, the handler instance dispatches requests to the\n * first interceptor in the chain, which dispatches to the second, etc, eventually reaching the\n * `HttpBackend`.\n *\n * In an `HttpInterceptor`, the `HttpHandler` parameter is the next interceptor in the chain.\n *\n * @publicApi\n */\nexport abstract class HttpHandler {\n abstract handle(req: HttpRequest<any>): Observable<HttpEvent<any>>;\n}\n\n/**\n * A final `HttpHandler` which will dispatch the request via browser HTTP APIs to a backend.\n *\n * Interceptors sit between the `HttpClient` interface and the `HttpBackend`.\n *\n * When injected, `HttpBackend` dispatches requests directly to the backend, without going\n * through the interceptor chain.\n *\n * @publicApi\n */\nexport abstract class HttpBackend implements HttpHandler {\n abstract handle(req: HttpRequest<any>): Observable<HttpEvent<any>>;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\ninterface Update {\n name: string;\n value?: string|string[];\n op: 'a'|'s'|'d';\n}\n\n/**\n * Represents the header configuration options for an HTTP request.\n * Instances are immutable. Modifying methods return a cloned\n * instance with the change. The original object is never changed.\n *\n * @publicApi\n */\nexport class HttpHeaders {\n /**\n * Internal map of lowercase header names to values.\n */\n // TODO(issue/24571): remove '!'.\n private headers!: Map<string, string[]>;\n\n\n /**\n * Internal map of lowercased header names to the normalized\n * form of the name (the form seen first).\n */\n private normalizedNames: Map<string, string> = new Map();\n\n /**\n * Complete the lazy initialization of this object (needed before reading).\n */\n private lazyInit!: HttpHeaders|Function|null;\n\n /**\n * Queued updates to be materialized the next initialization.\n */\n private lazyUpdate: Update[]|null = null;\n\n /** Constructs a new HTTP header object with the given values.*/\n\n constructor(headers?: string|{[name: string]: string | number | (string | number)[]}) {\n if (!headers) {\n this.headers = new Map<string, string[]>();\n } else if (typeof headers === 'string') {\n this.lazyInit = () => {\n this.headers = new Map<string, string[]>();\n headers.split('\\n').forEach(line => {\n const index = line.indexOf(':');\n if (index > 0) {\n const name = line.slice(0, index);\n const key = name.toLowerCase();\n const value = line.slice(index + 1).trim();\n this.maybeSetNormalizedName(name, key);\n if (this.headers.has(key)) {\n this.headers.get(key)!.push(value);\n } else {\n this.headers.set(key, [value]);\n }\n }\n });\n };\n } else {\n this.lazyInit = () => {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n assertValidHeaders(headers);\n }\n this.headers = new Map<string, string[]>();\n Object.entries(headers).forEach(([name, values]) => {\n let headerValues: string[];\n\n if (typeof values === 'string') {\n headerValues = [values];\n } else if (typeof values === 'number') {\n headerValues = [values.toString()];\n } else {\n headerValues = values.map((value) => value.toString());\n }\n\n if (headerValues.length > 0) {\n const key = name.toLowerCase();\n this.headers.set(key, headerValues);\n this.maybeSetNormalizedName(name, key);\n }\n });\n };\n }\n }\n\n /**\n * Checks for existence of a given header.\n *\n * @param name The header name to check for existence.\n *\n * @returns True if the header exists, false otherwise.\n */\n has(name: string): boolean {\n this.init();\n\n return this.headers.has(name.toLowerCase());\n }\n\n /**\n * Retrieves the first value of a given header.\n *\n * @param name The header name.\n *\n * @returns The value string if the header exists, null otherwise\n */\n get(name: string): string|null {\n this.init();\n\n const values = this.headers.get(name.toLowerCase());\n return values && values.length > 0 ? values[0] : null;\n }\n\n /**\n * Retrieves the names of the headers.\n *\n * @returns A list of header names.\n */\n keys(): string[] {\n this.init();\n\n return Array.from(this.normalizedNames.values());\n }\n\n /**\n * Retrieves a list of values for a given header.\n *\n * @param name The header name from which to retrieve values.\n *\n * @returns A string of values if the header exists, null otherwise.\n */\n getAll(name: string): string[]|null {\n this.init();\n\n return this.headers.get(name.toLowerCase()) || null;\n }\n\n /**\n * Appends a new value to the existing set of values for a header\n * and returns them in a clone of the original instance.\n *\n * @param name The header name for which to append the values.\n * @param value The value to append.\n *\n * @returns A clone of the HTTP headers object with the value appended to the given header.\n */\n\n append(name: string, value: string|string[]): HttpHeaders {\n return this.clone({name, value, op: 'a'});\n }\n /**\n * Sets or modifies a value for a given header in a clone of the original instance.\n * If the header already exists, its value is replaced with the given value\n * in the returned object.\n *\n * @param name The header name.\n * @param value The value or values to set or override for the given header.\n *\n * @returns A clone of the HTTP headers object with the newly set header value.\n */\n set(name: string, value: string|string[]): HttpHeaders {\n return this.clone({name, value, op: 's'});\n }\n /**\n * Deletes values for a given header in a clone of the original instance.\n *\n * @param name The header name.\n * @param value The value or values to delete for the given header.\n *\n * @returns A clone of the HTTP headers object with the given value deleted.\n */\n delete(name: string, value?: string|string[]): HttpHeaders {\n return this.clone({name, value, op: 'd'});\n }\n\n private maybeSetNormalizedName(name: string, lcName: string): void {\n if (!this.normalizedNames.has(lcName)) {\n this.normalizedNames.set(lcName, name);\n }\n }\n\n private init(): void {\n if (!!this.lazyInit) {\n if (this.lazyInit instanceof HttpHeaders) {\n this.copyFrom(this.lazyInit);\n } else {\n this.lazyInit();\n }\n this.lazyInit = null;\n if (!!this.lazyUpdate) {\n this.lazyUpdate.forEach(update => this.applyUpdate(update));\n this.lazyUpdate = null;\n }\n }\n }\n\n private copyFrom(other: HttpHeaders) {\n other.init();\n Array.from(other.headers.keys()).forEach(key => {\n this.headers.set(key, other.headers.get(key)!);\n this.normalizedNames.set(key, other.normalizedNames.get(key)!);\n });\n }\n\n private clone(update: Update): HttpHeaders {\n const clone = new HttpHeaders();\n clone.lazyInit =\n (!!this.lazyInit && this.lazyInit instanceof HttpHeaders) ? this.lazyInit : this;\n clone.lazyUpdate = (this.lazyUpdate || []).concat([update]);\n return clone;\n }\n\n private applyUpdate(update: Update): void {\n const key = update.name.toLowerCase();\n switch (update.op) {\n case 'a':\n case 's':\n let value = update.value!;\n if (typeof value === 'string') {\n value = [value];\n }\n if (value.length === 0) {\n return;\n }\n this.maybeSetNormalizedName(update.name, key);\n const base = (update.op === 'a' ? this.headers.get(key) : undefined) || [];\n base.push(...value);\n this.headers.set(key, base);\n break;\n case 'd':\n const toDelete = update.value as string | undefined;\n if (!toDelete) {\n this.headers.delete(key);\n this.normalizedNames.delete(key);\n } else {\n let existing = this.headers.get(key);\n if (!existing) {\n return;\n }\n existing = existing.filter(value => toDelete.indexOf(value) === -1);\n if (existing.length === 0) {\n this.headers.delete(key);\n this.normalizedNames.delete(key);\n } else {\n this.headers.set(key, existing);\n }\n }\n break;\n }\n }\n\n /**\n * @internal\n */\n forEach(fn: (name: string, values: string[]) => void) {\n this.init();\n Array.from(this.normalizedNames.keys())\n .forEach(key => fn(this.normalizedNames.get(key)!, this.headers.get(key)!));\n }\n}\n\n/**\n * Verifies that the headers object has the right shape: the values\n * must be either strings, numbers or arrays. Throws an error if an invalid\n * header value is present.\n */\nfunction assertValidHeaders(headers: Record<string, unknown>):\n asserts headers is Record<string, string|string[]|number|number[]> {\n for (const [key, value] of Object.entries(headers)) {\n if (!(typeof value === 'string' || typeof value === 'number') && !Array.isArray(value)) {\n throw new Error(\n `Unexpected value of the \\`${key}\\` header provided. ` +\n `Expecting either a string, a number or an array, but got: \\`${value}\\`.`);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * A codec for encoding and decoding parameters in URLs.\n *\n * Used by `HttpParams`.\n *\n * @publicApi\n **/\nexport interface HttpParameterCodec {\n encodeKey(key: string): string;\n encodeValue(value: string): string;\n\n decodeKey(key: string): string;\n decodeValue(value: string): string;\n}\n\n/**\n * Provides encoding and decoding of URL parameter and query-string values.\n *\n * Serializes and parses URL parameter keys and values to encode and decode them.\n * If you pass URL query parameters without encoding,\n * the query parameters can be misinterpreted at the receiving end.\n *\n *\n * @publicApi\n */\nexport class HttpUrlEncodingCodec implements HttpParameterCodec {\n /**\n * Encodes a key name for a URL parameter or query-string.\n * @param key The key name.\n * @returns The encoded key name.\n */\n encodeKey(key: string): string {\n return standardEncoding(key);\n }\n\n /**\n * Encodes the value of a URL parameter or query-string.\n * @param value The value.\n * @returns The encoded value.\n */\n encodeValue(value: string): string {\n return standardEncoding(value);\n }\n\n /**\n * Decodes an encoded URL parameter or query-string key.\n * @param key The encoded key name.\n * @returns The decoded key name.\n */\n decodeKey(key: string): string {\n return decodeURIComponent(key);\n }\n\n /**\n * Decodes an encoded URL parameter or query-string value.\n * @param value The encoded value.\n * @returns The decoded value.\n */\n decodeValue(value: string) {\n return decodeURIComponent(value);\n }\n}\n\n\nfunction paramParser(rawParams: string, codec: HttpParameterCodec): Map<string, string[]> {\n const map = new Map<string, string[]>();\n if (rawParams.length > 0) {\n // The `window.location.search` can be used while creating an instance of the `HttpParams` class\n // (e.g. `new HttpParams({ fromString: window.location.search })`). The `window.location.search`\n // may start with the `?` char, so we strip it if it's present.\n const params: string[] = rawParams.replace(/^\\?/, '').split('&');\n params.forEach((param: string) => {\n const eqIdx = param.indexOf('=');\n const [key, val]: string[] = eqIdx == -1 ?\n [codec.decodeKey(param), ''] :\n [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))];\n const list = map.get(key) || [];\n list.push(val);\n map.set(key, list);\n });\n }\n return map;\n}\n\n/**\n * Encode input string with standard encodeURIComponent and then un-encode specific characters.\n */\nconst STANDARD_ENCODING_REGEX = /%(\\d[a-f0-9])/gi;\nconst STANDARD_ENCODING_REPLACEMENTS: {[x: string]: string} = {\n '40': '@',\n '3A': ':',\n '24': '$',\n '2C': ',',\n '3B': ';',\n '3D': '=',\n '3F': '?',\n '2F': '/',\n};\n\nfunction standardEncoding(v: string): string {\n return encodeURIComponent(v).replace(\n STANDARD_ENCODING_REGEX, (s, t) => STANDARD_ENCODING_REPLACEMENTS[t] ?? s);\n}\n\nfunction valueToString(value: string|number|boolean): string {\n return `${value}`;\n}\n\ninterface Update {\n param: string;\n value?: string|number|boolean;\n op: 'a'|'d'|'s';\n}\n\n/**\n * Options used to construct an `HttpParams` instance.\n *\n * @publicApi\n */\nexport interface HttpParamsOptions {\n /**\n * String representation of the HTTP parameters in URL-query-string format.\n * Mutually exclusive with `fromObject`.\n */\n fromString?: string;\n\n /** Object map of the HTTP parameters. Mutually exclusive with `fromString`. */\n fromObject?: {[param: string]: string|number|boolean|ReadonlyArray<string|number|boolean>};\n\n /** Encoding codec used to parse and serialize the parameters. */\n encoder?: HttpParameterCodec;\n}\n\n/**\n * An HTTP request/response body that represents serialized parameters,\n * per the MIME type `application/x-www-form-urlencoded`.\n *\n * This class is immutable; all mutation operations return a new instance.\n *\n * @publicApi\n */\nexport class HttpParams {\n private map: Map<string, string[]>|null;\n private encoder: HttpParameterCodec;\n private updates: Update[]|null = null;\n private cloneFrom: HttpParams|null = null;\n\n constructor(options: HttpParamsOptions = {} as HttpParamsOptions) {\n this.encoder = options.encoder || new HttpUrlEncodingCodec();\n if (!!options.fromString) {\n if (!!options.fromObject) {\n throw new Error(`Cannot specify both fromString and fromObject.`);\n }\n this.map = paramParser(options.fromString, this.encoder);\n } else if (!!options.fromObject) {\n this.map = new Map<string, string[]>();\n Object.keys(options.fromObject).forEach(key => {\n const value = (options.fromObject as any)[key];\n // convert the values to strings\n const values = Array.isArray(value) ? value.map(valueToString) : [valueToString(value)];\n this.map!.set(key, values);\n });\n } else {\n this.map = null;\n }\n }\n\n /**\n * Reports whether the body includes one or more values for a given parameter.\n * @param param The parameter name.\n * @returns True if the parameter has one or more values,\n * false if it has no value or is not present.\n */\n has(param: string): boolean {\n this.init();\n return this.map!.has(param);\n }\n\n /**\n * Retrieves the first value for a parameter.\n * @param param The parameter name.\n * @returns The first value of the given parameter,\n * or `null` if the parameter is not present.\n */\n get(param: string): string|null {\n this.init();\n const res = this.map!.get(param);\n return !!res ? res[0] : null;\n }\n\n /**\n * Retrieves all values for a parameter.\n * @param param The parameter name.\n * @returns All values in a string array,\n * or `null` if the parameter not present.\n */\n getAll(param: string): string[]|null {\n this.init();\n return this.map!.get(param) || null;\n }\n\n /**\n * Retrieves all the parameters for this body.\n * @returns The parameter names in a string array.\n */\n keys(): string[] {\n this.init();\n return Array.from(this.map!.keys());\n }\n\n /**\n * Appends a new value to existing values for a parameter.\n * @param param The parameter name.\n * @param value The new value to add.\n * @return A new body with the appended value.\n */\n append(param: string, value: string|number|boolean): HttpParams {\n return this.clone({param, value, op: 'a'});\n }\n\n /**\n * Constructs a new body with appended values for the given parameter name.\n * @param params parameters and values\n * @return A new body with the new value.\n */\n appendAll(params: {[param: string]: string|number|boolean|ReadonlyArray<string|number|boolean>}):\n HttpParams {\n const updates: Update[] = [];\n Object.keys(params).forEach(param => {\n const value = params[param];\n if (Array.isArray(value)) {\n value.forEach(_value => {\n updates.push({param, value: _value, op: 'a'});\n });\n } else {\n updates.push({param, value: value as (string | number | boolean), op: 'a'});\n }\n });\n return this.clone(updates);\n }\n\n /**\n * Replaces the value for a parameter.\n * @param param The parameter name.\n * @param value The new value.\n * @return A new body with the new value.\n */\n set(param: string, value: string|number|boolean): HttpParams {\n return this.clone({param, value, op: 's'});\n }\n\n /**\n * Removes a given value or all values from a parameter.\n * @param param The parameter name.\n * @param value The value to remove, if provided.\n * @return A new body with the given value removed, or with all values\n * removed if no value is specified.\n */\n delete(param: string, value?: string|number|boolean): HttpParams {\n return this.clone({param, value, op: 'd'});\n }\n\n /**\n * Serializes the body to an encoded string, where key-value pairs (separated by `=`) are\n * separated by `&`s.\n */\n toString(): string {\n this.init();\n return this.keys()\n .map(key => {\n const eKey = this.encoder.encodeKey(key);\n // `a: ['1']` produces `'a=1'`\n // `b: []` produces `''`\n // `c: ['1', '2']` produces `'c=1&c=2'`\n return this.map!.get(key)!.map(value => eKey + '=' + this.encoder.encodeValue(value))\n .join('&');\n })\n // filter out empty values because `b: []` produces `''`\n // which results in `a=1&&c=1&c=2` instead of `a=1&c=1&c=2` if we don't\n .filter(param => param !== '')\n .join('&');\n }\n\n private clone(update: Update|Update[]): HttpParams {\n const clone = new HttpParams({encoder: this.encoder} as HttpParamsOptions);\n clone.cloneFrom = this.cloneFrom || this;\n clone.updates = (this.updates || []).concat(update);\n return clone;\n }\n\n private init() {\n if (this.map === null) {\n this.map = new Map<string, string[]>();\n }\n if (this.cloneFrom !== null) {\n this.cloneFrom.init();\n this.cloneFrom.keys().forEach(key => this.map!.set(key, this.cloneFrom!.map!.get(key)!));\n this.updates!.forEach(update => {\n switch (update.op) {\n case 'a':\n case 's':\n const base = (update.op === 'a' ? this.map!.get(update.param) : undefined) || [];\n base.push(valueToString(update.value!));\n this.map!.set(update.param, base);\n break;\n case 'd':\n if (update.value !== undefined) {\n let base = this.map!.get(update.param) || [];\n const idx = base.indexOf(valueToString(update.value));\n if (idx !== -1) {\n base.splice(idx, 1);\n }\n if (base.length > 0) {\n this.map!.set(update.param, base);\n } else {\n this.map!.delete(update.param);\n }\n } else {\n this.map!.delete(update.param);\n break;\n }\n }\n });\n this.cloneFrom = this.updates = null;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * A token used to manipulate and access values stored in `HttpContext`.\n *\n * @publicApi\n */\nexport class HttpContextToken<T> {\n constructor(public readonly defaultValue: () => T) {}\n}\n\n/**\n * Http context stores arbitrary user defined values and ensures type safety without\n * actually knowing the types. It is backed by a `Map` and guarantees that keys do not clash.\n *\n * This context is mutable and is shared between cloned requests unless explicitly specified.\n *\n * @usageNotes\n *\n * ### Usage Example\n *\n * ```typescript\n * // inside cache.interceptors.ts\n * export const IS_CACHE_ENABLED = new HttpContextToken<boolean>(() => false);\n *\n * export class CacheInterceptor implements HttpInterceptor {\n *\n * intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<HttpEvent<any>> {\n * if (req.context.get(IS_CACHE_ENABLED) === true) {\n * return ...;\n * }\n * return delegate.handle(req);\n * }\n * }\n *\n * // inside a service\n *\n * this.httpClient.get('/api/weather', {\n * context: new HttpContext().set(IS_CACHE_ENABLED, true)\n * }).subscribe(...);\n * ```\n *\n * @publicApi\n */\nexport class HttpContext {\n private readonly map = new Map<HttpContextToken<unknown>, unknown>();\n\n /**\n * Store a value in the context. If a value is already present it will be overwritten.\n *\n * @param token The reference to an instance of `HttpContextToken`.\n * @param value The value to store.\n *\n * @returns A reference to itself for easy chaining.\n */\n set<T>(token: HttpContextToken<T>, value: T): HttpContext {\n this.map.set(token, value);\n return this;\n }\n\n /**\n * Retrieve the value associated with the given token.\n *\n * @param token The reference to an instance of `HttpContextToken`.\n *\n * @returns The stored value or default if one is defined.\n */\n get<T>(token: HttpContextToken<T>): T {\n if (!this.map.has(token)) {\n this.map.set(token, token.defaultValue());\n }\n return this.map.get(token) as T;\n }\n\n /**\n * Delete the value associated with the given token.\n *\n * @param token The reference to an instance of `HttpContextToken`.\n *\n * @returns A reference to itself for easy chaining.\n */\n delete(token: HttpContextToken<unknown>): HttpContext {\n this.map.delete(token);\n return this;\n }\n\n /**\n * Checks for existence of a given token.\n *\n * @param token The reference to an instance of `HttpContextToken`.\n *\n * @returns True if the token exists, false otherwise.\n */\n has(token: HttpContextToken<unknown>): boolean {\n return this.map.has(token);\n }\n\n /**\n * @returns a list of tokens currently stored in the context.\n */\n keys(): IterableIterator<HttpContextToken<unknown>> {\n return this.map.keys();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {HttpContext} from './context';\nimport {HttpHeaders} from './headers';\nimport {HttpParams} from './params';\n\n\n/**\n * Construction interface for `HttpRequest`s.\n *\n * All values are optional and will override default values if provided.\n */\ninterface HttpRequestInit {\n headers?: HttpHeaders;\n context?: HttpContext;\n reportProgress?: boolean;\n params?: HttpParams;\n responseType?: 'arraybuffer'|'blob'|'json'|'text';\n withCredentials?: boolean;\n}\n\n/**\n * Determine whether the given HTTP method may include a body.\n */\nfunction mightHaveBody(method: string): boolean {\n switch (method) {\n case 'DELETE':\n case 'GET':\n case 'HEAD':\n case 'OPTIONS':\n case 'JSONP':\n return false;\n default:\n return true;\n }\n}\n\n/**\n * Safely assert whether the given value is an ArrayBuffer.\n *\n * In some execution environments ArrayBuffer is not defined.\n */\nfunction isArrayBuffer(value: any): value is ArrayBuffer {\n return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer;\n}\n\n/**\n * Safely assert whether the given value is a Blob.\n *\n * In some execution environments Blob is not defined.\n */\nfunction isBlob(value: any): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/**\n * Safely assert whether the given value is a FormData instance.\n *\n * In some execution environments FormData is not defined.\n */\nfunction isFormData(value: any): value is FormData {\n return typeof FormData !== 'undefined' && value instanceof FormData;\n}\n\n/**\n * Safely assert whether the given value is a URLSearchParams instance.\n *\n * In some execution environments URLSearchParams is not defined.\n */\nfunction isUrlSearchParams(value: any): value is URLSearchParams {\n return typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams;\n}\n\n/**\n * An outgoing HTTP request with an optional typed body.\n *\n * `HttpRequest` represents an outgoing request, including URL, method,\n * headers, body, and other request configuration options. Instances should be\n * assumed to be immutable. To modify a `HttpRequest`, the `clone`\n * method should be used.\n *\n * @publicApi\n */\nexport class HttpRequest<T> {\n /**\n * The request body, or `null` if one isn't set.\n *\n * Bodies are not enforced to be immutable, as they can include a reference to any\n * user-defined data type. However, interceptors should take care to preserve\n * idempotence by treating them as such.\n */\n readonly body: T|null = null;\n\n /**\n * Outgoing headers for this request.\n */\n // TODO(issue/24571): remove '!'.\n readonly headers!: HttpHeaders;\n\n /**\n * Shared and mutable context that can be used by interceptors\n */\n readonly context!: HttpContext;\n\n /**\n * Whether this request should be made in a way that exposes progress events.\n *\n * Progress events are expensive (change detection runs on each event) and so\n * they should only be requested if the consumer intends to monitor them.\n */\n readonly reportProgress: boolean = false;\n\n /**\n * Whether this request should be sent with outgoing credentials (cookies).\n */\n readonly withCredentials: boolean = false;\n\n /**\n * The expected response type of the server.\n *\n * This is used to parse the response appropriately before returning it to\n * the requestee.\n */\n readonly responseType: 'arraybuffer'|'blob'|'json'|'text' = 'json';\n\n /**\n * The outgoing HTTP request method.\n */\n readonly method: string;\n\n /**\n * Outgoing URL parameters.\n *\n * To pass a string representation of HTTP parameters in the URL-query-string format,\n * the `HttpParamsOptions`' `fromString` may be used. For example:\n *\n * ```\n * new HttpParams({fromString: 'angular=awesome'})\n * ```\n */\n // TODO(issue/24571): remove '!'.\n readonly params!: HttpParams;\n\n /**\n * The outgoing URL with all URL parameters set.\n */\n readonly urlWithParams: string;\n\n constructor(method: 'DELETE'|'GET'|'HEAD'|'JSONP'|'OPTIONS', url: string, init?: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n });\n constructor(method: 'POST'|'PUT'|'PATCH', url: string, body: T|null, init?: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n });\n constructor(method: string, url: string, body: T|null, init?: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n });\n constructor(\n method: string, readonly url: string, third?: T|{\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n }|null,\n fourth?: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n }) {\n this.method = method.toUpperCase();\n // Next, need to figure out which argument holds the HttpRequestInit\n // options, if any.\n let options: HttpRequestInit|undefined;\n\n // Check whether a body argument is expected. The only valid way to omit\n // the body argument is to use a known no-body method like GET.\n if (mightHaveBody(this.method) || !!fourth) {\n // Body is the third argument, options are the fourth.\n this.body = (third !== undefined) ? third as T : null;\n options = fourth;\n } else {\n // No body required, options are the third argument. The body stays null.\n options = third as HttpRequestInit;\n }\n\n // If options have been passed, interpret them.\n if (options) {\n // Normalize reportProgress and withCredentials.\n this.reportProgress = !!options.reportProgress;\n this.withCredentials = !!options.withCredentials;\n\n // Override default response type of 'json' if one is provided.\n if (!!options.responseType) {\n this.responseType = options.responseType;\n }\n\n // Override headers if they're provided.\n if (!!options.headers) {\n this.headers = options.headers;\n }\n\n if (!!options.context) {\n this.context = options.context;\n }\n\n if (!!options.params) {\n this.params = options.params;\n }\n }\n\n // If no headers have been passed in, construct a new HttpHeaders instance.\n if (!this.headers) {\n this.headers = new HttpHeaders();\n }\n\n // If no context have been passed in, construct a new HttpContext instance.\n if (!this.context) {\n this.context = new HttpContext();\n }\n\n // If no parameters have been passed in, construct a new HttpUrlEncodedParams instance.\n if (!this.params) {\n this.params = new HttpParams();\n this.urlWithParams = url;\n } else {\n // Encode the parameters to a string in preparation for inclusion in the URL.\n const params = this.params.toString();\n if (params.length === 0) {\n // No parameters, the visible URL is just the URL given at creation time.\n this.urlWithParams = url;\n } else {\n // Does the URL already have query parameters? Look for '?'.\n const qIdx = url.indexOf('?');\n // There are 3 cases to handle:\n // 1) No existing parameters -> append '?' followed by params.\n // 2) '?' exists and is followed by existing query string ->\n // append '&' followed by params.\n // 3) '?' exists at the end of the url -> append params directly.\n // This basically amounts to determining the character, if any, with\n // which to join the URL and parameters.\n const sep: string = qIdx === -1 ? '?' : (qIdx < url.length - 1 ? '&' : '');\n this.urlWithParams = url + sep + params;\n }\n }\n }\n\n /**\n * Transform the free-form body into a serialized format suitable for\n * transmission to the server.\n */\n serializeBody(): ArrayBuffer|Blob|FormData|string|null {\n // If no body is present, no need to serialize it.\n if (this.body === null) {\n return null;\n }\n // Check whether the body is already in a serialized form. If so,\n // it can just be returned directly.\n if (isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) ||\n isUrlSearchParams(this.body) || typeof this.body === 'string') {\n return this.body;\n }\n // Check whether the body is an instance of HttpUrlEncodedParams.\n if (this.body instanceof HttpParams) {\n return this.body.toString();\n }\n // Check whether the body is an object or array, and serialize with JSON if so.\n if (typeof this.body === 'object' || typeof this.body === 'boolean' ||\n Array.isArray(this.body)) {\n return JSON.stringify(this.body);\n }\n // Fall back on toString() for everything else.\n return (this.body as any).toString();\n }\n\n /**\n * Examine the body and attempt to infer an appropriate MIME type\n * for it.\n *\n * If no such type can be inferred, this method will return `null`.\n */\n detectContentTypeHeader(): string|null {\n // An empty body has no content type.\n if (this.body === null) {\n return null;\n }\n // FormData bodies rely on the browser's content type assignment.\n if (isFormData(this.body)) {\n return null;\n }\n // Blobs usually have their own content type. If it doesn't, then\n // no type can be inferred.\n if (isBlob(this.body)) {\n return this.body.type || null;\n }\n // Array buffers have unknown contents and thus no type can be inferred.\n if (isArrayBuffer(this.body)) {\n return null;\n }\n // Technically, strings could be a form of JSON data, but it's safe enough\n // to assume they're plain strings.\n if (typeof this.body === 'string') {\n return 'text/plain';\n }\n // `HttpUrlEncodedParams` has its own content-type.\n if (this.body instanceof HttpParams) {\n return 'application/x-www-form-urlencoded;charset=UTF-8';\n }\n // Arrays, objects, boolean and numbers will be encoded as JSON.\n if (typeof this.body === 'object' || typeof this.body === 'number' ||\n typeof this.body === 'boolean') {\n return 'application/json';\n }\n // No type could be inferred.\n return null;\n }\n\n clone(): HttpRequest<T>;\n clone(update: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n body?: T|null,\n method?: string,\n url?: string,\n setHeaders?: {[name: string]: string|string[]},\n setParams?: {[param: string]: string},\n }): HttpRequest<T>;\n clone<V>(update: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n body?: V|null,\n method?: string,\n url?: string,\n setHeaders?: {[name: string]: string|string[]},\n setParams?: {[param: string]: string},\n }): HttpRequest<V>;\n clone(update: {\n headers?: HttpHeaders,\n context?: HttpContext,\n reportProgress?: boolean,\n params?: HttpParams,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n body?: any|null,\n method?: string,\n url?: string,\n setHeaders?: {[name: string]: string|string[]},\n setParams?: {[param: string]: string};\n } = {}): HttpRequest<any> {\n // For method, url, and responseType, take the current value unless\n // it is overridden in the update hash.\n const method = update.method || this.method;\n const url = update.url || this.url;\n const responseType = update.responseType || this.responseType;\n\n // The body is somewhat special - a `null` value in update.body means\n // whatever current body is present is being overridden with an empty\n // body, whereas an `undefined` value in update.body implies no\n // override.\n const body = (update.body !== undefined) ? update.body : this.body;\n\n // Carefully handle the boolean options to differentiate between\n // `false` and `undefined` in the update args.\n const withCredentials =\n (update.withCredentials !== undefined) ? update.withCredentials : this.withCredentials;\n const reportProgress =\n (update.reportProgress !== undefined) ? update.reportProgress : this.reportProgress;\n\n // Headers and params may be appended to if `setHeaders` or\n // `setParams` are used.\n let headers = update.headers || this.headers;\n let params = update.params || this.params;\n\n // Pass on context if needed\n const context = update.context ?? this.context;\n\n // Check whether the caller has asked to add headers.\n if (update.setHeaders !== undefined) {\n // Set every requested header.\n headers =\n Object.keys(update.setHeaders)\n .reduce((headers, name) => headers.set(name, update.setHeaders![name]), headers);\n }\n\n // Check whether the caller has asked to set params.\n if (update.setParams) {\n // Set every requested param.\n params = Object.keys(update.setParams)\n .reduce((params, param) => params.set(param, update.setParams![param]), params);\n }\n\n // Finally, construct the new HttpRequest using the pieces from above.\n return new HttpRequest(method, url, body, {\n params,\n headers,\n context,\n reportProgress,\n responseType,\n withCredentials,\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {HttpHeaders} from './headers';\n\n/**\n * Type enumeration for the different kinds of `HttpEvent`.\n *\n * @publicApi\n */\nexport enum HttpEventType {\n /**\n * The request was sent out over the wire.\n */\n Sent,\n\n /**\n * An upload progress event was received.\n */\n UploadProgress,\n\n /**\n * The response status code and headers were received.\n */\n ResponseHeader,\n\n /**\n * A download progress event was received.\n */\n DownloadProgress,\n\n /**\n * The full response including the body was received.\n */\n Response,\n\n /**\n * A custom event from an interceptor or a backend.\n */\n User,\n}\n\n/**\n * Base interface for progress events.\n *\n * @publicApi\n */\nexport interface HttpProgressEvent {\n /**\n * Progress event type is either upload or download.\n */\n type: HttpEventType.DownloadProgress|HttpEventType.UploadProgress;\n\n /**\n * Number of bytes uploaded or downloaded.\n */\n loaded: number;\n\n /**\n * Total number of bytes to upload or download. Depending on the request or\n * response, this may not be computable and thus may not be present.\n */\n total?: number;\n}\n\n/**\n * A download progress event.\n *\n * @publicApi\n */\nexport interface HttpDownloadProgressEvent extends HttpProgressEvent {\n type: HttpEventType.DownloadProgress;\n\n /**\n * The partial response body as downloaded so far.\n *\n * Only present if the responseType was `text`.\n */\n partialText?: string;\n}\n\n/**\n * An upload progress event.\n *\n * @publicApi\n */\nexport interface HttpUploadProgressEvent extends HttpProgressEvent {\n type: HttpEventType.UploadProgress;\n}\n\n/**\n * An event indicating that the request was sent to the server. Useful\n * when a request may be retried multiple times, to distinguish between\n * retries on the final event stream.\n *\n * @publicApi\n */\nexport interface HttpSentEvent {\n type: HttpEventType.Sent;\n}\n\n/**\n * A user-defined event.\n *\n * Grouping all custom events under this type ensures they will be handled\n * and forwarded by all implementations of interceptors.\n *\n * @publicApi\n */\nexport interface HttpUserEvent<T> {\n type: HttpEventType.User;\n}\n\n/**\n * An error that represents a failed attempt to JSON.parse text coming back\n * from the server.\n *\n * It bundles the Error object with the actual response body that failed to parse.\n *\n *\n */\nexport interface HttpJsonParseError {\n error: Error;\n text: string;\n}\n\n/**\n * Union type for all possible events on the response stream.\n *\n * Typed according to the expected type of the response.\n *\n * @publicApi\n */\nexport type HttpEvent<T> =\n HttpSentEvent|HttpHeaderResponse|HttpResponse<T>|HttpProgressEvent|HttpUserEvent<T>;\n\n/**\n * Base class for both `HttpResponse` and `HttpHeaderResponse`.\n *\n * @publicApi\n */\nexport abstract class HttpResponseBase {\n /**\n * All response headers.\n */\n readonly headers: HttpHeaders;\n\n /**\n * Response status code.\n */\n readonly status: number;\n\n /**\n * Textual description of response status code, defaults to OK.\n *\n * Do not depend on this.\n */\n readonly statusText: string;\n\n /**\n * URL of the resource retrieved, or null if not available.\n */\n readonly url: string|null;\n\n /**\n * Whether the status code falls in the 2xx range.\n */\n readonly ok: boolean;\n\n /**\n * Type of the response, narrowed to either the full response or the header.\n */\n // TODO(issue/24571): remove '!'.\n readonly type!: HttpEventType.Response|HttpEventType.ResponseHeader;\n\n /**\n * Super-constructor for all responses.\n *\n * The single parameter accepted is an initialization hash. Any properties\n * of the response passed there will override the default values.\n */\n constructor(\n init: {\n headers?: HttpHeaders,\n status?: number,\n statusText?: string,\n url?: string,\n },\n defaultStatus: number = HttpStatusCode.Ok, defaultStatusText: string = 'OK') {\n // If the hash has values passed, use them to initialize the response.\n // Otherwise use the default values.\n this.headers = init.headers || new HttpHeaders();\n this.status = init.status !== undefined ? init.status : defaultStatus;\n this.statusText = init.statusText || defaultStatusText;\n this.url = init.url || null;\n\n // Cache the ok value to avoid defining a getter.\n this.ok = this.status >= 200 && this.status < 300;\n }\n}\n\n/**\n * A partial HTTP response which only includes the status and header data,\n * but no response body.\n *\n * `HttpHeaderResponse` is a `HttpEvent` available on the response\n * event stream, only when progress events are requested.\n *\n * @publicApi\n */\nexport class HttpHeaderResponse extends HttpResponseBase {\n /**\n * Create a new `HttpHeaderResponse` with the given parameters.\n */\n constructor(init: {\n headers?: HttpHeaders,\n status?: number,\n statusText?: string,\n url?: string,\n } = {}) {\n super(init);\n }\n\n override readonly type: HttpEventType.ResponseHeader = HttpEventType.ResponseHeader;\n\n /**\n * Copy this `HttpHeaderResponse`, overriding its contents with the\n * given parameter hash.\n */\n clone(update: {headers?: HttpHeaders; status?: number; statusText?: string; url?: string;} = {}):\n HttpHeaderResponse {\n // Perform a straightforward initialization of the new HttpHeaderResponse,\n // overriding the current parameters with new ones if given.\n return new HttpHeaderResponse({\n headers: update.headers || this.headers,\n status: update.status !== undefined ? update.status : this.status,\n statusText: update.statusText || this.statusText,\n url: update.url || this.url || undefined,\n });\n }\n}\n\n/**\n * A full HTTP response, including a typed response body (which may be `null`\n * if one was not returned).\n *\n * `HttpResponse` is a `HttpEvent` available on the response event\n * stream.\n *\n * @publicApi\n */\nexport class HttpResponse<T> extends HttpResponseBase {\n /**\n * The response body, or `null` if one was not returned.\n */\n readonly body: T|null;\n\n /**\n * Construct a new `HttpResponse`.\n */\n constructor(init: {\n body?: T|null,\n headers?: HttpHeaders;\n status?: number;\n statusText?: string;\n url?: string;\n } = {}) {\n super(init);\n this.body = init.body !== undefined ? init.body : null;\n }\n\n override readonly type: HttpEventType.Response = HttpEventType.Response;\n\n clone(): HttpResponse<T>;\n clone(update: {headers?: HttpHeaders; status?: number; statusText?: string; url?: string;}):\n HttpResponse<T>;\n clone<V>(update: {\n body?: V|null,\n headers?: HttpHeaders;\n status?: number;\n statusText?: string;\n url?: string;\n }): HttpResponse<V>;\n clone(update: {\n body?: any|null;\n headers?: HttpHeaders;\n status?: number;\n statusText?: string;\n url?: string;\n } = {}): HttpResponse<any> {\n return new HttpResponse<any>({\n body: (update.body !== undefined) ? update.body : this.body,\n headers: update.headers || this.headers,\n status: (update.status !== undefined) ? update.status : this.status,\n statusText: update.statusText || this.statusText,\n url: update.url || this.url || undefined,\n });\n }\n}\n\n/**\n * A response that represents an error or failure, either from a\n * non-successful HTTP status, an error while executing the request,\n * or some other failure which occurred during the parsing of the response.\n *\n * Any error returned on the `Observable` response stream will be\n * wrapped in an `HttpErrorResponse` to provide additional context about\n * the state of the HTTP layer when the error occurred. The error property\n * will contain either a wrapped Error object or the error response returned\n * from the server.\n *\n * @publicApi\n */\nexport class HttpErrorResponse extends HttpResponseBase implements Error {\n readonly name = 'HttpErrorResponse';\n readonly message: string;\n readonly error: any|null;\n\n /**\n * Errors are never okay, even when the status code is in the 2xx success range.\n */\n override readonly ok = false;\n\n constructor(init: {\n error?: any;\n headers?: HttpHeaders;\n status?: number;\n statusText?: string;\n url?: string;\n }) {\n // Initialize with a default status of 0 / Unknown Error.\n super(init, 0, 'Unknown Error');\n\n // If the response was successful, then this was a parse error. Otherwise, it was\n // a protocol-level failure of some sort. Either the request failed in transit\n // or the server returned an unsuccessful status code.\n if (this.status >= 200 && this.status < 300) {\n this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`;\n } else {\n this.message = `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${\n init.statusText}`;\n }\n this.error = init.error || null;\n }\n}\n\n/**\n * Http status codes.\n * As per https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\n * @publicApi\n */\nexport const enum HttpStatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Processing = 102,\n EarlyHints = 103,\n\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultiStatus = 207,\n AlreadyReported = 208,\n ImUsed = 226,\n\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n Unused = 306,\n TemporaryRedirect = 307,\n PermanentRedirect = 308,\n\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n PayloadTooLarge = 413,\n UriTooLong = 414,\n UnsupportedMediaType = 415,\n RangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n MisdirectedRequest = 421,\n UnprocessableEntity = 422,\n Locked = 423,\n FailedDependency = 424,\n TooEarly = 425,\n UpgradeRequired = 426,\n PreconditionRequired = 428,\n TooManyRequests = 429,\n RequestHeaderFieldsTooLarge = 431,\n UnavailableForLegalReasons = 451,\n\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n VariantAlsoNegotiates = 506,\n InsufficientStorage = 507,\n LoopDetected = 508,\n NotExtended = 510,\n NetworkAuthenticationRequired = 511\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable} from '@angular/core';\nimport {Observable, of} from 'rxjs';\nimport {concatMap, filter, map} from 'rxjs/operators';\n\nimport {HttpHandler} from './backend';\nimport {HttpContext} from './context';\nimport {HttpHeaders} from './headers';\nimport {HttpParams, HttpParamsOptions} from './params';\nimport {HttpRequest} from './request';\nimport {HttpEvent, HttpResponse} from './response';\n\n\n/**\n * Constructs an instance of `HttpRequestOptions<T>` from a source `HttpMethodOptions` and\n * the given `body`. This function clones the object and adds the body.\n *\n * Note that the `responseType` *options* value is a String that identifies the\n * single data type of the response.\n * A single overload version of the method handles each response type.\n * The value of `responseType` cannot be a union, as the combined signature could imply.\n *\n */\nfunction addBody<T>(\n options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n },\n body: T|null): any {\n return {\n body,\n headers: options.headers,\n context: options.context,\n observe: options.observe,\n params: options.params,\n reportProgress: options.reportProgress,\n responseType: options.responseType,\n withCredentials: options.withCredentials,\n };\n}\n\n/**\n * Performs HTTP requests.\n * This service is available as an injectable class, with methods to perform HTTP requests.\n * Each request method has multiple signatures, and the return type varies based on\n * the signature that is called (mainly the values of `observe` and `responseType`).\n *\n * Note that the `responseType` *options* value is a String that identifies the\n * single data type of the response.\n * A single overload version of the method handles each response type.\n * The value of `responseType` cannot be a union, as the combined signature could imply.\n\n *\n * @usageNotes\n * Sample HTTP requests for the [Tour of Heroes](/tutorial/tour-of-heroes/toh-pt0) application.\n *\n * ### HTTP Request Example\n *\n * ```\n * // GET heroes whose name contains search term\n * searchHeroes(term: string): observable<Hero[]>{\n *\n * const params = new HttpParams({fromString: 'name=term'});\n * return this.httpClient.request('GET', this.heroesUrl, {responseType:'json', params});\n * }\n * ```\n *\n * Alternatively, the parameter string can be used without invoking HttpParams\n * by directly joining to the URL.\n * ```\n * this.httpClient.request('GET', this.heroesUrl + '?' + 'name=term', {responseType:'json'});\n * ```\n *\n *\n * ### JSONP Example\n * ```\n * requestJsonp(url, callback = 'callback') {\n * return this.httpClient.jsonp(this.heroesURL, callback);\n * }\n * ```\n *\n * ### PATCH Example\n * ```\n * // PATCH one of the heroes' name\n * patchHero (id: number, heroName: string): Observable<{}> {\n * const url = `${this.heroesUrl}/${id}`; // PATCH api/heroes/42\n * return this.httpClient.patch(url, {name: heroName}, httpOptions)\n * .pipe(catchError(this.handleError('patchHero')));\n * }\n * ```\n *\n * @see [HTTP Guide](guide/http)\n * @see [HTTP Request](api/common/http/HttpRequest)\n *\n * @publicApi\n */\n@Injectable()\nexport class HttpClient {\n constructor(private handler: HttpHandler) {}\n\n /**\n * Sends an `HttpRequest` and returns a stream of `HttpEvent`s.\n *\n * @return An `Observable` of the response, with the response body as a stream of `HttpEvent`s.\n */\n request<R>(req: HttpRequest<any>): Observable<HttpEvent<R>>;\n\n /**\n * Constructs a request that interprets the body as an `ArrayBuffer` and returns the response in\n * an `ArrayBuffer`.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a request that interprets the body as a blob and returns\n * the response as a blob.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type `Blob`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a request that interprets the body as a text string and\n * returns a string value.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a request that interprets the body as an `ArrayBuffer` and returns the\n * the full event stream.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as an array of `HttpEvent`s for\n * the request.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n observe: 'events',\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a request that interprets the body as a `Blob` and returns\n * the full event stream.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body of type `Blob`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a request which interprets the body as a text string and returns the full event\n * stream.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body of type string.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object and returns the full\n * event stream.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body of type `Object`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n reportProgress?: boolean, observe: 'events',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<any>>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object and returns the full\n * event stream.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body of type `R`.\n */\n request<R>(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n reportProgress?: boolean, observe: 'events',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<R>>;\n\n /**\n * Constructs a request which interprets the body as an `ArrayBuffer`\n * and returns the full `HttpResponse`.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body as an `ArrayBuffer`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a request which interprets the body as a `Blob` and returns the full `HttpResponse`.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of type `Blob`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a request which interprets the body as a text stream and returns the full\n * `HttpResponse`.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the HTTP response, with the response body of type string.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object and returns the full\n * `HttpResponse`.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse`,\n * with the response body of type `Object`.\n */\n request(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n reportProgress?: boolean, observe: 'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object and returns\n * the full `HttpResponse` with the response body in the requested type.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse`, with the response body of type `R`.\n */\n request<R>(method: string, url: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n reportProgress?: boolean, observe: 'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<R>>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object and returns the full\n * `HttpResponse` as a JavaScript object.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of type `Object`.\n */\n request(method: string, url: string, options?: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n reportProgress?: boolean,\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a request which interprets the body as a JavaScript object\n * with the response body of the requested type.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of type `R`.\n */\n request<R>(method: string, url: string, options?: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n responseType?: 'json',\n reportProgress?: boolean,\n withCredentials?: boolean,\n }): Observable<R>;\n\n /**\n * Constructs a request where response type and requested observable are not known statically.\n *\n * @param method The HTTP method.\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the requested response, with body of type `any`.\n */\n request(method: string, url: string, options?: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n observe?: 'body'|'events'|'response',\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n }): Observable<any>;\n\n /**\n * Constructs an observable for a generic HTTP request that, when subscribed,\n * fires the request through the chain of registered interceptors and on to the\n * server.\n *\n * You can pass an `HttpRequest` directly as the only parameter. In this case,\n * the call returns an observable of the raw `HttpEvent` stream.\n *\n * Alternatively you can pass an HTTP method as the first parameter,\n * a URL string as the second, and an options hash containing the request body as the third.\n * See `addBody()`. In this case, the specified `responseType` and `observe` options determine the\n * type of returned observable.\n * * The `responseType` value determines how a successful response body is parsed.\n * * If `responseType` is the default `json`, you can pass a type interface for the resulting\n * object as a type parameter to the call.\n *\n * The `observe` value determines the return type, according to what you are interested in\n * observing.\n * * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including\n * progress events by default.\n * * An `observe` value of response returns an observable of `HttpResponse<T>`,\n * where the `T` parameter depends on the `responseType` and any optionally provided type\n * parameter.\n * * An `observe` value of body returns an observable of `<T>` with the same `T` body type.\n *\n */\n request(first: string|HttpRequest<any>, url?: string, options: {\n body?: any,\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n let req: HttpRequest<any>;\n // First, check whether the primary argument is an instance of `HttpRequest`.\n if (first instanceof HttpRequest) {\n // It is. The other arguments must be undefined (per the signatures) and can be\n // ignored.\n req = first;\n } else {\n // It's a string, so it represents a URL. Construct a request based on it,\n // and incorporate the remaining arguments (assuming `GET` unless a method is\n // provided.\n\n // Figure out the headers.\n let headers: HttpHeaders|undefined = undefined;\n if (options.headers instanceof HttpHeaders) {\n headers = options.headers;\n } else {\n headers = new HttpHeaders(options.headers);\n }\n\n // Sort out parameters.\n let params: HttpParams|undefined = undefined;\n if (!!options.params) {\n if (options.params instanceof HttpParams) {\n params = options.params;\n } else {\n params = new HttpParams({fromObject: options.params} as HttpParamsOptions);\n }\n }\n\n // Construct the request.\n req = new HttpRequest(first, url!, (options.body !== undefined ? options.body : null), {\n headers,\n context: options.context,\n params,\n reportProgress: options.reportProgress,\n // By default, JSON is assumed to be returned for all calls.\n responseType: options.responseType || 'json',\n withCredentials: options.withCredentials,\n });\n }\n\n // Start with an Observable.of() the initial request, and run the handler (which\n // includes all interceptors) inside a concatMap(). This way, the handler runs\n // inside an Observable chain, which causes interceptors to be re-run on every\n // subscription (this also makes retries re-run the handler, including interceptors).\n const events$: Observable<HttpEvent<any>> =\n of(req).pipe(concatMap((req: HttpRequest<any>) => this.handler.handle(req)));\n\n // If coming via the API signature which accepts a previously constructed HttpRequest,\n // the only option is to get the event stream. Otherwise, return the event stream if\n // that is what was requested.\n if (first instanceof HttpRequest || options.observe === 'events') {\n return events$;\n }\n\n // The requested stream contains either the full response or the body. In either\n // case, the first step is to filter the event stream to extract a stream of\n // responses(s).\n const res$: Observable<HttpResponse<any>> = <Observable<HttpResponse<any>>>events$.pipe(\n filter((event: HttpEvent<any>) => event instanceof HttpResponse));\n\n // Decide which stream to return.\n switch (options.observe || 'body') {\n case 'body':\n // The requested stream is the body. Map the response stream to the response\n // body. This could be done more simply, but a misbehaving interceptor might\n // transform the response body into a different format and ignore the requested\n // responseType. Guard against this by validating that the response is of the\n // requested type.\n switch (req.responseType) {\n case 'arraybuffer':\n return res$.pipe(map((res: HttpResponse<any>) => {\n // Validate that the body is an ArrayBuffer.\n if (res.body !== null && !(res.body instanceof ArrayBuffer)) {\n throw new Error('Response is not an ArrayBuffer.');\n }\n return res.body;\n }));\n case 'blob':\n return res$.pipe(map((res: HttpResponse<any>) => {\n // Validate that the body is a Blob.\n if (res.body !== null && !(res.body instanceof Blob)) {\n throw new Error('Response is not a Blob.');\n }\n return res.body;\n }));\n case 'text':\n return res$.pipe(map((res: HttpResponse<any>) => {\n // Validate that the body is a string.\n if (res.body !== null && typeof res.body !== 'string') {\n throw new Error('Response is not a string.');\n }\n return res.body;\n }));\n case 'json':\n default:\n // No validation needed for JSON responses, as they can be of any type.\n return res$.pipe(map((res: HttpResponse<any>) => res.body));\n }\n case 'response':\n // The response stream was requested directly, so return it.\n return res$;\n default:\n // Guard against new future observe types being added.\n throw new Error(`Unreachable: unhandled observe type ${options.observe}}`);\n }\n }\n\n /**\n * Constructs a `DELETE` request that interprets the body as an `ArrayBuffer`\n * and returns the response as an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response body as an `ArrayBuffer`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<ArrayBuffer>;\n\n\n /**\n * Constructs a `DELETE` request that interprets the body as a `Blob` and returns\n * the response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response body as a `Blob`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<Blob>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as a text string and returns\n * a string.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<string>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as an `ArrayBuffer`\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with response body as an `ArrayBuffer`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n body?: any|null\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as a `Blob`\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request, with the response body as a\n * `Blob`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as a text string\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with the response\n * body of type string.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with response body of\n * type `Object`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a `DELETE`request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request, with a response\n * body in the requested type.\n */\n delete<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | (string | number | boolean)[]},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as an `ArrayBuffer` and returns\n * the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse`, with the response body as an `ArrayBuffer`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as a `Blob` and returns the full\n * `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of type `Blob`.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as a text stream and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse`, with the response body of type string.\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `DELETE` request the interprets the body as a JavaScript object and returns\n * the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of type `Object`.\n *\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with the response body of the requested type.\n */\n delete<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<HttpResponse<T>>;\n\n /**\n * Constructs a `DELETE` request that interprets the body as JSON and\n * returns the response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type `Object`.\n */\n delete(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<Object>;\n\n /**\n * Constructs a DELETE request that interprets the body as JSON and returns\n * the response in a given type.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with response body in the requested type.\n */\n delete<T>(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n body?: any|null,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `DELETE` request to execute on the server. See the individual overloads for\n * details on the return type.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n */\n delete(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n body?: any|null,\n } = {}): Observable<any> {\n return this.request<any>('DELETE', url, options as any);\n }\n\n\n /**\n * Constructs a `GET` request that interprets the body as an `ArrayBuffer` and returns the\n * response in an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a `GET` request that interprets the body as a `Blob`\n * and returns the response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a `GET` request that interprets the body as a text string\n * and returns the response as a string value.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a `GET` request that interprets the body as an `ArrayBuffer` and returns\n * the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with the response\n * body as an `ArrayBuffer`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `GET` request that interprets the body as a `Blob` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `GET` request that interprets the body as a text string and returns\n * the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type `Object`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON and returns the full\n * event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with a response body in the requested type.\n */\n get<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a `GET` request that interprets the body as an `ArrayBuffer` and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as an `ArrayBuffer`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `GET` request that interprets the body as a `Blob` and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a `Blob`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `GET` request that interprets the body as a text stream and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body of type string.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse`,\n * with the response body of type `Object`.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the full `HttpResponse` for the request,\n * with a response body in the requested type.\n */\n get<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON and\n * returns the response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n *\n * @return An `Observable` of the response body as a JavaScript object.\n */\n get(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a `GET` request that interprets the body as JSON and returns\n * the response body in a given type.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse`, with a response body in the requested type.\n */\n get<T>(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `GET` request to execute on the server. See the individual overloads for\n * details on the return type.\n */\n get(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('GET', url, options as any);\n }\n\n\n /**\n * Constructs a `HEAD` request that interprets the body as an `ArrayBuffer` and\n * returns the response as an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as a `Blob` and returns\n * the response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as a text string and returns the response\n * as a string value.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as an `ArrayBuffer`\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as an `ArrayBuffer`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as a `Blob` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as a `Blob`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as a text string\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with the response body of type\n * string.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as JSON\n * and returns the full HTTP event stream.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with a response body of\n * type `Object`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as JSON and\n * returns the full event stream.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with a response body in the requested type.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n */\n head<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as an `ArrayBuffer`\n * and returns the full HTTP response.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as an `ArrayBuffer`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as a `Blob` and returns\n * the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a blob.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as text stream\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body of type string.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as JSON and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body of type `Object`.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body of the requested type.\n */\n head<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n\n * Constructs a `HEAD` request that interprets the body as JSON and\n * returns the response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the response, with the response body as an object parsed from JSON.\n */\n head(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a `HEAD` request that interprets the body as JSON and returns\n * the response in a given type.\n *\n * @param url The endpoint URL.\n * @param options The HTTP options to send with the request.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body of the given type.\n */\n head<T>(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `HEAD` request to execute on the server. The `HEAD` method returns\n * meta information about the resource without transferring the\n * resource itself. See the individual overloads for\n * details on the return type.\n */\n head(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('HEAD', url, options as any);\n }\n\n /**\n * Constructs a `JSONP` request for the given URL and name of the callback parameter.\n *\n * @param url The resource URL.\n * @param callbackParam The callback function name.\n *\n * @return An `Observable` of the response object, with response body as an object.\n */\n jsonp(url: string, callbackParam: string): Observable<Object>;\n\n /**\n * Constructs a `JSONP` request for the given URL and name of the callback parameter.\n *\n * @param url The resource URL.\n * @param callbackParam The callback function name.\n *\n * You must install a suitable interceptor, such as one provided by `HttpClientJsonpModule`.\n * If no such interceptor is reached,\n * then the `JSONP` request can be rejected by the configured backend.\n *\n * @return An `Observable` of the response object, with response body in the requested type.\n */\n jsonp<T>(url: string, callbackParam: string): Observable<T>;\n\n /**\n * Constructs an `Observable` that, when subscribed, causes a request with the special method\n * `JSONP` to be dispatched via the interceptor pipeline.\n * The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain\n * API endpoints that don't support newer,\n * and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol.\n * JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the\n * requests even if the API endpoint is not located on the same domain (origin) as the client-side\n * application making the request.\n * The endpoint API must support JSONP callback for JSONP requests to work.\n * The resource API returns the JSON response wrapped in a callback function.\n * You can pass the callback function name as one of the query parameters.\n * Note that JSONP requests can only be used with `GET` requests.\n *\n * @param url The resource URL.\n * @param callbackParam The callback function name.\n *\n */\n jsonp<T>(url: string, callbackParam: string): Observable<T> {\n return this.request<any>('JSONP', url, {\n params: new HttpParams().append(callbackParam, 'JSONP_CALLBACK'),\n observe: 'body',\n responseType: 'json',\n });\n }\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as an\n * `ArrayBuffer` and returns the response as an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as a `Blob` and returns\n * the response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as a text string and\n * returns a string value.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body of type string.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as an `ArrayBuffer`\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as an `ArrayBuffer`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as a `Blob` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as a `Blob`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as a text string\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with the response body of type string.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request with the response\n * body of type `Object`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as JSON and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with a response body in the requested type.\n */\n options<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as an `ArrayBuffer`\n * and returns the full HTTP response.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as an `ArrayBuffer`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as a `Blob`\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a `Blob`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as text stream\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body of type string.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body of type `Object`.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as JSON and\n * returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body in the requested type.\n */\n options<T>(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n\n * Constructs an `OPTIONS` request that interprets the body as JSON and returns the\n * response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as an object parsed from JSON.\n */\n options(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs an `OPTIONS` request that interprets the body as JSON and returns the\n * response in a given type.\n *\n * @param url The endpoint URL.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse`, with a response body of the given type.\n */\n options<T>(url: string, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an `Observable` that, when subscribed, causes the configured\n * `OPTIONS` request to execute on the server. This method allows the client\n * to determine the supported HTTP methods and other capabilities of an endpoint,\n * without implying a resource action. See the individual overloads for\n * details on the return type.\n */\n options(url: string, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('OPTIONS', url, options as any);\n }\n\n /**\n * Constructs a `PATCH` request that interprets the body as an `ArrayBuffer` and returns\n * the response as an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a `Blob` and returns the response\n * as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a text string and\n * returns the response as a string value.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with a response body of type string.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as an `ArrayBuffer` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with the response body as an `ArrayBuffer`.\n */\n\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a `Blob`\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request, with the\n * response body as `Blob`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a text string and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request, with a\n * response body of type string.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with a response body of type `Object`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as JSON\n * and returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of all the `HttpEvent`s for the request,\n * with a response body in the requested type.\n */\n patch<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as an `ArrayBuffer`\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as an `ArrayBuffer`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a `Blob` and returns the full\n * `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a `Blob`.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as a text stream and returns the\n * full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body of type string.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body in the requested type.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body in the given type.\n */\n patch<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n\n * Constructs a `PATCH` request that interprets the body as JSON and\n * returns the response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as an object parsed from JSON.\n */\n patch(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a `PATCH` request that interprets the body as JSON\n * and returns the response in a given type.\n *\n * @param url The endpoint URL.\n * @param body The resources to edit.\n * @param options HTTP options.\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body in the given type.\n */\n patch<T>(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `PATCH` request to execute on the server. See the individual overloads for\n * details on the return type.\n */\n patch(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('PATCH', url, addBody(options, body));\n }\n\n /**\n * Constructs a `POST` request that interprets the body as an `ArrayBuffer` and returns\n * an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options.\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a `POST` request that interprets the body as a `Blob` and returns the\n * response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a `POST` request that interprets the body as a text string and\n * returns the response as a string value.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with a response body of type string.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a `POST` request that interprets the body as an `ArrayBuffer` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as an `ArrayBuffer`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `POST` request that interprets the body as a `Blob`\n * and returns the response in an observable of the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with the response body as `Blob`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `POST` request that interprets the body as a text string and returns the full\n * event stream.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with a response body of type string.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a POST request that interprets the body as JSON and returns the full\n * event stream.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with a response body of type `Object`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a POST request that interprets the body as JSON and returns the full\n * event stream.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with a response body in the requested type.\n */\n post<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a POST request that interprets the body as an `ArrayBuffer`\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with the response body as an\n * `ArrayBuffer`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `POST` request that interprets the body as a `Blob` and returns the full\n * `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a `Blob`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `POST` request that interprets the body as a text stream and returns\n * the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body of type string.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `POST` request that interprets the body as JSON\n * and returns the full `HttpResponse`.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with a response body of type\n * `Object`.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `POST` request that interprets the body as JSON and returns the\n * full `HttpResponse`.\n *\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with a response body in the\n * requested type.\n */\n post<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n * Constructs a `POST` request that interprets the body as JSON\n * and returns the response body as an object parsed from JSON.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with the response body as an object parsed from JSON.\n */\n post(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a `POST` request that interprets the body as JSON\n * and returns an observable of the response.\n *\n * @param url The endpoint URL.\n * @param body The content to replace with.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with a response body in the\n * requested type.\n */\n post<T>(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `POST` request to execute on the server. The server responds with the location of\n * the replaced resource. See the individual overloads for\n * details on the return type.\n */\n post(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('POST', url, addBody(options, body));\n }\n\n /**\n * Constructs a `PUT` request that interprets the body as an `ArrayBuffer` and returns the\n * response as an `ArrayBuffer`.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with the response body as an `ArrayBuffer`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<ArrayBuffer>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a `Blob` and returns\n * the response as a `Blob`.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with the response body as a `Blob`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<Blob>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a text string and\n * returns the response as a string value.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the response, with a response body of type string.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<string>;\n\n /**\n * Constructs a `PUT` request that interprets the body as an `ArrayBuffer` and\n * returns the full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as an `ArrayBuffer`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpEvent<ArrayBuffer>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a `Blob` and returns the full event\n * stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with the response body as a `Blob`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Blob>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a text string and returns the full event\n * stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with a response body\n * of type string.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpEvent<string>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as JSON and returns the full\n * event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request, with a response body of\n * type `Object`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<Object>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as JSON and returns the\n * full event stream.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of all `HttpEvent`s for the request,\n * with a response body in the requested type.\n */\n put<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'events',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpEvent<T>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as an\n * `ArrayBuffer` and returns an observable of the full HTTP response.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with the response body as an\n * `ArrayBuffer`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'arraybuffer',\n withCredentials?: boolean,\n }): Observable<HttpResponse<ArrayBuffer>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a `Blob` and returns the\n * full HTTP response.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with the response body as a `Blob`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'blob',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Blob>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as a text stream and returns the\n * full HTTP response.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with a response body of type\n * string.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean, responseType: 'text',\n withCredentials?: boolean,\n }): Observable<HttpResponse<string>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as JSON and returns the full\n * HTTP response.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request, with a response body\n * of type 'Object`.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<Object>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as an instance of the requested type and\n * returns the full HTTP response.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the `HttpResponse` for the request,\n * with a response body in the requested type.\n */\n put<T>(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]}, observe: 'response',\n context?: HttpContext,\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<HttpResponse<T>>;\n\n /**\n * Constructs a `PUT` request that interprets the body as JSON\n * and returns an observable of JavaScript object.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the response as a JavaScript object.\n */\n put(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<Object>;\n\n /**\n * Constructs a `PUT` request that interprets the body as an instance of the requested type\n * and returns an observable of the requested type.\n *\n * @param url The endpoint URL.\n * @param body The resources to add/update.\n * @param options HTTP options\n *\n * @return An `Observable` of the requested type.\n */\n put<T>(url: string, body: any|null, options?: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'json',\n withCredentials?: boolean,\n }): Observable<T>;\n\n /**\n * Constructs an observable that, when subscribed, causes the configured\n * `PUT` request to execute on the server. The `PUT` method replaces an existing resource\n * with a new set of values.\n * See the individual overloads for details on the return type.\n */\n put(url: string, body: any|null, options: {\n headers?: HttpHeaders|{[header: string]: string | string[]},\n context?: HttpContext,\n observe?: 'body'|'events'|'response',\n params?: HttpParams|\n {[param: string]: string | number | boolean | ReadonlyArray<string|number|boolean>},\n reportProgress?: boolean,\n responseType?: 'arraybuffer'|'blob'|'json'|'text',\n withCredentials?: boolean,\n } = {}): Observable<any> {\n return this.request<any>('PUT', url, addBody(options, body));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, inject, Injectable, InjectionToken} from '@angular/core';\nimport {Observable} from 'rxjs';\n\nimport {HttpBackend, HttpHandler} from './backend';\nimport {HttpRequest} from './request';\nimport {HttpEvent} from './response';\n\n/**\n * Intercepts and handles an `HttpRequest` or `HttpResponse`.\n *\n * Most interceptors transform the outgoing request before passing it to the\n * next interceptor in the chain, by calling `next.handle(transformedReq)`.\n * An interceptor may transform the\n * response event stream as well, by applying additional RxJS operators on the stream\n * returned by `next.handle()`.\n *\n * More rarely, an interceptor may handle the request entirely,\n * and compose a new event stream instead of invoking `next.handle()`. This is an\n * acceptable behavior, but keep in mind that further interceptors will be skipped entirely.\n *\n * It is also rare but valid for an interceptor to return multiple responses on the\n * event stream for a single request.\n *\n * @publicApi\n *\n * @see [HTTP Guide](guide/http#intercepting-requests-and-responses)\n *\n * @usageNotes\n *\n * To use the same instance of `HttpInterceptors` for the entire app, import the `HttpClientModule`\n * only in your `AppModule`, and add the interceptors to the root application injector.\n * If you import `HttpClientModule` multiple times across different modules (for example, in lazy\n * loading modules), each import creates a new copy of the `HttpClientModule`, which overwrites the\n * interceptors provided in the root module.\n */\nexport interface HttpInterceptor {\n /**\n * Identifies and handles a given HTTP request.\n * @param req The outgoing request object to handle.\n * @param next The next interceptor in the chain, or the backend\n * if no interceptors remain in the chain.\n * @returns An observable of the event stream.\n */\n intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;\n}\n\n/**\n * Represents the next interceptor in an interceptor chain, or the real backend if there are no\n * further interceptors.\n *\n * Most interceptors will delegate to this function, and either modify the outgoing request or the\n * response when it arrives. Within the scope of the current request, however, this function may be\n * called any number of times, for any number of downstream requests. Such downstream requests need\n * not be to the same URL or even the same origin as the current request. It is also valid to not\n * call the downstream handler at all, and process the current request entirely within the\n * interceptor.\n *\n * This function should only be called within the scope of the request that's currently being\n * intercepted. Once that request is complete, this downstream handler function should not be\n * called.\n *\n * @publicApi\n *\n * @see [HTTP Guide](guide/http#intercepting-requests-and-responses)\n */\nexport type HttpHandlerFn = (req: HttpRequest<unknown>) => Observable<HttpEvent<unknown>>;\n\n/**\n * An interceptor for HTTP requests made via `HttpClient`.\n *\n * `HttpInterceptorFn`s are middleware functions which `HttpClient` calls when a request is made.\n * These functions have the opportunity to modify the outgoing request or any response that comes\n * back, as well as block, redirect, or otherwise change the request or response semantics.\n *\n * An `HttpHandlerFn` representing the next interceptor (or the backend which will make a real HTTP\n * request) is provided. Most interceptors will delegate to this function, but that is not required\n * (see `HttpHandlerFn` for more details).\n *\n * `HttpInterceptorFn`s have access to `inject()` via the `EnvironmentInjector` from which they were\n * configured.\n */\nexport type HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) =>\n Observable<HttpEvent<unknown>>;\n\n/**\n * Function which invokes an HTTP interceptor chain.\n *\n * Each interceptor in the interceptor chain is turned into a `ChainedInterceptorFn` which closes\n * over the rest of the chain (represented by another `ChainedInterceptorFn`). The last such\n * function in the chain will instead delegate to the `finalHandlerFn`, which is passed down when\n * the chain is invoked.\n *\n * This pattern allows for a chain of many interceptors to be composed and wrapped in a single\n * `HttpInterceptorFn`, which is a useful abstraction for including different kinds of interceptors\n * (e.g. legacy class-based interceptors) in the same chain.\n */\ntype ChainedInterceptorFn<RequestT> = (req: HttpRequest<RequestT>, finalHandlerFn: HttpHandlerFn) =>\n Observable<HttpEvent<RequestT>>;\n\nfunction interceptorChainEndFn(\n req: HttpRequest<any>, finalHandlerFn: HttpHandlerFn): Observable<HttpEvent<any>> {\n return finalHandlerFn(req);\n}\n\n/**\n * Constructs a `ChainedInterceptorFn` which adapts a legacy `HttpInterceptor` to the\n * `ChainedInterceptorFn` interface.\n */\nfunction adaptLegacyInterceptorToChain(\n chainTailFn: ChainedInterceptorFn<any>,\n interceptor: HttpInterceptor): ChainedInterceptorFn<any> {\n return (initialRequest, finalHandlerFn) => interceptor.intercept(initialRequest, {\n handle: (downstreamRequest) => chainTailFn(downstreamRequest, finalHandlerFn),\n });\n}\n\n/**\n * Constructs a `ChainedInterceptorFn` which wraps and invokes a functional interceptor in the given\n * injector.\n */\nfunction chainedInterceptorFn(\n chainTailFn: ChainedInterceptorFn<unknown>, interceptorFn: HttpInterceptorFn,\n injector: EnvironmentInjector): ChainedInterceptorFn<unknown> {\n // clang-format off\n return (initialRequest, finalHandlerFn) => injector.runInContext(() =>\n interceptorFn(\n initialRequest,\n downstreamRequest => chainTailFn(downstreamRequest, finalHandlerFn)\n )\n );\n // clang-format on\n}\n\n/**\n * A multi-provider token that represents the array of registered\n * `HttpInterceptor` objects.\n *\n * @publicApi\n */\nexport const HTTP_INTERCEPTORS = new InjectionToken<HttpInterceptor[]>('HTTP_INTERCEPTORS');\n\n/**\n * A multi-provided token of `HttpInterceptorFn`s.\n */\nexport const HTTP_INTERCEPTOR_FNS = new InjectionToken<HttpInterceptorFn[]>('HTTP_INTERCEPTOR_FNS');\n\n/**\n * Creates an `HttpInterceptorFn` which lazily initializes an interceptor chain from the legacy\n * class-based interceptors and runs the request through it.\n */\nexport function legacyInterceptorFnFactory(): HttpInterceptorFn {\n let chain: ChainedInterceptorFn<any>|null = null;\n\n return (req, handler) => {\n if (chain === null) {\n const interceptors = inject(HTTP_INTERCEPTORS, {optional: true}) ?? [];\n // Note: interceptors are wrapped right-to-left so that final execution order is\n // left-to-right. That is, if `interceptors` is the array `[a, b, c]`, we want to\n // produce a chain that is conceptually `c(b(a(end)))`, which we build from the inside\n // out.\n chain = interceptors.reduceRight(\n adaptLegacyInterceptorToChain, interceptorChainEndFn as ChainedInterceptorFn<any>);\n }\n\n return chain(req, handler);\n };\n}\n\n@Injectable()\nexport class HttpInterceptorHandler extends HttpHandler {\n private chain: ChainedInterceptorFn<unknown>|null = null;\n\n constructor(private backend: HttpBackend, private injector: EnvironmentInjector) {\n super();\n }\n\n override handle(initialRequest: HttpRequest<any>): Observable<HttpEvent<any>> {\n if (this.chain === null) {\n const dedupedInterceptorFns = Array.from(new Set(this.injector.get(HTTP_INTERCEPTOR_FNS)));\n\n // Note: interceptors are wrapped right-to-left so that final execution order is\n // left-to-right. That is, if `dedupedInterceptorFns` is the array `[a, b, c]`, we want to\n // produce a chain that is conceptually `c(b(a(end)))`, which we build from the inside\n // out.\n this.chain = dedupedInterceptorFns.reduceRight(\n (nextSequencedFn, interceptorFn) =>\n chainedInterceptorFn(nextSequencedFn, interceptorFn, this.injector),\n interceptorChainEndFn as ChainedInterceptorFn<unknown>);\n }\n return this.chain(initialRequest, downstreamRequest => this.backend.handle(downstreamRequest));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XhrFactory} from '@angular/common';\nimport {Injectable} from '@angular/core';\nimport {Observable, Observer} from 'rxjs';\n\nimport {HttpBackend} from './backend';\nimport {HttpHeaders} from './headers';\nimport {HttpRequest} from './request';\nimport {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpJsonParseError, HttpResponse, HttpStatusCode, HttpUploadProgressEvent} from './response';\n\n\nconst XSSI_PREFIX = /^\\)\\]\\}',?\\n/;\n\n/**\n * Determine an appropriate URL for the response, by checking either\n * XMLHttpRequest.responseURL or the X-Request-URL header.\n */\nfunction getResponseUrl(xhr: any): string|null {\n if ('responseURL' in xhr && xhr.responseURL) {\n return xhr.responseURL;\n }\n if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {\n return xhr.getResponseHeader('X-Request-URL');\n }\n return null;\n}\n\n/**\n * Uses `XMLHttpRequest` to send requests to a backend server.\n * @see {@link HttpHandler}\n * @see {@link JsonpClientBackend}\n *\n * @publicApi\n */\n@Injectable()\nexport class HttpXhrBackend implements HttpBackend {\n constructor(private xhrFactory: XhrFactory) {}\n\n /**\n * Processes a request and returns a stream of response events.\n * @param req The request object.\n * @returns An observable of the response events.\n */\n handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {\n // Quick check to give a better error message when a user attempts to use\n // HttpClient.jsonp() without installing the HttpClientJsonpModule\n if (req.method === 'JSONP') {\n throw new Error(\n `Attempted to construct Jsonp request without HttpClientJsonpModule installed.`);\n }\n\n // Everything happens on Observable subscription.\n return new Observable((observer: Observer<HttpEvent<any>>) => {\n // Start by setting up the XHR object with request method, URL, and withCredentials flag.\n const xhr = this.xhrFactory.build();\n xhr.open(req.method, req.urlWithParams);\n if (!!req.withCredentials) {\n xhr.withCredentials = true;\n }\n\n // Add all the requested headers.\n req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(',')));\n\n // Add an Accept header if one isn't present already.\n if (!req.headers.has('Accept')) {\n xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');\n }\n\n // Auto-detect the Content-Type header if one isn't present already.\n if (!req.headers.has('Content-Type')) {\n const detectedType = req.detectContentTypeHeader();\n // Sometimes Content-Type detection fails.\n if (detectedType !== null) {\n xhr.setRequestHeader('Content-Type', detectedType);\n }\n }\n\n // Set the responseType if one was requested.\n if (req.responseType) {\n const responseType = req.responseType.toLowerCase();\n\n // JSON responses need to be processed as text. This is because if the server\n // returns an XSSI-prefixed JSON response, the browser will fail to parse it,\n // xhr.response will be null, and xhr.responseText cannot be accessed to\n // retrieve the prefixed JSON data in order to strip the prefix. Thus, all JSON\n // is parsed by first requesting text and then applying JSON.parse.\n xhr.responseType = ((responseType !== 'json') ? responseType : 'text') as any;\n }\n\n // Serialize the request body if one is present. If not, this will be set to null.\n const reqBody = req.serializeBody();\n\n // If progress events are enabled, response headers will be delivered\n // in two events - the HttpHeaderResponse event and the full HttpResponse\n // event. However, since response headers don't change in between these\n // two events, it doesn't make sense to parse them twice. So headerResponse\n // caches the data extracted from the response whenever it's first parsed,\n // to ensure parsing isn't duplicated.\n let headerResponse: HttpHeaderResponse|null = null;\n\n // partialFromXhr extracts the HttpHeaderResponse from the current XMLHttpRequest\n // state, and memoizes it into headerResponse.\n const partialFromXhr = (): HttpHeaderResponse => {\n if (headerResponse !== null) {\n return headerResponse;\n }\n\n const statusText = xhr.statusText || 'OK';\n\n // Parse headers from XMLHttpRequest - this step is lazy.\n const headers = new HttpHeaders(xhr.getAllResponseHeaders());\n\n // Read the response URL from the XMLHttpResponse instance and fall back on the\n // request URL.\n const url = getResponseUrl(xhr) || req.url;\n\n // Construct the HttpHeaderResponse and memoize it.\n headerResponse = new HttpHeaderResponse({headers, status: xhr.status, statusText, url});\n return headerResponse;\n };\n\n // Next, a few closures are defined for the various events which XMLHttpRequest can\n // emit. This allows them to be unregistered as event listeners later.\n\n // First up is the load event, which represents a response being fully available.\n const onLoad = () => {\n // Read response state from the memoized partial data.\n let {headers, status, statusText, url} = partialFromXhr();\n\n // The body will be read out if present.\n let body: any|null = null;\n\n if (status !== HttpStatusCode.NoContent) {\n // Use XMLHttpRequest.response if set, responseText otherwise.\n body = (typeof xhr.response === 'undefined') ? xhr.responseText : xhr.response;\n }\n\n // Normalize another potential bug (this one comes from CORS).\n if (status === 0) {\n status = !!body ? HttpStatusCode.Ok : 0;\n }\n\n // ok determines whether the response will be transmitted on the event or\n // error channel. Unsuccessful status codes (not 2xx) will always be errors,\n // but a successful status code can still result in an error if the user\n // asked for JSON data and the body cannot be parsed as such.\n let ok = status >= 200 && status < 300;\n\n // Check whether the body needs to be parsed as JSON (in many cases the browser\n // will have done that already).\n if (req.responseType === 'json' && typeof body === 'string') {\n // Save the original body, before attempting XSSI prefix stripping.\n const originalBody = body;\n body = body.replace(XSSI_PREFIX, '');\n try {\n // Attempt the parse. If it fails, a parse error should be delivered to the user.\n body = body !== '' ? JSON.parse(body) : null;\n } catch (error) {\n // Since the JSON.parse failed, it's reasonable to assume this might not have been a\n // JSON response. Restore the original body (including any XSSI prefix) to deliver\n // a better error response.\n body = originalBody;\n\n // If this was an error request to begin with, leave it as a string, it probably\n // just isn't JSON. Otherwise, deliver the parsing error to the user.\n if (ok) {\n // Even though the response status was 2xx, this is still an error.\n ok = false;\n // The parse error contains the text of the body that failed to parse.\n body = {error, text: body} as HttpJsonParseError;\n }\n }\n }\n\n if (ok) {\n // A successful response is delivered on the event stream.\n observer.next(new HttpResponse({\n body,\n headers,\n status,\n statusText,\n url: url || undefined,\n }));\n // The full body has been received and delivered, no further events\n // are possible. This request is complete.\n observer.complete();\n } else {\n // An unsuccessful request is delivered on the error channel.\n observer.error(new HttpErrorResponse({\n // The error in this case is the response body (error from the server).\n error: body,\n headers,\n status,\n statusText,\n url: url || undefined,\n }));\n }\n };\n\n // The onError callback is called when something goes wrong at the network level.\n // Connection timeout, DNS error, offline, etc. These are actual errors, and are\n // transmitted on the error channel.\n const onError = (error: ProgressEvent) => {\n const {url} = partialFromXhr();\n const res = new HttpErrorResponse({\n error,\n status: xhr.status || 0,\n statusText: xhr.statusText || 'Unknown Error',\n url: url || undefined,\n });\n observer.error(res);\n };\n\n // The sentHeaders flag tracks whether the HttpResponseHeaders event\n // has been sent on the stream. This is necessary to track if progress\n // is enabled since the event will be sent on only the first download\n // progress event.\n let sentHeaders = false;\n\n // The download progress event handler, which is only registered if\n // progress events are enabled.\n const onDownProgress = (event: ProgressEvent) => {\n // Send the HttpResponseHeaders event if it hasn't been sent already.\n if (!sentHeaders) {\n observer.next(partialFromXhr());\n sentHeaders = true;\n }\n\n // Start building the download progress event to deliver on the response\n // event stream.\n let progressEvent: HttpDownloadProgressEvent = {\n type: HttpEventType.DownloadProgress,\n loaded: event.loaded,\n };\n\n // Set the total number of bytes in the event if it's available.\n if (event.lengthComputable) {\n progressEvent.total = event.total;\n }\n\n // If the request was for text content and a partial response is\n // available on XMLHttpRequest, include it in the progress event\n // to allow for streaming reads.\n if (req.responseType === 'text' && !!xhr.responseText) {\n progressEvent.partialText = xhr.responseText;\n }\n\n // Finally, fire the event.\n observer.next(progressEvent);\n };\n\n // The upload progress event handler, which is only registered if\n // progress events are enabled.\n const onUpProgress = (event: ProgressEvent) => {\n // Upload progress events are simpler. Begin building the progress\n // event.\n let progress: HttpUploadProgressEvent = {\n type: HttpEventType.UploadProgress,\n loaded: event.loaded,\n };\n\n // If the total number of bytes being uploaded is available, include\n // it.\n if (event.lengthComputable) {\n progress.total = event.total;\n }\n\n // Send the event.\n observer.next(progress);\n };\n\n // By default, register for load and error events.\n xhr.addEventListener('load', onLoad);\n xhr.addEventListener('error', onError);\n xhr.addEventListener('timeout', onError);\n xhr.addEventListener('abort', onError);\n\n // Progress events are only enabled if requested.\n if (req.reportProgress) {\n // Download progress is always enabled if requested.\n xhr.addEventListener('progress', onDownProgress);\n\n // Upload progress depends on whether there is a body to upload.\n if (reqBody !== null && xhr.upload) {\n xhr.upload.addEventListener('progress', onUpProgress);\n }\n }\n\n // Fire the request, and notify the event stream that it was fired.\n xhr.send(reqBody!);\n observer.next({type: HttpEventType.Sent});\n\n // This is the return from the Observable function, which is the\n // request cancellation handler.\n return () => {\n // On a cancellation, remove all registered event listeners.\n xhr.removeEventListener('error', onError);\n xhr.removeEventListener('abort', onError);\n xhr.removeEventListener('load', onLoad);\n xhr.removeEventListener('timeout', onError);\n if (req.reportProgress) {\n xhr.removeEventListener('progress', onDownProgress);\n if (reqBody !== null && xhr.upload) {\n xhr.upload.removeEventListener('progress', onUpProgress);\n }\n }\n\n // Finally, abort the in-flight request.\n if (xhr.readyState !== xhr.DONE) {\n xhr.abort();\n }\n };\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT, ɵparseCookieValue as parseCookieValue} from '@angular/common';\nimport {EnvironmentInjector, Inject, inject, Injectable, InjectionToken, PLATFORM_ID} from '@angular/core';\nimport {Observable} from 'rxjs';\n\nimport {HttpHandler} from './backend';\nimport {HttpHandlerFn, HttpInterceptor} from './interceptor';\nimport {HttpRequest} from './request';\nimport {HttpEvent} from './response';\n\nexport const XSRF_ENABLED = new InjectionToken<boolean>('XSRF_ENABLED');\n\nexport const XSRF_DEFAULT_COOKIE_NAME = 'XSRF-TOKEN';\nexport const XSRF_COOKIE_NAME = new InjectionToken<string>('XSRF_COOKIE_NAME', {\n providedIn: 'root',\n factory: () => XSRF_DEFAULT_COOKIE_NAME,\n});\n\nexport const XSRF_DEFAULT_HEADER_NAME = 'X-XSRF-TOKEN';\nexport const XSRF_HEADER_NAME = new InjectionToken<string>('XSRF_HEADER_NAME', {\n providedIn: 'root',\n factory: () => XSRF_DEFAULT_HEADER_NAME,\n});\n\n/**\n * Retrieves the current XSRF token to use with the next outgoing request.\n *\n * @publicApi\n */\nexport abstract class HttpXsrfTokenExtractor {\n /**\n * Get the XSRF token to use with an outgoing request.\n *\n * Will be called for every request, so the token may change between requests.\n */\n abstract getToken(): string|null;\n}\n\n/**\n * `HttpXsrfTokenExtractor` which retrieves the token from a cookie.\n */\n@Injectable()\nexport class HttpXsrfCookieExtractor implements HttpXsrfTokenExtractor {\n private lastCookieString: string = '';\n private lastToken: string|null = null;\n\n /**\n * @internal for testing\n */\n parseCount: number = 0;\n\n constructor(\n @Inject(DOCUMENT) private doc: any, @Inject(PLATFORM_ID) private platform: string,\n @Inject(XSRF_COOKIE_NAME) private cookieName: string) {}\n\n getToken(): string|null {\n if (this.platform === 'server') {\n return null;\n }\n const cookieString = this.doc.cookie || '';\n if (cookieString !== this.lastCookieString) {\n this.parseCount++;\n this.lastToken = parseCookieValue(cookieString, this.cookieName);\n this.lastCookieString = cookieString;\n }\n return this.lastToken;\n }\n}\n\nexport function xsrfInterceptorFn(\n req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> {\n const lcUrl = req.url.toLowerCase();\n // Skip both non-mutating requests and absolute URLs.\n // Non-mutating requests don't require a token, and absolute URLs require special handling\n // anyway as the cookie set\n // on our origin is not the same as the token expected by another origin.\n if (!inject(XSRF_ENABLED) || req.method === 'GET' || req.method === 'HEAD' ||\n lcUrl.startsWith('http://') || lcUrl.startsWith('https://')) {\n return next(req);\n }\n\n const token = inject(HttpXsrfTokenExtractor).getToken();\n const headerName = inject(XSRF_HEADER_NAME);\n\n // Be careful not to overwrite an existing header of the same name.\n if (token != null && !req.headers.has(headerName)) {\n req = req.clone({headers: req.headers.set(headerName, token)});\n }\n return next(req);\n}\n\n/**\n * `HttpInterceptor` which adds an XSRF token to eligible outgoing requests.\n */\n@Injectable()\nexport class HttpXsrfInterceptor implements HttpInterceptor {\n constructor(private injector: EnvironmentInjector) {}\n\n intercept(initialRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n return this.injector.runInContext(\n () =>\n xsrfInterceptorFn(initialRequest, downstreamRequest => next.handle(downstreamRequest)));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentProviders, inject, InjectionToken, makeEnvironmentProviders, Provider} from '@angular/core';\n\nimport {HttpBackend, HttpHandler} from './backend';\nimport {HttpClient} from './client';\nimport {HTTP_INTERCEPTOR_FNS, HttpInterceptorFn, HttpInterceptorHandler, legacyInterceptorFnFactory} from './interceptor';\nimport {jsonpCallbackContext, JsonpCallbackContext, JsonpClientBackend, jsonpInterceptorFn} from './jsonp';\nimport {HttpXhrBackend} from './xhr';\nimport {HttpXsrfCookieExtractor, HttpXsrfTokenExtractor, XSRF_COOKIE_NAME, XSRF_ENABLED, XSRF_HEADER_NAME, xsrfInterceptorFn} from './xsrf';\n\n/**\n * Identifies a particular kind of `HttpFeature`.\n *\n * @publicApi\n */\nexport enum HttpFeatureKind {\n Interceptors,\n LegacyInterceptors,\n CustomXsrfConfiguration,\n NoXsrfProtection,\n JsonpSupport,\n RequestsMadeViaParent,\n}\n\n/**\n * A feature for use when configuring `provideHttpClient`.\n *\n * @publicApi\n */\nexport interface HttpFeature<KindT extends HttpFeatureKind> {\n ɵkind: KindT;\n ɵproviders: Provider[];\n}\n\nfunction makeHttpFeature<KindT extends HttpFeatureKind>(\n kind: KindT, providers: Provider[]): HttpFeature<KindT> {\n return {\n ɵkind: kind,\n ɵproviders: providers,\n };\n}\n\n/**\n * Configures Angular's `HttpClient` service to be available for injection.\n *\n * By default, `HttpClient` will be configured for injection with its default options for XSRF\n * protection of outgoing requests. Additional configuration options can be provided by passing\n * feature functions to `provideHttpClient`. For example, HTTP interceptors can be added using the\n * `withInterceptors(...)` feature.\n *\n * @see {@link withInterceptors}\n * @see {@link withInterceptorsFromDi}\n * @see {@link withXsrfConfiguration}\n * @see {@link withNoXsrfProtection}\n * @see {@link withJsonpSupport}\n * @see {@link withRequestsMadeViaParent}\n */\nexport function provideHttpClient(...features: HttpFeature<HttpFeatureKind>[]):\n EnvironmentProviders {\n if (ngDevMode) {\n const featureKinds = new Set(features.map(f => f.ɵkind));\n if (featureKinds.has(HttpFeatureKind.NoXsrfProtection) &&\n featureKinds.has(HttpFeatureKind.CustomXsrfConfiguration)) {\n throw new Error(\n ngDevMode ?\n `Configuration error: found both withXsrfConfiguration() and withNoXsrfProtection() in the same call to provideHttpClient(), which is a contradiction.` :\n '');\n }\n }\n\n const providers: Provider[] = [\n HttpClient,\n HttpXhrBackend,\n HttpInterceptorHandler,\n {provide: HttpHandler, useExisting: HttpInterceptorHandler},\n {provide: HttpBackend, useExisting: HttpXhrBackend},\n {\n provide: HTTP_INTERCEPTOR_FNS,\n useValue: xsrfInterceptorFn,\n multi: true,\n },\n {provide: XSRF_ENABLED, useValue: true},\n {provide: HttpXsrfTokenExtractor, useClass: HttpXsrfCookieExtractor},\n ];\n\n for (const feature of features) {\n providers.push(...feature.ɵproviders);\n }\n\n return makeEnvironmentProviders(providers);\n}\n\n/**\n * Adds one or more functional-style HTTP interceptors to the configuration of the `HttpClient`\n * instance.\n *\n * @see {@link HttpInterceptorFn}\n * @see {@link provideHttpClient}\n * @publicApi\n */\nexport function withInterceptors(interceptorFns: HttpInterceptorFn[]):\n HttpFeature<HttpFeatureKind.Interceptors> {\n return makeHttpFeature(HttpFeatureKind.Interceptors, interceptorFns.map(interceptorFn => {\n return {\n provide: HTTP_INTERCEPTOR_FNS,\n useValue: interceptorFn,\n multi: true,\n };\n }));\n}\n\nconst LEGACY_INTERCEPTOR_FN = new InjectionToken<HttpInterceptorFn>('LEGACY_INTERCEPTOR_FN');\n\n/**\n * Includes class-based interceptors configured using a multi-provider in the current injector into\n * the configured `HttpClient` instance.\n *\n * Prefer `withInterceptors` and functional interceptors instead, as support for DI-provided\n * interceptors may be phased out in a later release.\n *\n * @see {@link HttpInterceptor}\n * @see {@link HTTP_INTERCEPTORS}\n * @see {@link provideHttpClient}\n */\nexport function withInterceptorsFromDi(): HttpFeature<HttpFeatureKind.LegacyInterceptors> {\n // Note: the legacy interceptor function is provided here via an intermediate token\n // (`LEGACY_INTERCEPTOR_FN`), using a pattern which guarantees that if these providers are\n // included multiple times, all of the multi-provider entries will have the same instance of the\n // interceptor function. That way, the `HttpINterceptorHandler` will dedup them and legacy\n // interceptors will not run multiple times.\n return makeHttpFeature(HttpFeatureKind.LegacyInterceptors, [\n {\n provide: LEGACY_INTERCEPTOR_FN,\n useFactory: legacyInterceptorFnFactory,\n },\n {\n provide: HTTP_INTERCEPTOR_FNS,\n useExisting: LEGACY_INTERCEPTOR_FN,\n multi: true,\n }\n ]);\n}\n\n/**\n * Customizes the XSRF protection for the configuration of the current `HttpClient` instance.\n *\n * This feature is incompatible with the `withNoXsrfProtection` feature.\n *\n * @see {@link provideHttpClient}\n */\nexport function withXsrfConfiguration(\n {cookieName, headerName}: {cookieName?: string, headerName?: string}):\n HttpFeature<HttpFeatureKind.CustomXsrfConfiguration> {\n const providers: Provider[] = [];\n if (cookieName !== undefined) {\n providers.push({provide: XSRF_COOKIE_NAME, useValue: cookieName});\n }\n if (headerName !== undefined) {\n providers.push({provide: XSRF_HEADER_NAME, useValue: headerName});\n }\n\n return makeHttpFeature(HttpFeatureKind.CustomXsrfConfiguration, providers);\n}\n\n/**\n * Disables XSRF protection in the configuration of the current `HttpClient` instance.\n *\n * This feature is incompatible with the `withXsrfConfiguration` feature.\n *\n * @see {@link provideHttpClient}\n */\nexport function withNoXsrfProtection(): HttpFeature<HttpFeatureKind.NoXsrfProtection> {\n return makeHttpFeature(HttpFeatureKind.NoXsrfProtection, [\n {\n provide: XSRF_ENABLED,\n useValue: false,\n },\n ]);\n}\n\n/**\n * Add JSONP support to the configuration of the current `HttpClient` instance.\n *\n * @see {@link provideHttpClient}\n */\nexport function withJsonpSupport(): HttpFeature<HttpFeatureKind.JsonpSupport> {\n return makeHttpFeature(HttpFeatureKind.JsonpSupport, [\n JsonpClientBackend,\n {provide: JsonpCallbackContext, useFactory: jsonpCallbackContext},\n {provide: HTTP_INTERCEPTOR_FNS, useValue: jsonpInterceptorFn, multi: true},\n ]);\n}\n\n/**\n * Configures the current `HttpClient` instance to make requests via the parent injector's\n * `HttpClient` instead of directly.\n *\n * By default, `provideHttpClient` configures `HttpClient` in its injector to be an independent\n * instance. For example, even if `HttpClient` is configured in the parent injector with\n * one or more interceptors, they will not intercept requests made via this instance.\n *\n * With this option enabled, once the request has passed through the current injector's\n * interceptors, it will be delegated to the parent injector's `HttpClient` chain instead of\n * dispatched directly, and interceptors in the parent configuration will be applied to the request.\n *\n * If there are several `HttpClient` instances in the injector hierarchy, it's possible for\n * `withRequestsMadeViaParent` to be used at multiple levels, which will cause the request to\n * \"bubble up\" until either reaching the root level or an `HttpClient` which was not configured with\n * this option.\n *\n * @see {@link provideHttpClient}\n * @developerPreview\n */\nexport function withRequestsMadeViaParent(): HttpFeature<HttpFeatureKind.RequestsMadeViaParent> {\n return makeHttpFeature(HttpFeatureKind.RequestsMadeViaParent, [\n {\n provide: HttpBackend,\n useFactory: () => {\n const handlerFromParent = inject(HttpHandler, {skipSelf: true, optional: true});\n if (ngDevMode && handlerFromParent === null) {\n throw new Error(\n 'withRequestsMadeViaParent() can only be used when the parent injector also configures HttpClient');\n }\n return handlerFromParent;\n },\n },\n ]);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ModuleWithProviders, NgModule} from '@angular/core';\n\nimport {HTTP_INTERCEPTORS} from './interceptor';\nimport {provideHttpClient, withInterceptorsFromDi, withJsonpSupport, withNoXsrfProtection, withXsrfConfiguration} from './provider';\nimport {HttpXsrfCookieExtractor, HttpXsrfInterceptor, HttpXsrfTokenExtractor, XSRF_DEFAULT_COOKIE_NAME, XSRF_DEFAULT_HEADER_NAME, XSRF_ENABLED} from './xsrf';\n\n/**\n * Configures XSRF protection support for outgoing requests.\n *\n * For a server that supports a cookie-based XSRF protection system,\n * use directly to configure XSRF protection with the correct\n * cookie and header names.\n *\n * If no names are supplied, the default cookie name is `XSRF-TOKEN`\n * and the default header name is `X-XSRF-TOKEN`.\n *\n * @publicApi\n */\n@NgModule({\n providers: [\n HttpXsrfInterceptor,\n {provide: HTTP_INTERCEPTORS, useExisting: HttpXsrfInterceptor, multi: true},\n {provide: HttpXsrfTokenExtractor, useClass: HttpXsrfCookieExtractor},\n withXsrfConfiguration({\n cookieName: XSRF_DEFAULT_COOKIE_NAME,\n headerName: XSRF_DEFAULT_HEADER_NAME,\n }).ɵproviders,\n {provide: XSRF_ENABLED, useValue: true},\n ],\n})\nexport class HttpClientXsrfModule {\n /**\n * Disable the default XSRF protection.\n */\n static disable(): ModuleWithProviders<HttpClientXsrfModule> {\n return {\n ngModule: HttpClientXsrfModule,\n providers: [\n withNoXsrfProtection().ɵproviders,\n ],\n };\n }\n\n /**\n * Configure XSRF protection.\n * @param options An object that can specify either or both\n * cookie name or header name.\n * - Cookie name default is `XSRF-TOKEN`.\n * - Header name default is `X-XSRF-TOKEN`.\n *\n */\n static withOptions(options: {\n cookieName?: string,\n headerName?: string,\n } = {}): ModuleWithProviders<HttpClientXsrfModule> {\n return {\n ngModule: HttpClientXsrfModule,\n providers: withXsrfConfiguration(options).ɵproviders,\n };\n }\n}\n\n/**\n * Configures the [dependency injector](guide/glossary#injector) for `HttpClient`\n * with supporting services for XSRF. Automatically imported by `HttpClientModule`.\n *\n * You can add interceptors to the chain behind `HttpClient` by binding them to the\n * multiprovider for built-in [DI token](guide/glossary#di-token) `HTTP_INTERCEPTORS`.\n *\n * @publicApi\n */\n@NgModule({\n /**\n * Configures the [dependency injector](guide/glossary#injector) where it is imported\n * with supporting services for HTTP communications.\n */\n providers: [\n provideHttpClient(withInterceptorsFromDi()),\n ],\n})\nexport class HttpClientModule {\n}\n\n/**\n * Configures the [dependency injector](guide/glossary#injector) for `HttpClient`\n * with supporting services for JSONP.\n * Without this module, Jsonp requests reach the backend\n * with method JSONP, where they are rejected.\n *\n * @publicApi\n */\n@NgModule({\n providers: [\n withJsonpSupport().ɵproviders,\n ],\n})\nexport class HttpClientJsonpModule {\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function getClosureSafeProperty<T>(objWithPropertyToExtract: T): string {\n for (let key in objWithPropertyToExtract) {\n if (objWithPropertyToExtract[key] === getClosureSafeProperty as any) {\n return key;\n }\n }\n throw Error('Could not find renamed property on target object.');\n}\n\n/**\n * Sets properties on a target object from a source object, but only if\n * the property doesn't already exist on the target object.\n * @param target The target to set properties on\n * @param source The source of the property keys and values to set\n */\nexport function fillProperties(target: {[key: string]: string}, source: {[key: string]: string}) {\n for (const key in source) {\n if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) {\n target[key] = source[key];\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function stringify(token: any): string {\n if (typeof token === 'string') {\n return token;\n }\n\n if (Array.isArray(token)) {\n return '[' + token.map(stringify).join(', ') + ']';\n }\n\n if (token == null) {\n return '' + token;\n }\n\n if (token.overriddenName) {\n return `${token.overriddenName}`;\n }\n\n if (token.name) {\n return `${token.name}`;\n }\n\n const res = token.toString();\n\n if (res == null) {\n return '' + res;\n }\n\n const newLineIndex = res.indexOf('\\n');\n return newLineIndex === -1 ? res : res.substring(0, newLineIndex);\n}\n\n/**\n * Concatenates two strings with separator, allocating new strings only when necessary.\n *\n * @param before before string.\n * @param separator separator string.\n * @param after after string.\n * @returns concatenated string.\n */\nexport function concatStringsWithSpace(before: string|null, after: string|null): string {\n return (before == null || before === '') ?\n (after === null ? '' : after) :\n ((after == null || after === '') ? before : before + ' ' + after);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\nimport {getClosureSafeProperty} from '../util/property';\nimport {stringify} from '../util/stringify';\n\n\n\n/**\n * An interface that a function passed into {@link forwardRef} has to implement.\n *\n * @usageNotes\n * ### Example\n *\n * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref_fn'}\n * @publicApi\n */\nexport interface ForwardRefFn {\n (): any;\n}\n\nconst __forward_ref__ = getClosureSafeProperty({__forward_ref__: getClosureSafeProperty});\n\n/**\n * Allows to refer to references which are not yet defined.\n *\n * For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of\n * DI is declared, but not yet defined. It is also used when the `token` which we use when creating\n * a query is not yet defined.\n *\n * @usageNotes\n * ### Example\n * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'}\n * @publicApi\n */\nexport function forwardRef(forwardRefFn: ForwardRefFn): Type<any> {\n (<any>forwardRefFn).__forward_ref__ = forwardRef;\n (<any>forwardRefFn).toString = function() {\n return stringify(this());\n };\n return (<Type<any>><any>forwardRefFn);\n}\n\n/**\n * Lazily retrieves the reference value from a forwardRef.\n *\n * Acts as the identity function when given a non-forward-ref value.\n *\n * @usageNotes\n * ### Example\n *\n * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'}\n *\n * @see `forwardRef`\n * @publicApi\n */\nexport function resolveForwardRef<T>(type: T): T {\n return isForwardRef(type) ? type() : type;\n}\n\n/** Checks whether a function is wrapped by a `forwardRef`. */\nexport function isForwardRef(fn: any): fn is() => any {\n return typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) &&\n fn.__forward_ref__ === forwardRef;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../../interface/type';\n\n/**\n * Configures the `Injector` to return a value for a token.\n * Base for `ValueProvider` decorator.\n *\n * @publicApi\n */\nexport interface ValueSansProvider {\n /**\n * The value to inject.\n */\n useValue: any;\n}\n\n/**\n * Configures the `Injector` to return a value for a token.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * ### Example\n *\n * {@example core/di/ts/provider_spec.ts region='ValueProvider'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface ValueProvider extends ValueSansProvider {\n /**\n * An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.\n */\n provide: any;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Configures the `Injector` to return an instance of `useClass` for a token.\n * Base for `StaticClassProvider` decorator.\n *\n * @publicApi\n */\nexport interface StaticClassSansProvider {\n /**\n * An optional class to instantiate for the `token`. By default, the `provide`\n * class is instantiated.\n */\n useClass: Type<any>;\n\n /**\n * A list of `token`s to be resolved by the injector. The list of values is then\n * used as arguments to the `useClass` constructor.\n */\n deps: any[];\n}\n\n/**\n * Configures the `Injector` to return an instance of `useClass` for a token.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='StaticClassProvider'}\n *\n * Note that following two providers are not equal:\n *\n * {@example core/di/ts/provider_spec.ts region='StaticClassProviderDifference'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface StaticClassProvider extends StaticClassSansProvider {\n /**\n * An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.\n */\n provide: any;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Configures the `Injector` to return an instance of a token.\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * ```ts\n * @Injectable(SomeModule, {deps: []})\n * class MyService {}\n * ```\n *\n * @publicApi\n */\nexport interface ConstructorSansProvider {\n /**\n * A list of `token`s to be resolved by the injector.\n */\n deps?: any[];\n}\n\n/**\n * Configures the `Injector` to return an instance of a token.\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface ConstructorProvider extends ConstructorSansProvider {\n /**\n * An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.\n */\n provide: Type<any>;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Configures the `Injector` to return a value of another `useExisting` token.\n *\n * @see `ExistingProvider`\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @publicApi\n */\nexport interface ExistingSansProvider {\n /**\n * Existing `token` to return. (Equivalent to `injector.get(useExisting)`)\n */\n useExisting: any;\n}\n\n/**\n * Configures the `Injector` to return a value of another `useExisting` token.\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='ExistingProvider'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface ExistingProvider extends ExistingSansProvider {\n /**\n * An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.\n */\n provide: any;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Configures the `Injector` to return a value by invoking a `useFactory` function.\n *\n * @see `FactoryProvider`\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @publicApi\n */\nexport interface FactorySansProvider {\n /**\n * A function to invoke to create a value for this `token`. The function is invoked with\n * resolved values of `token`s in the `deps` field.\n */\n useFactory: Function;\n\n /**\n * A list of `token`s to be resolved by the injector. The list of values is then\n * used as arguments to the `useFactory` function.\n */\n deps?: any[];\n}\n\n/**\n * Configures the `Injector` to return a value by invoking a `useFactory` function.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='FactoryProvider'}\n *\n * Dependencies can also be marked as optional:\n *\n * {@example core/di/ts/provider_spec.ts region='FactoryProviderOptionalDeps'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface FactoryProvider extends FactorySansProvider {\n /**\n * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).\n */\n provide: any;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Describes how an `Injector` should be configured as static (that is, without reflection).\n * A static provider provides tokens to an injector for various types of dependencies.\n *\n * @see `Injector.create()`.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection-providers).\n *\n * @publicApi\n */\nexport type StaticProvider =\n ValueProvider|ExistingProvider|StaticClassProvider|ConstructorProvider|FactoryProvider|any[];\n\n\n/**\n * Configures the `Injector` to return an instance of `Type` when `Type' is used as the token.\n *\n * Create an instance by invoking the `new` operator and supplying additional arguments.\n * This form is a short form of `TypeProvider`;\n *\n * For more details, see the [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='TypeProvider'}\n *\n * @publicApi\n */\nexport interface TypeProvider extends Type<any> {}\n\n/**\n * Configures the `Injector` to return a value by invoking a `useClass` function.\n * Base for `ClassProvider` decorator.\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @publicApi\n */\nexport interface ClassSansProvider {\n /**\n * Class to instantiate for the `token`.\n */\n useClass: Type<any>;\n}\n\n/**\n * Configures the `Injector` to return an instance of `useClass` for a token.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @usageNotes\n *\n * {@example core/di/ts/provider_spec.ts region='ClassProvider'}\n *\n * Note that following two providers are not equal:\n *\n * {@example core/di/ts/provider_spec.ts region='ClassProviderDifference'}\n *\n * ### Multi-value example\n *\n * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'}\n *\n * @publicApi\n */\nexport interface ClassProvider extends ClassSansProvider {\n /**\n * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`).\n */\n provide: any;\n\n /**\n * When true, injector returns an array of instances. This is useful to allow multiple\n * providers spread across many files to provide configuration information to a common token.\n */\n multi?: boolean;\n}\n\n/**\n * Describes how the `Injector` should be configured.\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n *\n * @see `StaticProvider`\n *\n * @publicApi\n */\nexport type Provider = TypeProvider|ValueProvider|ClassProvider|ConstructorProvider|\n ExistingProvider|FactoryProvider|any[];\n\n/**\n * Encapsulated `Provider`s that are only accepted during creation of an `EnvironmentInjector` (e.g.\n * in an `NgModule`).\n *\n * Using this wrapper type prevents providers which are only designed to work in\n * application/environment injectors from being accidentally included in\n * `@Component.providers` and ending up in a component injector.\n *\n * This wrapper type prevents access to the `Provider`s inside.\n *\n * @see `makeEnvironmentProviders`\n * @see `importProvidersFrom`\n *\n * @publicApi\n */\nexport type EnvironmentProviders = {\n ɵbrand: 'EnvironmentProviders';\n};\n\nexport interface InternalEnvironmentProviders extends EnvironmentProviders {\n ɵproviders: (Provider|EnvironmentProviders)[];\n\n /**\n * If present, indicates that the `EnvironmentProviders` were derived from NgModule providers.\n *\n * This is used to produce clearer error messages.\n */\n ɵfromNgModule?: true;\n}\n\nexport function isEnvironmentProviders(\n value: Provider|EnvironmentProviders|\n InternalEnvironmentProviders): value is InternalEnvironmentProviders {\n return value && !!(value as InternalEnvironmentProviders).ɵproviders;\n}\n\n/**\n * Describes a function that is used to process provider lists (such as provider\n * overrides).\n */\nexport type ProcessProvidersFunction = (providers: Provider[]) => Provider[];\n\n\n/**\n * A wrapper around an NgModule that associates it with [providers](guide/glossary#provider\n * \"Definition\"). Usage without a generic type is deprecated.\n *\n * @see [Deprecations](guide/deprecations#modulewithproviders-type-without-a-generic)\n *\n * @publicApi\n */\nexport interface ModuleWithProviders<T> {\n ngModule: Type<T>;\n providers?: Array<Provider|EnvironmentProviders>;\n}\n\n/**\n * Providers that were imported from NgModules via the `importProvidersFrom` function.\n *\n * These providers are meant for use in an application injector (or other environment injectors) and\n * should not be used in component injectors.\n *\n * This type cannot be directly implemented. It's returned from the `importProvidersFrom` function\n * and serves to prevent the extracted NgModule providers from being used in the wrong contexts.\n *\n * @see `importProvidersFrom`\n *\n * @publicApi\n * @deprecated replaced by `EnvironmentProviders`\n */\nexport type ImportedNgModuleProviders = EnvironmentProviders;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Base URL for the error details page.\n *\n * Keep this constant in sync across:\n * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts\n * - packages/core/src/error_details_base_url.ts\n */\nexport const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';\n\n/**\n * URL for the XSS security documentation.\n */\nexport const XSS_SECURITY_URL = 'https://g.co/ng/security#xss';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ERROR_DETAILS_PAGE_BASE_URL} from './error_details_base_url';\n\n/**\n * The list of error codes used in runtime code of the `core` package.\n * Reserved error code range: 100-999.\n *\n * Note: the minus sign denotes the fact that a particular code has a detailed guide on\n * angular.io. This extra annotation is needed to avoid introducing a separate set to store\n * error codes which have guides, which might leak into runtime code.\n *\n * Full list of available error guides can be found at https://angular.io/errors.\n */\nexport const enum RuntimeErrorCode {\n // Change Detection Errors\n EXPRESSION_CHANGED_AFTER_CHECKED = -100,\n RECURSIVE_APPLICATION_REF_TICK = 101,\n\n // Dependency Injection Errors\n CYCLIC_DI_DEPENDENCY = -200,\n PROVIDER_NOT_FOUND = -201,\n INVALID_FACTORY_DEPENDENCY = 202,\n MISSING_INJECTION_CONTEXT = -203,\n INVALID_INJECTION_TOKEN = 204,\n INJECTOR_ALREADY_DESTROYED = 205,\n PROVIDER_IN_WRONG_CONTEXT = 207,\n MISSING_INJECTION_TOKEN = 208,\n INVALID_MULTI_PROVIDER = -209,\n\n // Template Errors\n MULTIPLE_COMPONENTS_MATCH = -300,\n EXPORT_NOT_FOUND = -301,\n PIPE_NOT_FOUND = -302,\n UNKNOWN_BINDING = 303,\n UNKNOWN_ELEMENT = 304,\n TEMPLATE_STRUCTURE_ERROR = 305,\n INVALID_EVENT_BINDING = 306,\n HOST_DIRECTIVE_UNRESOLVABLE = 307,\n HOST_DIRECTIVE_NOT_STANDALONE = 308,\n DUPLICATE_DIRECTITVE = 309,\n HOST_DIRECTIVE_COMPONENT = 310,\n HOST_DIRECTIVE_UNDEFINED_BINDING = 311,\n HOST_DIRECTIVE_CONFLICTING_ALIAS = 312,\n\n // Bootstrap Errors\n MULTIPLE_PLATFORMS = 400,\n PLATFORM_NOT_FOUND = 401,\n ERROR_HANDLER_NOT_FOUND = 402,\n BOOTSTRAP_COMPONENTS_NOT_FOUND = -403,\n PLATFORM_ALREADY_DESTROYED = 404,\n ASYNC_INITIALIZERS_STILL_RUNNING = 405,\n APPLICATION_REF_ALREADY_DESTROYED = 406,\n RENDERER_NOT_FOUND = 407,\n\n // Styling Errors\n\n // Declarations Errors\n\n // i18n Errors\n INVALID_I18N_STRUCTURE = 700,\n MISSING_LOCALE_DATA = 701,\n\n // standalone errors\n IMPORT_PROVIDERS_FROM_STANDALONE = 800,\n\n // JIT Compilation Errors\n // Other\n INVALID_DIFFER_INPUT = 900,\n NO_SUPPORTING_DIFFER_FACTORY = 901,\n VIEW_ALREADY_ATTACHED = 902,\n INVALID_INHERITANCE = 903,\n UNSAFE_VALUE_IN_RESOURCE_URL = 904,\n UNSAFE_VALUE_IN_SCRIPT = 905,\n MISSING_GENERATED_DEF = 906,\n TYPE_IS_NOT_STANDALONE = 907,\n MISSING_ZONEJS = 908,\n UNEXPECTED_ZONE_STATE = 909,\n UNSAFE_IFRAME_ATTRS = -910,\n}\n\n/**\n * Class that represents a runtime error.\n * Formats and outputs the error message in a consistent way.\n *\n * Example:\n * ```\n * throw new RuntimeError(\n * RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,\n * ngDevMode && 'Injector has already been destroyed.');\n * ```\n *\n * Note: the `message` argument contains a descriptive error message as a string in development\n * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the\n * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic.\n */\nexport class RuntimeError<T extends number = RuntimeErrorCode> extends Error {\n constructor(public code: T, message: null|false|string) {\n super(formatRuntimeError<T>(code, message));\n }\n}\n\n/**\n * Called to format a runtime error.\n * See additional info on the `message` argument type in the `RuntimeError` class description.\n */\nexport function formatRuntimeError<T extends number = RuntimeErrorCode>(\n code: T, message: null|false|string): string {\n // Error code might be a negative number, which is a special marker that instructs the logic to\n // generate a link to the error details page on angular.io.\n // We also prepend `0` to non-compile-time errors.\n const fullCode = `NG0${Math.abs(code)}`;\n\n let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;\n\n if (ngDevMode && code < 0) {\n const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);\n const separator = addPeriodSeparator ? '.' : '';\n errorMessage =\n `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;\n }\n return errorMessage;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Used for stringify render output in Ivy.\n * Important! This function is very performance-sensitive and we should\n * be extra careful not to introduce megamorphic reads in it.\n * Check `core/test/render3/perf/render_stringify` for benchmarks and alternate implementations.\n */\nexport function renderStringify(value: any): string {\n if (typeof value === 'string') return value;\n if (value == null) return '';\n // Use `String` so that it invokes the `toString` method of the value. Note that this\n // appears to be faster than calling `value.toString` (see `render_stringify` benchmark).\n return String(value);\n}\n\n\n/**\n * Used to stringify a value so that it can be displayed in an error message.\n * Important! This function contains a megamorphic read and should only be\n * used for error messages.\n */\nexport function stringifyForError(value: any): string {\n if (typeof value === 'function') return value.name || value.toString();\n if (typeof value === 'object' && value != null && typeof value.type === 'function') {\n return value.type.name || value.type.toString();\n }\n\n return renderStringify(value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {isEnvironmentProviders} from '../di/interface/provider';\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {Type} from '../interface/type';\nimport {stringify} from '../util/stringify';\n\nimport {stringifyForError} from './util/stringify_utils';\n\n\n/** Called when directives inject each other (creating a circular dependency) */\nexport function throwCyclicDependencyError(token: string, path?: string[]): never {\n const depPath = path ? `. Dependency path: ${path.join(' > ')} > ${token}` : '';\n throw new RuntimeError(\n RuntimeErrorCode.CYCLIC_DI_DEPENDENCY,\n `Circular dependency in DI detected for ${token}${depPath}`);\n}\n\nexport function throwMixedMultiProviderError() {\n throw new Error(`Cannot mix multi providers and regular providers`);\n}\n\nexport function throwInvalidProviderError(\n ngModuleType?: Type<unknown>, providers?: any[], provider?: any): never {\n if (ngModuleType && providers) {\n const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');\n throw new Error(`Invalid provider for the NgModule '${\n stringify(ngModuleType)}' - only instances of Provider and Type are allowed, got: [${\n providerDetail.join(', ')}]`);\n } else if (isEnvironmentProviders(provider)) {\n if (provider.ɵfromNgModule) {\n throw new RuntimeError(\n RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT,\n `Invalid providers from 'importProvidersFrom' present in a non-environment injector. 'importProvidersFrom' can't be used for component providers.`);\n } else {\n throw new RuntimeError(\n RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT,\n `Invalid providers present in a non-environment injector. 'EnvironmentProviders' can't be used for component providers.`);\n }\n } else {\n throw new Error('Invalid provider');\n }\n}\n\n\n/** Throws an error when a token is not found in DI. */\nexport function throwProviderNotFoundError(token: any, injectorName?: string): never {\n const injectorDetails = injectorName ? ` in ${injectorName}` : '';\n throw new RuntimeError(\n RuntimeErrorCode.PROVIDER_NOT_FOUND,\n ngDevMode && `No provider for ${stringifyForError(token)} found${injectorDetails}`);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// The functions in this file verify that the assumptions we are making\n// about state in an instruction are correct before implementing any logic.\n// They are meant only to be called in dev mode as sanity checks.\n\nimport {stringify} from './stringify';\n\nexport function assertNumber(actual: any, msg: string): asserts actual is number {\n if (!(typeof actual === 'number')) {\n throwError(msg, typeof actual, 'number', '===');\n }\n}\n\nexport function assertNumberInRange(\n actual: any, minInclusive: number, maxInclusive: number): asserts actual is number {\n assertNumber(actual, 'Expected a number');\n assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to');\n assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to');\n}\n\nexport function assertString(actual: any, msg: string): asserts actual is string {\n if (!(typeof actual === 'string')) {\n throwError(msg, actual === null ? 'null' : typeof actual, 'string', '===');\n }\n}\n\nexport function assertFunction(actual: any, msg: string): asserts actual is Function {\n if (!(typeof actual === 'function')) {\n throwError(msg, actual === null ? 'null' : typeof actual, 'function', '===');\n }\n}\n\nexport function assertEqual<T>(actual: T, expected: T, msg: string) {\n if (!(actual == expected)) {\n throwError(msg, actual, expected, '==');\n }\n}\n\nexport function assertNotEqual<T>(actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual != expected)) {\n throwError(msg, actual, expected, '!=');\n }\n}\n\nexport function assertSame<T>(actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual === expected)) {\n throwError(msg, actual, expected, '===');\n }\n}\n\nexport function assertNotSame<T>(actual: T, expected: T, msg: string) {\n if (!(actual !== expected)) {\n throwError(msg, actual, expected, '!==');\n }\n}\n\nexport function assertLessThan<T>(actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual < expected)) {\n throwError(msg, actual, expected, '<');\n }\n}\n\nexport function assertLessThanOrEqual<T>(actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual <= expected)) {\n throwError(msg, actual, expected, '<=');\n }\n}\n\nexport function assertGreaterThan<T>(actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual > expected)) {\n throwError(msg, actual, expected, '>');\n }\n}\n\nexport function assertGreaterThanOrEqual<T>(\n actual: T, expected: T, msg: string): asserts actual is T {\n if (!(actual >= expected)) {\n throwError(msg, actual, expected, '>=');\n }\n}\n\nexport function assertNotDefined<T>(actual: T, msg: string) {\n if (actual != null) {\n throwError(msg, actual, null, '==');\n }\n}\n\nexport function assertDefined<T>(actual: T|null|undefined, msg: string): asserts actual is T {\n if (actual == null) {\n throwError(msg, actual, null, '!=');\n }\n}\n\nexport function throwError(msg: string): never;\nexport function throwError(msg: string, actual: any, expected: any, comparison: string): never;\nexport function throwError(msg: string, actual?: any, expected?: any, comparison?: string): never {\n throw new Error(\n `ASSERTION ERROR: ${msg}` +\n (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`));\n}\n\nexport function assertDomNode(node: any): asserts node is Node {\n // If we're in a worker, `Node` will not be defined.\n if (!(typeof Node !== 'undefined' && node instanceof Node) &&\n !(typeof node === 'object' && node != null &&\n node.constructor.name === 'WebWorkerRenderNode')) {\n throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`);\n }\n}\n\n\nexport function assertIndexInRange(arr: any[], index: number) {\n assertDefined(arr, 'Array must be defined.');\n const maxLen = arr.length;\n if (index < 0 || index >= maxLen) {\n throwError(`Index expected to be less than ${maxLen} but got ${index}`);\n }\n}\n\n\nexport function assertOneOf(value: any, ...validValues: any[]) {\n if (validValues.indexOf(value) !== -1) return true;\n throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${\n JSON.stringify(value)}.`);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../../interface/type';\nimport {getClosureSafeProperty} from '../../util/property';\n\nimport {ClassProvider, ConstructorProvider, EnvironmentProviders, ExistingProvider, FactoryProvider, StaticClassProvider, ValueProvider} from './provider';\n\n\n\n/**\n * Information about how a type or `InjectionToken` interfaces with the DI system.\n *\n * At a minimum, this includes a `factory` which defines how to create the given type `T`, possibly\n * requesting injection of other types if necessary.\n *\n * Optionally, a `providedIn` parameter specifies that the given type belongs to a particular\n * `Injector`, `NgModule`, or a special scope (e.g. `'root'`). A value of `null` indicates\n * that the injectable does not belong to any scope.\n *\n * @codeGenApi\n * @publicApi The ViewEngine compiler emits code with this type for injectables. This code is\n * deployed to npm, and should be treated as public api.\n\n */\nexport interface ɵɵInjectableDeclaration<T> {\n /**\n * Specifies that the given type belongs to a particular injector:\n * - `InjectorType` such as `NgModule`,\n * - `'root'` the root injector\n * - `'any'` all injectors.\n * - `null`, does not belong to any injector. Must be explicitly listed in the injector\n * `providers`.\n */\n providedIn: InjectorType<any>|'root'|'platform'|'any'|'environment'|null;\n\n /**\n * The token to which this definition belongs.\n *\n * Note that this may not be the same as the type that the `factory` will create.\n */\n token: unknown;\n\n /**\n * Factory method to execute to create an instance of the injectable.\n */\n factory: (t?: Type<any>) => T;\n\n /**\n * In a case of no explicit injector, a location where the instance of the injectable is stored.\n */\n value: T|undefined;\n}\n\n/**\n * Information about the providers to be included in an `Injector` as well as how the given type\n * which carries the information should be created by the DI system.\n *\n * An `InjectorDef` can import other types which have `InjectorDefs`, forming a deep nested\n * structure of providers with a defined priority (identically to how `NgModule`s also have\n * an import/dependency structure).\n *\n * NOTE: This is a private type and should not be exported\n *\n * @codeGenApi\n */\nexport interface ɵɵInjectorDef<T> {\n // TODO(alxhub): Narrow down the type here once decorators properly change the return type of the\n // class they are decorating (to add the ɵprov property for example).\n providers: (Type<any>|ValueProvider|ExistingProvider|FactoryProvider|ConstructorProvider|\n StaticClassProvider|ClassProvider|EnvironmentProviders|any[])[];\n\n imports: (InjectorType<any>|InjectorTypeWithProviders<any>)[];\n}\n\n/**\n * A `Type` which has a `ɵprov: ɵɵInjectableDeclaration` static field.\n *\n * `InjectableType`s contain their own Dependency Injection metadata and are usable in an\n * `InjectorDef`-based `StaticInjector`.\n *\n * @publicApi\n */\nexport interface InjectableType<T> extends Type<T> {\n /**\n * Opaque type whose structure is highly version dependent. Do not rely on any properties.\n */\n ɵprov: unknown;\n}\n\n/**\n * A type which has an `InjectorDef` static field.\n *\n * `InjectorTypes` can be used to configure a `StaticInjector`.\n *\n * This is an opaque type whose structure is highly version dependent. Do not rely on any\n * properties.\n *\n * @publicApi\n */\nexport interface InjectorType<T> extends Type<T> {\n ɵfac?: unknown;\n ɵinj: unknown;\n}\n\n/**\n * Describes the `InjectorDef` equivalent of a `ModuleWithProviders`, an `InjectorType` with an\n * associated array of providers.\n *\n * Objects of this type can be listed in the imports section of an `InjectorDef`.\n *\n * NOTE: This is a private type and should not be exported\n */\nexport interface InjectorTypeWithProviders<T> {\n ngModule: InjectorType<T>;\n providers?: (Type<any>|ValueProvider|ExistingProvider|FactoryProvider|ConstructorProvider|\n StaticClassProvider|ClassProvider|EnvironmentProviders|any[])[];\n}\n\n\n/**\n * Construct an injectable definition which defines how a token will be constructed by the DI\n * system, and in which injectors (if any) it will be available.\n *\n * This should be assigned to a static `ɵprov` field on a type, which will then be an\n * `InjectableType`.\n *\n * Options:\n * * `providedIn` determines which injectors will include the injectable, by either associating it\n * with an `@NgModule` or other `InjectorType`, or by specifying that this injectable should be\n * provided in the `'root'` injector, which will be the application-level injector in most apps.\n * * `factory` gives the zero argument function which will create an instance of the injectable.\n * The factory can call `inject` to access the `Injector` and request injection of dependencies.\n *\n * @codeGenApi\n * @publicApi This instruction has been emitted by ViewEngine for some time and is deployed to npm.\n */\nexport function ɵɵdefineInjectable<T>(opts: {\n token: unknown,\n providedIn?: Type<any>|'root'|'platform'|'any'|'environment'|null, factory: () => T,\n}): unknown {\n return {\n token: opts.token,\n providedIn: opts.providedIn as any || null,\n factory: opts.factory,\n value: undefined,\n } as ɵɵInjectableDeclaration<T>;\n}\n\n/**\n * @deprecated in v8, delete after v10. This API should be used only by generated code, and that\n * code should now use ɵɵdefineInjectable instead.\n * @publicApi\n */\nexport const defineInjectable = ɵɵdefineInjectable;\n\n/**\n * Construct an `InjectorDef` which configures an injector.\n *\n * This should be assigned to a static injector def (`ɵinj`) field on a type, which will then be an\n * `InjectorType`.\n *\n * Options:\n *\n * * `providers`: an optional array of providers to add to the injector. Each provider must\n * either have a factory or point to a type which has a `ɵprov` static property (the\n * type must be an `InjectableType`).\n * * `imports`: an optional array of imports of other `InjectorType`s or `InjectorTypeWithModule`s\n * whose providers will also be added to the injector. Locally provided types will override\n * providers from imports.\n *\n * @codeGenApi\n */\nexport function ɵɵdefineInjector(options: {providers?: any[], imports?: any[]}): unknown {\n return {providers: options.providers || [], imports: options.imports || []};\n}\n\n/**\n * Read the injectable def (`ɵprov`) for `type` in a way which is immune to accidentally reading\n * inherited value.\n *\n * @param type A type which may have its own (non-inherited) `ɵprov`.\n */\nexport function getInjectableDef<T>(type: any): ɵɵInjectableDeclaration<T>|null {\n return getOwnDefinition(type, NG_PROV_DEF) || getOwnDefinition(type, NG_INJECTABLE_DEF);\n}\n\nexport function isInjectable(type: any): boolean {\n return getInjectableDef(type) !== null;\n}\n\n/**\n * Return definition only if it is defined directly on `type` and is not inherited from a base\n * class of `type`.\n */\nfunction getOwnDefinition<T>(type: any, field: string): ɵɵInjectableDeclaration<T>|null {\n return type.hasOwnProperty(field) ? type[field] : null;\n}\n\n/**\n * Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors.\n *\n * @param type A type which may have `ɵprov`, via inheritance.\n *\n * @deprecated Will be removed in a future version of Angular, where an error will occur in the\n * scenario if we find the `ɵprov` on an ancestor only.\n */\nexport function getInheritedInjectableDef<T>(type: any): ɵɵInjectableDeclaration<T>|null {\n const def = type && (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF]);\n\n if (def) {\n ngDevMode &&\n console.warn(\n `DEPRECATED: DI is instantiating a token \"${\n type.name}\" that inherits its @Injectable decorator but does not provide one itself.\\n` +\n `This will become an error in a future version of Angular. Please add @Injectable() to the \"${\n type.name}\" class.`);\n return def;\n } else {\n return null;\n }\n}\n\n/**\n * Read the injector def type in a way which is immune to accidentally reading inherited value.\n *\n * @param type type which may have an injector def (`ɵinj`)\n */\nexport function getInjectorDef<T>(type: any): ɵɵInjectorDef<T>|null {\n return type && (type.hasOwnProperty(NG_INJ_DEF) || type.hasOwnProperty(NG_INJECTOR_DEF)) ?\n (type as any)[NG_INJ_DEF] :\n null;\n}\n\nexport const NG_PROV_DEF = getClosureSafeProperty({ɵprov: getClosureSafeProperty});\nexport const NG_INJ_DEF = getClosureSafeProperty({ɵinj: getClosureSafeProperty});\n\n// We need to keep these around so we can read off old defs if new defs are unavailable\nexport const NG_INJECTABLE_DEF = getClosureSafeProperty({ngInjectableDef: getClosureSafeProperty});\nexport const NG_INJECTOR_DEF = getClosureSafeProperty({ngInjectorDef: getClosureSafeProperty});\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\n/**\n * Special flag indicating that a decorator is of type `Inject`. It's used to make `Inject`\n * decorator tree-shakable (so we don't have to rely on the `instanceof` checks).\n * Note: this flag is not included into the `InjectFlags` since it's an internal-only API.\n */\nexport const enum DecoratorFlags {\n Inject = -1\n}\n\n/**\n * Injection flags for DI.\n *\n * @publicApi\n * @deprecated use an options object for `inject` instead.\n */\nexport enum InjectFlags {\n // TODO(alxhub): make this 'const' (and remove `InternalInjectFlags` enum) when ngc no longer\n // writes exports of it into ngfactory files.\n\n /** Check self and check parent injector if needed */\n Default = 0b0000,\n\n /**\n * Specifies that an injector should retrieve a dependency from any injector until reaching the\n * host element of the current component. (Only used with Element Injector)\n */\n Host = 0b0001,\n\n /** Don't ascend to ancestors of the node requesting injection. */\n Self = 0b0010,\n\n /** Skip the node that is requesting injection. */\n SkipSelf = 0b0100,\n\n /** Inject `defaultValue` instead if token not found. */\n Optional = 0b1000,\n}\n\n/**\n * This enum is an exact copy of the `InjectFlags` enum above, but the difference is that this is a\n * const enum, so actual enum values would be inlined in generated code. The `InjectFlags` enum can\n * be turned into a const enum when ViewEngine is removed (see TODO at the `InjectFlags` enum\n * above). The benefit of inlining is that we can use these flags at the top level without affecting\n * tree-shaking (see \"no-toplevel-property-access\" tslint rule for more info).\n * Keep this enum in sync with `InjectFlags` enum above.\n */\nexport const enum InternalInjectFlags {\n /** Check self and check parent injector if needed */\n Default = 0b0000,\n\n /**\n * Specifies that an injector should retrieve a dependency from any injector until reaching the\n * host element of the current component. (Only used with Element Injector)\n */\n Host = 0b0001,\n\n /** Don't ascend to ancestors of the node requesting injection. */\n Self = 0b0010,\n\n /** Skip the node that is requesting injection. */\n SkipSelf = 0b0100,\n\n /** Inject `defaultValue` instead if token not found. */\n Optional = 0b1000,\n\n /**\n * This token is being injected into a pipe.\n *\n * This flag is intentionally not in the public facing `InjectFlags` because it is only added by\n * the compiler and is not a developer applicable flag.\n */\n ForPipe = 0b10000,\n}\n\n/**\n * Type of the options argument to `inject`.\n *\n * @publicApi\n */\nexport interface InjectOptions {\n /**\n * Use optional injection, and return `null` if the requested token is not found.\n */\n optional?: boolean;\n\n /**\n * Start injection at the parent of the current injector.\n */\n skipSelf?: boolean;\n\n /**\n * Only query the current injector for the token, and don't fall back to the parent injector if\n * it's not found.\n */\n self?: boolean;\n\n /**\n * Stop injection at the host component's injector. Only relevant when injecting from an element\n * injector, and a no-op for environment injectors.\n */\n host?: boolean;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {throwProviderNotFoundError} from '../render3/errors_di';\nimport {assertNotEqual} from '../util/assert';\nimport {stringify} from '../util/stringify';\n\nimport {getInjectableDef, ɵɵInjectableDeclaration} from './interface/defs';\nimport {InjectFlags} from './interface/injector';\nimport {ProviderToken} from './provider_token';\n\n\n/**\n * Current implementation of inject.\n *\n * By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed\n * to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this\n * way for two reasons:\n * 1. `Injector` should not depend on ivy logic.\n * 2. To maintain tree shake-ability we don't want to bring in unnecessary code.\n */\nlet _injectImplementation: (<T>(token: ProviderToken<T>, flags?: InjectFlags) => T | null)|\n undefined;\nexport function getInjectImplementation() {\n return _injectImplementation;\n}\n\n\n/**\n * Sets the current inject implementation.\n */\nexport function setInjectImplementation(\n impl: (<T>(token: ProviderToken<T>, flags?: InjectFlags) => T | null)|\n undefined): (<T>(token: ProviderToken<T>, flags?: InjectFlags) => T | null)|undefined {\n const previous = _injectImplementation;\n _injectImplementation = impl;\n return previous;\n}\n\n\n/**\n * Injects `root` tokens in limp mode.\n *\n * If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to\n * `\"root\"`. This is known as the limp mode injection. In such case the value is stored in the\n * injectable definition.\n */\nexport function injectRootLimpMode<T>(\n token: ProviderToken<T>, notFoundValue: T|undefined, flags: InjectFlags): T|null {\n const injectableDef: ɵɵInjectableDeclaration<T>|null = getInjectableDef(token);\n if (injectableDef && injectableDef.providedIn == 'root') {\n return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :\n injectableDef.value;\n }\n if (flags & InjectFlags.Optional) return null;\n if (notFoundValue !== undefined) return notFoundValue;\n throwProviderNotFoundError(stringify(token), 'Injector');\n}\n\n\n/**\n * Assert that `_injectImplementation` is not `fn`.\n *\n * This is useful, to prevent infinite recursion.\n *\n * @param fn Function which it should not equal to\n */\nexport function assertInjectImplementationNotEqual(\n fn: (<T>(token: ProviderToken<T>, flags?: InjectFlags) => T | null)) {\n ngDevMode &&\n assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// TODO(jteplitz602): Load WorkerGlobalScope from lib.webworker.d.ts file #3492\ndeclare var WorkerGlobalScope: any;\n// CommonJS / Node have global context exposed as \"global\" variable.\n// We don't want to include the whole node.d.ts this this compilation unit so we'll just fake\n// the global \"global\" var for now.\ndeclare var global: any;\n\n// Always use __globalThis if available, which is the spec-defined global variable across all\n// environments, then fallback to __global first, because in Node tests both __global and\n// __window may be defined and _global should be __global in that case. Note: Typeof/Instanceof\n// checks are considered side-effects in Terser. We explicitly mark this as side-effect free:\n// https://github.com/terser/terser/issues/250.\nconst _global: any = (/* @__PURE__ */ (\n () => (typeof globalThis !== 'undefined' && globalThis) ||\n (typeof global !== 'undefined' && global) || (typeof window !== 'undefined' && window) ||\n (typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&\n self instanceof WorkerGlobalScope && self))());\n\n/**\n * Attention: whenever providing a new value, be sure to add an\n * entry into the corresponding `....externs.js` file,\n * so that closure won't use that global for its purposes.\n */\nexport {_global as global};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport '../util/ng_dev_mode';\n\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {Type} from '../interface/type';\nimport {stringify} from '../util/stringify';\n\nimport {resolveForwardRef} from './forward_ref';\nimport {getInjectImplementation, injectRootLimpMode} from './inject_switch';\nimport {Injector} from './injector';\nimport {DecoratorFlags, InjectFlags, InjectOptions, InternalInjectFlags} from './interface/injector';\nimport {ProviderToken} from './provider_token';\n\n\nconst _THROW_IF_NOT_FOUND = {};\nexport const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;\n\n/*\n * Name of a property (that we patch onto DI decorator), which is used as an annotation of which\n * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators\n * in the code, thus making them tree-shakable.\n */\nconst DI_DECORATOR_FLAG = '__NG_DI_FLAG__';\n\nexport const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';\nconst NG_TOKEN_PATH = 'ngTokenPath';\nconst NEW_LINE = /\\n/gm;\nconst NO_NEW_LINE = 'ɵ';\nexport const SOURCE = '__source';\n\n/**\n * Current injector value used by `inject`.\n * - `undefined`: it is an error to call `inject`\n * - `null`: `inject` can be called but there is no injector (limp-mode).\n * - Injector instance: Use the injector for resolution.\n */\nlet _currentInjector: Injector|undefined|null = undefined;\n\nexport function setCurrentInjector(injector: Injector|null|undefined): Injector|undefined|null {\n const former = _currentInjector;\n _currentInjector = injector;\n return former;\n}\n\nexport function injectInjectorOnly<T>(token: ProviderToken<T>): T;\nexport function injectInjectorOnly<T>(token: ProviderToken<T>, flags?: InjectFlags): T|null;\nexport function injectInjectorOnly<T>(token: ProviderToken<T>, flags = InjectFlags.Default): T|\n null {\n if (_currentInjector === undefined) {\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_INJECTION_CONTEXT,\n ngDevMode &&\n `inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with \\`EnvironmentInjector#runInContext\\`.`);\n } else if (_currentInjector === null) {\n return injectRootLimpMode(token, undefined, flags);\n } else {\n return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);\n }\n}\n\n/**\n * Generated instruction: injects a token from the currently active injector.\n *\n * (Additional documentation moved to `inject`, as it is the public API, and an alias for this\n * instruction)\n *\n * @see inject\n * @codeGenApi\n * @publicApi This instruction has been emitted by ViewEngine for some time and is deployed to npm.\n */\nexport function ɵɵinject<T>(token: ProviderToken<T>): T;\nexport function ɵɵinject<T>(token: ProviderToken<T>, flags?: InjectFlags): T|null;\nexport function ɵɵinject<T>(token: ProviderToken<T>, flags = InjectFlags.Default): T|null {\n return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);\n}\n\n/**\n * Throws an error indicating that a factory function could not be generated by the compiler for a\n * particular class.\n *\n * The name of the class is not mentioned here, but will be in the generated factory function name\n * and thus in the stack trace.\n *\n * @codeGenApi\n */\nexport function ɵɵinvalidFactoryDep(index: number): never {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_FACTORY_DEPENDENCY,\n ngDevMode &&\n `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${\n index} of the parameter list is invalid.\nThis can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.\n\nPlease check that 1) the type for the parameter at index ${\n index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.`);\n}\n\n/**\n * @param token A token that represents a dependency that should be injected.\n * @returns the injected value if operation is successful, `null` otherwise.\n * @throws if called outside of a supported context.\n *\n * @publicApi\n */\nexport function inject<T>(token: ProviderToken<T>): T;\n/**\n * @param token A token that represents a dependency that should be injected.\n * @param flags Control how injection is executed. The flags correspond to injection strategies that\n * can be specified with parameter decorators `@Host`, `@Self`, `@SkipSelf`, and `@Optional`.\n * @returns the injected value if operation is successful, `null` otherwise.\n * @throws if called outside of a supported context.\n *\n * @publicApi\n * @deprecated prefer an options object instead of `InjectFlags`\n */\nexport function inject<T>(token: ProviderToken<T>, flags?: InjectFlags): T|null;\n/**\n * @param token A token that represents a dependency that should be injected.\n * @param options Control how injection is executed. Options correspond to injection strategies\n * that can be specified with parameter decorators `@Host`, `@Self`, `@SkipSelf`, and\n * `@Optional`.\n * @returns the injected value if operation is successful.\n * @throws if called outside of a supported context, or if the token is not found.\n *\n * @publicApi\n */\nexport function inject<T>(token: ProviderToken<T>, options: InjectOptions&{optional?: false}): T;\n/**\n * @param token A token that represents a dependency that should be injected.\n * @param options Control how injection is executed. Options correspond to injection strategies\n * that can be specified with parameter decorators `@Host`, `@Self`, `@SkipSelf`, and\n * `@Optional`.\n * @returns the injected value if operation is successful, `null` if the token is not\n * found and optional injection has been requested.\n * @throws if called outside of a supported context, or if the token is not found and optional\n * injection was not requested.\n *\n * @publicApi\n */\nexport function inject<T>(token: ProviderToken<T>, options: InjectOptions): T|null;\n/**\n * Injects a token from the currently active injector.\n * `inject` is only supported during instantiation of a dependency by the DI system. It can be used\n * during:\n * - Construction (via the `constructor`) of a class being instantiated by the DI system, such\n * as an `@Injectable` or `@Component`.\n * - In the initializer for fields of such classes.\n * - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`.\n * - In the `factory` function specified for an `InjectionToken`.\n *\n * @param token A token that represents a dependency that should be injected.\n * @param flags Optional flags that control how injection is executed.\n * The flags correspond to injection strategies that can be specified with\n * parameter decorators `@Host`, `@Self`, `@SkipSelf`, and `@Optional`.\n * @returns the injected value if operation is successful, `null` otherwise.\n * @throws if called outside of a supported context.\n *\n * @usageNotes\n * In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a\n * field initializer:\n *\n * ```typescript\n * @Injectable({providedIn: 'root'})\n * export class Car {\n * radio: Radio|undefined;\n * // OK: field initializer\n * spareTyre = inject(Tyre);\n *\n * constructor() {\n * // OK: constructor body\n * this.radio = inject(Radio);\n * }\n * }\n * ```\n *\n * It is also legal to call `inject` from a provider's factory:\n *\n * ```typescript\n * providers: [\n * {provide: Car, useFactory: () => {\n * // OK: a class factory\n * const engine = inject(Engine);\n * return new Car(engine);\n * }}\n * ]\n * ```\n *\n * Calls to the `inject()` function outside of the class creation context will result in error. Most\n * notably, calls to `inject()` are disallowed after a class instance was created, in methods\n * (including lifecycle hooks):\n *\n * ```typescript\n * @Component({ ... })\n * export class CarComponent {\n * ngOnInit() {\n * // ERROR: too late, the component instance was already created\n * const engine = inject(Engine);\n * engine.start();\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport function inject<T>(\n token: ProviderToken<T>, flags: InjectFlags|InjectOptions = InjectFlags.Default): T|null {\n return ɵɵinject(token, convertToBitFlags(flags));\n}\n\n// Converts object-based DI flags (`InjectOptions`) to bit flags (`InjectFlags`).\nexport function convertToBitFlags(flags: InjectOptions|InjectFlags|undefined): InjectFlags|\n undefined {\n if (typeof flags === 'undefined' || typeof flags === 'number') {\n return flags;\n }\n\n // While TypeScript doesn't accept it without a cast, bitwise OR with false-y values in\n // JavaScript is a no-op. We can use that for a very codesize-efficient conversion from\n // `InjectOptions` to `InjectFlags`.\n return (InternalInjectFlags.Default | // comment to force a line break in the formatter\n ((flags.optional && InternalInjectFlags.Optional) as number) |\n ((flags.host && InternalInjectFlags.Host) as number) |\n ((flags.self && InternalInjectFlags.Self) as number) |\n ((flags.skipSelf && InternalInjectFlags.SkipSelf) as number)) as InjectFlags;\n}\n\nexport function injectArgs(types: (ProviderToken<any>|any[])[]): any[] {\n const args: any[] = [];\n for (let i = 0; i < types.length; i++) {\n const arg = resolveForwardRef(types[i]);\n if (Array.isArray(arg)) {\n if (arg.length === 0) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_DIFFER_INPUT,\n ngDevMode && 'Arguments array must have arguments.');\n }\n let type: Type<any>|undefined = undefined;\n let flags: InjectFlags = InjectFlags.Default;\n\n for (let j = 0; j < arg.length; j++) {\n const meta = arg[j];\n const flag = getInjectFlag(meta);\n if (typeof flag === 'number') {\n // Special case when we handle @Inject decorator.\n if (flag === DecoratorFlags.Inject) {\n type = meta.token;\n } else {\n flags |= flag;\n }\n } else {\n type = meta;\n }\n }\n\n args.push(ɵɵinject(type!, flags));\n } else {\n args.push(ɵɵinject(arg));\n }\n }\n return args;\n}\n\n/**\n * Attaches a given InjectFlag to a given decorator using monkey-patching.\n * Since DI decorators can be used in providers `deps` array (when provider is configured using\n * `useFactory`) without initialization (e.g. `Host`) and as an instance (e.g. `new Host()`), we\n * attach the flag to make it available both as a static property and as a field on decorator\n * instance.\n *\n * @param decorator Provided DI decorator.\n * @param flag InjectFlag that should be applied.\n */\nexport function attachInjectFlag(decorator: any, flag: InternalInjectFlags|DecoratorFlags): any {\n decorator[DI_DECORATOR_FLAG] = flag;\n decorator.prototype[DI_DECORATOR_FLAG] = flag;\n return decorator;\n}\n\n/**\n * Reads monkey-patched property that contains InjectFlag attached to a decorator.\n *\n * @param token Token that may contain monkey-patched DI flags property.\n */\nexport function getInjectFlag(token: any): number|undefined {\n return token[DI_DECORATOR_FLAG];\n}\n\nexport function catchInjectorError(\n e: any, token: any, injectorErrorName: string, source: string|null): never {\n const tokenPath: any[] = e[NG_TEMP_TOKEN_PATH];\n if (token[SOURCE]) {\n tokenPath.unshift(token[SOURCE]);\n }\n e.message = formatError('\\n' + e.message, tokenPath, injectorErrorName, source);\n e[NG_TOKEN_PATH] = tokenPath;\n e[NG_TEMP_TOKEN_PATH] = null;\n throw e;\n}\n\nexport function formatError(\n text: string, obj: any, injectorErrorName: string, source: string|null = null): string {\n text = text && text.charAt(0) === '\\n' && text.charAt(1) == NO_NEW_LINE ? text.slice(2) : text;\n let context = stringify(obj);\n if (Array.isArray(obj)) {\n context = obj.map(stringify).join(' -> ');\n } else if (typeof obj === 'object') {\n let parts = <string[]>[];\n for (let key in obj) {\n if (obj.hasOwnProperty(key)) {\n let value = obj[key];\n parts.push(\n key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));\n }\n }\n context = `{${parts.join(', ')}}`;\n }\n return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${\n text.replace(NEW_LINE, '\\n ')}`;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Convince closure compiler that the wrapped function has no side-effects.\n *\n * Closure compiler always assumes that `toString` has no side-effects. We use this quirk to\n * allow us to execute a function but have closure compiler mark the call as no-side-effects.\n * It is important that the return value for the `noSideEffects` function be assigned\n * to something which is retained otherwise the call to `noSideEffects` will be removed by closure\n * compiler.\n */\nexport function noSideEffects<T>(fn: () => T): T {\n return {toString: fn}.toString() as unknown as T;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\n/**\n * The strategy that the default change detector uses to detect changes.\n * When set, takes effect the next time change detection is triggered.\n *\n * @see {@link ChangeDetectorRef#usage-notes Change detection usage}\n *\n * @publicApi\n */\nexport enum ChangeDetectionStrategy {\n /**\n * Use the `CheckOnce` strategy, meaning that automatic change detection is deactivated\n * until reactivated by setting the strategy to `Default` (`CheckAlways`).\n * Change detection can still be explicitly invoked.\n * This strategy applies to all child directives and cannot be overridden.\n */\n OnPush = 0,\n\n /**\n * Use the default `CheckAlways` strategy, in which change detection is automatic until\n * explicitly deactivated.\n */\n Default = 1,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Defines the CSS styles encapsulation policies for the {@link Component} decorator's\n * `encapsulation` option.\n *\n * See {@link Component#encapsulation encapsulation}.\n *\n * @usageNotes\n * ### Example\n *\n * {@example core/ts/metadata/encapsulation.ts region='longform'}\n *\n * @publicApi\n */\nexport enum ViewEncapsulation {\n // TODO: consider making `ViewEncapsulation` a `const enum` instead. See\n // https://github.com/angular/angular/issues/44119 for additional information.\n\n /**\n * Emulates a native Shadow DOM encapsulation behavior by adding a specific attribute to the\n * component's host element and applying the same attribute to all the CSS selectors provided\n * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls}.\n *\n * This is the default option.\n */\n Emulated = 0,\n\n // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.\n\n /**\n * Doesn't provide any sort of CSS style encapsulation, meaning that all the styles provided\n * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls} are applicable\n * to any HTML element of the application regardless of their host Component.\n */\n None = 2,\n\n /**\n * Uses the browser's native Shadow DOM API to encapsulate CSS styles, meaning that it creates\n * a ShadowRoot for the component's host element which is then used to encapsulate\n * all the Component's styling.\n */\n ShadowDom = 3\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {initNgDevMode} from './ng_dev_mode';\n\n/**\n * This file contains reuseable \"empty\" symbols that can be used as default return values\n * in different parts of the rendering code. Because the same symbols are returned, this\n * allows for identity checks against these values to be consistently used by the framework\n * code.\n */\n\nexport const EMPTY_OBJ: {} = {};\nexport const EMPTY_ARRAY: any[] = [];\n\n// freezing the values prevents any code from accidentally inserting new values in\nif ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) {\n // These property accesses can be ignored because ngDevMode will be set to false\n // when optimizing code and the whole if statement will be dropped.\n // tslint:disable-next-line:no-toplevel-property-access\n Object.freeze(EMPTY_OBJ);\n // tslint:disable-next-line:no-toplevel-property-access\n Object.freeze(EMPTY_ARRAY);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {getClosureSafeProperty} from '../util/property';\n\nexport const NG_COMP_DEF = getClosureSafeProperty({ɵcmp: getClosureSafeProperty});\nexport const NG_DIR_DEF = getClosureSafeProperty({ɵdir: getClosureSafeProperty});\nexport const NG_PIPE_DEF = getClosureSafeProperty({ɵpipe: getClosureSafeProperty});\nexport const NG_MOD_DEF = getClosureSafeProperty({ɵmod: getClosureSafeProperty});\nexport const NG_FACTORY_DEF = getClosureSafeProperty({ɵfac: getClosureSafeProperty});\n\n/**\n * If a directive is diPublic, bloomAdd sets a property on the type with this constant as\n * the key and the directive's unique ID as the value. This allows us to map directives to their\n * bloom filter bit for DI.\n */\n// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.\nexport const NG_ELEMENT_ID = getClosureSafeProperty({__NG_ELEMENT_ID__: getClosureSafeProperty});\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectionStrategy} from '../change_detection/constants';\nimport {Mutable, Type} from '../interface/type';\nimport {NgModuleDef} from '../metadata/ng_module_def';\nimport {SchemaMetadata} from '../metadata/schema';\nimport {ViewEncapsulation} from '../metadata/view';\nimport {noSideEffects} from '../util/closure';\nimport {EMPTY_ARRAY, EMPTY_OBJ} from '../util/empty';\nimport {initNgDevMode} from '../util/ng_dev_mode';\nimport {stringify} from '../util/stringify';\n\nimport {NG_COMP_DEF, NG_DIR_DEF, NG_MOD_DEF, NG_PIPE_DEF} from './fields';\nimport {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, ContentQueriesFunction, DependencyTypeList, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, HostBindingsFunction, PipeDef, PipeDefListOrFactory, TypeOrFactory, ViewQueriesFunction} from './interfaces/definition';\nimport {TAttributes, TConstantsOrFactory} from './interfaces/node';\nimport {CssSelectorList} from './interfaces/projection';\n\ninterface DirectiveDefinition<T> {\n /**\n * Directive type, needed to configure the injector.\n */\n type: Type<T>;\n\n /** The selectors that will be used to match nodes to this directive. */\n selectors?: CssSelectorList;\n\n /**\n * A map of input names.\n *\n * The format is in: `{[actualPropertyName: string]:(string|[string, string])}`.\n *\n * Given:\n * ```\n * class MyComponent {\n * @Input()\n * publicInput1: string;\n *\n * @Input('publicInput2')\n * declaredInput2: string;\n * }\n * ```\n *\n * is described as:\n * ```\n * {\n * publicInput1: 'publicInput1',\n * declaredInput2: ['declaredInput2', 'publicInput2'],\n * }\n * ```\n *\n * Which the minifier may translate to:\n * ```\n * {\n * minifiedPublicInput1: 'publicInput1',\n * minifiedDeclaredInput2: [ 'publicInput2', 'declaredInput2'],\n * }\n * ```\n *\n * This allows the render to re-construct the minified, public, and declared names\n * of properties.\n *\n * NOTE:\n * - Because declared and public name are usually same we only generate the array\n * `['declared', 'public']` format when they differ.\n * - The reason why this API and `outputs` API is not the same is that `NgOnChanges` has\n * inconsistent behavior in that it uses declared names rather than minified or public. For\n * this reason `NgOnChanges` will be deprecated and removed in future version and this\n * API will be simplified to be consistent with `output`.\n */\n inputs?: {[P in keyof T]?: string|[string, string]};\n\n /**\n * A map of output names.\n *\n * The format is in: `{[actualPropertyName: string]:string}`.\n *\n * Which the minifier may translate to: `{[minifiedPropertyName: string]:string}`.\n *\n * This allows the render to re-construct the minified and non-minified names\n * of properties.\n */\n outputs?: {[P in keyof T]?: string};\n\n /**\n * A list of optional features to apply.\n *\n * See: {@link NgOnChangesFeature}, {@link ProvidersFeature}, {@link InheritDefinitionFeature}\n */\n features?: DirectiveDefFeature[];\n\n /**\n * Function executed by the parent template to allow child directive to apply host bindings.\n */\n hostBindings?: HostBindingsFunction<T>;\n\n /**\n * The number of bindings in this directive `hostBindings` (including pure fn bindings).\n *\n * Used to calculate the length of the component's LView array, so we\n * can pre-fill the array and set the host binding start index.\n */\n hostVars?: number;\n\n /**\n * Assign static attribute values to a host element.\n *\n * This property will assign static attribute values as well as class and style\n * values to a host element. Since attribute values can consist of different types of values,\n * the `hostAttrs` array must include the values in the following format:\n *\n * attrs = [\n * // static attributes (like `title`, `name`, `id`...)\n * attr1, value1, attr2, value,\n *\n * // a single namespace value (like `x:id`)\n * NAMESPACE_MARKER, namespaceUri1, name1, value1,\n *\n * // another single namespace value (like `x:name`)\n * NAMESPACE_MARKER, namespaceUri2, name2, value2,\n *\n * // a series of CSS classes that will be applied to the element (no spaces)\n * CLASSES_MARKER, class1, class2, class3,\n *\n * // a series of CSS styles (property + value) that will be applied to the element\n * STYLES_MARKER, prop1, value1, prop2, value2\n * ]\n *\n * All non-class and non-style attributes must be defined at the start of the list\n * first before all class and style values are set. When there is a change in value\n * type (like when classes and styles are introduced) a marker must be used to separate\n * the entries. The marker values themselves are set via entries found in the\n * [AttributeMarker] enum.\n */\n hostAttrs?: TAttributes;\n\n /**\n * Function to create instances of content queries associated with a given directive.\n */\n contentQueries?: ContentQueriesFunction<T>;\n\n /**\n * Additional set of instructions specific to view query processing. This could be seen as a\n * set of instructions to be inserted into the template function.\n */\n viewQuery?: ViewQueriesFunction<T>|null;\n\n /**\n * Defines the name that can be used in the template to assign this directive to a variable.\n *\n * See: {@link Directive.exportAs}\n */\n exportAs?: string[];\n\n /**\n * Whether this directive/component is standalone.\n */\n standalone?: boolean;\n}\n\ninterface ComponentDefinition<T> extends Omit<DirectiveDefinition<T>, 'features'> {\n /**\n * The number of nodes, local refs, and pipes in this component template.\n *\n * Used to calculate the length of this component's LView array, so we\n * can pre-fill the array and set the binding start index.\n */\n decls: number;\n\n /**\n * The number of bindings in this component template (including pure fn bindings).\n *\n * Used to calculate the length of this component's LView array, so we\n * can pre-fill the array and set the host binding start index.\n */\n vars: number;\n\n /**\n * Template function use for rendering DOM.\n *\n * This function has following structure.\n *\n * ```\n * function Template<T>(ctx:T, creationMode: boolean) {\n * if (creationMode) {\n * // Contains creation mode instructions.\n * }\n * // Contains binding update instructions\n * }\n * ```\n *\n * Common instructions are:\n * Creation mode instructions:\n * - `elementStart`, `elementEnd`\n * - `text`\n * - `container`\n * - `listener`\n *\n * Binding update instructions:\n * - `bind`\n * - `elementAttribute`\n * - `elementProperty`\n * - `elementClass`\n * - `elementStyle`\n *\n */\n template: ComponentTemplate<T>;\n\n /**\n * Constants for the nodes in the component's view.\n * Includes attribute arrays, local definition arrays etc.\n */\n consts?: TConstantsOrFactory;\n\n /**\n * An array of `ngContent[selector]` values that were found in the template.\n */\n ngContentSelectors?: string[];\n /**\n * A list of optional features to apply.\n *\n * See: {@link NgOnChangesFeature}, {@link ProvidersFeature}\n */\n features?: ComponentDefFeature[];\n\n /**\n * Defines template and style encapsulation options available for Component's {@link Component}.\n */\n encapsulation?: ViewEncapsulation;\n\n /**\n * Defines arbitrary developer-defined data to be stored on a renderer instance.\n * This is useful for renderers that delegate to other renderers.\n *\n * see: animation\n */\n data?: {[kind: string]: any};\n\n /**\n * A set of styles that the component needs to be present for component to render correctly.\n */\n styles?: string[];\n\n /**\n * The strategy that the default change detector uses to detect changes.\n * When set, takes effect the next time change detection is triggered.\n */\n changeDetection?: ChangeDetectionStrategy;\n\n /**\n * Registry of directives, components, and pipes that may be found in this component's view.\n *\n * This property is either an array of types or a function that returns the array of types. This\n * function may be necessary to support forward declarations.\n */\n dependencies?: TypeOrFactory<DependencyTypeList>;\n\n /**\n * The set of schemas that declare elements to be allowed in the component's template.\n */\n schemas?: SchemaMetadata[]|null;\n}\n\n/** Counter used to generate unique IDs for component definitions. */\nlet componentDefCount = 0;\n\n/**\n * Create a component definition object.\n *\n *\n * # Example\n * ```\n * class MyComponent {\n * // Generated by Angular Template Compiler\n * // [Symbol] syntax will not be supported by TypeScript until v2.7\n * static ɵcmp = defineComponent({\n * ...\n * });\n * }\n * ```\n * @codeGenApi\n */\nexport function ɵɵdefineComponent<T>(componentDefinition: ComponentDefinition<T>):\n Mutable<ComponentDef<any>, keyof ComponentDef<any>> {\n return noSideEffects(() => {\n // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.\n // See the `initNgDevMode` docstring for more information.\n (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();\n\n const baseDef = getNgDirectiveDef(componentDefinition as DirectiveDefinition<T>);\n const def: Mutable<ComponentDef<unknown>, keyof ComponentDef<unknown>> = {\n ...baseDef,\n decls: componentDefinition.decls,\n vars: componentDefinition.vars,\n template: componentDefinition.template,\n consts: componentDefinition.consts || null,\n ngContentSelectors: componentDefinition.ngContentSelectors,\n onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,\n directiveDefs: null!, // assigned in noSideEffects\n pipeDefs: null!, // assigned in noSideEffects\n dependencies: baseDef.standalone && componentDefinition.dependencies || null,\n getStandaloneInjector: null,\n data: componentDefinition.data || {},\n encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,\n id: `c${componentDefCount++}`,\n styles: componentDefinition.styles || EMPTY_ARRAY,\n _: null,\n schemas: componentDefinition.schemas || null,\n tView: null,\n };\n\n initFeatures(def);\n const dependencies = componentDefinition.dependencies;\n def.directiveDefs = extractDefListOrFactory(dependencies, /* pipeDef */ false);\n def.pipeDefs = extractDefListOrFactory(dependencies, /* pipeDef */ true);\n return def;\n });\n}\n\n/**\n * Generated next to NgModules to monkey-patch directive and pipe references onto a component's\n * definition, when generating a direct reference in the component file would otherwise create an\n * import cycle.\n *\n * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.\n *\n * @codeGenApi\n */\nexport function ɵɵsetComponentScope(\n type: ComponentType<any>, directives: Type<any>[]|(() => Type<any>[]),\n pipes: Type<any>[]|(() => Type<any>[])): void {\n const def = type.ɵcmp as ComponentDef<any>;\n def.directiveDefs = extractDefListOrFactory(directives, /* pipeDef */ false);\n def.pipeDefs = extractDefListOrFactory(pipes, /* pipeDef */ true);\n}\n\nexport function extractDirectiveDef(type: Type<any>): DirectiveDef<any>|ComponentDef<any>|null {\n return getComponentDef(type) || getDirectiveDef(type);\n}\n\nfunction nonNull<T>(value: T|null): value is T {\n return value !== null;\n}\n\n/**\n * @codeGenApi\n */\nexport function ɵɵdefineNgModule<T>(def: {\n /** Token representing the module. Used by DI. */\n type: T;\n\n /** List of components to bootstrap. */\n bootstrap?: Type<any>[] | (() => Type<any>[]);\n\n /** List of components, directives, and pipes declared by this module. */\n declarations?: Type<any>[] | (() => Type<any>[]);\n\n /** List of modules or `ModuleWithProviders` imported by this module. */\n imports?: Type<any>[] | (() => Type<any>[]);\n\n /**\n * List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this\n * module.\n */\n exports?: Type<any>[] | (() => Type<any>[]);\n\n /** The set of schemas that declare elements to be allowed in the NgModule. */\n schemas?: SchemaMetadata[] | null;\n\n /** Unique ID for the module that is used with `getModuleFactory`. */\n id?: string | null;\n}): unknown {\n return noSideEffects(() => {\n const res: NgModuleDef<T> = {\n type: def.type,\n bootstrap: def.bootstrap || EMPTY_ARRAY,\n declarations: def.declarations || EMPTY_ARRAY,\n imports: def.imports || EMPTY_ARRAY,\n exports: def.exports || EMPTY_ARRAY,\n transitiveCompileScopes: null,\n schemas: def.schemas || null,\n id: def.id || null,\n };\n return res;\n });\n}\n\n/**\n * Adds the module metadata that is necessary to compute the module's transitive scope to an\n * existing module definition.\n *\n * Scope metadata of modules is not used in production builds, so calls to this function can be\n * marked pure to tree-shake it from the bundle, allowing for all referenced declarations\n * to become eligible for tree-shaking as well.\n *\n * @codeGenApi\n */\nexport function ɵɵsetNgModuleScope(type: any, scope: {\n /** List of components, directives, and pipes declared by this module. */\n declarations?: Type<any>[]|(() => Type<any>[]);\n\n /** List of modules or `ModuleWithProviders` imported by this module. */\n imports?: Type<any>[] | (() => Type<any>[]);\n\n /**\n * List of modules, `ModuleWithProviders`, components, directives, or pipes exported by this\n * module.\n */\n exports?: Type<any>[] | (() => Type<any>[]);\n}): unknown {\n return noSideEffects(() => {\n const ngModuleDef = getNgModuleDef(type, true);\n ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;\n ngModuleDef.imports = scope.imports || EMPTY_ARRAY;\n ngModuleDef.exports = scope.exports || EMPTY_ARRAY;\n });\n}\n\n/**\n * Inverts an inputs or outputs lookup such that the keys, which were the\n * minified keys, are part of the values, and the values are parsed so that\n * the publicName of the property is the new key\n *\n * e.g. for\n *\n * ```\n * class Comp {\n * @Input()\n * propName1: string;\n *\n * @Input('publicName2')\n * declaredPropName2: number;\n * }\n * ```\n *\n * will be serialized as\n *\n * ```\n * {\n * propName1: 'propName1',\n * declaredPropName2: ['publicName2', 'declaredPropName2'],\n * }\n * ```\n *\n * which is than translated by the minifier as:\n *\n * ```\n * {\n * minifiedPropName1: 'propName1',\n * minifiedPropName2: ['publicName2', 'declaredPropName2'],\n * }\n * ```\n *\n * becomes: (public name => minifiedName)\n *\n * ```\n * {\n * 'propName1': 'minifiedPropName1',\n * 'publicName2': 'minifiedPropName2',\n * }\n * ```\n *\n * Optionally the function can take `secondary` which will result in: (public name => declared name)\n *\n * ```\n * {\n * 'propName1': 'propName1',\n * 'publicName2': 'declaredPropName2',\n * }\n * ```\n *\n\n */\nfunction invertObject<T>(\n obj?: {[P in keyof T]?: string|[string, string]},\n secondary?: {[key: string]: string}): {[P in keyof T]: string} {\n if (obj == null) return EMPTY_OBJ as any;\n const newLookup: any = {};\n for (const minifiedKey in obj) {\n if (obj.hasOwnProperty(minifiedKey)) {\n let publicName: string|[string, string] = obj[minifiedKey]!;\n let declaredName = publicName;\n if (Array.isArray(publicName)) {\n declaredName = publicName[1];\n publicName = publicName[0];\n }\n newLookup[publicName] = minifiedKey;\n if (secondary) {\n (secondary[publicName] = declaredName as string);\n }\n }\n }\n return newLookup;\n}\n\n/**\n * Create a directive definition object.\n *\n * # Example\n * ```ts\n * class MyDirective {\n * // Generated by Angular Template Compiler\n * // [Symbol] syntax will not be supported by TypeScript until v2.7\n * static ɵdir = ɵɵdefineDirective({\n * ...\n * });\n * }\n * ```\n *\n * @codeGenApi\n */\nexport function ɵɵdefineDirective<T>(directiveDefinition: DirectiveDefinition<T>):\n Mutable<DirectiveDef<any>, keyof DirectiveDef<any>> {\n return noSideEffects(() => {\n const def = getNgDirectiveDef(directiveDefinition);\n initFeatures(def);\n\n return def;\n });\n}\n\n/**\n * Create a pipe definition object.\n *\n * # Example\n * ```\n * class MyPipe implements PipeTransform {\n * // Generated by Angular Template Compiler\n * static ɵpipe = definePipe({\n * ...\n * });\n * }\n * ```\n * @param pipeDef Pipe definition generated by the compiler\n *\n * @codeGenApi\n */\nexport function ɵɵdefinePipe<T>(pipeDef: {\n /** Name of the pipe. Used for matching pipes in template to pipe defs. */\n name: string;\n\n /** Pipe class reference. Needed to extract pipe lifecycle hooks. */\n type: Type<T>;\n\n /** Whether the pipe is pure. */\n pure?: boolean;\n\n /**\n * Whether the pipe is standalone.\n */\n standalone?: boolean;\n}): unknown {\n return (<PipeDef<T>>{\n type: pipeDef.type,\n name: pipeDef.name,\n factory: null,\n pure: pipeDef.pure !== false,\n standalone: pipeDef.standalone === true,\n onDestroy: pipeDef.type.prototype.ngOnDestroy || null\n });\n}\n\n/**\n * The following getter methods retrieve the definition from the type. Currently the retrieval\n * honors inheritance, but in the future we may change the rule to require that definitions are\n * explicit. This would require some sort of migration strategy.\n */\n\nexport function getComponentDef<T>(type: any): ComponentDef<T>|null {\n return type[NG_COMP_DEF] || null;\n}\n\nexport function getDirectiveDef<T>(type: any): DirectiveDef<T>|null {\n return type[NG_DIR_DEF] || null;\n}\n\nexport function getPipeDef<T>(type: any): PipeDef<T>|null {\n return type[NG_PIPE_DEF] || null;\n}\n\n/**\n * Checks whether a given Component, Directive or Pipe is marked as standalone.\n * This will return false if passed anything other than a Component, Directive, or Pipe class\n * See this guide for additional information: https://angular.io/guide/standalone-components\n *\n * @param type A reference to a Component, Directive or Pipe.\n * @publicApi\n */\nexport function isStandalone(type: Type<unknown>): boolean {\n const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef(type);\n return def !== null ? def.standalone : false;\n}\n\nexport function getNgModuleDef<T>(type: any, throwNotFound: true): NgModuleDef<T>;\nexport function getNgModuleDef<T>(type: any): NgModuleDef<T>|null;\nexport function getNgModuleDef<T>(type: any, throwNotFound?: boolean): NgModuleDef<T>|null {\n const ngModuleDef = type[NG_MOD_DEF] || null;\n if (!ngModuleDef && throwNotFound === true) {\n throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`);\n }\n return ngModuleDef;\n}\n\nfunction getNgDirectiveDef<T>(directiveDefinition: DirectiveDefinition<T>):\n Mutable<DirectiveDef<unknown>, keyof DirectiveDef<unknown>> {\n const declaredInputs: Record<string, string> = {};\n\n return {\n type: directiveDefinition.type,\n providersResolver: null,\n factory: null,\n hostBindings: directiveDefinition.hostBindings || null,\n hostVars: directiveDefinition.hostVars || 0,\n hostAttrs: directiveDefinition.hostAttrs || null,\n contentQueries: directiveDefinition.contentQueries || null,\n declaredInputs,\n exportAs: directiveDefinition.exportAs || null,\n standalone: directiveDefinition.standalone === true,\n selectors: directiveDefinition.selectors || EMPTY_ARRAY,\n viewQuery: directiveDefinition.viewQuery || null,\n features: directiveDefinition.features || null,\n setInput: null,\n findHostDirectiveDefs: null,\n hostDirectives: null,\n inputs: invertObject(directiveDefinition.inputs, declaredInputs),\n outputs: invertObject(directiveDefinition.outputs),\n };\n}\n\nfunction initFeatures(definition:|Mutable<DirectiveDef<unknown>, keyof DirectiveDef<unknown>>|\n Mutable<ComponentDef<unknown>, keyof ComponentDef<unknown>>): void {\n definition.features?.forEach((fn) => fn(definition));\n}\n\nfunction extractDefListOrFactory(\n dependencies: TypeOrFactory<DependencyTypeList>|undefined,\n pipeDef: false): DirectiveDefListOrFactory|null;\nfunction extractDefListOrFactory(\n dependencies: TypeOrFactory<DependencyTypeList>|undefined, pipeDef: true): PipeDefListOrFactory|\n null;\nfunction extractDefListOrFactory(\n dependencies: TypeOrFactory<DependencyTypeList>|undefined, pipeDef: boolean): unknown {\n if (!dependencies) {\n return null;\n }\n\n const defExtractor = pipeDef ? getPipeDef : extractDirectiveDef;\n\n return () => (typeof dependencies === 'function' ? dependencies() : dependencies)\n .map(dep => defExtractor(dep))\n .filter(nonNull);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../../di/injector';\nimport {ProviderToken} from '../../di/provider_token';\nimport {SchemaMetadata} from '../../metadata/schema';\nimport {Sanitizer} from '../../sanitization/sanitizer';\n\nimport {LContainer} from './container';\nimport {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList, ViewQueriesFunction} from './definition';\nimport {I18nUpdateOpCodes, TI18n, TIcu} from './i18n';\nimport {TConstants, TNode} from './node';\nimport {LQueries, TQueries} from './query';\nimport {Renderer, RendererFactory} from './renderer';\nimport {RElement} from './renderer_dom';\nimport {TStylingKey, TStylingRange} from './styling';\n\n\n\n// Below are constants for LView indices to help us look up LView members\n// without having to remember the specific indices.\n// Uglify will inline these when minifying so there shouldn't be a cost.\nexport const HOST = 0;\nexport const TVIEW = 1;\nexport const FLAGS = 2;\nexport const PARENT = 3;\nexport const NEXT = 4;\nexport const TRANSPLANTED_VIEWS_TO_REFRESH = 5;\nexport const T_HOST = 6;\nexport const CLEANUP = 7;\nexport const CONTEXT = 8;\nexport const INJECTOR = 9;\nexport const RENDERER_FACTORY = 10;\nexport const RENDERER = 11;\nexport const SANITIZER = 12;\nexport const CHILD_HEAD = 13;\nexport const CHILD_TAIL = 14;\n// FIXME(misko): Investigate if the three declarations aren't all same thing.\nexport const DECLARATION_VIEW = 15;\nexport const DECLARATION_COMPONENT_VIEW = 16;\nexport const DECLARATION_LCONTAINER = 17;\nexport const PREORDER_HOOK_FLAGS = 18;\nexport const QUERIES = 19;\nexport const ID = 20;\nexport const EMBEDDED_VIEW_INJECTOR = 21;\n/**\n * Size of LView's header. Necessary to adjust for it when setting slots.\n *\n * IMPORTANT: `HEADER_OFFSET` should only be referred to the in the `ɵɵ*` instructions to translate\n * instruction index into `LView` index. All other indexes should be in the `LView` index space and\n * there should be no need to refer to `HEADER_OFFSET` anywhere else.\n */\nexport const HEADER_OFFSET = 22;\n\n\n// This interface replaces the real LView interface if it is an arg or a\n// return value of a public instruction. This ensures we don't need to expose\n// the actual interface, which should be kept private.\nexport interface OpaqueViewState {\n '__brand__': 'Brand for OpaqueViewState that nothing will match';\n}\n\n\n/**\n * `LView` stores all of the information needed to process the instructions as\n * they are invoked from the template. Each embedded view and component view has its\n * own `LView`. When processing a particular view, we set the `viewData` to that\n * `LView`. When that view is done processing, the `viewData` is set back to\n * whatever the original `viewData` was before (the parent `LView`).\n *\n * Keeping separate state for each view facilities view insertion / deletion, so we\n * don't have to edit the data array based on which views are present.\n */\nexport interface LView<T = unknown> extends Array<any> {\n /**\n * The node into which this `LView` is inserted.\n */\n [HOST]: RElement|null;\n\n /**\n * The static data for this view. We need a reference to this so we can easily walk up the\n * node tree in DI and get the TView.data array associated with a node (where the\n * directive defs are stored).\n */\n readonly[TVIEW]: TView;\n\n /** Flags for this view. See LViewFlags for more info. */\n [FLAGS]: LViewFlags;\n\n /**\n * This may store an {@link LView} or {@link LContainer}.\n *\n * `LView` - The parent view. This is needed when we exit the view and must restore the previous\n * LView. Without this, the render method would have to keep a stack of\n * views as it is recursively rendering templates.\n *\n * `LContainer` - The current view is part of a container, and is an embedded view.\n */\n [PARENT]: LView|LContainer|null;\n\n /**\n *\n * The next sibling LView or LContainer.\n *\n * Allows us to propagate between sibling view states that aren't in the same\n * container. Embedded views already have a node.next, but it is only set for\n * views in the same container. We need a way to link component views and views\n * across containers as well.\n */\n [NEXT]: LView|LContainer|null;\n\n /** Queries active for this view - nodes from a view are reported to those queries. */\n [QUERIES]: LQueries|null;\n\n /**\n * Store the `TNode` of the location where the current `LView` is inserted into.\n *\n * Given:\n * ```\n * <div>\n * <ng-template><span></span></ng-template>\n * </div>\n * ```\n *\n * We end up with two `TView`s.\n * - `parent` `TView` which contains `<div><!-- anchor --></div>`\n * - `child` `TView` which contains `<span></span>`\n *\n * Typically the `child` is inserted into the declaration location of the `parent`, but it can be\n * inserted anywhere. Because it can be inserted anywhere it is not possible to store the\n * insertion information in the `TView` and instead we must store it in the `LView[T_HOST]`.\n *\n * So to determine where is our insertion parent we would execute:\n * ```\n * const parentLView = lView[PARENT];\n * const parentTNode = lView[T_HOST];\n * const insertionParent = parentLView[parentTNode.index];\n * ```\n *\n *\n * If `null`, this is the root view of an application (root component is in this view) and it has\n * no parents.\n */\n [T_HOST]: TNode|null;\n\n /**\n * When a view is destroyed, listeners need to be released and outputs need to be\n * unsubscribed. This context array stores both listener functions wrapped with\n * their context and output subscription instances for a particular view.\n *\n * These change per LView instance, so they cannot be stored on TView. Instead,\n * TView.cleanup saves an index to the necessary context in this array.\n *\n * After `LView` is created it is possible to attach additional instance specific functions at the\n * end of the `lView[CLEANUP]` because we know that no more `T` level cleanup functions will be\n * added here.\n */\n [CLEANUP]: any[]|null;\n\n /**\n * - For dynamic views, this is the context with which to render the template (e.g.\n * `NgForContext`), or `{}` if not defined explicitly.\n * - For root view of the root component it's a reference to the component instance itself.\n * - For components, the context is a reference to the component instance itself.\n * - For inline views, the context is null.\n */\n [CONTEXT]: T;\n\n /** An optional Module Injector to be used as fall back after Element Injectors are consulted. */\n readonly[INJECTOR]: Injector|null;\n\n /** Factory to be used for creating Renderer. */\n [RENDERER_FACTORY]: RendererFactory;\n\n /** Renderer to be used for this view. */\n [RENDERER]: Renderer;\n\n /** An optional custom sanitizer. */\n [SANITIZER]: Sanitizer|null;\n\n /**\n * Reference to the first LView or LContainer beneath this LView in\n * the hierarchy.\n *\n * Necessary to store this so views can traverse through their nested views\n * to remove listeners and call onDestroy callbacks.\n */\n [CHILD_HEAD]: LView|LContainer|null;\n\n /**\n * The last LView or LContainer beneath this LView in the hierarchy.\n *\n * The tail allows us to quickly add a new state to the end of the view list\n * without having to propagate starting from the first child.\n */\n [CHILD_TAIL]: LView|LContainer|null;\n\n /**\n * View where this view's template was declared.\n *\n * The template for a dynamically created view may be declared in a different view than\n * it is inserted. We already track the \"insertion view\" (view where the template was\n * inserted) in LView[PARENT], but we also need access to the \"declaration view\"\n * (view where the template was declared). Otherwise, we wouldn't be able to call the\n * view's template function with the proper contexts. Context should be inherited from\n * the declaration view tree, not the insertion view tree.\n *\n * Example (AppComponent template):\n *\n * <ng-template #foo></ng-template> <-- declared here -->\n * <some-comp [tpl]=\"foo\"></some-comp> <-- inserted inside this component -->\n *\n * The <ng-template> above is declared in the AppComponent template, but it will be passed into\n * SomeComp and inserted there. In this case, the declaration view would be the AppComponent,\n * but the insertion view would be SomeComp. When we are removing views, we would want to\n * traverse through the insertion view to clean up listeners. When we are calling the\n * template function during change detection, we need the declaration view to get inherited\n * context.\n */\n [DECLARATION_VIEW]: LView|null;\n\n\n /**\n * Points to the declaration component view, used to track transplanted `LView`s.\n *\n * See: `DECLARATION_VIEW` which points to the actual `LView` where it was declared, whereas\n * `DECLARATION_COMPONENT_VIEW` points to the component which may not be same as\n * `DECLARATION_VIEW`.\n *\n * Example:\n * ```\n * <#VIEW #myComp>\n * <div *ngIf=\"true\">\n * <ng-template #myTmpl>...</ng-template>\n * </div>\n * </#VIEW>\n * ```\n * In the above case `DECLARATION_VIEW` for `myTmpl` points to the `LView` of `ngIf` whereas\n * `DECLARATION_COMPONENT_VIEW` points to `LView` of the `myComp` which owns the template.\n *\n * The reason for this is that all embedded views are always check-always whereas the component\n * view can be check-always or on-push. When we have a transplanted view it is important to\n * determine if we have transplanted a view from check-always declaration to on-push insertion\n * point. In such a case the transplanted view needs to be added to the `LContainer` in the\n * declared `LView` and CD during the declared view CD (in addition to the CD at the insertion\n * point.) (Any transplanted views which are intra Component are of no interest because the CD\n * strategy of declaration and insertion will always be the same, because it is the same\n * component.)\n *\n * Queries already track moved views in `LView[DECLARATION_LCONTAINER]` and\n * `LContainer[MOVED_VIEWS]`. However the queries also track `LView`s which moved within the same\n * component `LView`. Transplanted views are a subset of moved views, and we use\n * `DECLARATION_COMPONENT_VIEW` to differentiate them. As in this example.\n *\n * Example showing intra component `LView` movement.\n * ```\n * <#VIEW #myComp>\n * <div *ngIf=\"condition; then thenBlock else elseBlock\"></div>\n * <ng-template #thenBlock>Content to render when condition is true.</ng-template>\n * <ng-template #elseBlock>Content to render when condition is false.</ng-template>\n * </#VIEW>\n * ```\n * The `thenBlock` and `elseBlock` is moved but not transplanted.\n *\n * Example showing inter component `LView` movement (transplanted view).\n * ```\n * <#VIEW #myComp>\n * <ng-template #myTmpl>...</ng-template>\n * <insertion-component [template]=\"myTmpl\"></insertion-component>\n * </#VIEW>\n * ```\n * In the above example `myTmpl` is passed into a different component. If `insertion-component`\n * instantiates `myTmpl` and `insertion-component` is on-push then the `LContainer` needs to be\n * marked as containing transplanted views and those views need to be CD as part of the\n * declaration CD.\n *\n *\n * When change detection runs, it iterates over `[MOVED_VIEWS]` and CDs any child `LView`s where\n * the `DECLARATION_COMPONENT_VIEW` of the current component and the child `LView` does not match\n * (it has been transplanted across components.)\n *\n * Note: `[DECLARATION_COMPONENT_VIEW]` points to itself if the LView is a component view (the\n * simplest / most common case).\n *\n * see also:\n * - https://hackmd.io/@mhevery/rJUJsvv9H write up of the problem\n * - `LContainer[HAS_TRANSPLANTED_VIEWS]` which marks which `LContainer` has transplanted views.\n * - `LContainer[TRANSPLANT_HEAD]` and `LContainer[TRANSPLANT_TAIL]` storage for transplanted\n * - `LView[DECLARATION_LCONTAINER]` similar problem for queries\n * - `LContainer[MOVED_VIEWS]` similar problem for queries\n */\n [DECLARATION_COMPONENT_VIEW]: LView;\n\n /**\n * A declaration point of embedded views (ones instantiated based on the content of a\n * <ng-template>), null for other types of views.\n *\n * We need to track all embedded views created from a given declaration point so we can prepare\n * query matches in a proper order (query matches are ordered based on their declaration point and\n * _not_ the insertion point).\n */\n [DECLARATION_LCONTAINER]: LContainer|null;\n\n /**\n * More flags for this view. See PreOrderHookFlags for more info.\n */\n [PREORDER_HOOK_FLAGS]: PreOrderHookFlags;\n\n /**\n * The number of direct transplanted views which need a refresh or have descendants themselves\n * that need a refresh but have not marked their ancestors as Dirty. This tells us that during\n * change detection we should still descend to find those children to refresh, even if the parents\n * are not `Dirty`/`CheckAlways`.\n */\n [TRANSPLANTED_VIEWS_TO_REFRESH]: number;\n\n /** Unique ID of the view. Used for `__ngContext__` lookups in the `LView` registry. */\n [ID]: number;\n\n /**\n * Optional injector assigned to embedded views that takes\n * precedence over the element and module injectors.\n */\n readonly[EMBEDDED_VIEW_INJECTOR]: Injector|null;\n}\n\n/** Flags associated with an LView (saved in LView[FLAGS]) */\nexport const enum LViewFlags {\n /** The state of the init phase on the first 2 bits */\n InitPhaseStateIncrementer = 0b00000000001,\n InitPhaseStateMask = 0b00000000011,\n\n /**\n * Whether or not the view is in creationMode.\n *\n * This must be stored in the view rather than using `data` as a marker so that\n * we can properly support embedded views. Otherwise, when exiting a child view\n * back into the parent view, `data` will be defined and `creationMode` will be\n * improperly reported as false.\n */\n CreationMode = 0b00000000100,\n\n /**\n * Whether or not this LView instance is on its first processing pass.\n *\n * An LView instance is considered to be on its \"first pass\" until it\n * has completed one creation mode run and one update mode run. At this\n * time, the flag is turned off.\n */\n FirstLViewPass = 0b00000001000,\n\n /** Whether this view has default change detection strategy (checks always) or onPush */\n CheckAlways = 0b00000010000,\n\n /** Whether or not this view is currently dirty (needing check) */\n Dirty = 0b00000100000,\n\n /** Whether or not this view is currently attached to change detection tree. */\n Attached = 0b000001000000,\n\n /** Whether or not this view is destroyed. */\n Destroyed = 0b000010000000,\n\n /** Whether or not this view is the root view */\n IsRoot = 0b000100000000,\n\n /**\n * Whether this moved LView was needs to be refreshed at the insertion location because the\n * declaration was dirty.\n */\n RefreshTransplantedView = 0b001000000000,\n\n /** Indicates that the view **or any of its ancestors** have an embedded view injector. */\n HasEmbeddedViewInjector = 0b0010000000000,\n\n /**\n * Index of the current init phase on last 21 bits\n */\n IndexWithinInitPhaseIncrementer = 0b0100000000000,\n IndexWithinInitPhaseShift = 11,\n IndexWithinInitPhaseReset = 0b0011111111111,\n}\n\n/**\n * Possible states of the init phase:\n * - 00: OnInit hooks to be run.\n * - 01: AfterContentInit hooks to be run\n * - 10: AfterViewInit hooks to be run\n * - 11: All init hooks have been run\n */\nexport const enum InitPhaseState {\n OnInitHooksToBeRun = 0b00,\n AfterContentInitHooksToBeRun = 0b01,\n AfterViewInitHooksToBeRun = 0b10,\n InitPhaseCompleted = 0b11,\n}\n\n/** More flags associated with an LView (saved in LView[PREORDER_HOOK_FLAGS]) */\nexport const enum PreOrderHookFlags {\n /**\n The index of the next pre-order hook to be called in the hooks array, on the first 16\n bits\n */\n IndexOfTheNextPreOrderHookMaskMask = 0b01111111111111111,\n\n /**\n * The number of init hooks that have already been called, on the last 16 bits\n */\n NumberOfInitHooksCalledIncrementer = 0b010000000000000000,\n NumberOfInitHooksCalledShift = 16,\n NumberOfInitHooksCalledMask = 0b11111111111111110000000000000000,\n}\n\n/**\n * Stores a set of OpCodes to process `HostBindingsFunction` associated with a current view.\n *\n * In order to invoke `HostBindingsFunction` we need:\n * 1. 'elementIdx`: Index to the element associated with the `HostBindingsFunction`.\n * 2. 'directiveIdx`: Index to the directive associated with the `HostBindingsFunction`. (This will\n * become the context for the `HostBindingsFunction` invocation.)\n * 3. `bindingRootIdx`: Location where the bindings for the `HostBindingsFunction` start. Internally\n * `HostBindingsFunction` binding indexes start from `0` so we need to add `bindingRootIdx` to\n * it.\n * 4. `HostBindingsFunction`: A host binding function to execute.\n *\n * The above information needs to be encoded into the `HostBindingOpCodes` in an efficient manner.\n *\n * 1. `elementIdx` is encoded into the `HostBindingOpCodes` as `~elementIdx` (so a negative number);\n * 2. `directiveIdx`\n * 3. `bindingRootIdx`\n * 4. `HostBindingsFunction` is passed in as is.\n *\n * The `HostBindingOpCodes` array contains:\n * - negative number to select the element index.\n * - followed by 1 or more of:\n * - a number to select the directive index\n * - a number to select the bindingRoot index\n * - and a function to invoke.\n *\n * ## Example\n *\n * ```\n * const hostBindingOpCodes = [\n * ~30, // Select element 30\n * 40, 45, MyDir.ɵdir.hostBindings // Invoke host bindings on MyDir on element 30;\n * // directiveIdx = 40; bindingRootIdx = 45;\n * 50, 55, OtherDir.ɵdir.hostBindings // Invoke host bindings on OtherDire on element 30\n * // directiveIdx = 50; bindingRootIdx = 55;\n * ]\n * ```\n *\n * ## Pseudocode\n * ```\n * const hostBindingOpCodes = tView.hostBindingOpCodes;\n * if (hostBindingOpCodes === null) return;\n * for (let i = 0; i < hostBindingOpCodes.length; i++) {\n * const opCode = hostBindingOpCodes[i] as number;\n * if (opCode < 0) {\n * // Negative numbers are element indexes.\n * setSelectedIndex(~opCode);\n * } else {\n * // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex.\n * const directiveIdx = opCode;\n * const bindingRootIndx = hostBindingOpCodes[++i] as number;\n * const hostBindingFn = hostBindingOpCodes[++i] as HostBindingsFunction<any>;\n * setBindingRootForHostBindings(bindingRootIndx, directiveIdx);\n * const context = lView[directiveIdx];\n * hostBindingFn(RenderFlags.Update, context);\n * }\n * }\n * ```\n *\n */\nexport interface HostBindingOpCodes extends Array<number|HostBindingsFunction<any>> {\n __brand__: 'HostBindingOpCodes';\n debug?: string[];\n}\n\n/**\n * Explicitly marks `TView` as a specific type in `ngDevMode`\n *\n * It is useful to know conceptually what time of `TView` we are dealing with when\n * debugging an application (even if the runtime does not need it.) For this reason\n * we store this information in the `ngDevMode` `TView` and than use it for\n * better debugging experience.\n */\nexport const enum TViewType {\n /**\n * Root `TView` is the used to bootstrap components into. It is used in conjunction with\n * `LView` which takes an existing DOM node not owned by Angular and wraps it in `TView`/`LView`\n * so that other components can be loaded into it.\n */\n Root = 0,\n\n /**\n * `TView` associated with a Component. This would be the `TView` directly associated with the\n * component view (as opposed an `Embedded` `TView` which would be a child of `Component` `TView`)\n */\n Component = 1,\n\n /**\n * `TView` associated with a template. Such as `*ngIf`, `<ng-template>` etc... A `Component`\n * can have zero or more `Embedded` `TView`s.\n */\n Embedded = 2,\n}\n\n/**\n * The static data for an LView (shared between all templates of a\n * given type).\n *\n * Stored on the `ComponentDef.tView`.\n */\nexport interface TView {\n /**\n * Type of `TView` (`Root`|`Component`|`Embedded`).\n */\n type: TViewType;\n\n /**\n * This is a blueprint used to generate LView instances for this TView. Copying this\n * blueprint is faster than creating a new LView from scratch.\n */\n blueprint: LView;\n\n /**\n * The template function used to refresh the view of dynamically created views\n * and components. Will be null for inline views.\n */\n template: ComponentTemplate<{}>|null;\n\n /**\n * A function containing query-related instructions.\n */\n viewQuery: ViewQueriesFunction<{}>|null;\n\n /**\n * A `TNode` representing the declaration location of this `TView` (not part of this TView).\n */\n declTNode: TNode|null;\n\n // FIXME(misko): Why does `TView` not have `declarationTView` property?\n\n /** Whether or not this template has been processed in creation mode. */\n firstCreatePass: boolean;\n\n /**\n * Whether or not this template has been processed in update mode (e.g. change detected)\n *\n * `firstUpdatePass` is used by styling to set up `TData` to contain metadata about the styling\n * instructions. (Mainly to build up a linked list of styling priority order.)\n *\n * Typically this function gets cleared after first execution. If exception is thrown then this\n * flag can remain turned un until there is first successful (no exception) pass. This means that\n * individual styling instructions keep track of if they have already been added to the linked\n * list to prevent double adding.\n */\n firstUpdatePass: boolean;\n\n /** Static data equivalent of LView.data[]. Contains TNodes, PipeDefInternal or TI18n. */\n data: TData;\n\n /**\n * The binding start index is the index at which the data array\n * starts to store bindings only. Saving this value ensures that we\n * will begin reading bindings at the correct point in the array when\n * we are in update mode.\n *\n * -1 means that it has not been initialized.\n */\n bindingStartIndex: number;\n\n /**\n * The index where the \"expando\" section of `LView` begins. The expando\n * section contains injectors, directive instances, and host binding values.\n * Unlike the \"decls\" and \"vars\" sections of `LView`, the length of this\n * section cannot be calculated at compile-time because directives are matched\n * at runtime to preserve locality.\n *\n * We store this start index so we know where to start checking host bindings\n * in `setHostBindings`.\n */\n expandoStartIndex: number;\n\n /**\n * Whether or not there are any static view queries tracked on this view.\n *\n * We store this so we know whether or not we should do a view query\n * refresh after creation mode to collect static query results.\n */\n staticViewQueries: boolean;\n\n /**\n * Whether or not there are any static content queries tracked on this view.\n *\n * We store this so we know whether or not we should do a content query\n * refresh after creation mode to collect static query results.\n */\n staticContentQueries: boolean;\n\n /**\n * A reference to the first child node located in the view.\n */\n firstChild: TNode|null;\n\n /**\n * Stores the OpCodes to be replayed during change-detection to process the `HostBindings`\n *\n * See `HostBindingOpCodes` for encoding details.\n */\n hostBindingOpCodes: HostBindingOpCodes|null;\n\n /**\n * Full registry of directives and components that may be found in this view.\n *\n * It's necessary to keep a copy of the full def list on the TView so it's possible\n * to render template functions without a host component.\n */\n directiveRegistry: DirectiveDefList|null;\n\n /**\n * Full registry of pipes that may be found in this view.\n *\n * The property is either an array of `PipeDefs`s or a function which returns the array of\n * `PipeDefs`s. The function is necessary to be able to support forward declarations.\n *\n * It's necessary to keep a copy of the full def list on the TView so it's possible\n * to render template functions without a host component.\n */\n pipeRegistry: PipeDefList|null;\n\n /**\n * Array of ngOnInit, ngOnChanges and ngDoCheck hooks that should be executed for this view in\n * creation mode.\n *\n * This array has a flat structure and contains TNode indices, directive indices (where an\n * instance can be found in `LView`) and hook functions. TNode index is followed by the directive\n * index and a hook function. If there are multiple hooks for a given TNode, the TNode index is\n * not repeated and the next lifecycle hook information is stored right after the previous hook\n * function. This is done so that at runtime the system can efficiently iterate over all of the\n * functions to invoke without having to make any decisions/lookups.\n */\n preOrderHooks: HookData|null;\n\n /**\n * Array of ngOnChanges and ngDoCheck hooks that should be executed for this view in update mode.\n *\n * This array has the same structure as the `preOrderHooks` one.\n */\n preOrderCheckHooks: HookData|null;\n\n /**\n * Array of ngAfterContentInit and ngAfterContentChecked hooks that should be executed\n * for this view in creation mode.\n *\n * Even indices: Directive index\n * Odd indices: Hook function\n */\n contentHooks: HookData|null;\n\n /**\n * Array of ngAfterContentChecked hooks that should be executed for this view in update\n * mode.\n *\n * Even indices: Directive index\n * Odd indices: Hook function\n */\n contentCheckHooks: HookData|null;\n\n /**\n * Array of ngAfterViewInit and ngAfterViewChecked hooks that should be executed for\n * this view in creation mode.\n *\n * Even indices: Directive index\n * Odd indices: Hook function\n */\n viewHooks: HookData|null;\n\n /**\n * Array of ngAfterViewChecked hooks that should be executed for this view in\n * update mode.\n *\n * Even indices: Directive index\n * Odd indices: Hook function\n */\n viewCheckHooks: HookData|null;\n\n /**\n * Array of ngOnDestroy hooks that should be executed when this view is destroyed.\n *\n * Even indices: Directive index\n * Odd indices: Hook function\n */\n destroyHooks: DestroyHookData|null;\n\n /**\n * When a view is destroyed, listeners need to be released and outputs need to be\n * unsubscribed. This cleanup array stores both listener data (in chunks of 4)\n * and output data (in chunks of 2) for a particular view. Combining the arrays\n * saves on memory (70 bytes per array) and on a few bytes of code size (for two\n * separate for loops).\n *\n * If it's a native DOM listener or output subscription being stored:\n * 1st index is: event name `name = tView.cleanup[i+0]`\n * 2nd index is: index of native element or a function that retrieves global target (window,\n * document or body) reference based on the native element:\n * `typeof idxOrTargetGetter === 'function'`: global target getter function\n * `typeof idxOrTargetGetter === 'number'`: index of native element\n *\n * 3rd index is: index of listener function `listener = lView[CLEANUP][tView.cleanup[i+2]]`\n * 4th index is: `useCaptureOrIndx = tView.cleanup[i+3]`\n * `typeof useCaptureOrIndx == 'boolean' : useCapture boolean\n * `typeof useCaptureOrIndx == 'number':\n * `useCaptureOrIndx >= 0` `removeListener = LView[CLEANUP][useCaptureOrIndx]`\n * `useCaptureOrIndx < 0` `subscription = LView[CLEANUP][-useCaptureOrIndx]`\n *\n * If it's an output subscription or query list destroy hook:\n * 1st index is: output unsubscribe function / query list destroy function\n * 2nd index is: index of function context in LView.cleanupInstances[]\n * `tView.cleanup[i+0].call(lView[CLEANUP][tView.cleanup[i+1]])`\n */\n cleanup: any[]|null;\n\n /**\n * A list of element indices for child components that will need to be\n * refreshed when the current view has finished its check. These indices have\n * already been adjusted for the HEADER_OFFSET.\n *\n */\n components: number[]|null;\n\n /**\n * A collection of queries tracked in a given view.\n */\n queries: TQueries|null;\n\n /**\n * An array of indices pointing to directives with content queries alongside with the\n * corresponding query index. Each entry in this array is a tuple of:\n * - index of the first content query index declared by a given directive;\n * - index of a directive.\n *\n * We are storing those indexes so we can refresh content queries as part of a view refresh\n * process.\n */\n contentQueries: number[]|null;\n\n /**\n * Set of schemas that declare elements to be allowed inside the view.\n */\n schemas: SchemaMetadata[]|null;\n\n /**\n * Array of constants for the view. Includes attribute arrays, local definition arrays etc.\n * Used for directive matching, attribute bindings, local definitions and more.\n */\n consts: TConstants|null;\n\n /**\n * Indicates that there was an error before we managed to complete the first create pass of the\n * view. This means that the view is likely corrupted and we should try to recover it.\n */\n incompleteFirstPass: boolean;\n}\n\n/** Single hook callback function. */\nexport type HookFn = () => void;\n\n/**\n * Information necessary to call a hook. E.g. the callback that\n * needs to invoked and the index at which to find its context.\n */\nexport type HookEntry = number|HookFn;\n\n/**\n * Array of hooks that should be executed for a view and their directive indices.\n *\n * For each node of the view, the following data is stored:\n * 1) Node index (optional)\n * 2) A series of number/function pairs where:\n * - even indices are directive indices\n * - odd indices are hook functions\n *\n * Special cases:\n * - a negative directive index flags an init hook (ngOnInit, ngAfterContentInit, ngAfterViewInit)\n */\nexport type HookData = HookEntry[];\n\n/**\n * Array of destroy hooks that should be executed for a view and their directive indices.\n *\n * The array is set up as a series of number/function or number/(number|function)[]:\n * - Even indices represent the context with which hooks should be called.\n * - Odd indices are the hook functions themselves. If a value at an odd index is an array,\n * it represents the destroy hooks of a `multi` provider where:\n * - Even indices represent the index of the provider for which we've registered a destroy hook,\n * inside of the `multi` provider array.\n * - Odd indices are the destroy hook functions.\n * For example:\n * LView: `[0, 1, 2, AService, 4, [BService, CService, DService]]`\n * destroyHooks: `[3, AService.ngOnDestroy, 5, [0, BService.ngOnDestroy, 2, DService.ngOnDestroy]]`\n *\n * In the example above `AService` is a type provider with an `ngOnDestroy`, whereas `BService`,\n * `CService` and `DService` are part of a `multi` provider where only `BService` and `DService`\n * have an `ngOnDestroy` hook.\n */\nexport type DestroyHookData = (HookEntry|HookData)[];\n\n/**\n * Static data that corresponds to the instance-specific data array on an LView.\n *\n * Each node's static data is stored in tData at the same index that it's stored\n * in the data array. Any nodes that do not have static data store a null value in\n * tData to avoid a sparse array.\n *\n * Each pipe's definition is stored here at the same index as its pipe instance in\n * the data array.\n *\n * Each host property's name is stored here at the same index as its value in the\n * data array.\n *\n * Each property binding name is stored here at the same index as its value in\n * the data array. If the binding is an interpolation, the static string values\n * are stored parallel to the dynamic values. Example:\n *\n * id=\"prefix {{ v0 }} a {{ v1 }} b {{ v2 }} suffix\"\n *\n * LView | TView.data\n *------------------------\n * v0 value | 'a'\n * v1 value | 'b'\n * v2 value | id � prefix � suffix\n *\n * Injector bloom filters are also stored here.\n */\nexport type TData = (TNode|PipeDef<any>|DirectiveDef<any>|ComponentDef<any>|number|TStylingRange|\n TStylingKey|ProviderToken<any>|TI18n|I18nUpdateOpCodes|TIcu|null|string)[];\n\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nexport const unusedValueExportToPlacateAjd = 1;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {TNode} from './node';\nimport {RComment, RElement} from './renderer_dom';\nimport {HOST, LView, NEXT, PARENT, T_HOST, TRANSPLANTED_VIEWS_TO_REFRESH} from './view';\n\n\n\n/**\n * Special location which allows easy identification of type. If we have an array which was\n * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is\n * `LContainer`.\n */\nexport const TYPE = 1;\n\n/**\n * Below are constants for LContainer indices to help us look up LContainer members\n * without having to remember the specific indices.\n * Uglify will inline these when minifying so there shouldn't be a cost.\n */\n\n/**\n * Flag to signify that this `LContainer` may have transplanted views which need to be change\n * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.\n *\n * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip\n * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify\n * that the `MOVED_VIEWS` are transplanted and on-push.\n */\nexport const HAS_TRANSPLANTED_VIEWS = 2;\n\n// PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5\n// As we already have these constants in LView, we don't need to re-create them.\n\n// T_HOST is index 6\n// We already have this constants in LView, we don't need to re-create it.\n\nexport const NATIVE = 7;\nexport const VIEW_REFS = 8;\nexport const MOVED_VIEWS = 9;\n\n\n/**\n * Size of LContainer's header. Represents the index after which all views in the\n * container will be inserted. We need to keep a record of current views so we know\n * which views are already in the DOM (and don't need to be re-added) and so we can\n * remove views from the DOM when they are no longer required.\n */\nexport const CONTAINER_HEADER_OFFSET = 10;\n\n/**\n * The state associated with a container.\n *\n * This is an array so that its structure is closer to LView. This helps\n * when traversing the view tree (which is a mix of containers and component\n * views), so we can jump to viewOrContainer[NEXT] in the same way regardless\n * of type.\n */\nexport interface LContainer extends Array<any> {\n /**\n * The host element of this LContainer.\n *\n * The host could be an LView if this container is on a component node.\n * In that case, the component LView is its HOST.\n */\n readonly[HOST]: RElement|RComment|LView;\n\n /**\n * This is a type field which allows us to differentiate `LContainer` from `StylingContext` in an\n * efficient way. The value is always set to `true`\n */\n [TYPE]: true;\n\n /**\n * Flag to signify that this `LContainer` may have transplanted views which need to be change\n * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.\n *\n * This flag, once set, is never unset for the `LContainer`.\n */\n [HAS_TRANSPLANTED_VIEWS]: boolean;\n\n /**\n * Access to the parent view is necessary so we can propagate back\n * up from inside a container to parent[NEXT].\n */\n [PARENT]: LView;\n\n /**\n * This allows us to jump from a container to a sibling container or component\n * view with the same parent, so we can remove listeners efficiently.\n */\n [NEXT]: LView|LContainer|null;\n\n /**\n * The number of direct transplanted views which need a refresh or have descendants themselves\n * that need a refresh but have not marked their ancestors as Dirty. This tells us that during\n * change detection we should still descend to find those children to refresh, even if the parents\n * are not `Dirty`/`CheckAlways`.\n */\n [TRANSPLANTED_VIEWS_TO_REFRESH]: number;\n\n /**\n * A collection of views created based on the underlying `<ng-template>` element but inserted into\n * a different `LContainer`. We need to track views created from a given declaration point since\n * queries collect matches from the embedded view declaration point and _not_ the insertion point.\n */\n [MOVED_VIEWS]: LView[]|null;\n\n /**\n * Pointer to the `TNode` which represents the host of the container.\n */\n [T_HOST]: TNode;\n\n /** The comment element that serves as an anchor for this LContainer. */\n readonly[NATIVE]:\n RComment; // TODO(misko): remove as this value can be gotten by unwrapping `[HOST]`\n\n /**\n * Array of `ViewRef`s used by any `ViewContainerRef`s that point to this container.\n *\n * This is lazily initialized by `ViewContainerRef` when the first view is inserted.\n *\n * NOTE: This is stored as `any[]` because render3 should really not be aware of `ViewRef` and\n * doing so creates circular dependency.\n */\n [VIEW_REFS]: unknown[]|null;\n}\n\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nexport const unusedValueExportToPlacateAjd = 1;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {LContainer, TYPE} from './container';\nimport {ComponentDef, DirectiveDef} from './definition';\nimport {TNode, TNodeFlags} from './node';\nimport {RNode} from './renderer_dom';\nimport {FLAGS, LView, LViewFlags} from './view';\n\n\n/**\n * True if `value` is `LView`.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nexport function isLView(value: RNode|LView|LContainer|{}|null): value is LView {\n return Array.isArray(value) && typeof value[TYPE] === 'object';\n}\n\n/**\n * True if `value` is `LContainer`.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nexport function isLContainer(value: RNode|LView|LContainer|{}|null): value is LContainer {\n return Array.isArray(value) && value[TYPE] === true;\n}\n\nexport function isContentQueryHost(tNode: TNode): boolean {\n return (tNode.flags & TNodeFlags.hasContentQuery) !== 0;\n}\n\nexport function isComponentHost(tNode: TNode): boolean {\n return tNode.componentOffset > -1;\n}\n\nexport function isDirectiveHost(tNode: TNode): boolean {\n return (tNode.flags & TNodeFlags.isDirectiveHost) === TNodeFlags.isDirectiveHost;\n}\n\nexport function isComponentDef<T>(def: DirectiveDef<T>): def is ComponentDef<T> {\n return !!(def as ComponentDef<T>).template;\n}\n\nexport function isRootView(target: LView): boolean {\n return (target[FLAGS] & LViewFlags.IsRoot) !== 0;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\nimport {stringify} from '../util/stringify';\nimport {NG_FACTORY_DEF} from './fields';\n\n\n/**\n * Definition of what a factory function should look like.\n */\nexport type FactoryFn<T> = {\n /**\n * Subclasses without an explicit constructor call through to the factory of their base\n * definition, providing it with their own constructor to instantiate.\n */\n <U extends T>(t?: Type<U>): U;\n\n /**\n * If no constructor to instantiate is provided, an instance of type T itself is created.\n */\n (t?: undefined): T;\n};\n\n\nexport function getFactoryDef<T>(type: any, throwNotFound: true): FactoryFn<T>;\nexport function getFactoryDef<T>(type: any): FactoryFn<T>|null;\nexport function getFactoryDef<T>(type: any, throwNotFound?: boolean): FactoryFn<T>|null {\n const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);\n if (!hasFactoryDef && throwNotFound === true && ngDevMode) {\n throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`);\n }\n return hasFactoryDef ? type[NG_FACTORY_DEF] : null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Represents a basic change from a previous to a new value for a single\n * property on a directive instance. Passed as a value in a\n * {@link SimpleChanges} object to the `ngOnChanges` hook.\n *\n * @see `OnChanges`\n *\n * @publicApi\n */\nexport class SimpleChange {\n constructor(public previousValue: any, public currentValue: any, public firstChange: boolean) {}\n /**\n * Check whether the new value is the first value assigned.\n */\n isFirstChange(): boolean {\n return this.firstChange;\n }\n}\n\n/**\n * A hashtable of changes represented by {@link SimpleChange} objects stored\n * at the declared property name they belong to on a Directive or Component. This is\n * the type passed to the `ngOnChanges` hook.\n *\n * @see `OnChanges`\n *\n * @publicApi\n */\nexport interface SimpleChanges {\n [propName: string]: SimpleChange;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {OnChanges} from '../../interface/lifecycle_hooks';\nimport {SimpleChange, SimpleChanges} from '../../interface/simple_change';\nimport {assertString} from '../../util/assert';\nimport {EMPTY_OBJ} from '../../util/empty';\nimport {DirectiveDef, DirectiveDefFeature} from '../interfaces/definition';\n\n/**\n * The NgOnChangesFeature decorates a component with support for the ngOnChanges\n * lifecycle hook, so it should be included in any component that implements\n * that hook.\n *\n * If the component or directive uses inheritance, the NgOnChangesFeature MUST\n * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise\n * inherited properties will not be propagated to the ngOnChanges lifecycle\n * hook.\n *\n * Example usage:\n *\n * ```\n * static ɵcmp = defineComponent({\n * ...\n * inputs: {name: 'publicName'},\n * features: [NgOnChangesFeature]\n * });\n * ```\n *\n * @codeGenApi\n */\nexport function ɵɵNgOnChangesFeature<T>(): DirectiveDefFeature {\n return NgOnChangesFeatureImpl;\n}\n\nexport function NgOnChangesFeatureImpl<T>(definition: DirectiveDef<T>) {\n if (definition.type.prototype.ngOnChanges) {\n definition.setInput = ngOnChangesSetInput;\n }\n return rememberChangeHistoryAndInvokeOnChangesHook;\n}\n\n// This option ensures that the ngOnChanges lifecycle hook will be inherited\n// from superclasses (in InheritDefinitionFeature).\n/** @nocollapse */\n// tslint:disable-next-line:no-toplevel-property-access\n(ɵɵNgOnChangesFeature as DirectiveDefFeature).ngInherit = true;\n\n/**\n * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate\n * `ngOnChanges`.\n *\n * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are\n * found it invokes `ngOnChanges` on the component instance.\n *\n * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,\n * it is guaranteed to be called with component instance.\n */\nfunction rememberChangeHistoryAndInvokeOnChangesHook(this: OnChanges) {\n const simpleChangesStore = getSimpleChangesStore(this);\n const current = simpleChangesStore?.current;\n\n if (current) {\n const previous = simpleChangesStore!.previous;\n if (previous === EMPTY_OBJ) {\n simpleChangesStore!.previous = current;\n } else {\n // New changes are copied to the previous store, so that we don't lose history for inputs\n // which were not changed this time\n for (let key in current) {\n previous[key] = current[key];\n }\n }\n simpleChangesStore!.current = null;\n this.ngOnChanges(current);\n }\n}\n\n\nfunction ngOnChangesSetInput<T>(\n this: DirectiveDef<T>, instance: T, value: any, publicName: string, privateName: string): void {\n const declaredName = (this.declaredInputs as {[key: string]: string})[publicName];\n ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');\n const simpleChangesStore = getSimpleChangesStore(instance) ||\n setSimpleChangesStore(instance, {previous: EMPTY_OBJ, current: null});\n const current = simpleChangesStore.current || (simpleChangesStore.current = {});\n const previous = simpleChangesStore.previous;\n const previousChange = previous[declaredName];\n current[declaredName] = new SimpleChange(\n previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);\n\n (instance as any)[privateName] = value;\n}\n\nconst SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';\n\nfunction getSimpleChangesStore(instance: any): null|NgSimpleChangesStore {\n return instance[SIMPLE_CHANGES_STORE] || null;\n}\n\nfunction setSimpleChangesStore(instance: any, store: NgSimpleChangesStore): NgSimpleChangesStore {\n return instance[SIMPLE_CHANGES_STORE] = store;\n}\n\n/**\n * Data structure which is monkey-patched on the component instance and used by `ngOnChanges`\n * life-cycle hook to track previous input values.\n */\ninterface NgSimpleChangesStore {\n previous: SimpleChanges;\n current: SimpleChanges|null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Profiler events is an enum used by the profiler to distinguish between different calls of user\n * code invoked throughout the application lifecycle.\n */\nexport const enum ProfilerEvent {\n /**\n * Corresponds to the point in time before the runtime has called the template function of a\n * component with `RenderFlags.Create`.\n */\n TemplateCreateStart,\n\n /**\n * Corresponds to the point in time after the runtime has called the template function of a\n * component with `RenderFlags.Create`.\n */\n TemplateCreateEnd,\n\n /**\n * Corresponds to the point in time before the runtime has called the template function of a\n * component with `RenderFlags.Update`.\n */\n TemplateUpdateStart,\n\n /**\n * Corresponds to the point in time after the runtime has called the template function of a\n * component with `RenderFlags.Update`.\n */\n TemplateUpdateEnd,\n\n /**\n * Corresponds to the point in time before the runtime has called a lifecycle hook of a component\n * or directive.\n */\n LifecycleHookStart,\n\n /**\n * Corresponds to the point in time after the runtime has called a lifecycle hook of a component\n * or directive.\n */\n LifecycleHookEnd,\n\n /**\n * Corresponds to the point in time before the runtime has evaluated an expression associated with\n * an event or an output.\n */\n OutputStart,\n\n /**\n * Corresponds to the point in time after the runtime has evaluated an expression associated with\n * an event or an output.\n */\n OutputEnd,\n}\n\n/**\n * Profiler function which the runtime will invoke before and after user code.\n */\nexport interface Profiler {\n (event: ProfilerEvent, instance: {}|null, hookOrListener?: (e?: any) => any): void;\n}\n\n\nlet profilerCallback: Profiler|null = null;\n\n/**\n * Sets the callback function which will be invoked before and after performing certain actions at\n * runtime (for example, before and after running change detection).\n *\n * Warning: this function is *INTERNAL* and should not be relied upon in application's code.\n * The contract of the function might be changed in any release and/or the function can be removed\n * completely.\n *\n * @param profiler function provided by the caller or null value to disable profiling.\n */\nexport const setProfiler = (profiler: Profiler|null) => {\n profilerCallback = profiler;\n};\n\n/**\n * Profiler function which wraps user code executed by the runtime.\n *\n * @param event ProfilerEvent corresponding to the execution context\n * @param instance component instance\n * @param hookOrListener lifecycle hook function or output listener. The value depends on the\n * execution context\n * @returns\n */\nexport const profiler: Profiler = function(\n event: ProfilerEvent, instance: {}|null, hookOrListener?: (e?: any) => any) {\n if (profilerCallback != null /* both `null` and `undefined` */) {\n profilerCallback(event, instance, hookOrListener);\n }\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const SVG_NAMESPACE = 'svg';\nexport const MATH_ML_NAMESPACE = 'math';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertLessThan} from '../../util/assert';\nimport {assertTNode, assertTNodeForLView} from '../assert';\nimport {LContainer, TYPE} from '../interfaces/container';\nimport {TConstants, TNode} from '../interfaces/node';\nimport {RNode} from '../interfaces/renderer_dom';\nimport {isLContainer, isLView} from '../interfaces/type_checks';\nimport {FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, PARENT, PREORDER_HOOK_FLAGS, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TView} from '../interfaces/view';\n\n\n\n/**\n * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)\n * in same location in `LView`. This is because we don't want to pre-allocate space for it\n * because the storage is sparse. This file contains utilities for dealing with such data types.\n *\n * How do we know what is stored at a given location in `LView`.\n * - `Array.isArray(value) === false` => `RNode` (The normal storage value)\n * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.\n * - `typeof value[TYPE] === 'object'` => `LView`\n * - This happens when we have a component at a given location\n * - `typeof value[TYPE] === true` => `LContainer`\n * - This happens when we have `LContainer` binding at a given location.\n *\n *\n * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.\n */\n\n/**\n * Returns `RNode`.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nexport function unwrapRNode(value: RNode|LView|LContainer): RNode {\n while (Array.isArray(value)) {\n value = value[HOST] as any;\n }\n return value as RNode;\n}\n\n/**\n * Returns `LView` or `null` if not found.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nexport function unwrapLView(value: RNode|LView|LContainer): LView|null {\n while (Array.isArray(value)) {\n // This check is same as `isLView()` but we don't call at as we don't want to call\n // `Array.isArray()` twice and give JITer more work for inlining.\n if (typeof value[TYPE] === 'object') return value as LView;\n value = value[HOST] as any;\n }\n return null;\n}\n\n/**\n * Retrieves an element value from the provided `viewData`, by unwrapping\n * from any containers, component views, or style contexts.\n */\nexport function getNativeByIndex(index: number, lView: LView): RNode {\n ngDevMode && assertIndexInRange(lView, index);\n ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');\n return unwrapRNode(lView[index]);\n}\n\n/**\n * Retrieve an `RNode` for a given `TNode` and `LView`.\n *\n * This function guarantees in dev mode to retrieve a non-null `RNode`.\n *\n * @param tNode\n * @param lView\n */\nexport function getNativeByTNode(tNode: TNode, lView: LView): RNode {\n ngDevMode && assertTNodeForLView(tNode, lView);\n ngDevMode && assertIndexInRange(lView, tNode.index);\n const node: RNode = unwrapRNode(lView[tNode.index]);\n return node;\n}\n\n/**\n * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.\n *\n * Some `TNode`s don't have associated `RNode`s. For example `Projection`\n *\n * @param tNode\n * @param lView\n */\nexport function getNativeByTNodeOrNull(tNode: TNode|null, lView: LView): RNode|null {\n const index = tNode === null ? -1 : tNode.index;\n if (index !== -1) {\n ngDevMode && assertTNodeForLView(tNode!, lView);\n const node: RNode|null = unwrapRNode(lView[index]);\n return node;\n }\n return null;\n}\n\n\n// fixme(misko): The return Type should be `TNode|null`\nexport function getTNode(tView: TView, index: number): TNode {\n ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');\n ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');\n const tNode = tView.data[index] as TNode;\n ngDevMode && tNode !== null && assertTNode(tNode);\n return tNode;\n}\n\n/** Retrieves a value from any `LView` or `TData`. */\nexport function load<T>(view: LView|TData, index: number): T {\n ngDevMode && assertIndexInRange(view, index);\n return view[index];\n}\n\nexport function getComponentLViewByIndex(nodeIndex: number, hostView: LView): LView {\n // Could be an LView or an LContainer. If LContainer, unwrap to find LView.\n ngDevMode && assertIndexInRange(hostView, nodeIndex);\n const slotValue = hostView[nodeIndex];\n const lView = isLView(slotValue) ? slotValue : slotValue[HOST];\n return lView;\n}\n\n/** Checks whether a given view is in creation mode */\nexport function isCreationMode(view: LView): boolean {\n return (view[FLAGS] & LViewFlags.CreationMode) === LViewFlags.CreationMode;\n}\n\n/**\n * Returns a boolean for whether the view is attached to the change detection tree.\n *\n * Note: This determines whether a view should be checked, not whether it's inserted\n * into a container. For that, you'll want `viewAttachedToContainer` below.\n */\nexport function viewAttachedToChangeDetector(view: LView): boolean {\n return (view[FLAGS] & LViewFlags.Attached) === LViewFlags.Attached;\n}\n\n/** Returns a boolean for whether the view is attached to a container. */\nexport function viewAttachedToContainer(view: LView): boolean {\n return isLContainer(view[PARENT]);\n}\n\n/** Returns a constant from `TConstants` instance. */\nexport function getConstant<T>(consts: TConstants|null, index: null|undefined): null;\nexport function getConstant<T>(consts: TConstants, index: number): T|null;\nexport function getConstant<T>(consts: TConstants|null, index: number|null|undefined): T|null;\nexport function getConstant<T>(consts: TConstants|null, index: number|null|undefined): T|null {\n if (index === null || index === undefined) return null;\n ngDevMode && assertIndexInRange(consts!, index);\n return consts![index] as unknown as T;\n}\n\n/**\n * Resets the pre-order hook flags of the view.\n * @param lView the LView on which the flags are reset\n */\nexport function resetPreOrderHookFlags(lView: LView) {\n lView[PREORDER_HOOK_FLAGS] = 0;\n}\n\n/**\n * Updates the `TRANSPLANTED_VIEWS_TO_REFRESH` counter on the `LContainer` as well as the parents\n * whose\n * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh\n * or\n * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh\n */\nexport function updateTransplantedViewCount(lContainer: LContainer, amount: 1|- 1) {\n lContainer[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;\n let viewOrContainer: LView|LContainer = lContainer;\n let parent: LView|LContainer|null = lContainer[PARENT];\n while (parent !== null &&\n ((amount === 1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 1) ||\n (amount === -1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 0))) {\n parent[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;\n viewOrContainer = parent;\n parent = parent[PARENT];\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectFlags} from '../di/interface/injector';\nimport {assertDefined, assertEqual, assertGreaterThanOrEqual, assertLessThan, assertNotEqual, throwError} from '../util/assert';\n\nimport {assertLViewOrUndefined, assertTNodeForLView, assertTNodeForTView} from './assert';\nimport {DirectiveDef} from './interfaces/definition';\nimport {TNode, TNodeType} from './interfaces/node';\nimport {CONTEXT, DECLARATION_VIEW, HEADER_OFFSET, LView, OpaqueViewState, T_HOST, TData, TVIEW, TView, TViewType} from './interfaces/view';\nimport {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';\nimport {getTNode} from './util/view_utils';\n\n\n/**\n *\n */\ninterface LFrame {\n /**\n * Parent LFrame.\n *\n * This is needed when `leaveView` is called to restore the previous state.\n */\n parent: LFrame;\n\n /**\n * Child LFrame.\n *\n * This is used to cache existing LFrames to relieve the memory pressure.\n */\n child: LFrame|null;\n\n /**\n * State of the current view being processed.\n *\n * An array of nodes (text, element, container, etc), pipes, their bindings, and\n * any local variables that need to be stored between invocations.\n */\n lView: LView;\n\n /**\n * Current `TView` associated with the `LFrame.lView`.\n *\n * One can get `TView` from `lFrame[TVIEW]` however because it is so common it makes sense to\n * store it in `LFrame` for perf reasons.\n */\n tView: TView;\n\n /**\n * Used to set the parent property when nodes are created and track query results.\n *\n * This is used in conjunction with `isParent`.\n */\n currentTNode: TNode|null;\n\n /**\n * If `isParent` is:\n * - `true`: then `currentTNode` points to a parent node.\n * - `false`: then `currentTNode` points to previous node (sibling).\n */\n isParent: boolean;\n\n /**\n * Index of currently selected element in LView.\n *\n * Used by binding instructions. Updated as part of advance instruction.\n */\n selectedIndex: number;\n\n /**\n * Current pointer to the binding index.\n */\n bindingIndex: number;\n\n /**\n * The last viewData retrieved by nextContext().\n * Allows building nextContext() and reference() calls.\n *\n * e.g. const inner = x().$implicit; const outer = x().$implicit;\n */\n contextLView: LView|null;\n\n /**\n * Store the element depth count. This is used to identify the root elements of the template\n * so that we can then attach patch data `LView` to only those elements. We know that those\n * are the only places where the patch data could change, this way we will save on number\n * of places where tha patching occurs.\n */\n elementDepthCount: number;\n\n /**\n * Current namespace to be used when creating elements\n */\n currentNamespace: string|null;\n\n\n /**\n * The root index from which pure function instructions should calculate their binding\n * indices. In component views, this is TView.bindingStartIndex. In a host binding\n * context, this is the TView.expandoStartIndex + any dirs/hostVars before the given dir.\n */\n bindingRootIndex: number;\n\n /**\n * Current index of a View or Content Query which needs to be processed next.\n * We iterate over the list of Queries and increment current query index at every step.\n */\n currentQueryIndex: number;\n\n /**\n * When host binding is executing this points to the directive index.\n * `TView.data[currentDirectiveIndex]` is `DirectiveDef`\n * `LView[currentDirectiveIndex]` is directive instance.\n */\n currentDirectiveIndex: number;\n\n /**\n * Are we currently in i18n block as denoted by `ɵɵelementStart` and `ɵɵelementEnd`.\n *\n * This information is needed because while we are in i18n block all elements must be pre-declared\n * in the translation. (i.e. `Hello �#2�World�/#2�!` pre-declares element at `�#2�` location.)\n * This allocates `TNodeType.Placeholder` element at location `2`. If translator removes `�#2�`\n * from translation than the runtime must also ensure tha element at `2` does not get inserted\n * into the DOM. The translation does not carry information about deleted elements. Therefor the\n * only way to know that an element is deleted is that it was not pre-declared in the translation.\n *\n * This flag works by ensuring that elements which are created without pre-declaration\n * (`TNodeType.Placeholder`) are not inserted into the DOM render tree. (It does mean that the\n * element still gets instantiated along with all of its behavior [directives])\n */\n inI18n: boolean;\n}\n\n/**\n * All implicit instruction state is stored here.\n *\n * It is useful to have a single object where all of the state is stored as a mental model\n * (rather it being spread across many different variables.)\n *\n * PERF NOTE: Turns out that writing to a true global variable is slower than\n * having an intermediate object with properties.\n */\ninterface InstructionState {\n /**\n * Current `LFrame`\n *\n * `null` if we have not called `enterView`\n */\n lFrame: LFrame;\n\n /**\n * Stores whether directives should be matched to elements.\n *\n * When template contains `ngNonBindable` then we need to prevent the runtime from matching\n * directives on children of that element.\n *\n * Example:\n * ```\n * <my-comp my-directive>\n * Should match component / directive.\n * </my-comp>\n * <div ngNonBindable>\n * <my-comp my-directive>\n * Should not match component / directive because we are in ngNonBindable.\n * </my-comp>\n * </div>\n * ```\n */\n bindingsEnabled: boolean;\n}\n\nconst instructionState: InstructionState = {\n lFrame: createLFrame(null),\n bindingsEnabled: true,\n};\n\n/**\n * In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.\n *\n * Necessary to support ChangeDetectorRef.checkNoChanges().\n *\n * The `checkNoChanges` function is invoked only in ngDevMode=true and verifies that no unintended\n * changes exist in the change detector or its children.\n */\nlet _isInCheckNoChangesMode = false;\n\n/**\n * Returns true if the instruction state stack is empty.\n *\n * Intended to be called from tests only (tree shaken otherwise).\n */\nexport function specOnlyIsInstructionStateEmpty(): boolean {\n return instructionState.lFrame.parent === null;\n}\n\n\nexport function getElementDepthCount() {\n return instructionState.lFrame.elementDepthCount;\n}\n\nexport function increaseElementDepthCount() {\n instructionState.lFrame.elementDepthCount++;\n}\n\nexport function decreaseElementDepthCount() {\n instructionState.lFrame.elementDepthCount--;\n}\n\nexport function getBindingsEnabled(): boolean {\n return instructionState.bindingsEnabled;\n}\n\n\n/**\n * Enables directive matching on elements.\n *\n * * Example:\n * ```\n * <my-comp my-directive>\n * Should match component / directive.\n * </my-comp>\n * <div ngNonBindable>\n * <!-- ɵɵdisableBindings() -->\n * <my-comp my-directive>\n * Should not match component / directive because we are in ngNonBindable.\n * </my-comp>\n * <!-- ɵɵenableBindings() -->\n * </div>\n * ```\n *\n * @codeGenApi\n */\nexport function ɵɵenableBindings(): void {\n instructionState.bindingsEnabled = true;\n}\n\n/**\n * Disables directive matching on element.\n *\n * * Example:\n * ```\n * <my-comp my-directive>\n * Should match component / directive.\n * </my-comp>\n * <div ngNonBindable>\n * <!-- ɵɵdisableBindings() -->\n * <my-comp my-directive>\n * Should not match component / directive because we are in ngNonBindable.\n * </my-comp>\n * <!-- ɵɵenableBindings() -->\n * </div>\n * ```\n *\n * @codeGenApi\n */\nexport function ɵɵdisableBindings(): void {\n instructionState.bindingsEnabled = false;\n}\n\n/**\n * Return the current `LView`.\n */\nexport function getLView<T>(): LView<T> {\n return instructionState.lFrame.lView as LView<T>;\n}\n\n/**\n * Return the current `TView`.\n */\nexport function getTView(): TView {\n return instructionState.lFrame.tView;\n}\n\n/**\n * Restores `contextViewData` to the given OpaqueViewState instance.\n *\n * Used in conjunction with the getCurrentView() instruction to save a snapshot\n * of the current view and restore it when listeners are invoked. This allows\n * walking the declaration view tree in listeners to get vars from parent views.\n *\n * @param viewToRestore The OpaqueViewState instance to restore.\n * @returns Context of the restored OpaqueViewState instance.\n *\n * @codeGenApi\n */\nexport function ɵɵrestoreView<T = any>(viewToRestore: OpaqueViewState): T {\n instructionState.lFrame.contextLView = viewToRestore as any as LView;\n return (viewToRestore as any as LView)[CONTEXT] as unknown as T;\n}\n\n\n/**\n * Clears the view set in `ɵɵrestoreView` from memory. Returns the passed in\n * value so that it can be used as a return value of an instruction.\n *\n * @codeGenApi\n */\nexport function ɵɵresetView<T>(value?: T): T|undefined {\n instructionState.lFrame.contextLView = null;\n return value;\n}\n\n\nexport function getCurrentTNode(): TNode|null {\n let currentTNode = getCurrentTNodePlaceholderOk();\n while (currentTNode !== null && currentTNode.type === TNodeType.Placeholder) {\n currentTNode = currentTNode.parent;\n }\n return currentTNode;\n}\n\nexport function getCurrentTNodePlaceholderOk(): TNode|null {\n return instructionState.lFrame.currentTNode;\n}\n\nexport function getCurrentParentTNode(): TNode|null {\n const lFrame = instructionState.lFrame;\n const currentTNode = lFrame.currentTNode;\n return lFrame.isParent ? currentTNode : currentTNode!.parent;\n}\n\nexport function setCurrentTNode(tNode: TNode|null, isParent: boolean) {\n ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView);\n const lFrame = instructionState.lFrame;\n lFrame.currentTNode = tNode;\n lFrame.isParent = isParent;\n}\n\nexport function isCurrentTNodeParent(): boolean {\n return instructionState.lFrame.isParent;\n}\n\nexport function setCurrentTNodeAsNotParent(): void {\n instructionState.lFrame.isParent = false;\n}\n\nexport function getContextLView(): LView {\n const contextLView = instructionState.lFrame.contextLView;\n ngDevMode && assertDefined(contextLView, 'contextLView must be defined.');\n return contextLView!;\n}\n\nexport function isInCheckNoChangesMode(): boolean {\n !ngDevMode && throwError('Must never be called in production mode');\n return _isInCheckNoChangesMode;\n}\n\nexport function setIsInCheckNoChangesMode(mode: boolean): void {\n !ngDevMode && throwError('Must never be called in production mode');\n _isInCheckNoChangesMode = mode;\n}\n\n// top level variables should not be exported for performance reasons (PERF_NOTES.md)\nexport function getBindingRoot() {\n const lFrame = instructionState.lFrame;\n let index = lFrame.bindingRootIndex;\n if (index === -1) {\n index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;\n }\n return index;\n}\n\nexport function getBindingIndex(): number {\n return instructionState.lFrame.bindingIndex;\n}\n\nexport function setBindingIndex(value: number): number {\n return instructionState.lFrame.bindingIndex = value;\n}\n\nexport function nextBindingIndex(): number {\n return instructionState.lFrame.bindingIndex++;\n}\n\nexport function incrementBindingIndex(count: number): number {\n const lFrame = instructionState.lFrame;\n const index = lFrame.bindingIndex;\n lFrame.bindingIndex = lFrame.bindingIndex + count;\n return index;\n}\n\nexport function isInI18nBlock() {\n return instructionState.lFrame.inI18n;\n}\n\nexport function setInI18nBlock(isInI18nBlock: boolean): void {\n instructionState.lFrame.inI18n = isInI18nBlock;\n}\n\n/**\n * Set a new binding root index so that host template functions can execute.\n *\n * Bindings inside the host template are 0 index. But because we don't know ahead of time\n * how many host bindings we have we can't pre-compute them. For this reason they are all\n * 0 index and we just shift the root so that they match next available location in the LView.\n *\n * @param bindingRootIndex Root index for `hostBindings`\n * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive\n * whose `hostBindings` are being processed.\n */\nexport function setBindingRootForHostBindings(\n bindingRootIndex: number, currentDirectiveIndex: number) {\n const lFrame = instructionState.lFrame;\n lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex;\n setCurrentDirectiveIndex(currentDirectiveIndex);\n}\n\n/**\n * When host binding is executing this points to the directive index.\n * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef`\n * `LView[getCurrentDirectiveIndex()]` is directive instance.\n */\nexport function getCurrentDirectiveIndex(): number {\n return instructionState.lFrame.currentDirectiveIndex;\n}\n\n/**\n * Sets an index of a directive whose `hostBindings` are being processed.\n *\n * @param currentDirectiveIndex `TData` index where current directive instance can be found.\n */\nexport function setCurrentDirectiveIndex(currentDirectiveIndex: number): void {\n instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex;\n}\n\n/**\n * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being\n * executed.\n *\n * @param tData Current `TData` where the `DirectiveDef` will be looked up at.\n */\nexport function getCurrentDirectiveDef(tData: TData): DirectiveDef<any>|null {\n const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;\n return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex] as DirectiveDef<any>;\n}\n\nexport function getCurrentQueryIndex(): number {\n return instructionState.lFrame.currentQueryIndex;\n}\n\nexport function setCurrentQueryIndex(value: number): void {\n instructionState.lFrame.currentQueryIndex = value;\n}\n\n/**\n * Returns a `TNode` of the location where the current `LView` is declared at.\n *\n * @param lView an `LView` that we want to find parent `TNode` for.\n */\nfunction getDeclarationTNode(lView: LView): TNode|null {\n const tView = lView[TVIEW];\n\n // Return the declaration parent for embedded views\n if (tView.type === TViewType.Embedded) {\n ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');\n return tView.declTNode;\n }\n\n // Components don't have `TView.declTNode` because each instance of component could be\n // inserted in different location, hence `TView.declTNode` is meaningless.\n // Falling back to `T_HOST` in case we cross component boundary.\n if (tView.type === TViewType.Component) {\n return lView[T_HOST];\n }\n\n // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode.\n return null;\n}\n\n/**\n * This is a light weight version of the `enterView` which is needed by the DI system.\n *\n * @param lView `LView` location of the DI context.\n * @param tNode `TNode` for DI context\n * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration\n * tree from `tNode` until we find parent declared `TElementNode`.\n * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared\n * `TNode` if `flags` has `SkipSelf`). Failing to enter DI implies that no associated\n * `NodeInjector` can be found and we should instead use `ModuleInjector`.\n * - If `true` than this call must be fallowed by `leaveDI`\n * - If `false` than this call failed and we should NOT call `leaveDI`\n */\nexport function enterDI(lView: LView, tNode: TNode, flags: InjectFlags) {\n ngDevMode && assertLViewOrUndefined(lView);\n\n if (flags & InjectFlags.SkipSelf) {\n ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]);\n\n let parentTNode = tNode as TNode | null;\n let parentLView = lView;\n\n while (true) {\n ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined');\n parentTNode = parentTNode!.parent as TNode | null;\n if (parentTNode === null && !(flags & InjectFlags.Host)) {\n parentTNode = getDeclarationTNode(parentLView);\n if (parentTNode === null) break;\n\n // In this case, a parent exists and is definitely an element. So it will definitely\n // have an existing lView as the declaration view, which is why we can assume it's defined.\n ngDevMode && assertDefined(parentLView, 'Parent LView should be defined');\n parentLView = parentLView[DECLARATION_VIEW]!;\n\n // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives\n // We want to skip those and look only at Elements and ElementContainers to ensure\n // we're looking at true parent nodes, and not content or other types.\n if (parentTNode.type & (TNodeType.Element | TNodeType.ElementContainer)) {\n break;\n }\n } else {\n break;\n }\n }\n if (parentTNode === null) {\n // If we failed to find a parent TNode this means that we should use module injector.\n return false;\n } else {\n tNode = parentTNode;\n lView = parentLView;\n }\n }\n\n ngDevMode && assertTNodeForLView(tNode, lView);\n const lFrame = instructionState.lFrame = allocLFrame();\n lFrame.currentTNode = tNode;\n lFrame.lView = lView;\n\n return true;\n}\n\n/**\n * Swap the current lView with a new lView.\n *\n * For performance reasons we store the lView in the top level of the module.\n * This way we minimize the number of properties to read. Whenever a new view\n * is entered we have to store the lView for later, and when the view is\n * exited the state has to be restored\n *\n * @param newView New lView to become active\n * @returns the previously active lView;\n */\nexport function enterView(newView: LView): void {\n ngDevMode && assertNotEqual(newView[0], newView[1] as any, '????');\n ngDevMode && assertLViewOrUndefined(newView);\n const newLFrame = allocLFrame();\n if (ngDevMode) {\n assertEqual(newLFrame.isParent, true, 'Expected clean LFrame');\n assertEqual(newLFrame.lView, null, 'Expected clean LFrame');\n assertEqual(newLFrame.tView, null, 'Expected clean LFrame');\n assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame');\n assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame');\n assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');\n }\n const tView = newView[TVIEW];\n instructionState.lFrame = newLFrame;\n ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView);\n newLFrame.currentTNode = tView.firstChild!;\n newLFrame.lView = newView;\n newLFrame.tView = tView;\n newLFrame.contextLView = newView;\n newLFrame.bindingIndex = tView.bindingStartIndex;\n newLFrame.inI18n = false;\n}\n\n/**\n * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.\n */\nfunction allocLFrame() {\n const currentLFrame = instructionState.lFrame;\n const childLFrame = currentLFrame === null ? null : currentLFrame.child;\n const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;\n return newLFrame;\n}\n\nfunction createLFrame(parent: LFrame|null): LFrame {\n const lFrame: LFrame = {\n currentTNode: null,\n isParent: true,\n lView: null!,\n tView: null!,\n selectedIndex: -1,\n contextLView: null,\n elementDepthCount: 0,\n currentNamespace: null,\n currentDirectiveIndex: -1,\n bindingRootIndex: -1,\n bindingIndex: -1,\n currentQueryIndex: 0,\n parent: parent!,\n child: null,\n inI18n: false,\n };\n parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.\n return lFrame;\n}\n\n/**\n * A lightweight version of leave which is used with DI.\n *\n * This function only resets `currentTNode` and `LView` as those are the only properties\n * used with DI (`enterDI()`).\n *\n * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where\n * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`.\n */\nfunction leaveViewLight(): LFrame {\n const oldLFrame = instructionState.lFrame;\n instructionState.lFrame = oldLFrame.parent;\n oldLFrame.currentTNode = null!;\n oldLFrame.lView = null!;\n return oldLFrame;\n}\n\n/**\n * This is a lightweight version of the `leaveView` which is needed by the DI system.\n *\n * NOTE: this function is an alias so that we can change the type of the function to have `void`\n * return type.\n */\nexport const leaveDI: () => void = leaveViewLight;\n\n/**\n * Leave the current `LView`\n *\n * This pops the `LFrame` with the associated `LView` from the stack.\n *\n * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is\n * because for performance reasons we don't release `LFrame` but rather keep it for next use.\n */\nexport function leaveView() {\n const oldLFrame = leaveViewLight();\n oldLFrame.isParent = true;\n oldLFrame.tView = null!;\n oldLFrame.selectedIndex = -1;\n oldLFrame.contextLView = null;\n oldLFrame.elementDepthCount = 0;\n oldLFrame.currentDirectiveIndex = -1;\n oldLFrame.currentNamespace = null;\n oldLFrame.bindingRootIndex = -1;\n oldLFrame.bindingIndex = -1;\n oldLFrame.currentQueryIndex = 0;\n}\n\nexport function nextContextImpl<T = any>(level: number): T {\n const contextLView = instructionState.lFrame.contextLView =\n walkUpViews(level, instructionState.lFrame.contextLView!);\n return contextLView[CONTEXT] as unknown as T;\n}\n\nfunction walkUpViews(nestingLevel: number, currentView: LView): LView {\n while (nestingLevel > 0) {\n ngDevMode &&\n assertDefined(\n currentView[DECLARATION_VIEW],\n 'Declaration view should be defined if nesting level is greater than 0.');\n currentView = currentView[DECLARATION_VIEW]!;\n nestingLevel--;\n }\n return currentView;\n}\n\n/**\n * Gets the currently selected element index.\n *\n * Used with {@link property} instruction (and more in the future) to identify the index in the\n * current `LView` to act on.\n */\nexport function getSelectedIndex() {\n return instructionState.lFrame.selectedIndex;\n}\n\n/**\n * Sets the most recent index passed to {@link select}\n *\n * Used with {@link property} instruction (and more in the future) to identify the index in the\n * current `LView` to act on.\n *\n * (Note that if an \"exit function\" was set earlier (via `setElementExitFn()`) then that will be\n * run if and when the provided `index` value is different from the current selected index value.)\n */\nexport function setSelectedIndex(index: number) {\n ngDevMode && index !== -1 &&\n assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).');\n ngDevMode &&\n assertLessThan(\n index, instructionState.lFrame.lView.length, 'Can\\'t set index passed end of LView');\n instructionState.lFrame.selectedIndex = index;\n}\n\n/**\n * Gets the `tNode` that represents currently selected element.\n */\nexport function getSelectedTNode() {\n const lFrame = instructionState.lFrame;\n return getTNode(lFrame.tView, lFrame.selectedIndex);\n}\n\n/**\n * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.\n *\n * @codeGenApi\n */\nexport function ɵɵnamespaceSVG() {\n instructionState.lFrame.currentNamespace = SVG_NAMESPACE;\n}\n\n/**\n * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.\n *\n * @codeGenApi\n */\nexport function ɵɵnamespaceMathML() {\n instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;\n}\n\n/**\n * Sets the namespace used to create elements to `null`, which forces element creation to use\n * `createElement` rather than `createElementNS`.\n *\n * @codeGenApi\n */\nexport function ɵɵnamespaceHTML() {\n namespaceHTMLInternal();\n}\n\n/**\n * Sets the namespace used to create elements to `null`, which forces element creation to use\n * `createElement` rather than `createElementNS`.\n */\nexport function namespaceHTMLInternal() {\n instructionState.lFrame.currentNamespace = null;\n}\n\nexport function getNamespace(): string|null {\n return instructionState.lFrame.currentNamespace;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, OnChanges, OnDestroy, OnInit} from '../interface/lifecycle_hooks';\nimport {assertDefined, assertEqual, assertNotEqual} from '../util/assert';\nimport {assertFirstCreatePass} from './assert';\nimport {NgOnChangesFeatureImpl} from './features/ng_onchanges_feature';\nimport {DirectiveDef} from './interfaces/definition';\nimport {TNode} from './interfaces/node';\nimport {FLAGS, HookData, InitPhaseState, LView, LViewFlags, PREORDER_HOOK_FLAGS, PreOrderHookFlags, TView} from './interfaces/view';\nimport {profiler, ProfilerEvent} from './profiler';\nimport {isInCheckNoChangesMode} from './state';\n\n\n\n/**\n * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.\n *\n * Must be run *only* on the first template pass.\n *\n * Sets up the pre-order hooks on the provided `tView`,\n * see {@link HookData} for details about the data structure.\n *\n * @param directiveIndex The index of the directive in LView\n * @param directiveDef The definition containing the hooks to setup in tView\n * @param tView The current TView\n */\nexport function registerPreOrderHooks(\n directiveIndex: number, directiveDef: DirectiveDef<any>, tView: TView): void {\n ngDevMode && assertFirstCreatePass(tView);\n const {ngOnChanges, ngOnInit, ngDoCheck} =\n directiveDef.type.prototype as OnChanges & OnInit & DoCheck;\n\n if (ngOnChanges as Function | undefined) {\n const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef);\n (tView.preOrderHooks ??= []).push(directiveIndex, wrappedOnChanges);\n (tView.preOrderCheckHooks ??= []).push(directiveIndex, wrappedOnChanges);\n }\n\n if (ngOnInit) {\n (tView.preOrderHooks ??= []).push(0 - directiveIndex, ngOnInit);\n }\n\n if (ngDoCheck) {\n (tView.preOrderHooks ??= []).push(directiveIndex, ngDoCheck);\n (tView.preOrderCheckHooks ??= []).push(directiveIndex, ngDoCheck);\n }\n}\n\n/**\n *\n * Loops through the directives on the provided `tNode` and queues hooks to be\n * run that are not initialization hooks.\n *\n * Should be executed during `elementEnd()` and similar to\n * preserve hook execution order. Content, view, and destroy hooks for projected\n * components and directives must be called *before* their hosts.\n *\n * Sets up the content, view, and destroy hooks on the provided `tView`,\n * see {@link HookData} for details about the data structure.\n *\n * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up\n * separately at `elementStart`.\n *\n * @param tView The current TView\n * @param tNode The TNode whose directives are to be searched for hooks to queue\n */\nexport function registerPostOrderHooks(tView: TView, tNode: TNode): void {\n ngDevMode && assertFirstCreatePass(tView);\n // It's necessary to loop through the directives at elementEnd() (rather than processing in\n // directiveCreate) so we can preserve the current hook order. Content, view, and destroy\n // hooks for projected components and directives must be called *before* their hosts.\n for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {\n const directiveDef = tView.data[i] as DirectiveDef<any>;\n ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef');\n const lifecycleHooks: AfterContentInit&AfterContentChecked&AfterViewInit&AfterViewChecked&\n OnDestroy = directiveDef.type.prototype;\n const {\n ngAfterContentInit,\n ngAfterContentChecked,\n ngAfterViewInit,\n ngAfterViewChecked,\n ngOnDestroy\n } = lifecycleHooks;\n\n if (ngAfterContentInit) {\n (tView.contentHooks ??= []).push(-i, ngAfterContentInit);\n }\n\n if (ngAfterContentChecked) {\n (tView.contentHooks ??= []).push(i, ngAfterContentChecked);\n (tView.contentCheckHooks ??= []).push(i, ngAfterContentChecked);\n }\n\n if (ngAfterViewInit) {\n (tView.viewHooks ??= []).push(-i, ngAfterViewInit);\n }\n\n if (ngAfterViewChecked) {\n (tView.viewHooks ??= []).push(i, ngAfterViewChecked);\n (tView.viewCheckHooks ??= []).push(i, ngAfterViewChecked);\n }\n\n if (ngOnDestroy != null) {\n (tView.destroyHooks ??= []).push(i, ngOnDestroy);\n }\n }\n}\n\n/**\n * Executing hooks requires complex logic as we need to deal with 2 constraints.\n *\n * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only\n * once, across many change detection cycles. This must be true even if some hooks throw, or if\n * some recursively trigger a change detection cycle.\n * To solve that, it is required to track the state of the execution of these init hooks.\n * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},\n * and the index within that phase. They can be seen as a cursor in the following structure:\n * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]\n * They are are stored as flags in LView[FLAGS].\n *\n * 2. Pre-order hooks can be executed in batches, because of the select instruction.\n * To be able to pause and resume their execution, we also need some state about the hook's array\n * that is being processed:\n * - the index of the next hook to be executed\n * - the number of init hooks already found in the processed part of the array\n * They are are stored as flags in LView[PREORDER_HOOK_FLAGS].\n */\n\n\n/**\n * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were\n * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read\n * / write of the init-hooks related flags.\n * @param lView The LView where hooks are defined\n * @param hooks Hooks to be run\n * @param nodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nexport function executeCheckHooks(lView: LView, hooks: HookData, nodeIndex?: number|null) {\n callHooks(lView, hooks, InitPhaseState.InitPhaseCompleted, nodeIndex);\n}\n\n/**\n * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,\n * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.\n * @param lView The LView where hooks are defined\n * @param hooks Hooks to be run\n * @param initPhase A phase for which hooks should be run\n * @param nodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nexport function executeInitAndCheckHooks(\n lView: LView, hooks: HookData, initPhase: InitPhaseState, nodeIndex?: number|null) {\n ngDevMode &&\n assertNotEqual(\n initPhase, InitPhaseState.InitPhaseCompleted,\n 'Init pre-order hooks should not be called more than once');\n if ((lView[FLAGS] & LViewFlags.InitPhaseStateMask) === initPhase) {\n callHooks(lView, hooks, initPhase, nodeIndex);\n }\n}\n\nexport function incrementInitPhaseFlags(lView: LView, initPhase: InitPhaseState): void {\n ngDevMode &&\n assertNotEqual(\n initPhase, InitPhaseState.InitPhaseCompleted,\n 'Init hooks phase should not be incremented after all init hooks have been run.');\n let flags = lView[FLAGS];\n if ((flags & LViewFlags.InitPhaseStateMask) === initPhase) {\n flags &= LViewFlags.IndexWithinInitPhaseReset;\n flags += LViewFlags.InitPhaseStateIncrementer;\n lView[FLAGS] = flags;\n }\n}\n\n/**\n * Calls lifecycle hooks with their contexts, skipping init hooks if it's not\n * the first LView pass\n *\n * @param currentView The current view\n * @param arr The array in which the hooks are found\n * @param initPhaseState the current state of the init phase\n * @param currentNodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nfunction callHooks(\n currentView: LView, arr: HookData, initPhase: InitPhaseState,\n currentNodeIndex: number|null|undefined): void {\n ngDevMode &&\n assertEqual(\n isInCheckNoChangesMode(), false,\n 'Hooks should never be run when in check no changes mode.');\n const startIndex = currentNodeIndex !== undefined ?\n (currentView[PREORDER_HOOK_FLAGS] & PreOrderHookFlags.IndexOfTheNextPreOrderHookMaskMask) :\n 0;\n const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;\n const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1\n let lastNodeIndexFound = 0;\n for (let i = startIndex; i < max; i++) {\n const hook = arr[i + 1] as number | (() => void);\n if (typeof hook === 'number') {\n lastNodeIndexFound = arr[i] as number;\n if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {\n break;\n }\n } else {\n const isInitHook = arr[i] < 0;\n if (isInitHook)\n currentView[PREORDER_HOOK_FLAGS] += PreOrderHookFlags.NumberOfInitHooksCalledIncrementer;\n if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {\n callHook(currentView, initPhase, arr, i);\n currentView[PREORDER_HOOK_FLAGS] =\n (currentView[PREORDER_HOOK_FLAGS] & PreOrderHookFlags.NumberOfInitHooksCalledMask) + i +\n 2;\n }\n i++;\n }\n }\n}\n\n/**\n * Execute one hook against the current `LView`.\n *\n * @param currentView The current view\n * @param initPhaseState the current state of the init phase\n * @param arr The array in which the hooks are found\n * @param i The current index within the hook data array\n */\nfunction callHook(currentView: LView, initPhase: InitPhaseState, arr: HookData, i: number) {\n const isInitHook = arr[i] < 0;\n const hook = arr[i + 1] as () => void;\n const directiveIndex = isInitHook ? -arr[i] : arr[i] as number;\n const directive = currentView[directiveIndex];\n if (isInitHook) {\n const indexWithintInitPhase = currentView[FLAGS] >> LViewFlags.IndexWithinInitPhaseShift;\n // The init phase state must be always checked here as it may have been recursively updated.\n if (indexWithintInitPhase <\n (currentView[PREORDER_HOOK_FLAGS] >> PreOrderHookFlags.NumberOfInitHooksCalledShift) &&\n (currentView[FLAGS] & LViewFlags.InitPhaseStateMask) === initPhase) {\n currentView[FLAGS] += LViewFlags.IndexWithinInitPhaseIncrementer;\n profiler(ProfilerEvent.LifecycleHookStart, directive, hook);\n try {\n hook.call(directive);\n } finally {\n profiler(ProfilerEvent.LifecycleHookEnd, directive, hook);\n }\n }\n } else {\n profiler(ProfilerEvent.LifecycleHookStart, directive, hook);\n try {\n hook.call(directive);\n } finally {\n profiler(ProfilerEvent.LifecycleHookEnd, directive, hook);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectFlags} from '../../di/interface/injector';\nimport {ProviderToken} from '../../di/provider_token';\nimport {assertDefined, assertEqual} from '../../util/assert';\n\nimport {TDirectiveHostNode} from './node';\nimport {LView, TData} from './view';\n\n/**\n * Offsets of the `NodeInjector` data structure in the expando.\n *\n * `NodeInjector` is stored in both `LView` as well as `TView.data`. All storage requires 9 words.\n * First 8 are reserved for bloom filter and the 9th is reserved for the associated `TNode` as well\n * as parent `NodeInjector` pointer. All indexes are starting with `index` and have an offset as\n * shown.\n *\n * `LView` layout:\n * ```\n * index + 0: cumulative bloom filter\n * index + 1: cumulative bloom filter\n * index + 2: cumulative bloom filter\n * index + 3: cumulative bloom filter\n * index + 4: cumulative bloom filter\n * index + 5: cumulative bloom filter\n * index + 6: cumulative bloom filter\n * index + 7: cumulative bloom filter\n * index + 8: cumulative bloom filter\n * index + PARENT: Index to the parent injector. See `RelativeInjectorLocation`\n * `const parent = lView[index + NodeInjectorOffset.PARENT]`\n * ```\n *\n * `TViewData` layout:\n * ```\n * index + 0: cumulative bloom filter\n * index + 1: cumulative bloom filter\n * index + 2: cumulative bloom filter\n * index + 3: cumulative bloom filter\n * index + 4: cumulative bloom filter\n * index + 5: cumulative bloom filter\n * index + 6: cumulative bloom filter\n * index + 7: cumulative bloom filter\n * index + 8: cumulative bloom filter\n * index + TNODE: TNode associated with this `NodeInjector`\n * `const tNode = tView.data[index + NodeInjectorOffset.TNODE]`\n * ```\n */\nexport const enum NodeInjectorOffset {\n TNODE = 8,\n PARENT = 8,\n BLOOM_SIZE = 8,\n SIZE = 9,\n}\n\n/**\n * Represents a relative location of parent injector.\n *\n * The interfaces encodes number of parents `LView`s to traverse and index in the `LView`\n * pointing to the parent injector.\n */\nexport interface RelativeInjectorLocation {\n __brand__: 'RelativeInjectorLocationFlags';\n}\n\nexport const enum RelativeInjectorLocationFlags {\n InjectorIndexMask = 0b111111111111111,\n ViewOffsetShift = 16,\n NO_PARENT = -1,\n}\n\nexport const NO_PARENT_INJECTOR: RelativeInjectorLocation = -1 as any;\n\n/**\n * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in\n * `TView.data`. This allows us to store information about the current node's tokens (which\n * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be\n * shared, so they live in `LView`).\n *\n * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter\n * determines whether a directive is available on the associated node or not. This prevents us\n * from searching the directives array at this level unless it's probable the directive is in it.\n *\n * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters.\n *\n * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed\n * using interfaces as they were previously. The start index of each `LInjector` and `TInjector`\n * will differ based on where it is flattened into the main array, so it's not possible to know\n * the indices ahead of time and save their types here. The interfaces are still included here\n * for documentation purposes.\n *\n * export interface LInjector extends Array<any> {\n *\n * // Cumulative bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)\n * [0]: number;\n *\n * // Cumulative bloom for directive IDs 32-63\n * [1]: number;\n *\n * // Cumulative bloom for directive IDs 64-95\n * [2]: number;\n *\n * // Cumulative bloom for directive IDs 96-127\n * [3]: number;\n *\n * // Cumulative bloom for directive IDs 128-159\n * [4]: number;\n *\n * // Cumulative bloom for directive IDs 160 - 191\n * [5]: number;\n *\n * // Cumulative bloom for directive IDs 192 - 223\n * [6]: number;\n *\n * // Cumulative bloom for directive IDs 224 - 255\n * [7]: number;\n *\n * // We need to store a reference to the injector's parent so DI can keep looking up\n * // the injector tree until it finds the dependency it's looking for.\n * [PARENT_INJECTOR]: number;\n * }\n *\n * export interface TInjector extends Array<any> {\n *\n * // Shared node bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)\n * [0]: number;\n *\n * // Shared node bloom for directive IDs 32-63\n * [1]: number;\n *\n * // Shared node bloom for directive IDs 64-95\n * [2]: number;\n *\n * // Shared node bloom for directive IDs 96-127\n * [3]: number;\n *\n * // Shared node bloom for directive IDs 128-159\n * [4]: number;\n *\n * // Shared node bloom for directive IDs 160 - 191\n * [5]: number;\n *\n * // Shared node bloom for directive IDs 192 - 223\n * [6]: number;\n *\n * // Shared node bloom for directive IDs 224 - 255\n * [7]: number;\n *\n * // Necessary to find directive indices for a particular node.\n * [TNODE]: TElementNode|TElementContainerNode|TContainerNode;\n * }\n */\n\n/**\n * Factory for creating instances of injectors in the NodeInjector.\n *\n * This factory is complicated by the fact that it can resolve `multi` factories as well.\n *\n * NOTE: Some of the fields are optional which means that this class has two hidden classes.\n * - One without `multi` support (most common)\n * - One with `multi` values, (rare).\n *\n * Since VMs can cache up to 4 inline hidden classes this is OK.\n *\n * - Single factory: Only `resolving` and `factory` is defined.\n * - `providers` factory: `componentProviders` is a number and `index = -1`.\n * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.\n */\nexport class NodeInjectorFactory {\n /**\n * The inject implementation to be activated when using the factory.\n */\n injectImpl: null|(<T>(token: ProviderToken<T>, flags?: InjectFlags) => T);\n\n /**\n * Marker set to true during factory invocation to see if we get into recursive loop.\n * Recursive loop causes an error to be displayed.\n */\n resolving = false;\n\n /**\n * Marks that the token can see other Tokens declared in `viewProviders` on the same node.\n */\n canSeeViewProviders: boolean;\n\n /**\n * An array of factories to use in case of `multi` provider.\n */\n multi?: Array<() => any>;\n\n /**\n * Number of `multi`-providers which belong to the component.\n *\n * This is needed because when multiple components and directives declare the `multi` provider\n * they have to be concatenated in the correct order.\n *\n * Example:\n *\n * If we have a component and directive active an a single element as declared here\n * ```\n * component:\n * providers: [ {provide: String, useValue: 'component', multi: true} ],\n * viewProviders: [ {provide: String, useValue: 'componentView', multi: true} ],\n *\n * directive:\n * providers: [ {provide: String, useValue: 'directive', multi: true} ],\n * ```\n *\n * Then the expected results are:\n *\n * ```\n * providers: ['component', 'directive']\n * viewProviders: ['component', 'componentView', 'directive']\n * ```\n *\n * The way to think about it is that the `viewProviders` have been inserted after the component\n * but before the directives, which is why we need to know how many `multi`s have been declared by\n * the component.\n */\n componentProviders?: number;\n\n /**\n * Current index of the Factory in the `data`. Needed for `viewProviders` and `providers` merging.\n * See `providerFactory`.\n */\n index?: number;\n\n /**\n * Because the same `multi` provider can be declared in `providers` and `viewProviders` it is\n * possible for `viewProviders` to shadow the `providers`. For this reason we store the\n * `provideFactory` of the `providers` so that `providers` can be extended with `viewProviders`.\n *\n * Example:\n *\n * Given:\n * ```\n * providers: [ {provide: String, useValue: 'all', multi: true} ],\n * viewProviders: [ {provide: String, useValue: 'viewOnly', multi: true} ],\n * ```\n *\n * We have to return `['all']` in case of content injection, but `['all', 'viewOnly']` in case\n * of view injection. We further have to make sure that the shared instances (in our case\n * `all`) are the exact same instance in both the content as well as the view injection. (We\n * have to make sure that we don't double instantiate.) For this reason the `viewProviders`\n * `Factory` has a pointer to the shadowed `providers` factory so that it can instantiate the\n * `providers` (`['all']`) and then extend it with `viewProviders` (`['all'] + ['viewOnly'] =\n * ['all', 'viewOnly']`).\n */\n providerFactory?: NodeInjectorFactory|null;\n\n\n constructor(\n /**\n * Factory to invoke in order to create a new instance.\n */\n public factory:\n (this: NodeInjectorFactory, _: undefined,\n /**\n * array where injectables tokens are stored. This is used in\n * case of an error reporting to produce friendlier errors.\n */\n tData: TData,\n /**\n * array where existing instances of injectables are stored. This is used in case\n * of multi shadow is needed. See `multi` field documentation.\n */\n lView: LView,\n /**\n * The TNode of the same element injector.\n */\n tNode: TDirectiveHostNode) => any,\n /**\n * Set to `true` if the token is declared in `viewProviders` (or if it is component).\n */\n isViewProvider: boolean,\n injectImplementation: null|(<T>(token: ProviderToken<T>, flags?: InjectFlags) => T)) {\n ngDevMode && assertDefined(factory, 'Factory not specified');\n ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.');\n this.canSeeViewProviders = isViewProvider;\n this.injectImpl = injectImplementation;\n }\n}\n\nexport function isFactory(obj: any): obj is NodeInjectorFactory {\n return obj instanceof NodeInjectorFactory;\n}\n\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nexport const unusedValueExportToPlacateAjd = 1;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {CharCode} from '../../util/char_code';\nimport {AttributeMarker, TAttributes} from '../interfaces/node';\nimport {CssSelector} from '../interfaces/projection';\nimport {Renderer} from '../interfaces/renderer';\nimport {RElement} from '../interfaces/renderer_dom';\n\n\n\n/**\n * Assigns all attribute values to the provided element via the inferred renderer.\n *\n * This function accepts two forms of attribute entries:\n *\n * default: (key, value):\n * attrs = [key1, value1, key2, value2]\n *\n * namespaced: (NAMESPACE_MARKER, uri, name, value)\n * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]\n *\n * The `attrs` array can contain a mix of both the default and namespaced entries.\n * The \"default\" values are set without a marker, but if the function comes across\n * a marker value then it will attempt to set a namespaced value. If the marker is\n * not of a namespaced value then the function will quit and return the index value\n * where it stopped during the iteration of the attrs array.\n *\n * See [AttributeMarker] to understand what the namespace marker value is.\n *\n * Note that this instruction does not support assigning style and class values to\n * an element. See `elementStart` and `elementHostAttrs` to learn how styling values\n * are applied to an element.\n * @param renderer The renderer to be used\n * @param native The element that the attributes will be assigned to\n * @param attrs The attribute array of values that will be assigned to the element\n * @returns the index value that was last accessed in the attributes array\n */\nexport function setUpAttributes(renderer: Renderer, native: RElement, attrs: TAttributes): number {\n let i = 0;\n while (i < attrs.length) {\n const value = attrs[i];\n if (typeof value === 'number') {\n // only namespaces are supported. Other value types (such as style/class\n // entries) are not supported in this function.\n if (value !== AttributeMarker.NamespaceURI) {\n break;\n }\n\n // we just landed on the marker value ... therefore\n // we should skip to the next entry\n i++;\n\n const namespaceURI = attrs[i++] as string;\n const attrName = attrs[i++] as string;\n const attrVal = attrs[i++] as string;\n ngDevMode && ngDevMode.rendererSetAttribute++;\n renderer.setAttribute(native, attrName, attrVal, namespaceURI);\n } else {\n // attrName is string;\n const attrName = value as string;\n const attrVal = attrs[++i];\n // Standard attributes\n ngDevMode && ngDevMode.rendererSetAttribute++;\n if (isAnimationProp(attrName)) {\n renderer.setProperty(native, attrName, attrVal);\n } else {\n renderer.setAttribute(native, attrName, attrVal as string);\n }\n i++;\n }\n }\n\n // another piece of code may iterate over the same attributes array. Therefore\n // it may be helpful to return the exact spot where the attributes array exited\n // whether by running into an unsupported marker or if all the static values were\n // iterated over.\n return i;\n}\n\n/**\n * Test whether the given value is a marker that indicates that the following\n * attribute values in a `TAttributes` array are only the names of attributes,\n * and not name-value pairs.\n * @param marker The attribute marker to test.\n * @returns true if the marker is a \"name-only\" marker (e.g. `Bindings`, `Template` or `I18n`).\n */\nexport function isNameOnlyAttributeMarker(marker: string|AttributeMarker|CssSelector) {\n return marker === AttributeMarker.Bindings || marker === AttributeMarker.Template ||\n marker === AttributeMarker.I18n;\n}\n\nexport function isAnimationProp(name: string): boolean {\n // Perf note: accessing charCodeAt to check for the first character of a string is faster as\n // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that\n // charCodeAt doesn't allocate memory to return a substring.\n return name.charCodeAt(0) === CharCode.AT_SIGN;\n}\n\n/**\n * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.\n *\n * This merge function keeps the order of attrs same.\n *\n * @param dst Location of where the merged `TAttributes` should end up.\n * @param src `TAttributes` which should be appended to `dst`\n */\nexport function mergeHostAttrs(dst: TAttributes|null, src: TAttributes|null): TAttributes|null {\n if (src === null || src.length === 0) {\n // do nothing\n } else if (dst === null || dst.length === 0) {\n // We have source, but dst is empty, just make a copy.\n dst = src.slice();\n } else {\n let srcMarker: AttributeMarker = AttributeMarker.ImplicitAttributes;\n for (let i = 0; i < src.length; i++) {\n const item = src[i];\n if (typeof item === 'number') {\n srcMarker = item;\n } else {\n if (srcMarker === AttributeMarker.NamespaceURI) {\n // Case where we need to consume `key1`, `key2`, `value` items.\n } else if (\n srcMarker === AttributeMarker.ImplicitAttributes ||\n srcMarker === AttributeMarker.Styles) {\n // Case where we have to consume `key1` and `value` only.\n mergeHostAttribute(dst, srcMarker, item as string, null, src[++i] as string);\n } else {\n // Case where we have to consume `key1` only.\n mergeHostAttribute(dst, srcMarker, item as string, null, null);\n }\n }\n }\n }\n return dst;\n}\n\n/**\n * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.\n *\n * @param dst `TAttributes` to append to.\n * @param marker Region where the `key`/`value` should be added.\n * @param key1 Key to add to `TAttributes`\n * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)\n * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.\n */\nexport function mergeHostAttribute(\n dst: TAttributes, marker: AttributeMarker, key1: string, key2: string|null,\n value: string|null): void {\n let i = 0;\n // Assume that new markers will be inserted at the end.\n let markerInsertPosition = dst.length;\n // scan until correct type.\n if (marker === AttributeMarker.ImplicitAttributes) {\n markerInsertPosition = -1;\n } else {\n while (i < dst.length) {\n const dstValue = dst[i++];\n if (typeof dstValue === 'number') {\n if (dstValue === marker) {\n markerInsertPosition = -1;\n break;\n } else if (dstValue > marker) {\n // We need to save this as we want the markers to be inserted in specific order.\n markerInsertPosition = i - 1;\n break;\n }\n }\n }\n }\n\n // search until you find place of insertion\n while (i < dst.length) {\n const item = dst[i];\n if (typeof item === 'number') {\n // since `i` started as the index after the marker, we did not find it if we are at the next\n // marker\n break;\n } else if (item === key1) {\n // We already have same token\n if (key2 === null) {\n if (value !== null) {\n dst[i + 1] = value;\n }\n return;\n } else if (key2 === dst[i + 1]) {\n dst[i + 2] = value!;\n return;\n }\n }\n // Increment counter.\n i++;\n if (key2 !== null) i++;\n if (value !== null) i++;\n }\n\n // insert at location.\n if (markerInsertPosition !== -1) {\n dst.splice(markerInsertPosition, 0, marker);\n i = markerInsertPosition + 1;\n }\n dst.splice(i++, 0, key1);\n if (key2 !== null) {\n dst.splice(i++, 0, key2);\n }\n if (value !== null) {\n dst.splice(i++, 0, value);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertGreaterThan, assertNotEqual, assertNumber} from '../../util/assert';\nimport {NO_PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags} from '../interfaces/injector';\nimport {DECLARATION_VIEW, HEADER_OFFSET, LView} from '../interfaces/view';\n\n\n/// Parent Injector Utils ///////////////////////////////////////////////////////////////\nexport function hasParentInjector(parentLocation: RelativeInjectorLocation): boolean {\n return parentLocation !== NO_PARENT_INJECTOR;\n}\n\nexport function getParentInjectorIndex(parentLocation: RelativeInjectorLocation): number {\n ngDevMode && assertNumber(parentLocation, 'Number expected');\n ngDevMode && assertNotEqual(parentLocation as any, -1, 'Not a valid state.');\n const parentInjectorIndex =\n (parentLocation as any as number) & RelativeInjectorLocationFlags.InjectorIndexMask;\n ngDevMode &&\n assertGreaterThan(\n parentInjectorIndex, HEADER_OFFSET,\n 'Parent injector must be pointing past HEADER_OFFSET.');\n return (parentLocation as any as number) & RelativeInjectorLocationFlags.InjectorIndexMask;\n}\n\nexport function getParentInjectorViewOffset(parentLocation: RelativeInjectorLocation): number {\n return (parentLocation as any as number) >> RelativeInjectorLocationFlags.ViewOffsetShift;\n}\n\n/**\n * Unwraps a parent injector location number to find the view offset from the current injector,\n * then walks up the declaration view tree until the view is found that contains the parent\n * injector.\n *\n * @param location The location of the parent injector, which contains the view offset\n * @param startView The LView instance from which to start walking up the view tree\n * @returns The LView instance that contains the parent injector\n */\nexport function getParentInjectorView(location: RelativeInjectorLocation, startView: LView): LView {\n let viewOffset = getParentInjectorViewOffset(location);\n let parentView = startView;\n // For most cases, the parent injector can be found on the host node (e.g. for component\n // or container), but we must keep the loop here to support the rarer case of deeply nested\n // <ng-template> tags or inline views, where the parent injector might live many views\n // above the child injector.\n while (viewOffset > 0) {\n parentView = parentView[DECLARATION_VIEW]!;\n viewOffset--;\n }\n return parentView;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {isForwardRef, resolveForwardRef} from '../di/forward_ref';\nimport {injectRootLimpMode, setInjectImplementation} from '../di/inject_switch';\nimport {Injector} from '../di/injector';\nimport {convertToBitFlags} from '../di/injector_compatibility';\nimport {InjectorMarkers} from '../di/injector_marker';\nimport {InjectFlags, InjectOptions} from '../di/interface/injector';\nimport {ProviderToken} from '../di/provider_token';\nimport {Type} from '../interface/type';\nimport {assertDefined, assertEqual, assertIndexInRange} from '../util/assert';\nimport {noSideEffects} from '../util/closure';\n\nimport {assertDirectiveDef, assertNodeInjector, assertTNodeForLView} from './assert';\nimport {FactoryFn, getFactoryDef} from './definition_factory';\nimport {throwCyclicDependencyError, throwProviderNotFoundError} from './errors_di';\nimport {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';\nimport {registerPreOrderHooks} from './hooks';\nimport {DirectiveDef} from './interfaces/definition';\nimport {isFactory, NO_PARENT_INJECTOR, NodeInjectorFactory, NodeInjectorOffset, RelativeInjectorLocation, RelativeInjectorLocationFlags} from './interfaces/injector';\nimport {AttributeMarker, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';\nimport {isComponentDef, isComponentHost} from './interfaces/type_checks';\nimport {DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, EMBEDDED_VIEW_INJECTOR, FLAGS, INJECTOR, LView, LViewFlags, T_HOST, TData, TVIEW, TView, TViewType} from './interfaces/view';\nimport {assertTNodeType} from './node_assert';\nimport {enterDI, getCurrentTNode, getLView, leaveDI} from './state';\nimport {isNameOnlyAttributeMarker} from './util/attrs_utils';\nimport {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';\nimport {stringifyForError} from './util/stringify_utils';\n\n\n\n/**\n * Defines if the call to `inject` should include `viewProviders` in its resolution.\n *\n * This is set to true when we try to instantiate a component. This value is reset in\n * `getNodeInjectable` to a value which matches the declaration location of the token about to be\n * instantiated. This is done so that if we are injecting a token which was declared outside of\n * `viewProviders` we don't accidentally pull `viewProviders` in.\n *\n * Example:\n *\n * ```\n * @Injectable()\n * class MyService {\n * constructor(public value: String) {}\n * }\n *\n * @Component({\n * providers: [\n * MyService,\n * {provide: String, value: 'providers' }\n * ]\n * viewProviders: [\n * {provide: String, value: 'viewProviders'}\n * ]\n * })\n * class MyComponent {\n * constructor(myService: MyService, value: String) {\n * // We expect that Component can see into `viewProviders`.\n * expect(value).toEqual('viewProviders');\n * // `MyService` was not declared in `viewProviders` hence it can't see it.\n * expect(myService.value).toEqual('providers');\n * }\n * }\n *\n * ```\n */\nlet includeViewProviders = true;\n\nexport function setIncludeViewProviders(v: boolean): boolean {\n const oldValue = includeViewProviders;\n includeViewProviders = v;\n return oldValue;\n}\n\n/**\n * The number of slots in each bloom filter (used by DI). The larger this number, the fewer\n * directives that will share slots, and thus, the fewer false positives when checking for\n * the existence of a directive.\n */\nconst BLOOM_SIZE = 256;\nconst BLOOM_MASK = BLOOM_SIZE - 1;\n\n/**\n * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits,\n * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash\n * number.\n */\nconst BLOOM_BUCKET_BITS = 5;\n\n/** Counter used to generate unique IDs for directives. */\nlet nextNgElementId = 0;\n\n/** Value used when something wasn't found by an injector. */\nconst NOT_FOUND = {};\n\n/**\n * Registers this directive as present in its node's injector by flipping the directive's\n * corresponding bit in the injector's bloom filter.\n *\n * @param injectorIndex The index of the node injector where this token should be registered\n * @param tView The TView for the injector's bloom filters\n * @param type The directive token to register\n */\nexport function bloomAdd(\n injectorIndex: number, tView: TView, type: ProviderToken<any>|string): void {\n ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true');\n let id: number|undefined;\n if (typeof type === 'string') {\n id = type.charCodeAt(0) || 0;\n } else if (type.hasOwnProperty(NG_ELEMENT_ID)) {\n id = (type as any)[NG_ELEMENT_ID];\n }\n\n // Set a unique ID on the directive type, so if something tries to inject the directive,\n // we can easily retrieve the ID and hash it into the bloom bit that should be checked.\n if (id == null) {\n id = (type as any)[NG_ELEMENT_ID] = nextNgElementId++;\n }\n\n // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),\n // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.\n const bloomHash = id & BLOOM_MASK;\n\n // Create a mask that targets the specific bit associated with the directive.\n // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding\n // to bit positions 0 - 31 in a 32 bit integer.\n const mask = 1 << bloomHash;\n\n // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`.\n // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask\n // should be written to.\n (tView.data as number[])[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask;\n}\n\n/**\n * Creates (or gets an existing) injector for a given element or container.\n *\n * @param tNode for which an injector should be retrieved / created.\n * @param lView View where the node is stored\n * @returns Node injector\n */\nexport function getOrCreateNodeInjectorForNode(\n tNode: TElementNode|TContainerNode|TElementContainerNode, lView: LView): number {\n const existingInjectorIndex = getInjectorIndex(tNode, lView);\n if (existingInjectorIndex !== -1) {\n return existingInjectorIndex;\n }\n\n const tView = lView[TVIEW];\n if (tView.firstCreatePass) {\n tNode.injectorIndex = lView.length;\n insertBloom(tView.data, tNode); // foundation for node bloom\n insertBloom(lView, null); // foundation for cumulative bloom\n insertBloom(tView.blueprint, null);\n }\n\n const parentLoc = getParentInjectorLocation(tNode, lView);\n const injectorIndex = tNode.injectorIndex;\n\n // If a parent injector can't be found, its location is set to -1.\n // In that case, we don't need to set up a cumulative bloom\n if (hasParentInjector(parentLoc)) {\n const parentIndex = getParentInjectorIndex(parentLoc);\n const parentLView = getParentInjectorView(parentLoc, lView);\n const parentData = parentLView[TVIEW].data as any;\n // Creates a cumulative bloom filter that merges the parent's bloom filter\n // and its own cumulative bloom (which contains tokens for all ancestors)\n for (let i = 0; i < NodeInjectorOffset.BLOOM_SIZE; i++) {\n lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];\n }\n }\n\n lView[injectorIndex + NodeInjectorOffset.PARENT] = parentLoc;\n return injectorIndex;\n}\n\nfunction insertBloom(arr: any[], footer: TNode|null): void {\n arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);\n}\n\n\nexport function getInjectorIndex(tNode: TNode, lView: LView): number {\n if (tNode.injectorIndex === -1 ||\n // If the injector index is the same as its parent's injector index, then the index has been\n // copied down from the parent node. No injector has been created yet on this node.\n (tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex) ||\n // After the first template pass, the injector index might exist but the parent values\n // might not have been calculated yet for this instance\n lView[tNode.injectorIndex + NodeInjectorOffset.PARENT] === null) {\n return -1;\n } else {\n ngDevMode && assertIndexInRange(lView, tNode.injectorIndex);\n return tNode.injectorIndex;\n }\n}\n\n/**\n * Finds the index of the parent injector, with a view offset if applicable. Used to set the\n * parent injector initially.\n *\n * @returns Returns a number that is the combination of the number of LViews that we have to go up\n * to find the LView containing the parent inject AND the index of the injector within that LView.\n */\nexport function getParentInjectorLocation(tNode: TNode, lView: LView): RelativeInjectorLocation {\n if (tNode.parent && tNode.parent.injectorIndex !== -1) {\n // If we have a parent `TNode` and there is an injector associated with it we are done, because\n // the parent injector is within the current `LView`.\n return tNode.parent.injectorIndex as any; // ViewOffset is 0\n }\n\n // When parent injector location is computed it may be outside of the current view. (ie it could\n // be pointing to a declared parent location). This variable stores number of declaration parents\n // we need to walk up in order to find the parent injector location.\n let declarationViewOffset = 0;\n let parentTNode: TNode|null = null;\n let lViewCursor: LView|null = lView;\n\n // The parent injector is not in the current `LView`. We will have to walk the declared parent\n // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent\n // `NodeInjector`.\n while (lViewCursor !== null) {\n parentTNode = getTNodeFromLView(lViewCursor);\n\n if (parentTNode === null) {\n // If we have no parent, than we are done.\n return NO_PARENT_INJECTOR;\n }\n\n ngDevMode && parentTNode && assertTNodeForLView(parentTNode!, lViewCursor[DECLARATION_VIEW]!);\n // Every iteration of the loop requires that we go to the declared parent.\n declarationViewOffset++;\n lViewCursor = lViewCursor[DECLARATION_VIEW];\n\n if (parentTNode.injectorIndex !== -1) {\n // We found a NodeInjector which points to something.\n return (parentTNode.injectorIndex |\n (declarationViewOffset << RelativeInjectorLocationFlags.ViewOffsetShift)) as any;\n }\n }\n return NO_PARENT_INJECTOR;\n}\n/**\n * Makes a type or an injection token public to the DI system by adding it to an\n * injector's bloom filter.\n *\n * @param di The node injector in which a directive will be added\n * @param token The type or the injection token to be made public\n */\nexport function diPublicInInjector(\n injectorIndex: number, tView: TView, token: ProviderToken<any>): void {\n bloomAdd(injectorIndex, tView, token);\n}\n\n/**\n * Inject static attribute value into directive constructor.\n *\n * This method is used with `factory` functions which are generated as part of\n * `defineDirective` or `defineComponent`. The method retrieves the static value\n * of an attribute. (Dynamic attributes are not supported since they are not resolved\n * at the time of injection and can change over time.)\n *\n * # Example\n * Given:\n * ```\n * @Component(...)\n * class MyComponent {\n * constructor(@Attribute('title') title: string) { ... }\n * }\n * ```\n * When instantiated with\n * ```\n * <my-component title=\"Hello\"></my-component>\n * ```\n *\n * Then factory method generated is:\n * ```\n * MyComponent.ɵcmp = defineComponent({\n * factory: () => new MyComponent(injectAttribute('title'))\n * ...\n * })\n * ```\n *\n * @publicApi\n */\nexport function injectAttributeImpl(tNode: TNode, attrNameToInject: string): string|null {\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyContainer | TNodeType.AnyRNode);\n ngDevMode && assertDefined(tNode, 'expecting tNode');\n if (attrNameToInject === 'class') {\n return tNode.classes;\n }\n if (attrNameToInject === 'style') {\n return tNode.styles;\n }\n\n const attrs = tNode.attrs;\n if (attrs) {\n const attrsLength = attrs.length;\n let i = 0;\n while (i < attrsLength) {\n const value = attrs[i];\n\n // If we hit a `Bindings` or `Template` marker then we are done.\n if (isNameOnlyAttributeMarker(value)) break;\n\n // Skip namespaced attributes\n if (value === AttributeMarker.NamespaceURI) {\n // we skip the next two values\n // as namespaced attributes looks like\n // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',\n // 'existValue', ...]\n i = i + 2;\n } else if (typeof value === 'number') {\n // Skip to the first value of the marked attribute.\n i++;\n while (i < attrsLength && typeof attrs[i] === 'string') {\n i++;\n }\n } else if (value === attrNameToInject) {\n return attrs[i + 1] as string;\n } else {\n i = i + 2;\n }\n }\n }\n return null;\n}\n\n\nfunction notFoundValueOrThrow<T>(\n notFoundValue: T|null, token: ProviderToken<T>, flags: InjectFlags): T|null {\n if ((flags & InjectFlags.Optional) || notFoundValue !== undefined) {\n return notFoundValue;\n } else {\n throwProviderNotFoundError(token, 'NodeInjector');\n }\n}\n\n/**\n * Returns the value associated to the given token from the ModuleInjector or throws exception\n *\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector or throws an exception\n */\nfunction lookupTokenUsingModuleInjector<T>(\n lView: LView, token: ProviderToken<T>, flags: InjectFlags, notFoundValue?: any): T|null {\n if ((flags & InjectFlags.Optional) && notFoundValue === undefined) {\n // This must be set or the NullInjector will throw for optional deps\n notFoundValue = null;\n }\n\n if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {\n const moduleInjector = lView[INJECTOR];\n // switch to `injectInjectorOnly` implementation for module injector, since module injector\n // should not have access to Component/Directive DI scope (that may happen through\n // `directiveInject` implementation)\n const previousInjectImplementation = setInjectImplementation(undefined);\n try {\n if (moduleInjector) {\n return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);\n } else {\n return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);\n }\n } finally {\n setInjectImplementation(previousInjectImplementation);\n }\n }\n return notFoundValueOrThrow<T>(notFoundValue, token, flags);\n}\n\n/**\n * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.\n *\n * Look for the injector providing the token by walking up the node injector tree and then\n * the module injector tree.\n *\n * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom\n * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nexport function getOrCreateInjectable<T>(\n tNode: TDirectiveHostNode|null, lView: LView, token: ProviderToken<T>,\n flags: InjectFlags = InjectFlags.Default, notFoundValue?: any): T|null {\n if (tNode !== null) {\n // If the view or any of its ancestors have an embedded\n // view injector, we have to look it up there first.\n if (lView[FLAGS] & LViewFlags.HasEmbeddedViewInjector) {\n const embeddedInjectorValue =\n lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, NOT_FOUND);\n if (embeddedInjectorValue !== NOT_FOUND) {\n return embeddedInjectorValue;\n }\n }\n\n // Otherwise try the node injector.\n const value = lookupTokenUsingNodeInjector(tNode, lView, token, flags, NOT_FOUND);\n if (value !== NOT_FOUND) {\n return value;\n }\n }\n\n // Finally, fall back to the module injector.\n return lookupTokenUsingModuleInjector<T>(lView, token, flags, notFoundValue);\n}\n\n/**\n * Returns the value associated to the given token from the node injector.\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nfunction lookupTokenUsingNodeInjector<T>(\n tNode: TDirectiveHostNode, lView: LView, token: ProviderToken<T>, flags: InjectFlags,\n notFoundValue?: any) {\n const bloomHash = bloomHashBitOrFactory(token);\n // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef\n // so just call the factory function to create it.\n if (typeof bloomHash === 'function') {\n if (!enterDI(lView, tNode, flags)) {\n // Failed to enter DI, try module injector instead. If a token is injected with the @Host\n // flag, the module injector is not searched for that token in Ivy.\n return (flags & InjectFlags.Host) ?\n notFoundValueOrThrow<T>(notFoundValue, token, flags) :\n lookupTokenUsingModuleInjector<T>(lView, token, flags, notFoundValue);\n }\n try {\n const value = bloomHash(flags);\n if (value == null && !(flags & InjectFlags.Optional)) {\n throwProviderNotFoundError(token);\n } else {\n return value;\n }\n } finally {\n leaveDI();\n }\n } else if (typeof bloomHash === 'number') {\n // A reference to the previous injector TView that was found while climbing the element\n // injector tree. This is used to know if viewProviders can be accessed on the current\n // injector.\n let previousTView: TView|null = null;\n let injectorIndex = getInjectorIndex(tNode, lView);\n let parentLocation: RelativeInjectorLocation = NO_PARENT_INJECTOR;\n let hostTElementNode: TNode|null =\n flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null;\n\n // If we should skip this injector, or if there is no injector on this node, start by\n // searching the parent injector.\n if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) {\n parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) :\n lView[injectorIndex + NodeInjectorOffset.PARENT];\n\n if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) {\n injectorIndex = -1;\n } else {\n previousTView = lView[TVIEW];\n injectorIndex = getParentInjectorIndex(parentLocation);\n lView = getParentInjectorView(parentLocation, lView);\n }\n }\n\n // Traverse up the injector tree until we find a potential match or until we know there\n // *isn't* a match.\n while (injectorIndex !== -1) {\n ngDevMode && assertNodeInjector(lView, injectorIndex);\n\n // Check the current injector. If it matches, see if it contains token.\n const tView = lView[TVIEW];\n ngDevMode &&\n assertTNodeForLView(tView.data[injectorIndex + NodeInjectorOffset.TNODE] as TNode, lView);\n if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {\n // At this point, we have an injector which *may* contain the token, so we step through\n // the providers and directives associated with the injector's corresponding node to get\n // the instance.\n const instance: T|{}|null = searchTokensOnInjector<T>(\n injectorIndex, lView, token, previousTView, flags, hostTElementNode);\n if (instance !== NOT_FOUND) {\n return instance;\n }\n }\n parentLocation = lView[injectorIndex + NodeInjectorOffset.PARENT];\n if (parentLocation !== NO_PARENT_INJECTOR &&\n shouldSearchParent(\n flags,\n lView[TVIEW].data[injectorIndex + NodeInjectorOffset.TNODE] === hostTElementNode) &&\n bloomHasToken(bloomHash, injectorIndex, lView)) {\n // The def wasn't found anywhere on this node, so it was a false positive.\n // Traverse up the tree and continue searching.\n previousTView = tView;\n injectorIndex = getParentInjectorIndex(parentLocation);\n lView = getParentInjectorView(parentLocation, lView);\n } else {\n // If we should not search parent OR If the ancestor bloom filter value does not have the\n // bit corresponding to the directive we can give up on traversing up to find the specific\n // injector.\n injectorIndex = -1;\n }\n }\n }\n\n return notFoundValue;\n}\n\nfunction searchTokensOnInjector<T>(\n injectorIndex: number, lView: LView, token: ProviderToken<T>, previousTView: TView|null,\n flags: InjectFlags, hostTElementNode: TNode|null) {\n const currentTView = lView[TVIEW];\n const tNode = currentTView.data[injectorIndex + NodeInjectorOffset.TNODE] as TNode;\n // First, we need to determine if view providers can be accessed by the starting element.\n // There are two possibilities\n const canAccessViewProviders = previousTView == null ?\n // 1) This is the first invocation `previousTView == null` which means that we are at the\n // `TNode` of where injector is starting to look. In such a case the only time we are allowed\n // to look into the ViewProviders is if:\n // - we are on a component\n // - AND the injector set `includeViewProviders` to true (implying that the token can see\n // ViewProviders because it is the Component or a Service which itself was declared in\n // ViewProviders)\n (isComponentHost(tNode) && includeViewProviders) :\n // 2) `previousTView != null` which means that we are now walking across the parent nodes.\n // In such a case we are only allowed to look into the ViewProviders if:\n // - We just crossed from child View to Parent View `previousTView != currentTView`\n // - AND the parent TNode is an Element.\n // This means that we just came from the Component's View and therefore are allowed to see\n // into the ViewProviders.\n (previousTView != currentTView && ((tNode.type & TNodeType.AnyRNode) !== 0));\n\n // This special case happens when there is a @host on the inject and when we are searching\n // on the host element node.\n const isHostSpecialCase = (flags & InjectFlags.Host) && hostTElementNode === tNode;\n\n const injectableIdx = locateDirectiveOrProvider(\n tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);\n if (injectableIdx !== null) {\n return getNodeInjectable(lView, currentTView, injectableIdx, tNode as TElementNode);\n } else {\n return NOT_FOUND;\n }\n}\n\n/**\n * Searches for the given token among the node's directives and providers.\n *\n * @param tNode TNode on which directives are present.\n * @param tView The tView we are currently processing\n * @param token Provider token or type of a directive to look for.\n * @param canAccessViewProviders Whether view providers should be considered.\n * @param isHostSpecialCase Whether the host special case applies.\n * @returns Index of a found directive or provider, or null when none found.\n */\nexport function locateDirectiveOrProvider<T>(\n tNode: TNode, tView: TView, token: ProviderToken<T>|string, canAccessViewProviders: boolean,\n isHostSpecialCase: boolean|number): number|null {\n const nodeProviderIndexes = tNode.providerIndexes;\n const tInjectables = tView.data;\n\n const injectablesStart = nodeProviderIndexes & TNodeProviderIndexes.ProvidersStartIndexMask;\n const directivesStart = tNode.directiveStart;\n const directiveEnd = tNode.directiveEnd;\n const cptViewProvidersCount =\n nodeProviderIndexes >> TNodeProviderIndexes.CptViewProvidersCountShift;\n const startingIndex =\n canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount;\n // When the host special case applies, only the viewProviders and the component are visible\n const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;\n for (let i = startingIndex; i < endIndex; i++) {\n const providerTokenOrDef = tInjectables[i] as ProviderToken<any>| DirectiveDef<any>| string;\n if (i < directivesStart && token === providerTokenOrDef ||\n i >= directivesStart && (providerTokenOrDef as DirectiveDef<any>).type === token) {\n return i;\n }\n }\n if (isHostSpecialCase) {\n const dirDef = tInjectables[directivesStart] as DirectiveDef<any>;\n if (dirDef && isComponentDef(dirDef) && dirDef.type === token) {\n return directivesStart;\n }\n }\n return null;\n}\n\n/**\n * Retrieve or instantiate the injectable from the `LView` at particular `index`.\n *\n * This function checks to see if the value has already been instantiated and if so returns the\n * cached `injectable`. Otherwise if it detects that the value is still a factory it\n * instantiates the `injectable` and caches the value.\n */\nexport function getNodeInjectable(\n lView: LView, tView: TView, index: number, tNode: TDirectiveHostNode): any {\n let value = lView[index];\n const tData = tView.data;\n if (isFactory(value)) {\n const factory: NodeInjectorFactory = value;\n if (factory.resolving) {\n throwCyclicDependencyError(stringifyForError(tData[index]));\n }\n const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);\n factory.resolving = true;\n const previousInjectImplementation =\n factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null;\n const success = enterDI(lView, tNode, InjectFlags.Default);\n ngDevMode &&\n assertEqual(\n success, true,\n 'Because flags do not contain \\`SkipSelf\\' we expect this to always succeed.');\n try {\n value = lView[index] = factory.factory(undefined, tData, lView, tNode);\n // This code path is hit for both directives and providers.\n // For perf reasons, we want to avoid searching for hooks on providers.\n // It does no harm to try (the hooks just won't exist), but the extra\n // checks are unnecessary and this is a hot path. So we check to see\n // if the index of the dependency is in the directive range for this\n // tNode. If it's not, we know it's a provider and skip hook registration.\n if (tView.firstCreatePass && index >= tNode.directiveStart) {\n ngDevMode && assertDirectiveDef(tData[index]);\n registerPreOrderHooks(index, tData[index] as DirectiveDef<any>, tView);\n }\n } finally {\n previousInjectImplementation !== null &&\n setInjectImplementation(previousInjectImplementation);\n setIncludeViewProviders(previousIncludeViewProviders);\n factory.resolving = false;\n leaveDI();\n }\n }\n return value;\n}\n\n/**\n * Returns the bit in an injector's bloom filter that should be used to determine whether or not\n * the directive might be provided by the injector.\n *\n * When a directive is public, it is added to the bloom filter and given a unique ID that can be\n * retrieved on the Type. When the directive isn't public or the token is not a directive `null`\n * is returned as the node injector can not possibly provide that token.\n *\n * @param token the injection token\n * @returns the matching bit to check in the bloom filter or `null` if the token is not known.\n * When the returned value is negative then it represents special values such as `Injector`.\n */\nexport function bloomHashBitOrFactory(token: ProviderToken<any>|string): number|Function|undefined {\n ngDevMode && assertDefined(token, 'token must be defined');\n if (typeof token === 'string') {\n return token.charCodeAt(0) || 0;\n }\n const tokenId: number|undefined =\n // First check with `hasOwnProperty` so we don't get an inherited ID.\n token.hasOwnProperty(NG_ELEMENT_ID) ? (token as any)[NG_ELEMENT_ID] : undefined;\n // Negative token IDs are used for special objects such as `Injector`\n if (typeof tokenId === 'number') {\n if (tokenId >= 0) {\n return tokenId & BLOOM_MASK;\n } else {\n ngDevMode &&\n assertEqual(tokenId, InjectorMarkers.Injector, 'Expecting to get Special Injector Id');\n return createNodeInjector;\n }\n } else {\n return tokenId;\n }\n}\n\nexport function bloomHasToken(bloomHash: number, injectorIndex: number, injectorView: LView|TData) {\n // Create a mask that targets the specific bit associated with the directive we're looking for.\n // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding\n // to bit positions 0 - 31 in a 32 bit integer.\n const mask = 1 << bloomHash;\n\n // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of\n // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset\n // that should be used.\n const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)];\n\n // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,\n // this injector is a potential match.\n return !!(value & mask);\n}\n\n/** Returns true if flags prevent parent injector from being searched for tokens */\nfunction shouldSearchParent(flags: InjectFlags, isFirstHostTNode: boolean): boolean|number {\n return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);\n}\n\nexport class NodeInjector implements Injector {\n constructor(\n private _tNode: TElementNode|TContainerNode|TElementContainerNode|null,\n private _lView: LView) {}\n\n get(token: any, notFoundValue?: any, flags?: InjectFlags|InjectOptions): any {\n return getOrCreateInjectable(\n this._tNode, this._lView, token, convertToBitFlags(flags), notFoundValue);\n }\n}\n\n/** Creates a `NodeInjector` for the current node. */\nexport function createNodeInjector(): Injector {\n return new NodeInjector(getCurrentTNode()! as TDirectiveHostNode, getLView()) as any;\n}\n\n/**\n * @codeGenApi\n */\nexport function ɵɵgetInheritedFactory<T>(type: Type<any>): (type: Type<T>) => T {\n return noSideEffects(() => {\n const ownConstructor = type.prototype.constructor;\n const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor);\n const objectPrototype = Object.prototype;\n let parent = Object.getPrototypeOf(type.prototype).constructor;\n\n // Go up the prototype until we hit `Object`.\n while (parent && parent !== objectPrototype) {\n const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent);\n\n // If we hit something that has a factory and the factory isn't the same as the type,\n // we've found the inherited factory. Note the check that the factory isn't the type's\n // own factory is redundant in most cases, but if the user has custom decorators on the\n // class, this lookup will start one level down in the prototype chain, causing us to\n // find the own factory first and potentially triggering an infinite loop downstream.\n if (factory && factory !== ownFactory) {\n return factory;\n }\n\n parent = Object.getPrototypeOf(parent);\n }\n\n // There is no factory defined. Either this was improper usage of inheritance\n // (no Angular decorator on the superclass) or there is no constructor at all\n // in the inheritance chain. Since the two cases cannot be distinguished, the\n // latter has to be assumed.\n return t => new t();\n });\n}\n\nfunction getFactoryOf<T>(type: Type<any>): ((type?: Type<T>) => T | null)|null {\n if (isForwardRef(type)) {\n return () => {\n const factory = getFactoryOf<T>(resolveForwardRef(type));\n return factory && factory();\n };\n }\n return getFactoryDef<T>(type);\n}\n\n/**\n * Returns a value from the closest embedded or node injector.\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nfunction lookupTokenUsingEmbeddedInjector<T>(\n tNode: TDirectiveHostNode, lView: LView, token: ProviderToken<T>, flags: InjectFlags,\n notFoundValue?: any) {\n let currentTNode: TDirectiveHostNode|null = tNode;\n let currentLView: LView|null = lView;\n\n // When an LView with an embedded view injector is inserted, it'll likely be interlaced with\n // nodes who may have injectors (e.g. node injector -> embedded view injector -> node injector).\n // Since the bloom filters for the node injectors have already been constructed and we don't\n // have a way of extracting the records from an injector, the only way to maintain the correct\n // hierarchy when resolving the value is to walk it node-by-node while attempting to resolve\n // the token at each level.\n while (currentTNode !== null && currentLView !== null &&\n (currentLView[FLAGS] & LViewFlags.HasEmbeddedViewInjector) &&\n !(currentLView[FLAGS] & LViewFlags.IsRoot)) {\n ngDevMode && assertTNodeForLView(currentTNode, currentLView);\n\n // Note that this lookup on the node injector is using the `Self` flag, because\n // we don't want the node injector to look at any parent injectors since we\n // may hit the embedded view injector first.\n const nodeInjectorValue = lookupTokenUsingNodeInjector(\n currentTNode, currentLView, token, flags | InjectFlags.Self, NOT_FOUND);\n if (nodeInjectorValue !== NOT_FOUND) {\n return nodeInjectorValue;\n }\n\n // Has an explicit type due to a TS bug: https://github.com/microsoft/TypeScript/issues/33191\n let parentTNode: TElementNode|TContainerNode|null = currentTNode.parent;\n\n // `TNode.parent` includes the parent within the current view only. If it doesn't exist,\n // it means that we've hit the view boundary and we need to go up to the next view.\n if (!parentTNode) {\n // Before we go to the next LView, check if the token exists on the current embedded injector.\n const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR];\n if (embeddedViewInjector) {\n const embeddedViewInjectorValue =\n embeddedViewInjector.get(token, NOT_FOUND as T | {}, flags);\n if (embeddedViewInjectorValue !== NOT_FOUND) {\n return embeddedViewInjectorValue;\n }\n }\n\n // Otherwise keep going up the tree.\n parentTNode = getTNodeFromLView(currentLView);\n currentLView = currentLView[DECLARATION_VIEW];\n }\n\n currentTNode = parentTNode;\n }\n\n return notFoundValue;\n}\n\n/** Gets the TNode associated with an LView inside of the declaration view. */\nfunction getTNodeFromLView(lView: LView): TElementNode|TElementContainerNode|null {\n const tView = lView[TVIEW];\n const tViewType = tView.type;\n\n // The parent pointer differs based on `TView.type`.\n if (tViewType === TViewType.Embedded) {\n ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');\n return tView.declTNode as TElementContainerNode;\n } else if (tViewType === TViewType.Component) {\n // Components don't have `TView.declTNode` because each instance of component could be\n // inserted in different location, hence `TView.declTNode` is meaningless.\n return lView[T_HOST] as TElementNode;\n }\n\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {injectAttributeImpl} from '../di';\nimport {getCurrentTNode} from '../state';\n\n/**\n * Facade for the attribute injection from DI.\n *\n * @codeGenApi\n */\nexport function ɵɵinjectAttribute(attrNameToInject: string): string|null {\n return injectAttributeImpl(getCurrentTNode()!, attrNameToInject);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\n\nimport {noSideEffects} from './closure';\n\n\n\n/**\n * An interface implemented by all Angular type decorators, which allows them to be used as\n * decorators as well as Angular syntax.\n *\n * ```\n * @ng.Component({...})\n * class MyClass {...}\n * ```\n *\n * @publicApi\n */\nexport interface TypeDecorator {\n /**\n * Invoke as decorator.\n */\n <T extends Type<any>>(type: T): T;\n\n // Make TypeDecorator assignable to built-in ParameterDecorator type.\n // ParameterDecorator is declared in lib.d.ts as a `declare type`\n // so we cannot declare this interface as a subtype.\n // see https://github.com/angular/angular/issues/3379#issuecomment-126169417\n (target: Object, propertyKey?: string|symbol, parameterIndex?: number): void;\n}\n\nexport const ANNOTATIONS = '__annotations__';\nexport const PARAMETERS = '__parameters__';\nexport const PROP_METADATA = '__prop__metadata__';\n\n/**\n * @suppress {globalThis}\n */\nexport function makeDecorator<T>(\n name: string, props?: (...args: any[]) => any, parentClass?: any,\n additionalProcessing?: (type: Type<T>) => void,\n typeFn?: (type: Type<T>, ...args: any[]) => void):\n {new (...args: any[]): any; (...args: any[]): any; (...args: any[]): (cls: any) => any;} {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n\n function DecoratorFactory(\n this: unknown|typeof DecoratorFactory, ...args: any[]): (cls: Type<T>) => any {\n if (this instanceof DecoratorFactory) {\n metaCtor.call(this, ...args);\n return this as typeof DecoratorFactory;\n }\n\n const annotationInstance = new (DecoratorFactory as any)(...args);\n return function TypeDecorator(cls: Type<T>) {\n if (typeFn) typeFn(cls, ...args);\n // Use of Object.defineProperty is important since it creates non-enumerable property which\n // prevents the property is copied during subclassing.\n const annotations = cls.hasOwnProperty(ANNOTATIONS) ?\n (cls as any)[ANNOTATIONS] :\n (Object.defineProperty(cls, ANNOTATIONS, {value: []}) as any)[ANNOTATIONS];\n annotations.push(annotationInstance);\n\n\n if (additionalProcessing) additionalProcessing(cls);\n\n return cls;\n };\n }\n\n if (parentClass) {\n DecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n\n DecoratorFactory.prototype.ngMetadataName = name;\n (DecoratorFactory as any).annotationCls = DecoratorFactory;\n return DecoratorFactory as any;\n });\n}\n\nfunction makeMetadataCtor(props?: (...args: any[]) => any): any {\n return function ctor(this: any, ...args: any[]) {\n if (props) {\n const values = props(...args);\n for (const propName in values) {\n this[propName] = values[propName];\n }\n }\n };\n}\n\nexport function makeParamDecorator(\n name: string, props?: (...args: any[]) => any, parentClass?: any): any {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n function ParamDecoratorFactory(\n this: unknown|typeof ParamDecoratorFactory, ...args: any[]): any {\n if (this instanceof ParamDecoratorFactory) {\n metaCtor.apply(this, args);\n return this;\n }\n const annotationInstance = new (<any>ParamDecoratorFactory)(...args);\n\n (<any>ParamDecorator).annotation = annotationInstance;\n return ParamDecorator;\n\n function ParamDecorator(cls: any, unusedKey: any, index: number): any {\n // Use of Object.defineProperty is important since it creates non-enumerable property which\n // prevents the property is copied during subclassing.\n const parameters = cls.hasOwnProperty(PARAMETERS) ?\n (cls as any)[PARAMETERS] :\n Object.defineProperty(cls, PARAMETERS, {value: []})[PARAMETERS];\n\n // there might be gaps if some in between parameters do not have annotations.\n // we pad with nulls.\n while (parameters.length <= index) {\n parameters.push(null);\n }\n\n (parameters[index] = parameters[index] || []).push(annotationInstance);\n return cls;\n }\n }\n if (parentClass) {\n ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n ParamDecoratorFactory.prototype.ngMetadataName = name;\n (<any>ParamDecoratorFactory).annotationCls = ParamDecoratorFactory;\n return ParamDecoratorFactory;\n });\n}\n\nexport function makePropDecorator(\n name: string, props?: (...args: any[]) => any, parentClass?: any,\n additionalProcessing?: (target: any, name: string, ...args: any[]) => void): any {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n\n function PropDecoratorFactory(this: unknown|typeof PropDecoratorFactory, ...args: any[]): any {\n if (this instanceof PropDecoratorFactory) {\n metaCtor.apply(this, args);\n return this;\n }\n\n const decoratorInstance = new (<any>PropDecoratorFactory)(...args);\n\n function PropDecorator(target: any, name: string) {\n const constructor = target.constructor;\n // Use of Object.defineProperty is important because it creates a non-enumerable property\n // which prevents the property from being copied during subclassing.\n const meta = constructor.hasOwnProperty(PROP_METADATA) ?\n (constructor as any)[PROP_METADATA] :\n Object.defineProperty(constructor, PROP_METADATA, {value: {}})[PROP_METADATA];\n meta[name] = meta.hasOwnProperty(name) && meta[name] || [];\n meta[name].unshift(decoratorInstance);\n\n if (additionalProcessing) additionalProcessing(target, name, ...args);\n }\n\n return PropDecorator;\n }\n\n if (parentClass) {\n PropDecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n\n PropDecoratorFactory.prototype.ngMetadataName = name;\n (<any>PropDecoratorFactory).annotationCls = PropDecoratorFactory;\n return PropDecoratorFactory;\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\nimport {assertLessThan} from '../util/assert';\n\nimport {ɵɵdefineInjectable} from './interface/defs';\n\n/**\n * Creates a token that can be used in a DI Provider.\n *\n * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a\n * runtime representation) such as when injecting an interface, callable type, array or\n * parameterized type.\n *\n * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by\n * the `Injector`. This provides an additional level of type safety.\n *\n * ```\n * interface MyInterface {...}\n * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));\n * // myInterface is inferred to be MyInterface.\n * ```\n *\n * When creating an `InjectionToken`, you can optionally specify a factory function which returns\n * (possibly by creating) a default value of the parameterized type `T`. This sets up the\n * `InjectionToken` using this factory as a provider as if it was defined explicitly in the\n * application's root injector. If the factory function, which takes zero arguments, needs to inject\n * dependencies, it can do so using the `inject` function.\n * As you can see in the Tree-shakable InjectionToken example below.\n *\n * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which\n * overrides the above behavior and marks the token as belonging to a particular `@NgModule` (note:\n * this option is now deprecated). As mentioned above, `'root'` is the default value for\n * `providedIn`.\n *\n * The `providedIn: NgModule` and `providedIn: 'any'` options are deprecated.\n *\n * @usageNotes\n * ### Basic Examples\n *\n * ### Plain InjectionToken\n *\n * {@example core/di/ts/injector_spec.ts region='InjectionToken'}\n *\n * ### Tree-shakable InjectionToken\n *\n * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}\n *\n *\n * @publicApi\n */\nexport class InjectionToken<T> {\n /** @internal */\n readonly ngMetadataName = 'InjectionToken';\n\n readonly ɵprov: unknown;\n\n /**\n * @param _desc Description for the token,\n * used only for debugging purposes,\n * it should but does not need to be unique\n * @param options Options for the token's usage, as described above\n */\n constructor(protected _desc: string, options?: {\n providedIn?: Type<any>|'root'|'platform'|'any'|null, factory: () => T\n }) {\n this.ɵprov = undefined;\n if (typeof options == 'number') {\n (typeof ngDevMode === 'undefined' || ngDevMode) &&\n assertLessThan(options, 0, 'Only negative numbers are supported here');\n // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.\n // See `InjectorMarkers`\n (this as any).__NG_ELEMENT_ID__ = options;\n } else if (options !== undefined) {\n this.ɵprov = ɵɵdefineInjectable({\n token: this,\n providedIn: options.providedIn || 'root',\n factory: options.factory,\n });\n }\n }\n\n /**\n * @internal\n */\n get multi(): InjectionToken<Array<T>> {\n return this as InjectionToken<Array<T>>;\n }\n\n toString(): string {\n return `InjectionToken ${this._desc}`;\n }\n}\n\nexport interface InjectableDefToken<T> extends InjectionToken<T> {\n ɵprov: unknown;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertEqual, assertLessThanOrEqual} from './assert';\n\n/**\n * Determines if the contents of two arrays is identical\n *\n * @param a first array\n * @param b second array\n * @param identityAccessor Optional function for extracting stable object identity from a value in\n * the array.\n */\nexport function arrayEquals<T>(a: T[], b: T[], identityAccessor?: (value: T) => unknown): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n let valueA = a[i];\n let valueB = b[i];\n if (identityAccessor) {\n valueA = identityAccessor(valueA) as any;\n valueB = identityAccessor(valueB) as any;\n }\n if (valueB !== valueA) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Flattens an array.\n */\nexport function flatten(list: any[]): any[] {\n return list.flat(Number.POSITIVE_INFINITY);\n}\n\nexport function deepForEach<T>(input: (T|any[])[], fn: (value: T) => void): void {\n input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value));\n}\n\nexport function addToArray(arr: any[], index: number, value: any): void {\n // perf: array.push is faster than array.splice!\n if (index >= arr.length) {\n arr.push(value);\n } else {\n arr.splice(index, 0, value);\n }\n}\n\nexport function removeFromArray(arr: any[], index: number): any {\n // perf: array.pop is faster than array.splice!\n if (index >= arr.length - 1) {\n return arr.pop();\n } else {\n return arr.splice(index, 1)[0];\n }\n}\n\nexport function newArray<T = any>(size: number): T[];\nexport function newArray<T>(size: number, value: T): T[];\nexport function newArray<T>(size: number, value?: T): T[] {\n const list: T[] = [];\n for (let i = 0; i < size; i++) {\n list.push(value!);\n }\n return list;\n}\n\n/**\n * Remove item from array (Same as `Array.splice()` but faster.)\n *\n * `Array.splice()` is not as fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * https://jsperf.com/fast-array-splice (About 20x faster)\n *\n * @param array Array to splice\n * @param index Index of element in array to remove.\n * @param count Number of items to remove.\n */\nexport function arraySplice(array: any[], index: number, count: number): void {\n const length = array.length - count;\n while (index < length) {\n array[index] = array[index + count];\n index++;\n }\n while (count--) {\n array.pop(); // shrink the array\n }\n}\n\n/**\n * Same as `Array.splice(index, 0, value)` but faster.\n *\n * `Array.splice()` is not fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * @param array Array to splice.\n * @param index Index in array where the `value` should be added.\n * @param value Value to add to array.\n */\nexport function arrayInsert(array: any[], index: number, value: any): void {\n ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\\'t insert past array end.');\n let end = array.length;\n while (end > index) {\n const previousEnd = end - 1;\n array[end] = array[previousEnd];\n end = previousEnd;\n }\n array[index] = value;\n}\n\n/**\n * Same as `Array.splice2(index, 0, value1, value2)` but faster.\n *\n * `Array.splice()` is not fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * @param array Array to splice.\n * @param index Index in array where the `value` should be added.\n * @param value1 Value to add to array.\n * @param value2 Value to add to array.\n */\nexport function arrayInsert2(array: any[], index: number, value1: any, value2: any): void {\n ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\\'t insert past array end.');\n let end = array.length;\n if (end == index) {\n // inserting at the end.\n array.push(value1, value2);\n } else if (end === 1) {\n // corner case when we have less items in array than we have items to insert.\n array.push(value2, array[0]);\n array[0] = value1;\n } else {\n end--;\n array.push(array[end - 1], array[end]);\n while (end > index) {\n const previousEnd = end - 2;\n array[end] = array[previousEnd];\n end--;\n }\n array[index] = value1;\n array[index + 1] = value2;\n }\n}\n\n\n/**\n * Get an index of an `value` in a sorted `array`.\n *\n * NOTE:\n * - This uses binary search algorithm for fast removals.\n *\n * @param array A sorted array to binary search.\n * @param value The value to look for.\n * @returns index of the value.\n * - positive index if value found.\n * - negative index if value not found. (`~index` to get the value where it should have been\n * located)\n */\nexport function arrayIndexOfSorted(array: string[], value: string): number {\n return _arrayIndexOfSorted(array, value, 0);\n}\n\n\n/**\n * `KeyValueArray` is an array where even positions contain keys and odd positions contain values.\n *\n * `KeyValueArray` provides a very efficient way of iterating over its contents. For small\n * sets (~10) the cost of binary searching an `KeyValueArray` has about the same performance\n * characteristics that of a `Map` with significantly better memory footprint.\n *\n * If used as a `Map` the keys are stored in alphabetical order so that they can be binary searched\n * for retrieval.\n *\n * See: `keyValueArraySet`, `keyValueArrayGet`, `keyValueArrayIndexOf`, `keyValueArrayDelete`.\n */\nexport interface KeyValueArray<VALUE> extends Array<VALUE|string> {\n __brand__: 'array-map';\n}\n\n/**\n * Set a `value` for a `key`.\n *\n * @param keyValueArray to modify.\n * @param key The key to locate or create.\n * @param value The value to set for a `key`.\n * @returns index (always even) of where the value vas set.\n */\nexport function keyValueArraySet<V>(\n keyValueArray: KeyValueArray<V>, key: string, value: V): number {\n let index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it set it.\n keyValueArray[index | 1] = value;\n } else {\n index = ~index;\n arrayInsert2(keyValueArray, index, key, value);\n }\n return index;\n}\n\n/**\n * Retrieve a `value` for a `key` (on `undefined` if not found.)\n *\n * @param keyValueArray to search.\n * @param key The key to locate.\n * @return The `value` stored at the `key` location or `undefined if not found.\n */\nexport function keyValueArrayGet<V>(keyValueArray: KeyValueArray<V>, key: string): V|undefined {\n const index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it retrieve it.\n return keyValueArray[index | 1] as V;\n }\n return undefined;\n}\n\n/**\n * Retrieve a `key` index value in the array or `-1` if not found.\n *\n * @param keyValueArray to search.\n * @param key The key to locate.\n * @returns index of where the key is (or should have been.)\n * - positive (even) index if key found.\n * - negative index if key not found. (`~index` (even) to get the index where it should have\n * been inserted.)\n */\nexport function keyValueArrayIndexOf<V>(keyValueArray: KeyValueArray<V>, key: string): number {\n return _arrayIndexOfSorted(keyValueArray as string[], key, 1);\n}\n\n/**\n * Delete a `key` (and `value`) from the `KeyValueArray`.\n *\n * @param keyValueArray to modify.\n * @param key The key to locate or delete (if exist).\n * @returns index of where the key was (or should have been.)\n * - positive (even) index if key found and deleted.\n * - negative index if key not found. (`~index` (even) to get the index where it should have\n * been.)\n */\nexport function keyValueArrayDelete<V>(keyValueArray: KeyValueArray<V>, key: string): number {\n const index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it remove it.\n arraySplice(keyValueArray, index, 2);\n }\n return index;\n}\n\n\n/**\n * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.\n *\n * NOTE:\n * - This uses binary search algorithm for fast removals.\n *\n * @param array A sorted array to binary search.\n * @param value The value to look for.\n * @param shift grouping shift.\n * - `0` means look at every location\n * - `1` means only look at every other (even) location (the odd locations are to be ignored as\n * they are values.)\n * @returns index of the value.\n * - positive index if value found.\n * - negative index if value not found. (`~index` to get the value where it should have been\n * inserted)\n */\nfunction _arrayIndexOfSorted(array: string[], value: string, shift: number): number {\n ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array');\n let start = 0;\n let end = array.length >> shift;\n while (end !== start) {\n const middle = start + ((end - start) >> 1); // find the middle.\n const current = array[middle << shift];\n if (value === current) {\n return (middle << shift);\n } else if (current > value) {\n end = middle;\n } else {\n start = middle + 1; // We already searched middle so make it non-inclusive by adding 1\n }\n }\n return ~(end << shift);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {makeParamDecorator} from '../util/decorators';\n\nimport {attachInjectFlag} from './injector_compatibility';\nimport {DecoratorFlags, InternalInjectFlags} from './interface/injector';\n\n\n/**\n * Type of the Inject decorator / constructor function.\n *\n * @publicApi\n */\nexport interface InjectDecorator {\n /**\n * Parameter decorator on a dependency parameter of a class constructor\n * that specifies a custom provider of the dependency.\n *\n * @usageNotes\n * The following example shows a class constructor that specifies a\n * custom provider of a dependency using the parameter decorator.\n *\n * When `@Inject()` is not present, the injector uses the type annotation of the\n * parameter as the provider.\n *\n * <code-example path=\"core/di/ts/metadata_spec.ts\" region=\"InjectWithoutDecorator\">\n * </code-example>\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection)\n *\n */\n (token: any): any;\n new(token: any): Inject;\n}\n\n/**\n * Type of the Inject metadata.\n *\n * @publicApi\n */\nexport interface Inject {\n /**\n * A [DI token](guide/glossary#di-token) that maps to the dependency to be injected.\n */\n token: any;\n}\n\n/**\n * Inject decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nexport const Inject: InjectDecorator = attachInjectFlag(\n // Disable tslint because `DecoratorFlags` is a const enum which gets inlined.\n // tslint:disable-next-line: no-toplevel-property-access\n makeParamDecorator('Inject', (token: any) => ({token})), DecoratorFlags.Inject);\n\n/**\n * Type of the Optional decorator / constructor function.\n *\n * @publicApi\n */\nexport interface OptionalDecorator {\n /**\n * Parameter decorator to be used on constructor parameters,\n * which marks the parameter as being an optional dependency.\n * The DI framework provides `null` if the dependency is not found.\n *\n * Can be used together with other parameter decorators\n * that modify how dependency injection operates.\n *\n * @usageNotes\n *\n * The following code allows the possibility of a `null` result:\n *\n * <code-example path=\"core/di/ts/metadata_spec.ts\" region=\"Optional\">\n * </code-example>\n *\n * @see [\"Dependency Injection Guide\"](guide/dependency-injection).\n */\n (): any;\n new(): Optional;\n}\n\n/**\n * Type of the Optional metadata.\n *\n * @publicApi\n */\nexport interface Optional {}\n\n/**\n * Optional decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nexport const Optional: OptionalDecorator =\n // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n // tslint:disable-next-line: no-toplevel-property-access\n attachInjectFlag(makeParamDecorator('Optional'), InternalInjectFlags.Optional);\n\n/**\n * Type of the Self decorator / constructor function.\n *\n * @publicApi\n */\nexport interface SelfDecorator {\n /**\n * Parameter decorator to be used on constructor parameters,\n * which tells the DI framework to start dependency resolution from the local injector.\n *\n * Resolution works upward through the injector hierarchy, so the children\n * of this class must configure their own providers or be prepared for a `null` result.\n *\n * @usageNotes\n *\n * In the following example, the dependency can be resolved\n * by the local injector when instantiating the class itself, but not\n * when instantiating a child.\n *\n * <code-example path=\"core/di/ts/metadata_spec.ts\" region=\"Self\">\n * </code-example>\n *\n * @see `SkipSelf`\n * @see `Optional`\n *\n */\n (): any;\n new(): Self;\n}\n\n/**\n * Type of the Self metadata.\n *\n * @publicApi\n */\nexport interface Self {}\n\n/**\n * Self decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nexport const Self: SelfDecorator =\n // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n // tslint:disable-next-line: no-toplevel-property-access\n attachInjectFlag(makeParamDecorator('Self'), InternalInjectFlags.Self);\n\n\n/**\n * Type of the `SkipSelf` decorator / constructor function.\n *\n * @publicApi\n */\nexport interface SkipSelfDecorator {\n /**\n * Parameter decorator to be used on constructor parameters,\n * which tells the DI framework to start dependency resolution from the parent injector.\n * Resolution works upward through the injector hierarchy, so the local injector\n * is not checked for a provider.\n *\n * @usageNotes\n *\n * In the following example, the dependency can be resolved when\n * instantiating a child, but not when instantiating the class itself.\n *\n * <code-example path=\"core/di/ts/metadata_spec.ts\" region=\"SkipSelf\">\n * </code-example>\n *\n * @see [Dependency Injection guide](guide/dependency-injection-in-action#skip).\n * @see `Self`\n * @see `Optional`\n *\n */\n (): any;\n new(): SkipSelf;\n}\n\n/**\n * Type of the `SkipSelf` metadata.\n *\n * @publicApi\n */\nexport interface SkipSelf {}\n\n/**\n * `SkipSelf` decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nexport const SkipSelf: SkipSelfDecorator =\n // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n // tslint:disable-next-line: no-toplevel-property-access\n attachInjectFlag(makeParamDecorator('SkipSelf'), InternalInjectFlags.SkipSelf);\n\n/**\n * Type of the `Host` decorator / constructor function.\n *\n * @publicApi\n */\nexport interface HostDecorator {\n /**\n * Parameter decorator on a view-provider parameter of a class constructor\n * that tells the DI framework to resolve the view by checking injectors of child\n * elements, and stop when reaching the host element of the current component.\n *\n * @usageNotes\n *\n * The following shows use with the `@Optional` decorator, and allows for a `null` result.\n *\n * <code-example path=\"core/di/ts/metadata_spec.ts\" region=\"Host\">\n * </code-example>\n *\n * For an extended example, see [\"Dependency Injection\n * Guide\"](guide/dependency-injection-in-action#optional).\n */\n (): any;\n new(): Host;\n}\n\n/**\n * Type of the Host metadata.\n *\n * @publicApi\n */\nexport interface Host {}\n\n/**\n * Host decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nexport const Host: HostDecorator =\n // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n // tslint:disable-next-line: no-toplevel-property-access\n attachInjectFlag(makeParamDecorator('Host'), InternalInjectFlags.Host);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ViewEncapsulation} from '../metadata/view';\n\n\n/**\n * Used by `RendererFactory2` to associate custom rendering data and styles\n * with a rendering implementation.\n * @publicApi\n */\nexport interface RendererType2 {\n /**\n * A unique identifying string for the new renderer, used when creating\n * unique styles for encapsulation.\n */\n id: string;\n /**\n * The view encapsulation type, which determines how styles are applied to\n * DOM elements. One of\n * - `Emulated` (default): Emulate native scoping of styles.\n * - `Native`: Use the native encapsulation mechanism of the renderer.\n * - `ShadowDom`: Use modern [Shadow\n * DOM](https://w3c.github.io/webcomponents/spec/shadow/) and\n * create a ShadowRoot for component's host element.\n * - `None`: Do not provide any template or style encapsulation.\n */\n encapsulation: ViewEncapsulation;\n /**\n * Defines CSS styles to be stored on a renderer instance.\n */\n styles: (string|any[])[];\n /**\n * Defines arbitrary developer-defined data to be stored on a renderer instance.\n * This is useful for renderers that delegate to other renderers.\n */\n data: {[kind: string]: any};\n}\n\n\n/**\n * Flags for renderer-specific style modifiers.\n * @publicApi\n */\nexport enum RendererStyleFlags2 {\n // TODO(misko): This needs to be refactored into a separate file so that it can be imported from\n // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails\n // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.\n /**\n * Marks a style as important.\n */\n Important = 1 << 0,\n /**\n * Marks a style as using dash case naming (this-is-dash-case).\n */\n DashCase = 1 << 1\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Disallowed strings in the comment.\n *\n * see: https://html.spec.whatwg.org/multipage/syntax.html#comments\n */\nconst COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;\n/**\n * Delimiter in the disallowed strings which needs to be wrapped with zero with character.\n */\nconst COMMENT_DELIMITER = /(<|>)/;\nconst COMMENT_DELIMITER_ESCAPED = '\\u200B$1\\u200B';\n\n/**\n * Escape the content of comment strings so that it can be safely inserted into a comment node.\n *\n * The issue is that HTML does not specify any way to escape comment end text inside the comment.\n * Consider: `<!-- The way you close a comment is with \">\", and \"->\" at the beginning or by \"-->\" or\n * \"--!>\" at the end. -->`. Above the `\"-->\"` is meant to be text not an end to the comment. This\n * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)\n *\n * see: https://html.spec.whatwg.org/multipage/syntax.html#comments\n *\n * ```\n * div.innerHTML = div.innerHTML\n * ```\n *\n * One would expect that the above code would be safe to do, but it turns out that because comment\n * text is not escaped, the comment may contain text which will prematurely close the comment\n * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which\n * may contain such text and expect them to be safe.)\n *\n * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and\n * surrounding them with `_>_` where the `_` is a zero width space `\\u200B`. The result is that if a\n * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the\n * text it will render normally but it will not cause the HTML parser to close/open the comment.\n *\n * @param value text to make safe for comment node by escaping the comment open/close character\n * sequence.\n */\nexport function escapeCommentText(value: string): string {\n return value.replace(\n COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertNumber} from '../../util/assert';\n\nimport {ID, LView} from './view';\n\n// Keeps track of the currently-active LViews.\nconst TRACKED_LVIEWS = new Map<number, LView>();\n\n// Used for generating unique IDs for LViews.\nlet uniqueIdCounter = 0;\n\n/** Gets a unique ID that can be assigned to an LView. */\nexport function getUniqueLViewId(): number {\n return uniqueIdCounter++;\n}\n\n/** Starts tracking an LView. */\nexport function registerLView(lView: LView): void {\n ngDevMode && assertNumber(lView[ID], 'LView must have an ID in order to be registered');\n TRACKED_LVIEWS.set(lView[ID], lView);\n}\n\n/** Gets an LView by its unique ID. */\nexport function getLViewById(id: number): LView|null {\n ngDevMode && assertNumber(id, 'ID used for LView lookup must be a number');\n return TRACKED_LVIEWS.get(id) || null;\n}\n\n/** Stops tracking an LView. */\nexport function unregisterLView(lView: LView): void {\n ngDevMode && assertNumber(lView[ID], 'Cannot stop tracking an LView that does not have an ID');\n TRACKED_LVIEWS.delete(lView[ID]);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {getLViewById} from './lview_tracking';\nimport {RNode} from './renderer_dom';\nimport {LView} from './view';\n\n\n/**\n * The internal view context which is specific to a given DOM element, directive or\n * component instance. Each value in here (besides the LView and element node details)\n * can be present, null or undefined. If undefined then it implies the value has not been\n * looked up yet, otherwise, if null, then a lookup was executed and nothing was found.\n *\n * Each value will get filled when the respective value is examined within the getContext\n * function. The component, element and each directive instance will share the same instance\n * of the context.\n */\nexport class LContext {\n /**\n * The instance of the Component node.\n */\n public component: {}|null|undefined;\n\n /**\n * The list of active directives that exist on this element.\n */\n public directives: any[]|null|undefined;\n\n /**\n * The map of local references (local reference name => element or directive instance) that\n * exist on this element.\n */\n public localRefs: {[key: string]: any}|null|undefined;\n\n /** Component's parent view data. */\n get lView(): LView|null {\n return getLViewById(this.lViewId);\n }\n\n constructor(\n /**\n * ID of the component's parent view data.\n */\n private lViewId: number,\n\n /**\n * The index instance of the node.\n */\n public nodeIndex: number,\n\n /**\n * The instance of the DOM node that is attached to the lNode.\n */\n public native: RNode) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport '../util/ng_dev_mode';\n\nimport {assertDefined, assertDomNode} from '../util/assert';\nimport {EMPTY_ARRAY} from '../util/empty';\n\nimport {assertLView} from './assert';\nimport {LContext} from './interfaces/context';\nimport {getLViewById, registerLView} from './interfaces/lview_tracking';\nimport {TNode, TNodeFlags} from './interfaces/node';\nimport {RElement, RNode} from './interfaces/renderer_dom';\nimport {isLView} from './interfaces/type_checks';\nimport {CONTEXT, HEADER_OFFSET, HOST, ID, LView, TVIEW} from './interfaces/view';\nimport {getComponentLViewByIndex, unwrapRNode} from './util/view_utils';\n\n\n\n/**\n * Returns the matching `LContext` data for a given DOM node, directive or component instance.\n *\n * This function will examine the provided DOM element, component, or directive instance\\'s\n * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched\n * value will be that of the newly created `LContext`.\n *\n * If the monkey-patched value is the `LView` instance then the context value for that\n * target will be created and the monkey-patch reference will be updated. Therefore when this\n * function is called it may mutate the provided element\\'s, component\\'s or any of the associated\n * directive\\'s monkey-patch values.\n *\n * If the monkey-patch value is not detected then the code will walk up the DOM until an element\n * is found which contains a monkey-patch reference. When that occurs then the provided element\n * will be updated with a new context (which is then returned). If the monkey-patch value is not\n * detected for a component/directive instance then it will throw an error (all components and\n * directives should be automatically monkey-patched by ivy).\n *\n * @param target Component, Directive or DOM Node.\n */\nexport function getLContext(target: any): LContext|null {\n let mpValue = readPatchedData(target);\n if (mpValue) {\n // only when it's an array is it considered an LView instance\n // ... otherwise it's an already constructed LContext instance\n if (isLView(mpValue)) {\n const lView: LView = mpValue!;\n let nodeIndex: number;\n let component: any = undefined;\n let directives: any[]|null|undefined = undefined;\n\n if (isComponentInstance(target)) {\n nodeIndex = findViaComponent(lView, target);\n if (nodeIndex == -1) {\n throw new Error('The provided component was not found in the application');\n }\n component = target;\n } else if (isDirectiveInstance(target)) {\n nodeIndex = findViaDirective(lView, target);\n if (nodeIndex == -1) {\n throw new Error('The provided directive was not found in the application');\n }\n directives = getDirectivesAtNodeIndex(nodeIndex, lView);\n } else {\n nodeIndex = findViaNativeElement(lView, target as RElement);\n if (nodeIndex == -1) {\n return null;\n }\n }\n\n // the goal is not to fill the entire context full of data because the lookups\n // are expensive. Instead, only the target data (the element, component, container, ICU\n // expression or directive details) are filled into the context. If called multiple times\n // with different target values then the missing target data will be filled in.\n const native = unwrapRNode(lView[nodeIndex]);\n const existingCtx = readPatchedData(native);\n const context: LContext = (existingCtx && !Array.isArray(existingCtx)) ?\n existingCtx :\n createLContext(lView, nodeIndex, native);\n\n // only when the component has been discovered then update the monkey-patch\n if (component && context.component === undefined) {\n context.component = component;\n attachPatchData(context.component, context);\n }\n\n // only when the directives have been discovered then update the monkey-patch\n if (directives && context.directives === undefined) {\n context.directives = directives;\n for (let i = 0; i < directives.length; i++) {\n attachPatchData(directives[i], context);\n }\n }\n\n attachPatchData(context.native, context);\n mpValue = context;\n }\n } else {\n const rElement = target as RElement;\n ngDevMode && assertDomNode(rElement);\n\n // if the context is not found then we need to traverse upwards up the DOM\n // to find the nearest element that has already been monkey patched with data\n let parent = rElement as any;\n while (parent = parent.parentNode) {\n const parentContext = readPatchedData(parent);\n if (parentContext) {\n const lView = Array.isArray(parentContext) ? parentContext as LView : parentContext.lView;\n\n // the edge of the app was also reached here through another means\n // (maybe because the DOM was changed manually).\n if (!lView) {\n return null;\n }\n\n const index = findViaNativeElement(lView, rElement);\n if (index >= 0) {\n const native = unwrapRNode(lView[index]);\n const context = createLContext(lView, index, native);\n attachPatchData(native, context);\n mpValue = context;\n break;\n }\n }\n }\n }\n return (mpValue as LContext) || null;\n}\n\n/**\n * Creates an empty instance of a `LContext` context\n */\nfunction createLContext(lView: LView, nodeIndex: number, native: RNode): LContext {\n return new LContext(lView[ID], nodeIndex, native);\n}\n\n/**\n * Takes a component instance and returns the view for that component.\n *\n * @param componentInstance\n * @returns The component's view\n */\nexport function getComponentViewByInstance(componentInstance: {}): LView {\n let patchedData = readPatchedData(componentInstance);\n let lView: LView;\n\n if (isLView(patchedData)) {\n const contextLView: LView = patchedData;\n const nodeIndex = findViaComponent(contextLView, componentInstance);\n lView = getComponentLViewByIndex(nodeIndex, contextLView);\n const context = createLContext(contextLView, nodeIndex, lView[HOST] as RElement);\n context.component = componentInstance;\n attachPatchData(componentInstance, context);\n attachPatchData(context.native, context);\n } else {\n const context = patchedData as unknown as LContext;\n const contextLView = context.lView!;\n ngDevMode && assertLView(contextLView);\n lView = getComponentLViewByIndex(context.nodeIndex, contextLView);\n }\n return lView;\n}\n\n/**\n * This property will be monkey-patched on elements, components and directives.\n */\nconst MONKEY_PATCH_KEY_NAME = '__ngContext__';\n\n/**\n * Assigns the given data to the given target (which could be a component,\n * directive or DOM node instance) using monkey-patching.\n */\nexport function attachPatchData(target: any, data: LView|LContext) {\n ngDevMode && assertDefined(target, 'Target expected');\n // Only attach the ID of the view in order to avoid memory leaks (see #41047). We only do this\n // for `LView`, because we have control over when an `LView` is created and destroyed, whereas\n // we can't know when to remove an `LContext`.\n if (isLView(data)) {\n target[MONKEY_PATCH_KEY_NAME] = data[ID];\n registerLView(data);\n } else {\n target[MONKEY_PATCH_KEY_NAME] = data;\n }\n}\n\n/**\n * Returns the monkey-patch value data present on the target (which could be\n * a component, directive or a DOM node).\n */\nexport function readPatchedData(target: any): LView|LContext|null {\n ngDevMode && assertDefined(target, 'Target expected');\n const data = target[MONKEY_PATCH_KEY_NAME];\n return (typeof data === 'number') ? getLViewById(data) : data || null;\n}\n\nexport function readPatchedLView<T>(target: any): LView<T>|null {\n const value = readPatchedData(target);\n if (value) {\n return (isLView(value) ? value : value.lView) as LView<T>;\n }\n return null;\n}\n\nexport function isComponentInstance(instance: any): boolean {\n return instance && instance.constructor && instance.constructor.ɵcmp;\n}\n\nexport function isDirectiveInstance(instance: any): boolean {\n return instance && instance.constructor && instance.constructor.ɵdir;\n}\n\n/**\n * Locates the element within the given LView and returns the matching index\n */\nfunction findViaNativeElement(lView: LView, target: RElement): number {\n const tView = lView[TVIEW];\n for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {\n if (unwrapRNode(lView[i]) === target) {\n return i;\n }\n }\n\n return -1;\n}\n\n/**\n * Locates the next tNode (child, sibling or parent).\n */\nfunction traverseNextElement(tNode: TNode): TNode|null {\n if (tNode.child) {\n return tNode.child;\n } else if (tNode.next) {\n return tNode.next;\n } else {\n // Let's take the following template: <div><span>text</span></div><component/>\n // After checking the text node, we need to find the next parent that has a \"next\" TNode,\n // in this case the parent `div`, so that we can find the component.\n while (tNode.parent && !tNode.parent.next) {\n tNode = tNode.parent;\n }\n return tNode.parent && tNode.parent.next;\n }\n}\n\n/**\n * Locates the component within the given LView and returns the matching index\n */\nfunction findViaComponent(lView: LView, componentInstance: {}): number {\n const componentIndices = lView[TVIEW].components;\n if (componentIndices) {\n for (let i = 0; i < componentIndices.length; i++) {\n const elementComponentIndex = componentIndices[i];\n const componentView = getComponentLViewByIndex(elementComponentIndex, lView);\n if (componentView[CONTEXT] === componentInstance) {\n return elementComponentIndex;\n }\n }\n } else {\n const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);\n const rootComponent = rootComponentView[CONTEXT];\n if (rootComponent === componentInstance) {\n // we are dealing with the root element here therefore we know that the\n // element is the very first element after the HEADER data in the lView\n return HEADER_OFFSET;\n }\n }\n return -1;\n}\n\n/**\n * Locates the directive within the given LView and returns the matching index\n */\nfunction findViaDirective(lView: LView, directiveInstance: {}): number {\n // if a directive is monkey patched then it will (by default)\n // have a reference to the LView of the current view. The\n // element bound to the directive being search lives somewhere\n // in the view data. We loop through the nodes and check their\n // list of directives for the instance.\n let tNode = lView[TVIEW].firstChild;\n while (tNode) {\n const directiveIndexStart = tNode.directiveStart;\n const directiveIndexEnd = tNode.directiveEnd;\n for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {\n if (lView[i] === directiveInstance) {\n return tNode.index;\n }\n }\n tNode = traverseNextElement(tNode);\n }\n return -1;\n}\n\n/**\n * Returns a list of directives applied to a node at a specific index. The list includes\n * directives matched by selector and any host directives, but it excludes components.\n * Use `getComponentAtNodeIndex` to find the component applied to a node.\n *\n * @param nodeIndex The node index\n * @param lView The target view data\n */\nexport function getDirectivesAtNodeIndex(nodeIndex: number, lView: LView): any[]|null {\n const tNode = lView[TVIEW].data[nodeIndex] as TNode;\n if (tNode.directiveStart === 0) return EMPTY_ARRAY;\n const results: any[] = [];\n for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {\n const directiveInstance = lView[i];\n if (!isComponentInstance(directiveInstance)) {\n results.push(directiveInstance);\n }\n }\n return results;\n}\n\nexport function getComponentAtNodeIndex(nodeIndex: number, lView: LView): {}|null {\n const tNode = lView[TVIEW].data[nodeIndex] as TNode;\n const {directiveStart, componentOffset} = tNode;\n return componentOffset > -1 ? lView[directiveStart + componentOffset] : null;\n}\n\n/**\n * Returns a map of local references (local reference name => element or directive instance) that\n * exist on a given element.\n */\nexport function discoverLocalRefs(lView: LView, nodeIndex: number): {[key: string]: any}|null {\n const tNode = lView[TVIEW].data[nodeIndex] as TNode;\n if (tNode && tNode.localNames) {\n const result: {[key: string]: any} = {};\n let localIndex = tNode.index + 1;\n for (let i = 0; i < tNode.localNames.length; i += 2) {\n result[tNode.localNames[i]] = lView[localIndex];\n localIndex++;\n }\n return result;\n }\n\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @fileoverview\n *\n * This file provides mechanism by which code relevant to the `TIcuContainerNode` is only loaded if\n * ICU is present in the template.\n */\n\nimport {TIcuContainerNode} from '../interfaces/node';\nimport {RNode} from '../interfaces/renderer_dom';\nimport {LView} from '../interfaces/view';\n\n\nlet _icuContainerIterate: (tIcuContainerNode: TIcuContainerNode, lView: LView) =>\n (() => RNode | null);\n\n/**\n * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.\n */\nexport function icuContainerIterate(tIcuContainerNode: TIcuContainerNode, lView: LView): () =>\n RNode | null {\n return _icuContainerIterate(tIcuContainerNode, lView);\n}\n\n/**\n * Ensures that `IcuContainerVisitor`'s implementation is present.\n *\n * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the\n * bundler to tree shake ICU logic and only load it if ICU instruction is executed.\n */\nexport function ensureIcuContainerVisitorLoaded(\n loader: () => ((tIcuContainerNode: TIcuContainerNode, lView: LView) => (() => RNode | null))) {\n if (_icuContainerIterate === undefined) {\n // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it\n // can be inlined into call-site.\n _icuContainerIterate = loader();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertDefined} from '../../util/assert';\nimport {assertLView} from '../assert';\nimport {readPatchedLView} from '../context_discovery';\nimport {LContainer} from '../interfaces/container';\nimport {isLContainer, isLView} from '../interfaces/type_checks';\nimport {CHILD_HEAD, CONTEXT, FLAGS, LView, LViewFlags, NEXT, PARENT} from '../interfaces/view';\n\n\n/**\n * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of\n * that LContainer, which is an LView\n * @param lView the lView whose parent to get\n */\nexport function getLViewParent(lView: LView): LView|null {\n ngDevMode && assertLView(lView);\n const parent = lView[PARENT];\n return isLContainer(parent) ? parent[PARENT]! : parent;\n}\n\n/**\n * Retrieve the root view from any component or `LView` by walking the parent `LView` until\n * reaching the root `LView`.\n *\n * @param componentOrLView any component or `LView`\n */\nexport function getRootView<T>(componentOrLView: LView|{}): LView<T> {\n ngDevMode && assertDefined(componentOrLView, 'component');\n let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView)!;\n while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {\n lView = getLViewParent(lView)!;\n }\n ngDevMode && assertLView(lView);\n return lView as LView<T>;\n}\n\n/**\n * Returns the context information associated with the application where the target is situated. It\n * does this by walking the parent views until it gets to the root view, then getting the context\n * off of that.\n *\n * @param viewOrComponent the `LView` or component to get the root context for.\n */\nexport function getRootContext<T>(viewOrComponent: LView<T>|{}): T {\n const rootView = getRootView(viewOrComponent);\n ngDevMode &&\n assertDefined(rootView[CONTEXT], 'Root view has no context. Perhaps it is disconnected?');\n return rootView[CONTEXT] as T;\n}\n\n\n/**\n * Gets the first `LContainer` in the LView or `null` if none exists.\n */\nexport function getFirstLContainer(lView: LView): LContainer|null {\n return getNearestLContainer(lView[CHILD_HEAD]);\n}\n\n/**\n * Gets the next `LContainer` that is a sibling of the given container.\n */\nexport function getNextLContainer(container: LContainer): LContainer|null {\n return getNearestLContainer(container[NEXT]);\n}\n\nfunction getNearestLContainer(viewOrContainer: LContainer|LView|null) {\n while (viewOrContainer !== null && !isLContainer(viewOrContainer)) {\n viewOrContainer = viewOrContainer[NEXT];\n }\n return viewOrContainer as LContainer | null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ViewEncapsulation} from '../metadata/view';\nimport {RendererStyleFlags2} from '../render/api_flags';\nimport {addToArray, removeFromArray} from '../util/array_utils';\nimport {assertDefined, assertEqual, assertFunction, assertNumber, assertString} from '../util/assert';\nimport {escapeCommentText} from '../util/dom';\n\nimport {assertLContainer, assertLView, assertParentView, assertProjectionSlots, assertTNodeForLView} from './assert';\nimport {attachPatchData} from './context_discovery';\nimport {icuContainerIterate} from './i18n/i18n_tree_shaking';\nimport {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE} from './interfaces/container';\nimport {ComponentDef} from './interfaces/definition';\nimport {NodeInjectorFactory} from './interfaces/injector';\nimport {unregisterLView} from './interfaces/lview_tracking';\nimport {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from './interfaces/node';\nimport {Renderer} from './interfaces/renderer';\nimport {RComment, RElement, RNode, RTemplate, RText} from './interfaces/renderer_dom';\nimport {isLContainer, isLView} from './interfaces/type_checks';\nimport {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, DestroyHookData, FLAGS, HookData, HookFn, HOST, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView, TViewType} from './interfaces/view';\nimport {assertTNodeType} from './node_assert';\nimport {profiler, ProfilerEvent} from './profiler';\nimport {setUpAttributes} from './util/attrs_utils';\nimport {getLViewParent} from './util/view_traversal_utils';\nimport {getNativeByTNode, unwrapRNode, updateTransplantedViewCount} from './util/view_utils';\n\nconst enum WalkTNodeTreeAction {\n /** node create in the native environment. Run on initial creation. */\n Create = 0,\n\n /**\n * node insert in the native environment.\n * Run when existing node has been detached and needs to be re-attached.\n */\n Insert = 1,\n\n /** node detach from the native environment */\n Detach = 2,\n\n /** node destruction using the renderer's API */\n Destroy = 3,\n}\n\n\n\n/**\n * NOTE: for performance reasons, the possible actions are inlined within the function instead of\n * being passed as an argument.\n */\nfunction applyToElementOrContainer(\n action: WalkTNodeTreeAction, renderer: Renderer, parent: RElement|null,\n lNodeToHandle: RNode|LContainer|LView, beforeNode?: RNode|null) {\n // If this slot was allocated for a text node dynamically created by i18n, the text node itself\n // won't be created until i18nApply() in the update block, so this node should be skipped.\n // For more info, see \"ICU expressions should work inside an ngTemplateOutlet inside an ngFor\"\n // in `i18n_spec.ts`.\n if (lNodeToHandle != null) {\n let lContainer: LContainer|undefined;\n let isComponent = false;\n // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is\n // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if\n // it has LContainer so that we can process all of those cases appropriately.\n if (isLContainer(lNodeToHandle)) {\n lContainer = lNodeToHandle;\n } else if (isLView(lNodeToHandle)) {\n isComponent = true;\n ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');\n lNodeToHandle = lNodeToHandle[HOST]!;\n }\n const rNode: RNode = unwrapRNode(lNodeToHandle);\n\n if (action === WalkTNodeTreeAction.Create && parent !== null) {\n if (beforeNode == null) {\n nativeAppendChild(renderer, parent, rNode);\n } else {\n nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);\n }\n } else if (action === WalkTNodeTreeAction.Insert && parent !== null) {\n nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);\n } else if (action === WalkTNodeTreeAction.Detach) {\n nativeRemoveNode(renderer, rNode, isComponent);\n } else if (action === WalkTNodeTreeAction.Destroy) {\n ngDevMode && ngDevMode.rendererDestroyNode++;\n renderer.destroyNode!(rNode);\n }\n if (lContainer != null) {\n applyContainer(renderer, action, lContainer, parent, beforeNode);\n }\n }\n}\n\nexport function createTextNode(renderer: Renderer, value: string): RText {\n ngDevMode && ngDevMode.rendererCreateTextNode++;\n ngDevMode && ngDevMode.rendererSetText++;\n return renderer.createText(value);\n}\n\nexport function updateTextNode(renderer: Renderer, rNode: RText, value: string): void {\n ngDevMode && ngDevMode.rendererSetText++;\n renderer.setValue(rNode, value);\n}\n\nexport function createCommentNode(renderer: Renderer, value: string): RComment {\n ngDevMode && ngDevMode.rendererCreateComment++;\n return renderer.createComment(escapeCommentText(value));\n}\n\n/**\n * Creates a native element from a tag name, using a renderer.\n * @param renderer A renderer to use\n * @param name the tag name\n * @param namespace Optional namespace for element.\n * @returns the element created\n */\nexport function createElementNode(\n renderer: Renderer, name: string, namespace: string|null): RElement {\n ngDevMode && ngDevMode.rendererCreateElement++;\n return renderer.createElement(name, namespace);\n}\n\n\n/**\n * Removes all DOM elements associated with a view.\n *\n * Because some root nodes of the view may be containers, we sometimes need\n * to propagate deeply into the nested containers to remove all elements in the\n * views beneath it.\n *\n * @param tView The `TView' of the `LView` from which elements should be added or removed\n * @param lView The view from which elements should be added or removed\n */\nexport function removeViewFromContainer(tView: TView, lView: LView): void {\n const renderer = lView[RENDERER];\n applyView(tView, lView, renderer, WalkTNodeTreeAction.Detach, null, null);\n lView[HOST] = null;\n lView[T_HOST] = null;\n}\n\n/**\n * Adds all DOM elements associated with a view.\n *\n * Because some root nodes of the view may be containers, we sometimes need\n * to propagate deeply into the nested containers to add all elements in the\n * views beneath it.\n *\n * @param tView The `TView' of the `LView` from which elements should be added or removed\n * @param parentTNode The `TNode` where the `LView` should be attached to.\n * @param renderer Current renderer to use for DOM manipulations.\n * @param lView The view from which elements should be added or removed\n * @param parentNativeNode The parent `RElement` where it should be inserted into.\n * @param beforeNode The node before which elements should be added, if insert mode\n */\nexport function addViewToContainer(\n tView: TView, parentTNode: TNode, renderer: Renderer, lView: LView, parentNativeNode: RElement,\n beforeNode: RNode|null): void {\n lView[HOST] = parentNativeNode;\n lView[T_HOST] = parentTNode;\n applyView(tView, lView, renderer, WalkTNodeTreeAction.Insert, parentNativeNode, beforeNode);\n}\n\n\n/**\n * Detach a `LView` from the DOM by detaching its nodes.\n *\n * @param tView The `TView' of the `LView` to be detached\n * @param lView the `LView` to be detached.\n */\nexport function renderDetachView(tView: TView, lView: LView) {\n applyView(tView, lView, lView[RENDERER], WalkTNodeTreeAction.Detach, null, null);\n}\n\n/**\n * Traverses down and up the tree of views and containers to remove listeners and\n * call onDestroy callbacks.\n *\n * Notes:\n * - Because it's used for onDestroy calls, it needs to be bottom-up.\n * - Must process containers instead of their views to avoid splicing\n * when views are destroyed and re-added.\n * - Using a while loop because it's faster than recursion\n * - Destroy only called on movement to sibling or movement to parent (laterally or up)\n *\n * @param rootView The view to destroy\n */\nexport function destroyViewTree(rootView: LView): void {\n // If the view has no children, we can clean it up and return early.\n let lViewOrLContainer = rootView[CHILD_HEAD];\n if (!lViewOrLContainer) {\n return cleanUpView(rootView[TVIEW], rootView);\n }\n\n while (lViewOrLContainer) {\n let next: LView|LContainer|null = null;\n\n if (isLView(lViewOrLContainer)) {\n // If LView, traverse down to child.\n next = lViewOrLContainer[CHILD_HEAD];\n } else {\n ngDevMode && assertLContainer(lViewOrLContainer);\n // If container, traverse down to its first LView.\n const firstView: LView|undefined = lViewOrLContainer[CONTAINER_HEADER_OFFSET];\n if (firstView) next = firstView;\n }\n\n if (!next) {\n // Only clean up view when moving to the side or up, as destroy hooks\n // should be called in order from the bottom up.\n while (lViewOrLContainer && !lViewOrLContainer![NEXT] && lViewOrLContainer !== rootView) {\n if (isLView(lViewOrLContainer)) {\n cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);\n }\n lViewOrLContainer = lViewOrLContainer[PARENT];\n }\n if (lViewOrLContainer === null) lViewOrLContainer = rootView;\n if (isLView(lViewOrLContainer)) {\n cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);\n }\n next = lViewOrLContainer && lViewOrLContainer![NEXT];\n }\n lViewOrLContainer = next;\n }\n}\n\n/**\n * Inserts a view into a container.\n *\n * This adds the view to the container's array of active views in the correct\n * position. It also adds the view's elements to the DOM if the container isn't a\n * root node of another view (in that case, the view's elements will be added when\n * the container's parent view is added later).\n *\n * @param tView The `TView' of the `LView` to insert\n * @param lView The view to insert\n * @param lContainer The container into which the view should be inserted\n * @param index Which index in the container to insert the child view into\n */\nexport function insertView(tView: TView, lView: LView, lContainer: LContainer, index: number) {\n ngDevMode && assertLView(lView);\n ngDevMode && assertLContainer(lContainer);\n const indexInContainer = CONTAINER_HEADER_OFFSET + index;\n const containerLength = lContainer.length;\n\n if (index > 0) {\n // This is a new view, we need to add it to the children.\n lContainer[indexInContainer - 1][NEXT] = lView;\n }\n if (index < containerLength - CONTAINER_HEADER_OFFSET) {\n lView[NEXT] = lContainer[indexInContainer];\n addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView);\n } else {\n lContainer.push(lView);\n lView[NEXT] = null;\n }\n\n lView[PARENT] = lContainer;\n\n // track views where declaration and insertion points are different\n const declarationLContainer = lView[DECLARATION_LCONTAINER];\n if (declarationLContainer !== null && lContainer !== declarationLContainer) {\n trackMovedView(declarationLContainer, lView);\n }\n\n // notify query that a new view has been added\n const lQueries = lView[QUERIES];\n if (lQueries !== null) {\n lQueries.insertView(tView);\n }\n\n // Sets the attached flag\n lView[FLAGS] |= LViewFlags.Attached;\n}\n\n/**\n * Track views created from the declaration container (TemplateRef) and inserted into a\n * different LContainer.\n */\nfunction trackMovedView(declarationContainer: LContainer, lView: LView) {\n ngDevMode && assertDefined(lView, 'LView required');\n ngDevMode && assertLContainer(declarationContainer);\n const movedViews = declarationContainer[MOVED_VIEWS];\n const insertedLContainer = lView[PARENT] as LContainer;\n ngDevMode && assertLContainer(insertedLContainer);\n const insertedComponentLView = insertedLContainer[PARENT]![DECLARATION_COMPONENT_VIEW];\n ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');\n const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW];\n ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView');\n if (declaredComponentLView !== insertedComponentLView) {\n // At this point the declaration-component is not same as insertion-component; this means that\n // this is a transplanted view. Mark the declared lView as having transplanted views so that\n // those views can participate in CD.\n declarationContainer[HAS_TRANSPLANTED_VIEWS] = true;\n }\n if (movedViews === null) {\n declarationContainer[MOVED_VIEWS] = [lView];\n } else {\n movedViews.push(lView);\n }\n}\n\nfunction detachMovedView(declarationContainer: LContainer, lView: LView) {\n ngDevMode && assertLContainer(declarationContainer);\n ngDevMode &&\n assertDefined(\n declarationContainer[MOVED_VIEWS],\n 'A projected view should belong to a non-empty projected views collection');\n const movedViews = declarationContainer[MOVED_VIEWS]!;\n const declarationViewIndex = movedViews.indexOf(lView);\n const insertionLContainer = lView[PARENT] as LContainer;\n ngDevMode && assertLContainer(insertionLContainer);\n\n // If the view was marked for refresh but then detached before it was checked (where the flag\n // would be cleared and the counter decremented), we need to decrement the view counter here\n // instead.\n if (lView[FLAGS] & LViewFlags.RefreshTransplantedView) {\n lView[FLAGS] &= ~LViewFlags.RefreshTransplantedView;\n updateTransplantedViewCount(insertionLContainer, -1);\n }\n\n movedViews.splice(declarationViewIndex, 1);\n}\n\n/**\n * Detaches a view from a container.\n *\n * This method removes the view from the container's array of active views. It also\n * removes the view's elements from the DOM.\n *\n * @param lContainer The container from which to detach a view\n * @param removeIndex The index of the view to detach\n * @returns Detached LView instance.\n */\nexport function detachView(lContainer: LContainer, removeIndex: number): LView|undefined {\n if (lContainer.length <= CONTAINER_HEADER_OFFSET) return;\n\n const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;\n const viewToDetach = lContainer[indexInContainer];\n\n if (viewToDetach) {\n const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];\n if (declarationLContainer !== null && declarationLContainer !== lContainer) {\n detachMovedView(declarationLContainer, viewToDetach);\n }\n\n\n if (removeIndex > 0) {\n lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT] as LView;\n }\n const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);\n removeViewFromContainer(viewToDetach[TVIEW], viewToDetach);\n\n // notify query that a view has been removed\n const lQueries = removedLView[QUERIES];\n if (lQueries !== null) {\n lQueries.detachView(removedLView[TVIEW]);\n }\n\n viewToDetach[PARENT] = null;\n viewToDetach[NEXT] = null;\n // Unsets the attached flag\n viewToDetach[FLAGS] &= ~LViewFlags.Attached;\n }\n return viewToDetach;\n}\n\n/**\n * A standalone function which destroys an LView,\n * conducting clean up (e.g. removing listeners, calling onDestroys).\n *\n * @param tView The `TView' of the `LView` to be destroyed\n * @param lView The view to be destroyed.\n */\nexport function destroyLView(tView: TView, lView: LView) {\n if (!(lView[FLAGS] & LViewFlags.Destroyed)) {\n const renderer = lView[RENDERER];\n if (renderer.destroyNode) {\n applyView(tView, lView, renderer, WalkTNodeTreeAction.Destroy, null, null);\n }\n\n destroyViewTree(lView);\n }\n}\n\n/**\n * Calls onDestroys hooks for all directives and pipes in a given view and then removes all\n * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks\n * can be propagated to @Output listeners.\n *\n * @param tView `TView` for the `LView` to clean up.\n * @param lView The LView to clean up\n */\nfunction cleanUpView(tView: TView, lView: LView): void {\n if (!(lView[FLAGS] & LViewFlags.Destroyed)) {\n // Usually the Attached flag is removed when the view is detached from its parent, however\n // if it's a root view, the flag won't be unset hence why we're also removing on destroy.\n lView[FLAGS] &= ~LViewFlags.Attached;\n\n // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook\n // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If\n // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.\n // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is\n // really more of an \"afterDestroy\" hook if you think about it.\n lView[FLAGS] |= LViewFlags.Destroyed;\n\n executeOnDestroys(tView, lView);\n processCleanups(tView, lView);\n // For component views only, the local renderer is destroyed at clean up time.\n if (lView[TVIEW].type === TViewType.Component) {\n ngDevMode && ngDevMode.rendererDestroy++;\n lView[RENDERER].destroy();\n }\n\n const declarationContainer = lView[DECLARATION_LCONTAINER];\n // we are dealing with an embedded view that is still inserted into a container\n if (declarationContainer !== null && isLContainer(lView[PARENT])) {\n // and this is a projected view\n if (declarationContainer !== lView[PARENT]) {\n detachMovedView(declarationContainer, lView);\n }\n\n // For embedded views still attached to a container: remove query result from this view.\n const lQueries = lView[QUERIES];\n if (lQueries !== null) {\n lQueries.detachView(tView);\n }\n }\n\n // Unregister the view once everything else has been cleaned up.\n unregisterLView(lView);\n }\n}\n\n/** Removes listeners and unsubscribes from output subscriptions */\nfunction processCleanups(tView: TView, lView: LView): void {\n const tCleanup = tView.cleanup;\n const lCleanup = lView[CLEANUP]!;\n // `LCleanup` contains both share information with `TCleanup` as well as instance specific\n // information appended at the end. We need to know where the end of the `TCleanup` information\n // is, and we track this with `lastLCleanupIndex`.\n let lastLCleanupIndex = -1;\n if (tCleanup !== null) {\n for (let i = 0; i < tCleanup.length - 1; i += 2) {\n if (typeof tCleanup[i] === 'string') {\n // This is a native DOM listener. It will occupy 4 entries in the TCleanup array (hence i +=\n // 2 at the end of this block).\n const targetIdx = tCleanup[i + 3];\n ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');\n if (targetIdx >= 0) {\n // unregister\n lCleanup[lastLCleanupIndex = targetIdx]();\n } else {\n // Subscription\n lCleanup[lastLCleanupIndex = -targetIdx].unsubscribe();\n }\n i += 2;\n } else {\n // This is a cleanup function that is grouped with the index of its context\n const context = lCleanup[lastLCleanupIndex = tCleanup[i + 1]];\n tCleanup[i].call(context);\n }\n }\n }\n if (lCleanup !== null) {\n for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {\n const instanceCleanupFn = lCleanup[i];\n ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');\n instanceCleanupFn();\n }\n lView[CLEANUP] = null;\n }\n}\n\n/** Calls onDestroy hooks for this view */\nfunction executeOnDestroys(tView: TView, lView: LView): void {\n let destroyHooks: DestroyHookData|null;\n\n if (tView != null && (destroyHooks = tView.destroyHooks) != null) {\n for (let i = 0; i < destroyHooks.length; i += 2) {\n const context = lView[destroyHooks[i] as number];\n\n // Only call the destroy hook if the context has been requested.\n if (!(context instanceof NodeInjectorFactory)) {\n const toCall = destroyHooks[i + 1] as HookFn | HookData;\n\n if (Array.isArray(toCall)) {\n for (let j = 0; j < toCall.length; j += 2) {\n const callContext = context[toCall[j] as number];\n const hook = toCall[j + 1] as HookFn;\n profiler(ProfilerEvent.LifecycleHookStart, callContext, hook);\n try {\n hook.call(callContext);\n } finally {\n profiler(ProfilerEvent.LifecycleHookEnd, callContext, hook);\n }\n }\n } else {\n profiler(ProfilerEvent.LifecycleHookStart, context, toCall);\n try {\n toCall.call(context);\n } finally {\n profiler(ProfilerEvent.LifecycleHookEnd, context, toCall);\n }\n }\n }\n }\n }\n}\n\n/**\n * Returns a native element if a node can be inserted into the given parent.\n *\n * There are two reasons why we may not be able to insert a element immediately.\n * - Projection: When creating a child content element of a component, we have to skip the\n * insertion because the content of a component will be projected.\n * `<component><content>delayed due to projection</content></component>`\n * - Parent container is disconnected: This can happen when we are inserting a view into\n * parent container, which itself is disconnected. For example the parent container is part\n * of a View which has not be inserted or is made for projection but has not been inserted\n * into destination.\n *\n * @param tView: Current `TView`.\n * @param tNode: `TNode` for which we wish to retrieve render parent.\n * @param lView: Current `LView`.\n */\nexport function getParentRElement(tView: TView, tNode: TNode, lView: LView): RElement|null {\n return getClosestRElement(tView, tNode.parent, lView);\n}\n\n/**\n * Get closest `RElement` or `null` if it can't be found.\n *\n * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.\n * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).\n * If `TNode` is `null` then return host `RElement`:\n * - return `null` if projection\n * - return `null` if parent container is disconnected (we have no parent.)\n *\n * @param tView: Current `TView`.\n * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is\n * needed).\n * @param lView: Current `LView`.\n * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)\n */\nexport function getClosestRElement(tView: TView, tNode: TNode|null, lView: LView): RElement|null {\n let parentTNode: TNode|null = tNode;\n // Skip over element and ICU containers as those are represented by a comment node and\n // can't be used as a render parent.\n while (parentTNode !== null &&\n (parentTNode.type & (TNodeType.ElementContainer | TNodeType.Icu))) {\n tNode = parentTNode;\n parentTNode = tNode.parent;\n }\n\n // If the parent tNode is null, then we are inserting across views: either into an embedded view\n // or a component view.\n if (parentTNode === null) {\n // We are inserting a root element of the component view into the component host element and\n // it should always be eager.\n return lView[HOST];\n } else {\n ngDevMode && assertTNodeType(parentTNode, TNodeType.AnyRNode | TNodeType.Container);\n const {componentOffset} = parentTNode;\n if (componentOffset > -1) {\n ngDevMode && assertTNodeForLView(parentTNode, lView);\n const {encapsulation} =\n (tView.data[parentTNode.directiveStart + componentOffset] as ComponentDef<unknown>);\n // We've got a parent which is an element in the current view. We just need to verify if the\n // parent element is not a component. Component's content nodes are not inserted immediately\n // because they will be projected, and so doing insert at this point would be wasteful.\n // Since the projection would then move it to its final destination. Note that we can't\n // make this assumption when using the Shadow DOM, because the native projection placeholders\n // (<content> or <slot>) have to be in place as elements are being inserted.\n if (encapsulation === ViewEncapsulation.None ||\n encapsulation === ViewEncapsulation.Emulated) {\n return null;\n }\n }\n\n return getNativeByTNode(parentTNode, lView) as RElement;\n }\n}\n\n/**\n * Inserts a native node before another native node for a given parent.\n * This is a utility function that can be used when native nodes were determined.\n */\nexport function nativeInsertBefore(\n renderer: Renderer, parent: RElement, child: RNode, beforeNode: RNode|null,\n isMove: boolean): void {\n ngDevMode && ngDevMode.rendererInsertBefore++;\n renderer.insertBefore(parent, child, beforeNode, isMove);\n}\n\nfunction nativeAppendChild(renderer: Renderer, parent: RElement, child: RNode): void {\n ngDevMode && ngDevMode.rendererAppendChild++;\n ngDevMode && assertDefined(parent, 'parent node must be defined');\n renderer.appendChild(parent, child);\n}\n\nfunction nativeAppendOrInsertBefore(\n renderer: Renderer, parent: RElement, child: RNode, beforeNode: RNode|null, isMove: boolean) {\n if (beforeNode !== null) {\n nativeInsertBefore(renderer, parent, child, beforeNode, isMove);\n } else {\n nativeAppendChild(renderer, parent, child);\n }\n}\n\n/** Removes a node from the DOM given its native parent. */\nfunction nativeRemoveChild(\n renderer: Renderer, parent: RElement, child: RNode, isHostElement?: boolean): void {\n renderer.removeChild(parent, child, isHostElement);\n}\n\n/** Checks if an element is a `<template>` node. */\nfunction isTemplateNode(node: RElement): node is RTemplate {\n return node.tagName === 'TEMPLATE' && (node as RTemplate).content !== undefined;\n}\n\n/**\n * Returns a native parent of a given native node.\n */\nexport function nativeParentNode(renderer: Renderer, node: RNode): RElement|null {\n return renderer.parentNode(node);\n}\n\n/**\n * Returns a native sibling of a given native node.\n */\nexport function nativeNextSibling(renderer: Renderer, node: RNode): RNode|null {\n return renderer.nextSibling(node);\n}\n\n/**\n * Find a node in front of which `currentTNode` should be inserted.\n *\n * This method determines the `RNode` in front of which we should insert the `currentRNode`. This\n * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.\n *\n * @param parentTNode parent `TNode`\n * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)\n * @param lView current `LView`\n */\nfunction getInsertInFrontOfRNode(parentTNode: TNode, currentTNode: TNode, lView: LView): RNode|\n null {\n return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);\n}\n\n\n/**\n * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into\n * account)\n *\n * This method determines the `RNode` in front of which we should insert the `currentRNode`. This\n * does not take `TNode.insertBeforeIndex` into account.\n *\n * @param parentTNode parent `TNode`\n * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)\n * @param lView current `LView`\n */\nexport function getInsertInFrontOfRNodeWithNoI18n(\n parentTNode: TNode, currentTNode: TNode, lView: LView): RNode|null {\n if (parentTNode.type & (TNodeType.ElementContainer | TNodeType.Icu)) {\n return getNativeByTNode(parentTNode, lView);\n }\n return null;\n}\n\n/**\n * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.\n *\n * This function will only be set if i18n code runs.\n */\nlet _getInsertInFrontOfRNodeWithI18n: (parentTNode: TNode, currentTNode: TNode, lView: LView) =>\n RNode | null = getInsertInFrontOfRNodeWithNoI18n;\n\n/**\n * Tree shakable boundary for `processI18nInsertBefore` function.\n *\n * This function will only be set if i18n code runs.\n */\nlet _processI18nInsertBefore: (\n renderer: Renderer, childTNode: TNode, lView: LView, childRNode: RNode|RNode[],\n parentRElement: RElement|null) => void;\n\nexport function setI18nHandling(\n getInsertInFrontOfRNodeWithI18n: (parentTNode: TNode, currentTNode: TNode, lView: LView) =>\n RNode | null,\n processI18nInsertBefore: (\n renderer: Renderer, childTNode: TNode, lView: LView, childRNode: RNode|RNode[],\n parentRElement: RElement|null) => void) {\n _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;\n _processI18nInsertBefore = processI18nInsertBefore;\n}\n\n/**\n * Appends the `child` native node (or a collection of nodes) to the `parent`.\n *\n * @param tView The `TView' to be appended\n * @param lView The current LView\n * @param childRNode The native child (or children) that should be appended\n * @param childTNode The TNode of the child element\n */\nexport function appendChild(\n tView: TView, lView: LView, childRNode: RNode|RNode[], childTNode: TNode): void {\n const parentRNode = getParentRElement(tView, childTNode, lView);\n const renderer = lView[RENDERER];\n const parentTNode: TNode = childTNode.parent || lView[T_HOST]!;\n const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);\n if (parentRNode != null) {\n if (Array.isArray(childRNode)) {\n for (let i = 0; i < childRNode.length; i++) {\n nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);\n }\n } else {\n nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);\n }\n }\n\n _processI18nInsertBefore !== undefined &&\n _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);\n}\n\n/**\n * Returns the first native node for a given LView, starting from the provided TNode.\n *\n * Native nodes are returned in the order in which those appear in the native tree (DOM).\n */\nfunction getFirstNativeNode(lView: LView, tNode: TNode|null): RNode|null {\n if (tNode !== null) {\n ngDevMode &&\n assertTNodeType(\n tNode,\n TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Icu | TNodeType.Projection);\n\n const tNodeType = tNode.type;\n if (tNodeType & TNodeType.AnyRNode) {\n return getNativeByTNode(tNode, lView);\n } else if (tNodeType & TNodeType.Container) {\n return getBeforeNodeForView(-1, lView[tNode.index]);\n } else if (tNodeType & TNodeType.ElementContainer) {\n const elIcuContainerChild = tNode.child;\n if (elIcuContainerChild !== null) {\n return getFirstNativeNode(lView, elIcuContainerChild);\n } else {\n const rNodeOrLContainer = lView[tNode.index];\n if (isLContainer(rNodeOrLContainer)) {\n return getBeforeNodeForView(-1, rNodeOrLContainer);\n } else {\n return unwrapRNode(rNodeOrLContainer);\n }\n }\n } else if (tNodeType & TNodeType.Icu) {\n let nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);\n let rNode: RNode|null = nextRNode();\n // If the ICU container has no nodes, than we use the ICU anchor as the node.\n return rNode || unwrapRNode(lView[tNode.index]);\n } else {\n const projectionNodes = getProjectionNodes(lView, tNode);\n if (projectionNodes !== null) {\n if (Array.isArray(projectionNodes)) {\n return projectionNodes[0];\n }\n const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);\n ngDevMode && assertParentView(parentView);\n return getFirstNativeNode(parentView!, projectionNodes);\n } else {\n return getFirstNativeNode(lView, tNode.next);\n }\n }\n }\n\n return null;\n}\n\nexport function getProjectionNodes(lView: LView, tNode: TNode|null): TNode|RNode[]|null {\n if (tNode !== null) {\n const componentView = lView[DECLARATION_COMPONENT_VIEW];\n const componentHost = componentView[T_HOST] as TElementNode;\n const slotIdx = tNode.projection as number;\n ngDevMode && assertProjectionSlots(lView);\n return componentHost.projection![slotIdx];\n }\n return null;\n}\n\nexport function getBeforeNodeForView(viewIndexInContainer: number, lContainer: LContainer): RNode|\n null {\n const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;\n if (nextViewIndex < lContainer.length) {\n const lView = lContainer[nextViewIndex] as LView;\n const firstTNodeOfView = lView[TVIEW].firstChild;\n if (firstTNodeOfView !== null) {\n return getFirstNativeNode(lView, firstTNodeOfView);\n }\n }\n\n return lContainer[NATIVE];\n}\n\n/**\n * Removes a native node itself using a given renderer. To remove the node we are looking up its\n * parent from the native tree as not all platforms / browsers support the equivalent of\n * node.remove().\n *\n * @param renderer A renderer to be used\n * @param rNode The native node that should be removed\n * @param isHostElement A flag indicating if a node to be removed is a host of a component.\n */\nexport function nativeRemoveNode(renderer: Renderer, rNode: RNode, isHostElement?: boolean): void {\n ngDevMode && ngDevMode.rendererRemoveNode++;\n const nativeParent = nativeParentNode(renderer, rNode);\n if (nativeParent) {\n nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);\n }\n}\n\n\n/**\n * Performs the operation of `action` on the node. Typically this involves inserting or removing\n * nodes on the LView or projection boundary.\n */\nfunction applyNodes(\n renderer: Renderer, action: WalkTNodeTreeAction, tNode: TNode|null, lView: LView,\n parentRElement: RElement|null, beforeNode: RNode|null, isProjection: boolean) {\n while (tNode != null) {\n ngDevMode && assertTNodeForLView(tNode, lView);\n ngDevMode &&\n assertTNodeType(\n tNode,\n TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Projection | TNodeType.Icu);\n const rawSlotValue = lView[tNode.index];\n const tNodeType = tNode.type;\n if (isProjection) {\n if (action === WalkTNodeTreeAction.Create) {\n rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);\n tNode.flags |= TNodeFlags.isProjected;\n }\n }\n if ((tNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) {\n if (tNodeType & TNodeType.ElementContainer) {\n applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n } else if (tNodeType & TNodeType.Icu) {\n const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);\n let rNode: RNode|null;\n while (rNode = nextRNode()) {\n applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);\n }\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n } else if (tNodeType & TNodeType.Projection) {\n applyProjectionRecursive(\n renderer, action, lView, tNode as TProjectionNode, parentRElement, beforeNode);\n } else {\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.Container);\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n }\n }\n tNode = isProjection ? tNode.projectionNext : tNode.next;\n }\n}\n\n\n/**\n * `applyView` performs operation on the view as specified in `action` (insert, detach, destroy)\n *\n * Inserting a view without projection or containers at top level is simple. Just iterate over the\n * root nodes of the View, and for each node perform the `action`.\n *\n * Things get more complicated with containers and projections. That is because coming across:\n * - Container: implies that we have to insert/remove/destroy the views of that container as well\n * which in turn can have their own Containers at the View roots.\n * - Projection: implies that we have to insert/remove/destroy the nodes of the projection. The\n * complication is that the nodes we are projecting can themselves have Containers\n * or other Projections.\n *\n * As you can see this is a very recursive problem. Yes recursion is not most efficient but the\n * code is complicated enough that trying to implemented with recursion becomes unmaintainable.\n *\n * @param tView The `TView' which needs to be inserted, detached, destroyed\n * @param lView The LView which needs to be inserted, detached, destroyed.\n * @param renderer Renderer to use\n * @param action action to perform (insert, detach, destroy)\n * @param parentRElement parent DOM element for insertion (Removal does not need it).\n * @param beforeNode Before which node the insertions should happen.\n */\nfunction applyView(\n tView: TView, lView: LView, renderer: Renderer, action: WalkTNodeTreeAction.Destroy,\n parentRElement: null, beforeNode: null): void;\nfunction applyView(\n tView: TView, lView: LView, renderer: Renderer, action: WalkTNodeTreeAction,\n parentRElement: RElement|null, beforeNode: RNode|null): void;\nfunction applyView(\n tView: TView, lView: LView, renderer: Renderer, action: WalkTNodeTreeAction,\n parentRElement: RElement|null, beforeNode: RNode|null): void {\n applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);\n}\n\n/**\n * `applyProjection` performs operation on the projection.\n *\n * Inserting a projection requires us to locate the projected nodes from the parent component. The\n * complication is that those nodes themselves could be re-projected from their parent component.\n *\n * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed\n * @param lView The `LView` which needs to be inserted, detached, destroyed.\n * @param tProjectionNode node to project\n */\nexport function applyProjection(tView: TView, lView: LView, tProjectionNode: TProjectionNode) {\n const renderer = lView[RENDERER];\n const parentRNode = getParentRElement(tView, tProjectionNode, lView);\n const parentTNode = tProjectionNode.parent || lView[T_HOST]!;\n let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);\n applyProjectionRecursive(\n renderer, WalkTNodeTreeAction.Create, lView, tProjectionNode, parentRNode, beforeNode);\n}\n\n/**\n * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,\n * detach, destroy)\n *\n * Inserting a projection requires us to locate the projected nodes from the parent component. The\n * complication is that those nodes themselves could be re-projected from their parent component.\n *\n * @param renderer Render to use\n * @param action action to perform (insert, detach, destroy)\n * @param lView The LView which needs to be inserted, detached, destroyed.\n * @param tProjectionNode node to project\n * @param parentRElement parent DOM element for insertion/removal.\n * @param beforeNode Before which node the insertions should happen.\n */\nfunction applyProjectionRecursive(\n renderer: Renderer, action: WalkTNodeTreeAction, lView: LView, tProjectionNode: TProjectionNode,\n parentRElement: RElement|null, beforeNode: RNode|null) {\n const componentLView = lView[DECLARATION_COMPONENT_VIEW];\n const componentNode = componentLView[T_HOST] as TElementNode;\n ngDevMode &&\n assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');\n const nodeToProjectOrRNodes = componentNode.projection![tProjectionNode.projection]!;\n if (Array.isArray(nodeToProjectOrRNodes)) {\n // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we\n // need to support passing projectable nodes, so we cheat and put them in the TNode\n // of the Host TView. (Yes we put instance info at the T Level). We can get away with it\n // because we know that that TView is not shared and therefore it will not be a problem.\n // This should be refactored and cleaned up.\n for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {\n const rNode = nodeToProjectOrRNodes[i];\n applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);\n }\n } else {\n let nodeToProject: TNode|null = nodeToProjectOrRNodes;\n const projectedComponentLView = componentLView[PARENT] as LView;\n applyNodes(\n renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);\n }\n}\n\n\n/**\n * `applyContainer` performs an operation on the container and its views as specified by\n * `action` (insert, detach, destroy)\n *\n * Inserting a Container is complicated by the fact that the container may have Views which\n * themselves have containers or projections.\n *\n * @param renderer Renderer to use\n * @param action action to perform (insert, detach, destroy)\n * @param lContainer The LContainer which needs to be inserted, detached, destroyed.\n * @param parentRElement parent DOM element for insertion/removal.\n * @param beforeNode Before which node the insertions should happen.\n */\nfunction applyContainer(\n renderer: Renderer, action: WalkTNodeTreeAction, lContainer: LContainer,\n parentRElement: RElement|null, beforeNode: RNode|null|undefined) {\n ngDevMode && assertLContainer(lContainer);\n const anchor = lContainer[NATIVE]; // LContainer has its own before node.\n const native = unwrapRNode(lContainer);\n // An LContainer can be created dynamically on any node by injecting ViewContainerRef.\n // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor\n // node (comment in the DOM) that will be different from the LContainer's host node. In this\n // particular case we need to execute action on 2 nodes:\n // - container's host node (this is done in the executeActionOnElementOrContainer)\n // - container's host node (this is done here)\n if (anchor !== native) {\n // This is very strange to me (Misko). I would expect that the native is same as anchor. I\n // don't see a reason why they should be different, but they are.\n //\n // If they are we need to process the second anchor as well.\n applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);\n }\n for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {\n const lView = lContainer[i] as LView;\n applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);\n }\n}\n\n/**\n * Writes class/style to element.\n *\n * @param renderer Renderer to use.\n * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)\n * @param rNode The Node to write to.\n * @param prop Property to write to. This would be the class/style name.\n * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add\n * otherwise).\n */\nexport function applyStyling(\n renderer: Renderer, isClassBased: boolean, rNode: RElement, prop: string, value: any) {\n if (isClassBased) {\n // We actually want JS true/false here because any truthy value should add the class\n if (!value) {\n ngDevMode && ngDevMode.rendererRemoveClass++;\n renderer.removeClass(rNode, prop);\n } else {\n ngDevMode && ngDevMode.rendererAddClass++;\n renderer.addClass(rNode, prop);\n }\n } else {\n let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase as number;\n if (value == null /** || value === undefined */) {\n ngDevMode && ngDevMode.rendererRemoveStyle++;\n renderer.removeStyle(rNode, prop, flags);\n } else {\n // A value is important if it ends with `!important`. The style\n // parser strips any semicolons at the end of the value.\n const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;\n\n if (isImportant) {\n // !important has to be stripped from the value for it to be valid.\n value = value.slice(0, -10);\n flags! |= RendererStyleFlags2.Important;\n }\n\n ngDevMode && ngDevMode.rendererSetStyle++;\n renderer.setStyle(rNode, prop, value, flags);\n }\n }\n}\n\n\n/**\n * Write `cssText` to `RElement`.\n *\n * This function does direct write without any reconciliation. Used for writing initial values, so\n * that static styling values do not pull in the style parser.\n *\n * @param renderer Renderer to use\n * @param element The element which needs to be updated.\n * @param newValue The new class list to write.\n */\nexport function writeDirectStyle(renderer: Renderer, element: RElement, newValue: string) {\n ngDevMode && assertString(newValue, '\\'newValue\\' should be a string');\n renderer.setAttribute(element, 'style', newValue);\n ngDevMode && ngDevMode.rendererSetStyle++;\n}\n\n/**\n * Write `className` to `RElement`.\n *\n * This function does direct write without any reconciliation. Used for writing initial values, so\n * that static styling values do not pull in the style parser.\n *\n * @param renderer Renderer to use\n * @param element The element which needs to be updated.\n * @param newValue The new class list to write.\n */\nexport function writeDirectClass(renderer: Renderer, element: RElement, newValue: string) {\n ngDevMode && assertString(newValue, '\\'newValue\\' should be a string');\n if (newValue === '') {\n // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.\n renderer.removeAttribute(element, 'class');\n } else {\n renderer.setAttribute(element, 'class', newValue);\n }\n ngDevMode && ngDevMode.rendererSetClassName++;\n}\n\n/** Sets up the static DOM attributes on an `RNode`. */\nexport function setupStaticAttributes(renderer: Renderer, element: RElement, tNode: TNode) {\n const {mergedAttrs, classes, styles} = tNode;\n\n if (mergedAttrs !== null) {\n setUpAttributes(renderer, element, mergedAttrs);\n }\n\n if (classes !== null) {\n writeDirectClass(renderer, element, classes);\n }\n\n if (styles !== null) {\n writeDirectStyle(renderer, element, styles);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @fileoverview\n * A module to facilitate use of a Trusted Types policy internally within\n * Angular. It lazily constructs the Trusted Types policy, providing helper\n * utilities for promoting strings to Trusted Types. When Trusted Types are not\n * available, strings are used as a fallback.\n * @security All use of this module is security-sensitive and should go through\n * security review.\n */\n\nimport {global} from '../global';\nimport {TrustedHTML, TrustedScript, TrustedScriptURL, TrustedTypePolicy, TrustedTypePolicyFactory} from './trusted_type_defs';\n\n/**\n * The Trusted Types policy, or null if Trusted Types are not\n * enabled/supported, or undefined if the policy has not been created yet.\n */\nlet policy: TrustedTypePolicy|null|undefined;\n\n/**\n * Returns the Trusted Types policy, or null if Trusted Types are not\n * enabled/supported. The first call to this function will create the policy.\n */\nfunction getPolicy(): TrustedTypePolicy|null {\n if (policy === undefined) {\n policy = null;\n if (global.trustedTypes) {\n try {\n policy = (global.trustedTypes as TrustedTypePolicyFactory).createPolicy('angular', {\n createHTML: (s: string) => s,\n createScript: (s: string) => s,\n createScriptURL: (s: string) => s,\n });\n } catch {\n // trustedTypes.createPolicy throws if called with a name that is\n // already registered, even in report-only mode. Until the API changes,\n // catch the error not to break the applications functionally. In such\n // cases, the code will fall back to using strings.\n }\n }\n }\n return policy;\n}\n\n/**\n * Unsafely promote a string to a TrustedHTML, falling back to strings when\n * Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that the\n * provided string will never cause an XSS vulnerability if used in a context\n * that will be interpreted as HTML by a browser, e.g. when assigning to\n * element.innerHTML.\n */\nexport function trustedHTMLFromString(html: string): TrustedHTML|string {\n return getPolicy()?.createHTML(html) || html;\n}\n\n/**\n * Unsafely promote a string to a TrustedScript, falling back to strings when\n * Trusted Types are not available.\n * @security In particular, it must be assured that the provided string will\n * never cause an XSS vulnerability if used in a context that will be\n * interpreted and executed as a script by a browser, e.g. when calling eval.\n */\nexport function trustedScriptFromString(script: string): TrustedScript|string {\n return getPolicy()?.createScript(script) || script;\n}\n\n/**\n * Unsafely promote a string to a TrustedScriptURL, falling back to strings\n * when Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that the\n * provided string will never cause an XSS vulnerability if used in a context\n * that will cause a browser to load and execute a resource, e.g. when\n * assigning to script.src.\n */\nexport function trustedScriptURLFromString(url: string): TrustedScriptURL|string {\n return getPolicy()?.createScriptURL(url) || url;\n}\n\n/**\n * Unsafely call the Function constructor with the given string arguments. It\n * is only available in development mode, and should be stripped out of\n * production code.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only called from development code, as use in production code can lead to\n * XSS vulnerabilities.\n */\nexport function newTrustedFunctionForDev(...args: string[]): Function {\n if (typeof ngDevMode === 'undefined') {\n throw new Error('newTrustedFunctionForDev should never be called in production');\n }\n if (!global.trustedTypes) {\n // In environments that don't support Trusted Types, fall back to the most\n // straightforward implementation:\n return new Function(...args);\n }\n\n // Chrome currently does not support passing TrustedScript to the Function\n // constructor. The following implements the workaround proposed on the page\n // below, where the Chromium bug is also referenced:\n // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor\n const fnArgs = args.slice(0, -1).join(',');\n const fnBody = args[args.length - 1];\n const body = `(function anonymous(${fnArgs}\n) { ${fnBody}\n})`;\n\n // Using eval directly confuses the compiler and prevents this module from\n // being stripped out of JS binaries even if not used. The global['eval']\n // indirection fixes that.\n const fn = global['eval'](trustedScriptFromString(body) as string) as Function;\n if (fn.bind === undefined) {\n // Workaround for a browser bug that only exists in Chrome 83, where passing\n // a TrustedScript to eval just returns the TrustedScript back without\n // evaluating it. In that case, fall back to the most straightforward\n // implementation:\n return new Function(...args);\n }\n\n // To completely mimic the behavior of calling \"new Function\", two more\n // things need to happen:\n // 1. Stringifying the resulting function should return its source code\n fn.toString = () => body;\n // 2. When calling the resulting function, `this` should refer to `global`\n return fn.bind(global);\n\n // When Trusted Types support in Function constructors is widely available,\n // the implementation of this function can be simplified to:\n // return new Function(...args.map(a => trustedScriptFromString(a)));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Most of the use of `document` in Angular is from within the DI system so it is possible to simply\n * inject the `DOCUMENT` token and are done.\n *\n * Ivy is special because it does not rely upon the DI and must get hold of the document some other\n * way.\n *\n * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.\n * Wherever ivy needs the global document, it calls `getDocument()` instead.\n *\n * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to\n * tell ivy what the global `document` is.\n *\n * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)\n * by calling `setDocument()` when providing the `DOCUMENT` token.\n */\nlet DOCUMENT: Document|undefined = undefined;\n\n/**\n * Tell ivy what the `document` is for this platform.\n *\n * It is only necessary to call this if the current platform is not a browser.\n *\n * @param document The object representing the global `document` in this environment.\n */\nexport function setDocument(document: Document|undefined): void {\n DOCUMENT = document;\n}\n\n/**\n * Access the object that represents the `document` for this platform.\n *\n * Ivy calls this whenever it needs to access the `document` object.\n * For example to create the renderer or to do sanitization.\n */\nexport function getDocument(): Document {\n if (DOCUMENT !== undefined) {\n return DOCUMENT;\n } else if (typeof document !== 'undefined') {\n return document;\n }\n // No \"document\" can be found. This should only happen if we are running ivy outside Angular and\n // the current platform is not a browser. Since this is not a supported scenario at the moment\n // this should not happen in Angular apps.\n // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a\n // public API. Meanwhile we just return `undefined` and let the application fail.\n return undefined!;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @fileoverview\n * A module to facilitate use of a Trusted Types policy internally within\n * Angular specifically for bypassSecurityTrust* and custom sanitizers. It\n * lazily constructs the Trusted Types policy, providing helper utilities for\n * promoting strings to Trusted Types. When Trusted Types are not available,\n * strings are used as a fallback.\n * @security All use of this module is security-sensitive and should go through\n * security review.\n */\n\nimport {global} from '../global';\nimport {TrustedHTML, TrustedScript, TrustedScriptURL, TrustedTypePolicy, TrustedTypePolicyFactory} from './trusted_type_defs';\n\n/**\n * The Trusted Types policy, or null if Trusted Types are not\n * enabled/supported, or undefined if the policy has not been created yet.\n */\nlet policy: TrustedTypePolicy|null|undefined;\n\n/**\n * Returns the Trusted Types policy, or null if Trusted Types are not\n * enabled/supported. The first call to this function will create the policy.\n */\nfunction getPolicy(): TrustedTypePolicy|null {\n if (policy === undefined) {\n policy = null;\n if (global.trustedTypes) {\n try {\n policy = (global.trustedTypes as TrustedTypePolicyFactory)\n .createPolicy('angular#unsafe-bypass', {\n createHTML: (s: string) => s,\n createScript: (s: string) => s,\n createScriptURL: (s: string) => s,\n });\n } catch {\n // trustedTypes.createPolicy throws if called with a name that is\n // already registered, even in report-only mode. Until the API changes,\n // catch the error not to break the applications functionally. In such\n // cases, the code will fall back to using strings.\n }\n }\n }\n return policy;\n}\n\n/**\n * Unsafely promote a string to a TrustedHTML, falling back to strings when\n * Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only passed strings that come directly from custom sanitizers or the\n * bypassSecurityTrust* functions.\n */\nexport function trustedHTMLFromStringBypass(html: string): TrustedHTML|string {\n return getPolicy()?.createHTML(html) || html;\n}\n\n/**\n * Unsafely promote a string to a TrustedScript, falling back to strings when\n * Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only passed strings that come directly from custom sanitizers or the\n * bypassSecurityTrust* functions.\n */\nexport function trustedScriptFromStringBypass(script: string): TrustedScript|string {\n return getPolicy()?.createScript(script) || script;\n}\n\n/**\n * Unsafely promote a string to a TrustedScriptURL, falling back to strings\n * when Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only passed strings that come directly from custom sanitizers or the\n * bypassSecurityTrust* functions.\n */\nexport function trustedScriptURLFromStringBypass(url: string): TrustedScriptURL|string {\n return getPolicy()?.createScriptURL(url) || url;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XSS_SECURITY_URL} from '../error_details_base_url';\n\nexport const enum BypassType {\n Url = 'URL',\n Html = 'HTML',\n ResourceUrl = 'ResourceURL',\n Script = 'Script',\n Style = 'Style',\n}\n\n/**\n * Marker interface for a value that's safe to use in a particular context.\n *\n * @publicApi\n */\nexport interface SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as HTML.\n *\n * @publicApi\n */\nexport interface SafeHtml extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as style (CSS).\n *\n * @publicApi\n */\nexport interface SafeStyle extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as JavaScript.\n *\n * @publicApi\n */\nexport interface SafeScript extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as a URL linking to a document.\n *\n * @publicApi\n */\nexport interface SafeUrl extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as a URL to load executable code from.\n *\n * @publicApi\n */\nexport interface SafeResourceUrl extends SafeValue {}\n\n\nabstract class SafeValueImpl implements SafeValue {\n constructor(public changingThisBreaksApplicationSecurity: string) {}\n\n abstract getTypeName(): string;\n\n toString() {\n return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` +\n ` (see ${XSS_SECURITY_URL})`;\n }\n}\n\nclass SafeHtmlImpl extends SafeValueImpl implements SafeHtml {\n override getTypeName() {\n return BypassType.Html;\n }\n}\nclass SafeStyleImpl extends SafeValueImpl implements SafeStyle {\n override getTypeName() {\n return BypassType.Style;\n }\n}\nclass SafeScriptImpl extends SafeValueImpl implements SafeScript {\n override getTypeName() {\n return BypassType.Script;\n }\n}\nclass SafeUrlImpl extends SafeValueImpl implements SafeUrl {\n override getTypeName() {\n return BypassType.Url;\n }\n}\nclass SafeResourceUrlImpl extends SafeValueImpl implements SafeResourceUrl {\n override getTypeName() {\n return BypassType.ResourceUrl;\n }\n}\n\nexport function unwrapSafeValue(value: SafeValue): string;\nexport function unwrapSafeValue<T>(value: T): T;\nexport function unwrapSafeValue<T>(value: T|SafeValue): T {\n return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity as any as T :\n value as any as T;\n}\n\n\nexport function allowSanitizationBypassAndThrow(\n value: any, type: BypassType.Html): value is SafeHtml;\nexport function allowSanitizationBypassAndThrow(\n value: any, type: BypassType.ResourceUrl): value is SafeResourceUrl;\nexport function allowSanitizationBypassAndThrow(\n value: any, type: BypassType.Script): value is SafeScript;\nexport function allowSanitizationBypassAndThrow(\n value: any, type: BypassType.Style): value is SafeStyle;\nexport function allowSanitizationBypassAndThrow(value: any, type: BypassType.Url): value is SafeUrl;\nexport function allowSanitizationBypassAndThrow(value: any, type: BypassType): boolean;\nexport function allowSanitizationBypassAndThrow(value: any, type: BypassType): boolean {\n const actualType = getSanitizationBypassType(value);\n if (actualType != null && actualType !== type) {\n // Allow ResourceURLs in URL contexts, they are strictly more trusted.\n if (actualType === BypassType.ResourceUrl && type === BypassType.Url) return true;\n throw new Error(`Required a safe ${type}, got a ${actualType} (see ${XSS_SECURITY_URL})`);\n }\n return actualType === type;\n}\n\nexport function getSanitizationBypassType(value: any): BypassType|null {\n return value instanceof SafeValueImpl && value.getTypeName() as BypassType || null;\n}\n\n/**\n * Mark `html` string as trusted.\n *\n * This function wraps the trusted string in `String` and brands it in a way which makes it\n * recognizable to {@link htmlSanitizer} to be trusted implicitly.\n *\n * @param trustedHtml `html` string which needs to be implicitly trusted.\n * @returns a `html` which has been branded to be implicitly trusted.\n */\nexport function bypassSanitizationTrustHtml(trustedHtml: string): SafeHtml {\n return new SafeHtmlImpl(trustedHtml);\n}\n/**\n * Mark `style` string as trusted.\n *\n * This function wraps the trusted string in `String` and brands it in a way which makes it\n * recognizable to {@link styleSanitizer} to be trusted implicitly.\n *\n * @param trustedStyle `style` string which needs to be implicitly trusted.\n * @returns a `style` hich has been branded to be implicitly trusted.\n */\nexport function bypassSanitizationTrustStyle(trustedStyle: string): SafeStyle {\n return new SafeStyleImpl(trustedStyle);\n}\n/**\n * Mark `script` string as trusted.\n *\n * This function wraps the trusted string in `String` and brands it in a way which makes it\n * recognizable to {@link scriptSanitizer} to be trusted implicitly.\n *\n * @param trustedScript `script` string which needs to be implicitly trusted.\n * @returns a `script` which has been branded to be implicitly trusted.\n */\nexport function bypassSanitizationTrustScript(trustedScript: string): SafeScript {\n return new SafeScriptImpl(trustedScript);\n}\n/**\n * Mark `url` string as trusted.\n *\n * This function wraps the trusted string in `String` and brands it in a way which makes it\n * recognizable to {@link urlSanitizer} to be trusted implicitly.\n *\n * @param trustedUrl `url` string which needs to be implicitly trusted.\n * @returns a `url` which has been branded to be implicitly trusted.\n */\nexport function bypassSanitizationTrustUrl(trustedUrl: string): SafeUrl {\n return new SafeUrlImpl(trustedUrl);\n}\n/**\n * Mark `url` string as trusted.\n *\n * This function wraps the trusted string in `String` and brands it in a way which makes it\n * recognizable to {@link resourceUrlSanitizer} to be trusted implicitly.\n *\n * @param trustedResourceUrl `url` string which needs to be implicitly trusted.\n * @returns a `url` which has been branded to be implicitly trusted.\n */\nexport function bypassSanitizationTrustResourceUrl(trustedResourceUrl: string): SafeResourceUrl {\n return new SafeResourceUrlImpl(trustedResourceUrl);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {trustedHTMLFromString} from '../util/security/trusted_types';\n\n/**\n * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML\n * that needs sanitizing.\n * Depending upon browser support we use one of two strategies for doing this.\n * Default: DOMParser strategy\n * Fallback: InertDocument strategy\n */\nexport function getInertBodyHelper(defaultDoc: Document): InertBodyHelper {\n const inertDocumentHelper = new InertDocumentHelper(defaultDoc);\n return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper;\n}\n\nexport interface InertBodyHelper {\n /**\n * Get an inert DOM element containing DOM created from the dirty HTML string provided.\n */\n getInertBodyElement: (html: string) => HTMLElement | null;\n}\n\n/**\n * Uses DOMParser to create and fill an inert body element.\n * This is the default strategy used in browsers that support it.\n */\nclass DOMParserHelper implements InertBodyHelper {\n constructor(private inertDocumentHelper: InertBodyHelper) {}\n\n getInertBodyElement(html: string): HTMLElement|null {\n // We add these extra elements to ensure that the rest of the content is parsed as expected\n // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the\n // `<head>` tag. Note that the `<body>` tag is closed implicitly to prevent unclosed tags\n // in `html` from consuming the otherwise explicit `</body>` tag.\n html = '<body><remove></remove>' + html;\n try {\n const body = new window.DOMParser()\n .parseFromString(trustedHTMLFromString(html) as string, 'text/html')\n .body as HTMLBodyElement;\n if (body === null) {\n // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only\n // becomes available in the following tick of the JS engine. In that case we fall back to\n // the `inertDocumentHelper` instead.\n return this.inertDocumentHelper.getInertBodyElement(html);\n }\n body.removeChild(body.firstChild!);\n return body;\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Use an HTML5 `template` element to create and fill an inert DOM element.\n * This is the fallback strategy if the browser does not support DOMParser.\n */\nclass InertDocumentHelper implements InertBodyHelper {\n private inertDocument: Document;\n\n constructor(private defaultDoc: Document) {\n this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert');\n }\n\n getInertBodyElement(html: string): HTMLElement|null {\n const templateEl = this.inertDocument.createElement('template');\n templateEl.innerHTML = trustedHTMLFromString(html) as string;\n return templateEl;\n }\n}\n\n/**\n * We need to determine whether the DOMParser exists in the global context and\n * supports parsing HTML; HTML parsing support is not as wide as other formats, see\n * https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility.\n *\n * @suppress {uselessCode}\n */\nexport function isDOMParserAvailable() {\n try {\n return !!new window.DOMParser().parseFromString(\n trustedHTMLFromString('') as string, 'text/html');\n } catch {\n return false;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XSS_SECURITY_URL} from '../error_details_base_url';\n\n/**\n * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation\n * contexts.\n *\n * This regular expression matches a subset of URLs that will not cause script\n * execution if used in URL context within a HTML document. Specifically, this\n * regular expression matches if:\n * (1) Either a protocol that is not javascript:, and that has valid characters\n * (alphanumeric or [+-.]).\n * (2) or no protocol. A protocol must be followed by a colon. The below\n * allows that by allowing colons only after one of the characters [/?#].\n * A colon after a hash (#) must be in the fragment.\n * Otherwise, a colon after a (?) must be in a query.\n * Otherwise, a colon after a single solidus (/) must be in a path.\n * Otherwise, a colon after a double solidus (//) must be in the authority\n * (before port).\n *\n * The pattern disallows &, used in HTML entity declarations before\n * one of the characters in [/?#]. This disallows HTML entities used in the\n * protocol name, which should never happen, e.g. \"http\" for \"http\".\n * It also disallows HTML entities in the first path part of a relative path,\n * e.g. \"foo<bar/baz\". Our existing escaping functions should not produce\n * that. More importantly, it disallows masking of a colon,\n * e.g. \"javascript:...\".\n *\n * This regular expression was taken from the Closure sanitization library.\n */\nconst SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:\\/?#]*(?:[\\/?#]|$))/i;\nexport function _sanitizeUrl(url: string): string {\n url = String(url);\n if (url.match(SAFE_URL_PATTERN)) return url;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(`WARNING: sanitizing unsafe URL value ${url} (see ${XSS_SECURITY_URL})`);\n }\n\n return 'unsafe:' + url;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XSS_SECURITY_URL} from '../error_details_base_url';\nimport {TrustedHTML} from '../util/security/trusted_type_defs';\nimport {trustedHTMLFromString} from '../util/security/trusted_types';\n\nimport {getInertBodyHelper, InertBodyHelper} from './inert_body';\nimport {_sanitizeUrl} from './url_sanitizer';\n\nfunction tagSet(tags: string): {[k: string]: boolean} {\n const res: {[k: string]: boolean} = {};\n for (const t of tags.split(',')) res[t] = true;\n return res;\n}\n\nfunction merge(...sets: {[k: string]: boolean}[]): {[k: string]: boolean} {\n const res: {[k: string]: boolean} = {};\n for (const s of sets) {\n for (const v in s) {\n if (s.hasOwnProperty(v)) res[v] = true;\n }\n }\n return res;\n}\n\n// Good source of info about elements and attributes\n// https://html.spec.whatwg.org/#semantics\n// https://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// https://html.spec.whatwg.org/#void-elements\nconst VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr');\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// https://html.spec.whatwg.org/#optional-tags\nconst OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr');\nconst OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt');\nconst OPTIONAL_END_TAG_ELEMENTS =\n merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS);\n\n// Safe Block Elements - HTML5\nconst BLOCK_ELEMENTS = merge(\n OPTIONAL_END_TAG_BLOCK_ELEMENTS,\n tagSet(\n 'address,article,' +\n 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +\n 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul'));\n\n// Inline Elements - HTML5\nconst INLINE_ELEMENTS = merge(\n OPTIONAL_END_TAG_INLINE_ELEMENTS,\n tagSet(\n 'a,abbr,acronym,audio,b,' +\n 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' +\n 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video'));\n\nexport const VALID_ELEMENTS =\n merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS);\n\n// Attributes that have href and hence need to be sanitized\nexport const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');\n\nconst HTML_ATTRS = tagSet(\n 'abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' +\n 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' +\n 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' +\n 'scope,scrolling,shape,size,sizes,span,srclang,srcset,start,summary,tabindex,target,title,translate,type,usemap,' +\n 'valign,value,vspace,width');\n\n// Accessibility attributes as per WAI-ARIA 1.1 (W3C Working Draft 14 December 2018)\nconst ARIA_ATTRS = tagSet(\n 'aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,' +\n 'aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,' +\n 'aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,' +\n 'aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,' +\n 'aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,' +\n 'aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,' +\n 'aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext');\n\n// NB: This currently consciously doesn't support SVG. SVG sanitization has had several security\n// issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via\n// innerHTML is required, SVG attributes should be added here.\n\n// NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those\n// can be sanitized, but they increase security surface area without a legitimate use case, so they\n// are left out here.\n\nexport const VALID_ATTRS = merge(URI_ATTRS, HTML_ATTRS, ARIA_ATTRS);\n\n// Elements whose content should not be traversed/preserved, if the elements themselves are invalid.\n//\n// Typically, `<invalid>Some content</invalid>` would traverse (and in this case preserve)\n// `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we\n// don't want to preserve the content, if the elements themselves are going to be removed.\nconst SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');\n\n/**\n * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe\n * attributes.\n */\nclass SanitizingHtmlSerializer {\n // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just\n // because characters were re-encoded.\n public sanitizedSomething = false;\n private buf: string[] = [];\n\n sanitizeChildren(el: Element): string {\n // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters.\n // However this code never accesses properties off of `document` before deleting its contents\n // again, so it shouldn't be vulnerable to DOM clobbering.\n let current: Node = el.firstChild!;\n let traverseContent = true;\n while (current) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n traverseContent = this.startElement(current as Element);\n } else if (current.nodeType === Node.TEXT_NODE) {\n this.chars(current.nodeValue!);\n } else {\n // Strip non-element, non-text nodes.\n this.sanitizedSomething = true;\n }\n if (traverseContent && current.firstChild) {\n current = current.firstChild!;\n continue;\n }\n while (current) {\n // Leaving the element. Walk up and to the right, closing tags as we go.\n if (current.nodeType === Node.ELEMENT_NODE) {\n this.endElement(current as Element);\n }\n\n let next = this.checkClobberedElement(current, current.nextSibling!);\n\n if (next) {\n current = next;\n break;\n }\n\n current = this.checkClobberedElement(current, current.parentNode!);\n }\n }\n return this.buf.join('');\n }\n\n /**\n * Sanitizes an opening element tag (if valid) and returns whether the element's contents should\n * be traversed. Element content must always be traversed (even if the element itself is not\n * valid/safe), unless the element is one of `SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS`.\n *\n * @param element The element to sanitize.\n * @return True if the element's contents should be traversed.\n */\n private startElement(element: Element): boolean {\n const tagName = element.nodeName.toLowerCase();\n if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {\n this.sanitizedSomething = true;\n return !SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS.hasOwnProperty(tagName);\n }\n this.buf.push('<');\n this.buf.push(tagName);\n const elAttrs = element.attributes;\n for (let i = 0; i < elAttrs.length; i++) {\n const elAttr = elAttrs.item(i);\n const attrName = elAttr!.name;\n const lower = attrName.toLowerCase();\n if (!VALID_ATTRS.hasOwnProperty(lower)) {\n this.sanitizedSomething = true;\n continue;\n }\n let value = elAttr!.value;\n // TODO(martinprobst): Special case image URIs for data:image/...\n if (URI_ATTRS[lower]) value = _sanitizeUrl(value);\n this.buf.push(' ', attrName, '=\"', encodeEntities(value), '\"');\n }\n this.buf.push('>');\n return true;\n }\n\n private endElement(current: Element) {\n const tagName = current.nodeName.toLowerCase();\n if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {\n this.buf.push('</');\n this.buf.push(tagName);\n this.buf.push('>');\n }\n }\n\n private chars(chars: string) {\n this.buf.push(encodeEntities(chars));\n }\n\n checkClobberedElement(node: Node, nextNode: Node): Node {\n if (nextNode &&\n (node.compareDocumentPosition(nextNode) &\n Node.DOCUMENT_POSITION_CONTAINED_BY) === Node.DOCUMENT_POSITION_CONTAINED_BY) {\n throw new Error(`Failed to sanitize html because the element is clobbered: ${\n (node as Element).outerHTML}`);\n }\n return nextNode;\n }\n}\n\n// Regular Expressions for parsing tags and attributes\nconst SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g;\n// ! to ~ is the ASCII range.\nconst NON_ALPHANUMERIC_REGEXP = /([^\\#-~ |!])/g;\n\n/**\n * Escapes all potentially dangerous characters, so that the\n * resulting string can be safely inserted into attribute or\n * element text.\n * @param value\n */\nfunction encodeEntities(value: string) {\n return value.replace(/&/g, '&')\n .replace(\n SURROGATE_PAIR_REGEXP,\n function(match: string) {\n const hi = match.charCodeAt(0);\n const low = match.charCodeAt(1);\n return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';\n })\n .replace(\n NON_ALPHANUMERIC_REGEXP,\n function(match: string) {\n return '&#' + match.charCodeAt(0) + ';';\n })\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nlet inertBodyHelper: InertBodyHelper;\n\n/**\n * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to\n * the DOM in a browser environment.\n */\nexport function _sanitizeHtml(defaultDoc: any, unsafeHtmlInput: string): TrustedHTML|string {\n let inertBodyElement: HTMLElement|null = null;\n try {\n inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc);\n // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).\n let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : '';\n inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);\n\n // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser\n // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous.\n let mXSSAttempts = 5;\n let parsedHtml = unsafeHtml;\n\n do {\n if (mXSSAttempts === 0) {\n throw new Error('Failed to sanitize html because the input is unstable');\n }\n mXSSAttempts--;\n\n unsafeHtml = parsedHtml;\n parsedHtml = inertBodyElement!.innerHTML;\n inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);\n } while (unsafeHtml !== parsedHtml);\n\n const sanitizer = new SanitizingHtmlSerializer();\n const safeHtml = sanitizer.sanitizeChildren(\n getTemplateContent(inertBodyElement!) as Element || inertBodyElement);\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && sanitizer.sanitizedSomething) {\n console.warn(`WARNING: sanitizing HTML stripped some content, see ${XSS_SECURITY_URL}`);\n }\n\n return trustedHTMLFromString(safeHtml);\n } finally {\n // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.\n if (inertBodyElement) {\n const parent = getTemplateContent(inertBodyElement) || inertBodyElement;\n while (parent.firstChild) {\n parent.removeChild(parent.firstChild);\n }\n }\n }\n}\n\nexport function getTemplateContent(el: Node): Node|null {\n return 'content' in (el as any /** Microsoft/TypeScript#21517 */) && isTemplateElement(el) ?\n el.content :\n null;\n}\nfunction isTemplateElement(el: Node): el is HTMLTemplateElement {\n return el.nodeType === Node.ELEMENT_NODE && el.nodeName === 'TEMPLATE';\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * A SecurityContext marks a location that has dangerous security implications, e.g. a DOM property\n * like `innerHTML` that could cause Cross Site Scripting (XSS) security bugs when improperly\n * handled.\n *\n * See DomSanitizer for more details on security in Angular applications.\n *\n * @publicApi\n */\nexport enum SecurityContext {\n NONE = 0,\n HTML = 1,\n STYLE = 2,\n SCRIPT = 3,\n URL = 4,\n RESOURCE_URL = 5,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XSS_SECURITY_URL} from '../error_details_base_url';\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {getDocument} from '../render3/interfaces/document';\nimport {SANITIZER} from '../render3/interfaces/view';\nimport {getLView} from '../render3/state';\nimport {renderStringify} from '../render3/util/stringify_utils';\nimport {TrustedHTML, TrustedScript, TrustedScriptURL} from '../util/security/trusted_type_defs';\nimport {trustedHTMLFromString, trustedScriptURLFromString} from '../util/security/trusted_types';\nimport {trustedHTMLFromStringBypass, trustedScriptFromStringBypass, trustedScriptURLFromStringBypass} from '../util/security/trusted_types_bypass';\n\nimport {allowSanitizationBypassAndThrow, BypassType, unwrapSafeValue} from './bypass';\nimport {_sanitizeHtml as _sanitizeHtml} from './html_sanitizer';\nimport {Sanitizer} from './sanitizer';\nimport {SecurityContext} from './security';\nimport {_sanitizeUrl as _sanitizeUrl} from './url_sanitizer';\n\n\n\n/**\n * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing\n * dangerous content.\n *\n * This method parses the `html` and locates potentially dangerous content (such as urls and\n * javascript) and removes it.\n *\n * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustHtml}.\n *\n * @param unsafeHtml untrusted `html`, typically from the user.\n * @returns `html` string which is safe to display to user, because all of the dangerous javascript\n * and urls have been removed.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeHtml(unsafeHtml: any): TrustedHTML|string {\n const sanitizer = getSanitizer();\n if (sanitizer) {\n return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');\n }\n if (allowSanitizationBypassAndThrow(unsafeHtml, BypassType.Html)) {\n return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));\n }\n return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));\n}\n\n/**\n * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing\n * dangerous content.\n *\n * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustStyle}.\n *\n * @param unsafeStyle untrusted `style`, typically from the user.\n * @returns `style` string which is safe to bind to the `style` properties.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeStyle(unsafeStyle: any): string {\n const sanitizer = getSanitizer();\n if (sanitizer) {\n return sanitizer.sanitize(SecurityContext.STYLE, unsafeStyle) || '';\n }\n if (allowSanitizationBypassAndThrow(unsafeStyle, BypassType.Style)) {\n return unwrapSafeValue(unsafeStyle);\n }\n return renderStringify(unsafeStyle);\n}\n\n/**\n * A `url` sanitizer which converts untrusted `url` **string** into trusted string by removing\n * dangerous\n * content.\n *\n * This method parses the `url` and locates potentially dangerous content (such as javascript) and\n * removes it.\n *\n * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustUrl}.\n *\n * @param unsafeUrl untrusted `url`, typically from the user.\n * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because\n * all of the dangerous javascript has been removed.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeUrl(unsafeUrl: any): string {\n const sanitizer = getSanitizer();\n if (sanitizer) {\n return sanitizer.sanitize(SecurityContext.URL, unsafeUrl) || '';\n }\n if (allowSanitizationBypassAndThrow(unsafeUrl, BypassType.Url)) {\n return unwrapSafeValue(unsafeUrl);\n }\n return _sanitizeUrl(renderStringify(unsafeUrl));\n}\n\n/**\n * A `url` sanitizer which only lets trusted `url`s through.\n *\n * This passes only `url`s marked trusted by calling {@link bypassSanitizationTrustResourceUrl}.\n *\n * @param unsafeResourceUrl untrusted `url`, typically from the user.\n * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because\n * only trusted `url`s have been allowed to pass.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeResourceUrl(unsafeResourceUrl: any): TrustedScriptURL|string {\n const sanitizer = getSanitizer();\n if (sanitizer) {\n return trustedScriptURLFromStringBypass(\n sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');\n }\n if (allowSanitizationBypassAndThrow(unsafeResourceUrl, BypassType.ResourceUrl)) {\n return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));\n }\n throw new RuntimeError(\n RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL,\n ngDevMode && `unsafe value used in a resource URL context (see ${XSS_SECURITY_URL})`);\n}\n\n/**\n * A `script` sanitizer which only lets trusted javascript through.\n *\n * This passes only `script`s marked trusted by calling {@link\n * bypassSanitizationTrustScript}.\n *\n * @param unsafeScript untrusted `script`, typically from the user.\n * @returns `url` string which is safe to bind to the `<script>` element such as `<img src>`,\n * because only trusted `scripts` have been allowed to pass.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeScript(unsafeScript: any): TrustedScript|string {\n const sanitizer = getSanitizer();\n if (sanitizer) {\n return trustedScriptFromStringBypass(\n sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');\n }\n if (allowSanitizationBypassAndThrow(unsafeScript, BypassType.Script)) {\n return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));\n }\n throw new RuntimeError(\n RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT,\n ngDevMode && 'unsafe value used in a script context');\n}\n\n/**\n * A template tag function for promoting the associated constant literal to a\n * TrustedHTML. Interpolation is explicitly not allowed.\n *\n * @param html constant template literal containing trusted HTML.\n * @returns TrustedHTML wrapping `html`.\n *\n * @security This is a security-sensitive function and should only be used to\n * convert constant values of attributes and properties found in\n * application-provided Angular templates to TrustedHTML.\n *\n * @codeGenApi\n */\nexport function ɵɵtrustConstantHtml(html: TemplateStringsArray): TrustedHTML|string {\n // The following runtime check ensures that the function was called as a\n // template tag (e.g. ɵɵtrustConstantHtml`content`), without any interpolation\n // (e.g. not ɵɵtrustConstantHtml`content ${variable}`). A TemplateStringsArray\n // is an array with a `raw` property that is also an array. The associated\n // template literal has no interpolation if and only if the length of the\n // TemplateStringsArray is 1.\n if (ngDevMode && (!Array.isArray(html) || !Array.isArray(html.raw) || html.length !== 1)) {\n throw new Error(`Unexpected interpolation in trusted HTML constant: ${html.join('?')}`);\n }\n return trustedHTMLFromString(html[0]);\n}\n\n/**\n * A template tag function for promoting the associated constant literal to a\n * TrustedScriptURL. Interpolation is explicitly not allowed.\n *\n * @param url constant template literal containing a trusted script URL.\n * @returns TrustedScriptURL wrapping `url`.\n *\n * @security This is a security-sensitive function and should only be used to\n * convert constant values of attributes and properties found in\n * application-provided Angular templates to TrustedScriptURL.\n *\n * @codeGenApi\n */\nexport function ɵɵtrustConstantResourceUrl(url: TemplateStringsArray): TrustedScriptURL|string {\n // The following runtime check ensures that the function was called as a\n // template tag (e.g. ɵɵtrustConstantResourceUrl`content`), without any\n // interpolation (e.g. not ɵɵtrustConstantResourceUrl`content ${variable}`). A\n // TemplateStringsArray is an array with a `raw` property that is also an\n // array. The associated template literal has no interpolation if and only if\n // the length of the TemplateStringsArray is 1.\n if (ngDevMode && (!Array.isArray(url) || !Array.isArray(url.raw) || url.length !== 1)) {\n throw new Error(`Unexpected interpolation in trusted URL constant: ${url.join('?')}`);\n }\n return trustedScriptURLFromString(url[0]);\n}\n\n/**\n * Detects which sanitizer to use for URL property, based on tag name and prop name.\n *\n * The rules are based on the RESOURCE_URL context config from\n * `packages/compiler/src/schema/dom_security_schema.ts`.\n * If tag and prop names don't match Resource URL schema, use URL sanitizer.\n */\nexport function getUrlSanitizer(tag: string, prop: string) {\n if ((prop === 'src' &&\n (tag === 'embed' || tag === 'frame' || tag === 'iframe' || tag === 'media' ||\n tag === 'script')) ||\n (prop === 'href' && (tag === 'base' || tag === 'link'))) {\n return ɵɵsanitizeResourceUrl;\n }\n return ɵɵsanitizeUrl;\n}\n\n/**\n * Sanitizes URL, selecting sanitizer function based on tag and property names.\n *\n * This function is used in case we can't define security context at compile time, when only prop\n * name is available. This happens when we generate host bindings for Directives/Components. The\n * host element is unknown at compile time, so we defer calculation of specific sanitizer to\n * runtime.\n *\n * @param unsafeUrl untrusted `url`, typically from the user.\n * @param tag target element tag name.\n * @param prop name of the property that contains the value.\n * @returns `url` string which is safe to bind.\n *\n * @codeGenApi\n */\nexport function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl: any, tag: string, prop: string): any {\n return getUrlSanitizer(tag, prop)(unsafeUrl);\n}\n\nexport function validateAgainstEventProperties(name: string) {\n if (name.toLowerCase().startsWith('on')) {\n const errorMessage =\n `Binding to event property '${name}' is disallowed for security reasons, ` +\n `please use (${name.slice(2)})=...` +\n `\\nIf '${name}' is a directive input, make sure the directive is imported by the` +\n ` current module.`;\n throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);\n }\n}\n\nexport function validateAgainstEventAttributes(name: string) {\n if (name.toLowerCase().startsWith('on')) {\n const errorMessage =\n `Binding to event attribute '${name}' is disallowed for security reasons, ` +\n `please use (${name.slice(2)})=...`;\n throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);\n }\n}\n\nfunction getSanitizer(): Sanitizer|null {\n const lView = getLView();\n return lView && lView[SANITIZER];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from './injection_token';\n\n/**\n * A multi-provider token for initialization functions that will run upon construction of an\n * environment injector.\n *\n * @publicApi\n */\nexport const ENVIRONMENT_INITIALIZER = new InjectionToken<() => void>('ENVIRONMENT_INITIALIZER');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from './injection_token';\nimport {Injector} from './injector';\nimport {InjectorMarkers} from './injector_marker';\n\n\n\n/**\n * An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.\n *\n * Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a\n * project.\n *\n * @publicApi\n */\nexport const INJECTOR = new InjectionToken<Injector>(\n 'INJECTOR',\n // Disable tslint because this is const enum which gets inlined not top level prop access.\n // tslint:disable-next-line: no-toplevel-property-access\n InjectorMarkers.Injector as any, // Special value used by Ivy to identify `Injector`.\n);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\n\nimport {InjectionToken} from './injection_token';\n\nexport const INJECTOR_DEF_TYPES = new InjectionToken<Type<unknown>>('INJECTOR_DEF_TYPES');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {stringify} from '../util/stringify';\nimport {Injector} from './injector';\nimport {THROW_IF_NOT_FOUND} from './injector_compatibility';\n\nexport class NullInjector implements Injector {\n get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {\n if (notFoundValue === THROW_IF_NOT_FOUND) {\n const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);\n error.name = 'NullInjectorError';\n throw error;\n }\n return notFoundValue;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {Type} from '../interface/type';\nimport {getComponentDef} from '../render3/definition';\nimport {getFactoryDef} from '../render3/definition_factory';\nimport {throwCyclicDependencyError, throwInvalidProviderError} from '../render3/errors_di';\nimport {stringifyForError} from '../render3/util/stringify_utils';\nimport {deepForEach} from '../util/array_utils';\nimport {EMPTY_ARRAY} from '../util/empty';\nimport {getClosureSafeProperty} from '../util/property';\nimport {stringify} from '../util/stringify';\n\nimport {resolveForwardRef} from './forward_ref';\nimport {ENVIRONMENT_INITIALIZER} from './initializer_token';\nimport {ɵɵinject as inject} from './injector_compatibility';\nimport {getInjectorDef, InjectorType, InjectorTypeWithProviders} from './interface/defs';\nimport {ClassProvider, ConstructorProvider, EnvironmentProviders, ExistingProvider, FactoryProvider, ImportedNgModuleProviders, InternalEnvironmentProviders, isEnvironmentProviders, ModuleWithProviders, Provider, StaticClassProvider, TypeProvider, ValueProvider} from './interface/provider';\nimport {INJECTOR_DEF_TYPES} from './internal_tokens';\n\n/**\n * Wrap an array of `Provider`s into `EnvironmentProviders`, preventing them from being accidentally\n * referenced in `@Component in a component injector.\n */\nexport function makeEnvironmentProviders(providers: (Provider|EnvironmentProviders)[]):\n EnvironmentProviders {\n return {\n ɵproviders: providers,\n } as unknown as EnvironmentProviders;\n}\n\n/**\n * A source of providers for the `importProvidersFrom` function.\n *\n * @publicApi\n */\nexport type ImportProvidersSource =\n Type<unknown>|ModuleWithProviders<unknown>|Array<ImportProvidersSource>;\n\n/**\n * Collects providers from all NgModules and standalone components, including transitively imported\n * ones.\n *\n * Providers extracted via `importProvidersFrom` are only usable in an application injector or\n * another environment injector (such as a route injector). They should not be used in component\n * providers.\n *\n * More information about standalone components can be found in [this\n * guide](guide/standalone-components).\n *\n * @usageNotes\n * The results of the `importProvidersFrom` call can be used in the `bootstrapApplication` call:\n *\n * ```typescript\n * await bootstrapApplication(RootComponent, {\n * providers: [\n * importProvidersFrom(NgModuleOne, NgModuleTwo)\n * ]\n * });\n * ```\n *\n * You can also use the `importProvidersFrom` results in the `providers` field of a route, when a\n * standalone component is used:\n *\n * ```typescript\n * export const ROUTES: Route[] = [\n * {\n * path: 'foo',\n * providers: [\n * importProvidersFrom(NgModuleOne, NgModuleTwo)\n * ],\n * component: YourStandaloneComponent\n * }\n * ];\n * ```\n *\n * @returns Collected providers from the specified list of types.\n * @publicApi\n */\nexport function importProvidersFrom(...sources: ImportProvidersSource[]): EnvironmentProviders {\n return {\n ɵproviders: internalImportProvidersFrom(true, sources),\n ɵfromNgModule: true,\n } as InternalEnvironmentProviders;\n}\n\nexport function internalImportProvidersFrom(\n checkForStandaloneCmp: boolean, ...sources: ImportProvidersSource[]): Provider[] {\n const providersOut: SingleProvider[] = [];\n const dedup = new Set<Type<unknown>>(); // already seen types\n let injectorTypesWithProviders: InjectorTypeWithProviders<unknown>[]|undefined;\n deepForEach(sources, source => {\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && checkForStandaloneCmp) {\n const cmpDef = getComponentDef(source);\n if (cmpDef?.standalone) {\n throw new RuntimeError(\n RuntimeErrorCode.IMPORT_PROVIDERS_FROM_STANDALONE,\n `Importing providers supports NgModule or ModuleWithProviders but got a standalone component \"${\n stringifyForError(source)}\"`);\n }\n }\n\n // Narrow `source` to access the internal type analogue for `ModuleWithProviders`.\n const internalSource = source as Type<unknown>| InjectorTypeWithProviders<unknown>;\n if (walkProviderTree(internalSource, providersOut, [], dedup)) {\n injectorTypesWithProviders ||= [];\n injectorTypesWithProviders.push(internalSource);\n }\n });\n // Collect all providers from `ModuleWithProviders` types.\n if (injectorTypesWithProviders !== undefined) {\n processInjectorTypesWithProviders(injectorTypesWithProviders, providersOut);\n }\n\n return providersOut;\n}\n\n/**\n * Collects all providers from the list of `ModuleWithProviders` and appends them to the provided\n * array.\n */\nfunction processInjectorTypesWithProviders(\n typesWithProviders: InjectorTypeWithProviders<unknown>[], providersOut: Provider[]): void {\n for (let i = 0; i < typesWithProviders.length; i++) {\n const {ngModule, providers} = typesWithProviders[i];\n deepForEachProvider(providers! as Array<Provider|InternalEnvironmentProviders>, provider => {\n ngDevMode && validateProvider(provider, providers || EMPTY_ARRAY, ngModule);\n providersOut.push(provider);\n });\n }\n}\n\n/**\n * Internal type for a single provider in a deep provider array.\n */\nexport type SingleProvider = TypeProvider|ValueProvider|ClassProvider|ConstructorProvider|\n ExistingProvider|FactoryProvider|StaticClassProvider;\n\n/**\n * The logic visits an `InjectorType`, an `InjectorTypeWithProviders`, or a standalone\n * `ComponentType`, and all of its transitive providers and collects providers.\n *\n * If an `InjectorTypeWithProviders` that declares providers besides the type is specified,\n * the function will return \"true\" to indicate that the providers of the type definition need\n * to be processed. This allows us to process providers of injector types after all imports of\n * an injector definition are processed. (following View Engine semantics: see FW-1349)\n */\nexport function walkProviderTree(\n container: Type<unknown>|InjectorTypeWithProviders<unknown>, providersOut: SingleProvider[],\n parents: Type<unknown>[],\n dedup: Set<Type<unknown>>): container is InjectorTypeWithProviders<unknown> {\n container = resolveForwardRef(container);\n if (!container) return false;\n\n // The actual type which had the definition. Usually `container`, but may be an unwrapped type\n // from `InjectorTypeWithProviders`.\n let defType: Type<unknown>|null = null;\n\n let injDef = getInjectorDef(container);\n const cmpDef = !injDef && getComponentDef(container);\n if (!injDef && !cmpDef) {\n // `container` is not an injector type or a component type. It might be:\n // * An `InjectorTypeWithProviders` that wraps an injector type.\n // * A standalone directive or pipe that got pulled in from a standalone component's\n // dependencies.\n // Try to unwrap it as an `InjectorTypeWithProviders` first.\n const ngModule: Type<unknown>|undefined =\n (container as InjectorTypeWithProviders<any>).ngModule as Type<unknown>| undefined;\n injDef = getInjectorDef(ngModule);\n if (injDef) {\n defType = ngModule!;\n } else {\n // Not a component or injector type, so ignore it.\n return false;\n }\n } else if (cmpDef && !cmpDef.standalone) {\n return false;\n } else {\n defType = container as Type<unknown>;\n }\n\n // Check for circular dependencies.\n if (ngDevMode && parents.indexOf(defType) !== -1) {\n const defName = stringify(defType);\n const path = parents.map(stringify);\n throwCyclicDependencyError(defName, path);\n }\n\n // Check for multiple imports of the same module\n const isDuplicate = dedup.has(defType);\n\n if (cmpDef) {\n if (isDuplicate) {\n // This component definition has already been processed.\n return false;\n }\n dedup.add(defType);\n\n if (cmpDef.dependencies) {\n const deps =\n typeof cmpDef.dependencies === 'function' ? cmpDef.dependencies() : cmpDef.dependencies;\n for (const dep of deps) {\n walkProviderTree(dep, providersOut, parents, dedup);\n }\n }\n } else if (injDef) {\n // First, include providers from any imports.\n if (injDef.imports != null && !isDuplicate) {\n // Before processing defType's imports, add it to the set of parents. This way, if it ends\n // up deeply importing itself, this can be detected.\n ngDevMode && parents.push(defType);\n // Add it to the set of dedups. This way we can detect multiple imports of the same module\n dedup.add(defType);\n\n let importTypesWithProviders: (InjectorTypeWithProviders<any>[])|undefined;\n try {\n deepForEach(injDef.imports, imported => {\n if (walkProviderTree(imported, providersOut, parents, dedup)) {\n importTypesWithProviders ||= [];\n // If the processed import is an injector type with providers, we store it in the\n // list of import types with providers, so that we can process those afterwards.\n importTypesWithProviders.push(imported);\n }\n });\n } finally {\n // Remove it from the parents set when finished.\n ngDevMode && parents.pop();\n }\n\n // Imports which are declared with providers (TypeWithProviders) need to be processed\n // after all imported modules are processed. This is similar to how View Engine\n // processes/merges module imports in the metadata resolver. See: FW-1349.\n if (importTypesWithProviders !== undefined) {\n processInjectorTypesWithProviders(importTypesWithProviders, providersOut);\n }\n }\n\n if (!isDuplicate) {\n // Track the InjectorType and add a provider for it.\n // It's important that this is done after the def's imports.\n const factory = getFactoryDef(defType) || (() => new defType!());\n\n // Append extra providers to make more info available for consumers (to retrieve an injector\n // type), as well as internally (to calculate an injection scope correctly and eagerly\n // instantiate a `defType` when an injector is created).\n providersOut.push(\n // Provider to create `defType` using its factory.\n {provide: defType, useFactory: factory, deps: EMPTY_ARRAY},\n\n // Make this `defType` available to an internal logic that calculates injector scope.\n {provide: INJECTOR_DEF_TYPES, useValue: defType, multi: true},\n\n // Provider to eagerly instantiate `defType` via `ENVIRONMENT_INITIALIZER`.\n {provide: ENVIRONMENT_INITIALIZER, useValue: () => inject(defType!), multi: true} //\n );\n }\n\n // Next, include providers listed on the definition itself.\n const defProviders = injDef.providers as Array<SingleProvider|InternalEnvironmentProviders>;\n if (defProviders != null && !isDuplicate) {\n const injectorType = container as InjectorType<any>;\n deepForEachProvider(defProviders, provider => {\n ngDevMode && validateProvider(provider as SingleProvider, defProviders, injectorType);\n providersOut.push(provider as SingleProvider);\n });\n }\n } else {\n // Should not happen, but just in case.\n return false;\n }\n\n return (\n defType !== container &&\n (container as InjectorTypeWithProviders<any>).providers !== undefined);\n}\n\nfunction validateProvider(\n provider: SingleProvider, providers: Array<SingleProvider|InternalEnvironmentProviders>,\n containerType: Type<unknown>): void {\n if (isTypeProvider(provider) || isValueProvider(provider) || isFactoryProvider(provider) ||\n isExistingProvider(provider)) {\n return;\n }\n\n // Here we expect the provider to be a `useClass` provider (by elimination).\n const classRef = resolveForwardRef(\n provider && ((provider as StaticClassProvider | ClassProvider).useClass || provider.provide));\n if (!classRef) {\n throwInvalidProviderError(containerType, providers, provider);\n }\n}\n\nfunction deepForEachProvider(\n providers: Array<Provider|InternalEnvironmentProviders>,\n fn: (provider: SingleProvider) => void): void {\n for (let provider of providers) {\n if (isEnvironmentProviders(provider)) {\n provider = provider.ɵproviders;\n }\n if (Array.isArray(provider)) {\n deepForEachProvider(provider, fn);\n } else {\n fn(provider);\n }\n }\n}\n\nexport const USE_VALUE =\n getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});\n\nexport function isValueProvider(value: SingleProvider): value is ValueProvider {\n return value !== null && typeof value == 'object' && USE_VALUE in value;\n}\n\nexport function isExistingProvider(value: SingleProvider): value is ExistingProvider {\n return !!(value && (value as ExistingProvider).useExisting);\n}\n\nexport function isFactoryProvider(value: SingleProvider): value is FactoryProvider {\n return !!(value && (value as FactoryProvider).useFactory);\n}\n\nexport function isTypeProvider(value: SingleProvider): value is TypeProvider {\n return typeof value === 'function';\n}\n\nexport function isClassProvider(value: SingleProvider): value is ClassProvider {\n return !!(value as StaticClassProvider | ClassProvider).useClass;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from './injection_token';\n\n\nexport type InjectorScope = 'root'|'platform'|'environment';\n\n/**\n * An internal token whose presence in an injector indicates that the injector should treat itself\n * as a root scoped injector when processing requests for unknown tokens which may indicate\n * they are provided in the root scope.\n */\nexport const INJECTOR_SCOPE = new InjectionToken<InjectorScope|null>('Set Injector scope.');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport '../util/ng_dev_mode';\n\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {OnDestroy} from '../interface/lifecycle_hooks';\nimport {Type} from '../interface/type';\nimport {getComponentDef} from '../render3/definition';\nimport {FactoryFn, getFactoryDef} from '../render3/definition_factory';\nimport {throwCyclicDependencyError, throwInvalidProviderError, throwMixedMultiProviderError} from '../render3/errors_di';\nimport {newArray} from '../util/array_utils';\nimport {EMPTY_ARRAY} from '../util/empty';\nimport {stringify} from '../util/stringify';\n\nimport {resolveForwardRef} from './forward_ref';\nimport {ENVIRONMENT_INITIALIZER} from './initializer_token';\nimport {setInjectImplementation} from './inject_switch';\nimport {InjectionToken} from './injection_token';\nimport {Injector} from './injector';\nimport {catchInjectorError, convertToBitFlags, injectArgs, NG_TEMP_TOKEN_PATH, setCurrentInjector, THROW_IF_NOT_FOUND, ɵɵinject} from './injector_compatibility';\nimport {INJECTOR} from './injector_token';\nimport {getInheritedInjectableDef, getInjectableDef, InjectorType, ɵɵInjectableDeclaration} from './interface/defs';\nimport {InjectFlags, InjectOptions} from './interface/injector';\nimport {ClassProvider, ConstructorProvider, EnvironmentProviders, InternalEnvironmentProviders, isEnvironmentProviders, Provider, StaticClassProvider} from './interface/provider';\nimport {INJECTOR_DEF_TYPES} from './internal_tokens';\nimport {NullInjector} from './null_injector';\nimport {isExistingProvider, isFactoryProvider, isTypeProvider, isValueProvider, SingleProvider} from './provider_collection';\nimport {ProviderToken} from './provider_token';\nimport {INJECTOR_SCOPE, InjectorScope} from './scope';\n\n/**\n * Marker which indicates that a value has not yet been created from the factory function.\n */\nconst NOT_YET = {};\n\n/**\n * Marker which indicates that the factory function for a token is in the process of being called.\n *\n * If the injector is asked to inject a token with its value set to CIRCULAR, that indicates\n * injection of a dependency has recursively attempted to inject the original token, and there is\n * a circular dependency among the providers.\n */\nconst CIRCULAR = {};\n\n/**\n * A lazily initialized NullInjector.\n */\nlet NULL_INJECTOR: Injector|undefined = undefined;\n\nexport function getNullInjector(): Injector {\n if (NULL_INJECTOR === undefined) {\n NULL_INJECTOR = new NullInjector();\n }\n return NULL_INJECTOR;\n}\n\n/**\n * An entry in the injector which tracks information about the given token, including a possible\n * current value.\n */\ninterface Record<T> {\n factory: (() => T)|undefined;\n value: T|{};\n multi: any[]|undefined;\n}\n\n/**\n * An `Injector` that's part of the environment injector hierarchy, which exists outside of the\n * component tree.\n */\nexport abstract class EnvironmentInjector implements Injector {\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue: undefined, options: InjectOptions&{\n optional?: false;\n }): T;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue: null|undefined, options: InjectOptions): T\n |null;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue?: T, options?: InjectOptions): T;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n * @deprecated use object-based flags (`InjectOptions`) instead.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T;\n /**\n * @deprecated from v4.0.0 use ProviderToken<T>\n * @suppress {duplicate}\n */\n abstract get(token: any, notFoundValue?: any): any;\n\n /**\n * Runs the given function in the context of this `EnvironmentInjector`.\n *\n * Within the function's stack frame, `inject` can be used to inject dependencies from this\n * injector. Note that `inject` is only usable synchronously, and cannot be used in any\n * asynchronous callbacks or after any `await` points.\n *\n * @param fn the closure to be run in the context of this injector\n * @returns the return value of the function, if any\n */\n abstract runInContext<ReturnT>(fn: () => ReturnT): ReturnT;\n\n abstract destroy(): void;\n\n /**\n * @internal\n */\n abstract onDestroy(callback: () => void): void;\n}\n\nexport class R3Injector extends EnvironmentInjector {\n /**\n * Map of tokens to records which contain the instances of those tokens.\n * - `null` value implies that we don't have the record. Used by tree-shakable injectors\n * to prevent further searches.\n */\n private records = new Map<ProviderToken<any>, Record<any>|null>();\n\n /**\n * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.\n */\n private _ngOnDestroyHooks = new Set<OnDestroy>();\n\n private _onDestroyHooks: Array<() => void> = [];\n\n /**\n * Flag indicating that this injector was previously destroyed.\n */\n get destroyed(): boolean {\n return this._destroyed;\n }\n private _destroyed = false;\n\n private injectorDefTypes: Set<Type<unknown>>;\n\n constructor(\n providers: Array<Provider|EnvironmentProviders>, readonly parent: Injector,\n readonly source: string|null, readonly scopes: Set<InjectorScope>) {\n super();\n // Start off by creating Records for every provider.\n forEachSingleProvider(\n providers as Array<Provider|InternalEnvironmentProviders>,\n provider => this.processProvider(provider));\n\n // Make sure the INJECTOR token provides this injector.\n this.records.set(INJECTOR, makeRecord(undefined, this));\n\n // And `EnvironmentInjector` if the current injector is supposed to be env-scoped.\n if (scopes.has('environment')) {\n this.records.set(EnvironmentInjector, makeRecord(undefined, this));\n }\n\n // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide\n // any injectable scoped to APP_ROOT_SCOPE.\n const record = this.records.get(INJECTOR_SCOPE) as Record<InjectorScope|null>;\n if (record != null && typeof record.value === 'string') {\n this.scopes.add(record.value as InjectorScope);\n }\n\n this.injectorDefTypes =\n new Set(this.get(INJECTOR_DEF_TYPES.multi, EMPTY_ARRAY, InjectFlags.Self));\n }\n\n /**\n * Destroy the injector and release references to every instance or provider associated with it.\n *\n * Also calls the `OnDestroy` lifecycle hooks of every instance that was created for which a\n * hook was found.\n */\n override destroy(): void {\n this.assertNotDestroyed();\n\n // Set destroyed = true first, in case lifecycle hooks re-enter destroy().\n this._destroyed = true;\n try {\n // Call all the lifecycle hooks.\n for (const service of this._ngOnDestroyHooks) {\n service.ngOnDestroy();\n }\n for (const hook of this._onDestroyHooks) {\n hook();\n }\n } finally {\n // Release all references.\n this.records.clear();\n this._ngOnDestroyHooks.clear();\n this.injectorDefTypes.clear();\n this._onDestroyHooks.length = 0;\n }\n }\n\n override onDestroy(callback: () => void): void {\n this._onDestroyHooks.push(callback);\n }\n\n override runInContext<ReturnT>(fn: () => ReturnT): ReturnT {\n this.assertNotDestroyed();\n\n const previousInjector = setCurrentInjector(this);\n const previousInjectImplementation = setInjectImplementation(undefined);\n try {\n return fn();\n } finally {\n setCurrentInjector(previousInjector);\n setInjectImplementation(previousInjectImplementation);\n }\n }\n\n override get<T>(\n token: ProviderToken<T>, notFoundValue: any = THROW_IF_NOT_FOUND,\n flags: InjectFlags|InjectOptions = InjectFlags.Default): T {\n this.assertNotDestroyed();\n flags = convertToBitFlags(flags) as InjectFlags;\n\n // Set the injection context.\n const previousInjector = setCurrentInjector(this);\n const previousInjectImplementation = setInjectImplementation(undefined);\n try {\n // Check for the SkipSelf flag.\n if (!(flags & InjectFlags.SkipSelf)) {\n // SkipSelf isn't set, check if the record belongs to this injector.\n let record: Record<T>|undefined|null = this.records.get(token);\n if (record === undefined) {\n // No record, but maybe the token is scoped to this injector. Look for an injectable\n // def with a scope matching this injector.\n const def = couldBeInjectableType(token) && getInjectableDef(token);\n if (def && this.injectableDefInScope(def)) {\n // Found an injectable def and it's scoped to this injector. Pretend as if it was here\n // all along.\n record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);\n } else {\n record = null;\n }\n this.records.set(token, record);\n }\n // If a record was found, get the instance for it and return it.\n if (record != null /* NOT null || undefined */) {\n return this.hydrate(token, record);\n }\n }\n\n // Select the next injector based on the Self flag - if self is set, the next injector is\n // the NullInjector, otherwise it's the parent.\n const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector();\n // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue\n // is undefined, the value is null, otherwise it's the notFoundValue.\n notFoundValue = (flags & InjectFlags.Optional) && notFoundValue === THROW_IF_NOT_FOUND ?\n null :\n notFoundValue;\n return nextInjector.get(token, notFoundValue);\n } catch (e: any) {\n if (e.name === 'NullInjectorError') {\n const path: any[] = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];\n path.unshift(stringify(token));\n if (previousInjector) {\n // We still have a parent injector, keep throwing\n throw e;\n } else {\n // Format & throw the final error message when we don't have any previous injector\n return catchInjectorError(e, token, 'R3InjectorError', this.source);\n }\n } else {\n throw e;\n }\n } finally {\n // Lastly, restore the previous injection context.\n setInjectImplementation(previousInjectImplementation);\n setCurrentInjector(previousInjector);\n }\n }\n\n /** @internal */\n resolveInjectorInitializers() {\n const previousInjector = setCurrentInjector(this);\n const previousInjectImplementation = setInjectImplementation(undefined);\n try {\n const initializers = this.get(ENVIRONMENT_INITIALIZER.multi, EMPTY_ARRAY, InjectFlags.Self);\n if (ngDevMode && !Array.isArray(initializers)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_MULTI_PROVIDER,\n 'Unexpected type of the `ENVIRONMENT_INITIALIZER` token value ' +\n `(expected an array, but got ${typeof initializers}). ` +\n 'Please check that the `ENVIRONMENT_INITIALIZER` token is configured as a ' +\n '`multi: true` provider.');\n }\n for (const initializer of initializers) {\n initializer();\n }\n } finally {\n setCurrentInjector(previousInjector);\n setInjectImplementation(previousInjectImplementation);\n }\n }\n\n override toString() {\n const tokens: string[] = [];\n const records = this.records;\n for (const token of records.keys()) {\n tokens.push(stringify(token));\n }\n return `R3Injector[${tokens.join(', ')}]`;\n }\n\n private assertNotDestroyed(): void {\n if (this._destroyed) {\n throw new RuntimeError(\n RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,\n ngDevMode && 'Injector has already been destroyed.');\n }\n }\n\n /**\n * Process a `SingleProvider` and add it.\n */\n private processProvider(provider: SingleProvider): void {\n // Determine the token from the provider. Either it's its own token, or has a {provide: ...}\n // property.\n provider = resolveForwardRef(provider);\n let token: any =\n isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide);\n\n // Construct a `Record` for the provider.\n const record = providerToRecord(provider);\n\n if (!isTypeProvider(provider) && provider.multi === true) {\n // If the provider indicates that it's a multi-provider, process it specially.\n // First check whether it's been defined already.\n let multiRecord = this.records.get(token);\n if (multiRecord) {\n // It has. Throw a nice error if\n if (ngDevMode && multiRecord.multi === undefined) {\n throwMixedMultiProviderError();\n }\n } else {\n multiRecord = makeRecord(undefined, NOT_YET, true);\n multiRecord.factory = () => injectArgs(multiRecord!.multi!);\n this.records.set(token, multiRecord);\n }\n token = provider;\n multiRecord.multi!.push(provider);\n } else {\n const existing = this.records.get(token);\n if (ngDevMode && existing && existing.multi !== undefined) {\n throwMixedMultiProviderError();\n }\n }\n this.records.set(token, record);\n }\n\n private hydrate<T>(token: ProviderToken<T>, record: Record<T>): T {\n if (ngDevMode && record.value === CIRCULAR) {\n throwCyclicDependencyError(stringify(token));\n } else if (record.value === NOT_YET) {\n record.value = CIRCULAR;\n record.value = record.factory!();\n }\n if (typeof record.value === 'object' && record.value && hasOnDestroy(record.value)) {\n this._ngOnDestroyHooks.add(record.value);\n }\n return record.value as T;\n }\n\n private injectableDefInScope(def: ɵɵInjectableDeclaration<any>): boolean {\n if (!def.providedIn) {\n return false;\n }\n const providedIn = resolveForwardRef(def.providedIn);\n if (typeof providedIn === 'string') {\n return providedIn === 'any' || (this.scopes.has(providedIn));\n } else {\n return this.injectorDefTypes.has(providedIn);\n }\n }\n}\n\nfunction injectableDefOrInjectorDefFactory(token: ProviderToken<any>): FactoryFn<any> {\n // Most tokens will have an injectable def directly on them, which specifies a factory directly.\n const injectableDef = getInjectableDef(token);\n const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);\n\n if (factory !== null) {\n return factory;\n }\n\n // InjectionTokens should have an injectable def (ɵprov) and thus should be handled above.\n // If it's missing that, it's an error.\n if (token instanceof InjectionToken) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_INJECTION_TOKEN,\n ngDevMode && `Token ${stringify(token)} is missing a ɵprov definition.`);\n }\n\n // Undecorated types can sometimes be created if they have no constructor arguments.\n if (token instanceof Function) {\n return getUndecoratedInjectableFactory(token);\n }\n\n // There was no way to resolve a factory for this token.\n throw new RuntimeError(RuntimeErrorCode.INVALID_INJECTION_TOKEN, ngDevMode && 'unreachable');\n}\n\nfunction getUndecoratedInjectableFactory(token: Function) {\n // If the token has parameters then it has dependencies that we cannot resolve implicitly.\n const paramLength = token.length;\n if (paramLength > 0) {\n const args: string[] = newArray(paramLength, '?');\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_INJECTION_TOKEN,\n ngDevMode && `Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`);\n }\n\n // The constructor function appears to have no parameters.\n // This might be because it inherits from a super-class. In which case, use an injectable\n // def from an ancestor if there is one.\n // Otherwise this really is a simple class with no dependencies, so return a factory that\n // just instantiates the zero-arg constructor.\n const inheritedInjectableDef = getInheritedInjectableDef(token);\n if (inheritedInjectableDef !== null) {\n return () => inheritedInjectableDef.factory(token as Type<any>);\n } else {\n return () => new (token as Type<any>)();\n }\n}\n\nfunction providerToRecord(provider: SingleProvider): Record<any> {\n if (isValueProvider(provider)) {\n return makeRecord(undefined, provider.useValue);\n } else {\n const factory: (() => any)|undefined = providerToFactory(provider);\n return makeRecord(factory, NOT_YET);\n }\n}\n\n/**\n * Converts a `SingleProvider` into a factory function.\n *\n * @param provider provider to convert to factory\n */\nexport function providerToFactory(\n provider: SingleProvider, ngModuleType?: InjectorType<any>, providers?: any[]): () => any {\n let factory: (() => any)|undefined = undefined;\n if (ngDevMode && isEnvironmentProviders(provider)) {\n throwInvalidProviderError(undefined, providers, provider);\n }\n\n if (isTypeProvider(provider)) {\n const unwrappedProvider = resolveForwardRef(provider);\n return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider);\n } else {\n if (isValueProvider(provider)) {\n factory = () => resolveForwardRef(provider.useValue);\n } else if (isFactoryProvider(provider)) {\n factory = () => provider.useFactory(...injectArgs(provider.deps || []));\n } else if (isExistingProvider(provider)) {\n factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));\n } else {\n const classRef = resolveForwardRef(\n provider &&\n ((provider as StaticClassProvider | ClassProvider).useClass || provider.provide));\n if (ngDevMode && !classRef) {\n throwInvalidProviderError(ngModuleType, providers, provider);\n }\n if (hasDeps(provider)) {\n factory = () => new (classRef)(...injectArgs(provider.deps));\n } else {\n return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef);\n }\n }\n }\n return factory;\n}\n\nfunction makeRecord<T>(\n factory: (() => T)|undefined, value: T|{}, multi: boolean = false): Record<T> {\n return {\n factory: factory,\n value: value,\n multi: multi ? [] : undefined,\n };\n}\n\nfunction hasDeps(value: ClassProvider|ConstructorProvider|\n StaticClassProvider): value is ClassProvider&{deps: any[]} {\n return !!(value as any).deps;\n}\n\nfunction hasOnDestroy(value: any): value is OnDestroy {\n return value !== null && typeof value === 'object' &&\n typeof (value as OnDestroy).ngOnDestroy === 'function';\n}\n\nfunction couldBeInjectableType(value: any): value is ProviderToken<any> {\n return (typeof value === 'function') ||\n (typeof value === 'object' && value instanceof InjectionToken);\n}\n\nfunction forEachSingleProvider(\n providers: Array<Provider|EnvironmentProviders>, fn: (provider: SingleProvider) => void): void {\n for (const provider of providers) {\n if (Array.isArray(provider)) {\n forEachSingleProvider(provider, fn);\n } else if (provider && isEnvironmentProviders(provider)) {\n forEachSingleProvider(provider.ɵproviders, fn);\n } else {\n fn(provider as SingleProvider);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef} from '../change_detection/change_detection';\nimport {Injector} from '../di/injector';\nimport {EnvironmentInjector} from '../di/r3_injector';\nimport {Type} from '../interface/type';\n\nimport {ElementRef} from './element_ref';\nimport {NgModuleRef} from './ng_module_factory';\nimport {ViewRef} from './view_ref';\n\n/**\n * Represents a component created by a `ComponentFactory`.\n * Provides access to the component instance and related objects,\n * and provides the means of destroying the instance.\n *\n * @publicApi\n */\nexport abstract class ComponentRef<C> {\n /**\n * Updates a specified input name to a new value. Using this method will properly mark for check\n * component using the `OnPush` change detection strategy. It will also assure that the\n * `OnChanges` lifecycle hook runs when a dynamically created component is change-detected.\n *\n * @param name The name of an input.\n * @param value The new value of an input.\n */\n abstract setInput(name: string, value: unknown): void;\n\n /**\n * The host or anchor [element](guide/glossary#element) for this component instance.\n */\n abstract get location(): ElementRef;\n\n /**\n * The [dependency injector](guide/glossary#injector) for this component instance.\n */\n abstract get injector(): Injector;\n\n /**\n * This component instance.\n */\n abstract get instance(): C;\n\n /**\n * The [host view](guide/glossary#view-hierarchy) defined by the template\n * for this component instance.\n */\n abstract get hostView(): ViewRef;\n\n /**\n * The change detector for this component instance.\n */\n abstract get changeDetectorRef(): ChangeDetectorRef;\n\n /**\n * The type of this component (as created by a `ComponentFactory` class).\n */\n abstract get componentType(): Type<any>;\n\n /**\n * Destroys the component instance and all of the data structures associated with it.\n */\n abstract destroy(): void;\n\n /**\n * A lifecycle hook that provides additional developer-defined cleanup\n * functionality for the component.\n * @param callback A handler function that cleans up developer-defined data\n * associated with this component. Called when the `destroy()` method is invoked.\n */\n abstract onDestroy(callback: Function): void;\n}\n\n/**\n * Base class for a factory that can create a component dynamically.\n * Instantiate a factory for a given type of component with `resolveComponentFactory()`.\n * Use the resulting `ComponentFactory.create()` method to create a component of that type.\n *\n * @see [Dynamic Components](guide/dynamic-component-loader)\n *\n * @publicApi\n *\n * @deprecated Angular no longer requires Component factories. Please use other APIs where\n * Component class can be used directly.\n */\nexport abstract class ComponentFactory<C> {\n /**\n * The component's HTML selector.\n */\n abstract get selector(): string;\n /**\n * The type of component the factory will create.\n */\n abstract get componentType(): Type<any>;\n /**\n * Selector for all <ng-content> elements in the component.\n */\n abstract get ngContentSelectors(): string[];\n /**\n * The inputs of the component.\n */\n abstract get inputs(): {propName: string, templateName: string}[];\n /**\n * The outputs of the component.\n */\n abstract get outputs(): {propName: string, templateName: string}[];\n /**\n * Creates a new component.\n */\n abstract create(\n injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any,\n environmentInjector?: EnvironmentInjector|NgModuleRef<any>): ComponentRef<C>;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '../interface/type';\nimport {stringify} from '../util/stringify';\n\nimport {ComponentFactory} from './component_factory';\n\nexport function noComponentFactoryError(component: Function) {\n const error = Error(`No component factory found for ${\n stringify(component)}. Did you add it to @NgModule.entryComponents?`);\n (error as any)[ERROR_COMPONENT] = component;\n return error;\n}\n\nconst ERROR_COMPONENT = 'ngComponent';\n\nexport function getComponent(error: Error): Type<any> {\n return (error as any)[ERROR_COMPONENT];\n}\n\n\nclass _NullComponentFactoryResolver implements ComponentFactoryResolver {\n resolveComponentFactory<T>(component: {new(...args: any[]): T}): ComponentFactory<T> {\n throw noComponentFactoryError(component);\n }\n}\n\n/**\n * A simple registry that maps `Components` to generated `ComponentFactory` classes\n * that can be used to create instances of components.\n * Use to obtain the factory for a given component type,\n * then use the factory's `create()` method to create a component of that type.\n *\n * Note: since v13, dynamic component creation via\n * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)\n * does **not** require resolving component factory: component class can be used directly.\n *\n * @publicApi\n *\n * @deprecated Angular no longer requires Component factories. Please use other APIs where\n * Component class can be used directly.\n */\nexport abstract class ComponentFactoryResolver {\n static NULL: ComponentFactoryResolver = (/* @__PURE__ */ new _NullComponentFactoryResolver());\n /**\n * Retrieves the factory object that creates a component of the given type.\n * @param component The component type.\n */\n abstract resolveComponentFactory<T>(component: Type<T>): ComponentFactory<T>;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {TNode} from '../render3/interfaces/node';\nimport {RElement} from '../render3/interfaces/renderer_dom';\nimport {LView} from '../render3/interfaces/view';\nimport {getCurrentTNode, getLView} from '../render3/state';\nimport {getNativeByTNode} from '../render3/util/view_utils';\n\n/**\n * Creates an ElementRef from the most recent node.\n *\n * @returns The ElementRef instance to use\n */\nexport function injectElementRef(): ElementRef {\n return createElementRef(getCurrentTNode()!, getLView());\n}\n\n/**\n * Creates an ElementRef given a node.\n *\n * @param tNode The node for which you'd like an ElementRef\n * @param lView The view to which the node belongs\n * @returns The ElementRef instance to use\n */\nexport function createElementRef(tNode: TNode, lView: LView): ElementRef {\n return new ElementRef(getNativeByTNode(tNode, lView) as RElement);\n}\n\n/**\n * A wrapper around a native element inside of a View.\n *\n * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM\n * element.\n *\n * @security Permitting direct access to the DOM can make your application more vulnerable to\n * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the\n * [Security Guide](https://g.co/ng/security).\n *\n * @publicApi\n */\n// Note: We don't expose things like `Injector`, `ViewContainer`, ... here,\n// i.e. users have to ask for what they need. With that, we can build better analysis tools\n// and could do better codegen in the future.\nexport class ElementRef<T = any> {\n /**\n * The underlying native element or `null` if direct access to native elements is not supported\n * (e.g. when the application runs in a web worker).\n *\n * <div class=\"callout is-critical\">\n * <header>Use with caution</header>\n * <p>\n * Use this API as the last resort when direct access to DOM is needed. Use templating and\n * data-binding provided by Angular instead. Alternatively you can take a look at {@link\n * Renderer2}\n * which provides API that can safely be used even when direct access to native elements is not\n * supported.\n * </p>\n * <p>\n * Relying on direct DOM access creates tight coupling between your application and rendering\n * layers which will make it impossible to separate the two and deploy your application into a\n * web worker.\n * </p>\n * </div>\n *\n */\n public nativeElement: T;\n\n constructor(nativeElement: T) {\n this.nativeElement = nativeElement;\n }\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__: () => ElementRef = injectElementRef;\n}\n\n/**\n * Unwraps `ElementRef` and return the `nativeElement`.\n *\n * @param value value to unwrap\n * @returns `nativeElement` if `ElementRef` otherwise returns value as is.\n */\nexport function unwrapElementRef<T, R>(value: T|ElementRef<R>): T|R {\n return value instanceof ElementRef ? value.nativeElement : value;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {isLView} from '../render3/interfaces/type_checks';\nimport {RENDERER} from '../render3/interfaces/view';\nimport {getCurrentTNode, getLView} from '../render3/state';\nimport {getComponentLViewByIndex} from '../render3/util/view_utils';\n\nimport {RendererStyleFlags2, RendererType2} from './api_flags';\n\n\n/**\n * Creates and initializes a custom renderer that implements the `Renderer2` base class.\n *\n * @publicApi\n */\nexport abstract class RendererFactory2 {\n /**\n * Creates and initializes a custom renderer for a host DOM element.\n * @param hostElement The element to render.\n * @param type The base class to implement.\n * @returns The new custom renderer instance.\n */\n abstract createRenderer(hostElement: any, type: RendererType2|null): Renderer2;\n /**\n * A callback invoked when rendering has begun.\n */\n abstract begin?(): void;\n /**\n * A callback invoked when rendering has completed.\n */\n abstract end?(): void;\n /**\n * Use with animations test-only mode. Notifies the test when rendering has completed.\n * @returns The asynchronous result of the developer-defined function.\n */\n abstract whenRenderingDone?(): Promise<any>;\n}\n\n\n/**\n * Extend this base class to implement custom rendering. By default, Angular\n * renders a template into DOM. You can use custom rendering to intercept\n * rendering calls, or to render to something other than DOM.\n *\n * Create your custom renderer using `RendererFactory2`.\n *\n * Use a custom renderer to bypass Angular's templating and\n * make custom UI changes that can't be expressed declaratively.\n * For example if you need to set a property or an attribute whose name is\n * not statically known, use the `setProperty()` or\n * `setAttribute()` method.\n *\n * @publicApi\n */\nexport abstract class Renderer2 {\n /**\n * Use to store arbitrary developer-defined data on a renderer instance,\n * as an object containing key-value pairs.\n * This is useful for renderers that delegate to other renderers.\n */\n abstract get data(): {[key: string]: any};\n\n /**\n * Implement this callback to destroy the renderer or the host element.\n */\n abstract destroy(): void;\n /**\n * Implement this callback to create an instance of the host element.\n * @param name An identifying name for the new element, unique within the namespace.\n * @param namespace The namespace for the new element.\n * @returns The new element.\n */\n abstract createElement(name: string, namespace?: string|null): any;\n /**\n * Implement this callback to add a comment to the DOM of the host element.\n * @param value The comment text.\n * @returns The modified element.\n */\n abstract createComment(value: string): any;\n\n /**\n * Implement this callback to add text to the DOM of the host element.\n * @param value The text string.\n * @returns The modified element.\n */\n abstract createText(value: string): any;\n /**\n * If null or undefined, the view engine won't call it.\n * This is used as a performance optimization for production mode.\n */\n // TODO(issue/24571): remove '!'.\n destroyNode!: ((node: any) => void)|null;\n /**\n * Appends a child to a given parent node in the host element DOM.\n * @param parent The parent node.\n * @param newChild The new child node.\n */\n abstract appendChild(parent: any, newChild: any): void;\n /**\n * Implement this callback to insert a child node at a given position in a parent node\n * in the host element DOM.\n * @param parent The parent node.\n * @param newChild The new child nodes.\n * @param refChild The existing child node before which `newChild` is inserted.\n * @param isMove Optional argument which signifies if the current `insertBefore` is a result of a\n * move. Animation uses this information to trigger move animations. In the past the Animation\n * would always assume that any `insertBefore` is a move. This is not strictly true because\n * with runtime i18n it is possible to invoke `insertBefore` as a result of i18n and it should\n * not trigger an animation move.\n */\n abstract insertBefore(parent: any, newChild: any, refChild: any, isMove?: boolean): void;\n /**\n * Implement this callback to remove a child node from the host element's DOM.\n * @param parent The parent node.\n * @param oldChild The child node to remove.\n * @param isHostElement Optionally signal to the renderer whether this element is a host element\n * or not\n */\n abstract removeChild(parent: any, oldChild: any, isHostElement?: boolean): void;\n /**\n * Implement this callback to prepare an element to be bootstrapped\n * as a root element, and return the element instance.\n * @param selectorOrNode The DOM element.\n * @param preserveContent Whether the contents of the root element\n * should be preserved, or cleared upon bootstrap (default behavior).\n * Use with `ViewEncapsulation.ShadowDom` to allow simple native\n * content projection via `<slot>` elements.\n * @returns The root element.\n */\n abstract selectRootElement(selectorOrNode: string|any, preserveContent?: boolean): any;\n /**\n * Implement this callback to get the parent of a given node\n * in the host element's DOM.\n * @param node The child node to query.\n * @returns The parent node, or null if there is no parent.\n * For WebWorkers, always returns true.\n * This is because the check is synchronous,\n * and the caller can't rely on checking for null.\n */\n abstract parentNode(node: any): any;\n /**\n * Implement this callback to get the next sibling node of a given node\n * in the host element's DOM.\n * @returns The sibling node, or null if there is no sibling.\n * For WebWorkers, always returns a value.\n * This is because the check is synchronous,\n * and the caller can't rely on checking for null.\n */\n abstract nextSibling(node: any): any;\n /**\n * Implement this callback to set an attribute value for an element in the DOM.\n * @param el The element.\n * @param name The attribute name.\n * @param value The new value.\n * @param namespace The namespace.\n */\n abstract setAttribute(el: any, name: string, value: string, namespace?: string|null): void;\n\n /**\n * Implement this callback to remove an attribute from an element in the DOM.\n * @param el The element.\n * @param name The attribute name.\n * @param namespace The namespace.\n */\n abstract removeAttribute(el: any, name: string, namespace?: string|null): void;\n /**\n * Implement this callback to add a class to an element in the DOM.\n * @param el The element.\n * @param name The class name.\n */\n abstract addClass(el: any, name: string): void;\n\n /**\n * Implement this callback to remove a class from an element in the DOM.\n * @param el The element.\n * @param name The class name.\n */\n abstract removeClass(el: any, name: string): void;\n\n /**\n * Implement this callback to set a CSS style for an element in the DOM.\n * @param el The element.\n * @param style The name of the style.\n * @param value The new value.\n * @param flags Flags for style variations. No flags are set by default.\n */\n abstract setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void;\n\n /**\n * Implement this callback to remove the value from a CSS style for an element in the DOM.\n * @param el The element.\n * @param style The name of the style.\n * @param flags Flags for style variations to remove, if set. ???\n */\n abstract removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void;\n\n /**\n * Implement this callback to set the value of a property of an element in the DOM.\n * @param el The element.\n * @param name The property name.\n * @param value The new value.\n */\n abstract setProperty(el: any, name: string, value: any): void;\n\n /**\n * Implement this callback to set the value of a node in the host element.\n * @param node The node.\n * @param value The new value.\n */\n abstract setValue(node: any, value: string): void;\n\n /**\n * Implement this callback to start an event listener.\n * @param target The context in which to listen for events. Can be\n * the entire window or document, the body of the document, or a specific\n * DOM element.\n * @param eventName The event to listen for.\n * @param callback A handler function to invoke when the event occurs.\n * @returns An \"unlisten\" function for disposing of this handler.\n */\n abstract listen(\n target: 'window'|'document'|'body'|any, eventName: string,\n callback: (event: any) => boolean | void): () => void;\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__: () => Renderer2 = () => injectRenderer2();\n}\n\n/** Injects a Renderer2 for the current component. */\nexport function injectRenderer2(): Renderer2 {\n // We need the Renderer to be based on the component that it's being injected into, however since\n // DI happens before we've entered its view, `getLView` will return the parent view instead.\n const lView = getLView();\n const tNode = getCurrentTNode()!;\n const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);\n return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER] as Renderer2;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵɵdefineInjectable} from '../di/interface/defs';\nimport {SecurityContext} from './security';\n\n/**\n * Sanitizer is used by the views to sanitize potentially dangerous values.\n *\n * @publicApi\n */\nexport abstract class Sanitizer {\n abstract sanitize(context: SecurityContext, value: {}|string|null): string|null;\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable({\n token: Sanitizer,\n providedIn: 'root',\n factory: () => null,\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @description Represents the version of Angular\n *\n * @publicApi\n */\nexport class Version {\n public readonly major: string;\n public readonly minor: string;\n public readonly patch: string;\n\n constructor(public full: string) {\n this.major = full.split('.')[0];\n this.minor = full.split('.')[1];\n this.patch = full.split('.').slice(2).join('.');\n }\n}\n\n/**\n * @publicApi\n */\nexport const VERSION = new Version('15.2.9');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// This default value is when checking the hierarchy for a token.\n//\n// It means both:\n// - the token is not provided by the current injector,\n// - only the element injectors should be checked (ie do not check module injectors\n//\n// mod1\n// /\n// el1 mod2\n// \\ /\n// el2\n//\n// When requesting el2.injector.get(token), we should check in the following order and return the\n// first found value:\n// - el2.injector.get(token, default)\n// - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module\n// - mod2.injector.get(token, default)\nexport const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const ERROR_ORIGINAL_ERROR = 'ngOriginalError';\n\nexport function wrappedError(message: string, originalError: any): Error {\n const msg = `${message} caused by: ${\n originalError instanceof Error ? originalError.message : originalError}`;\n const error = Error(msg);\n (error as any)[ERROR_ORIGINAL_ERROR] = originalError;\n return error;\n}\n\nexport function getOriginalError(error: Error): Error {\n return (error as any)[ERROR_ORIGINAL_ERROR];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {getOriginalError} from './util/errors';\n\n/**\n * Provides a hook for centralized exception handling.\n *\n * The default implementation of `ErrorHandler` prints error messages to the `console`. To\n * intercept error handling, write a custom exception handler that replaces this default as\n * appropriate for your app.\n *\n * @usageNotes\n * ### Example\n *\n * ```\n * class MyErrorHandler implements ErrorHandler {\n * handleError(error) {\n * // do something with the exception\n * }\n * }\n *\n * @NgModule({\n * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]\n * })\n * class MyModule {}\n * ```\n *\n * @publicApi\n */\nexport class ErrorHandler {\n /**\n * @internal\n */\n _console: Console = console;\n\n handleError(error: any): void {\n const originalError = this._findOriginalError(error);\n\n this._console.error('ERROR', error);\n if (originalError) {\n this._console.error('ORIGINAL ERROR', originalError);\n }\n }\n\n /** @internal */\n _findOriginalError(error: any): Error|null {\n let e = error && getOriginalError(error);\n while (e && getOriginalError(e)) {\n e = getOriginalError(e);\n }\n\n return e || null;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RElement} from '../interfaces/renderer_dom';\n\n\n/**\n *\n * @codeGenApi\n */\nexport function ɵɵresolveWindow(element: RElement&{ownerDocument: Document}) {\n return element.ownerDocument.defaultView;\n}\n\n/**\n *\n * @codeGenApi\n */\nexport function ɵɵresolveDocument(element: RElement&{ownerDocument: Document}) {\n return element.ownerDocument;\n}\n\n/**\n *\n * @codeGenApi\n */\nexport function ɵɵresolveBody(element: RElement&{ownerDocument: Document}) {\n return element.ownerDocument.body;\n}\n\n/**\n * The special delimiter we use to separate property names, prefixes, and suffixes\n * in property binding metadata. See storeBindingMetadata().\n *\n * We intentionally use the Unicode \"REPLACEMENT CHARACTER\" (U+FFFD) as a delimiter\n * because it is a very uncommon character that is unlikely to be part of a user's\n * property names or interpolation strings. If it is in fact used in a property\n * binding, DebugElement.properties will not return the correct value for that\n * binding. However, there should be no runtime effect for real applications.\n *\n * This character is typically rendered as a question mark inside of a diamond.\n * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)\n *\n */\nexport const INTERPOLATION_DELIMITER = `�`;\n\n/**\n * Unwrap a value which might be behind a closure (for forward declaration reasons).\n */\nexport function maybeUnwrapFn<T>(value: T|(() => T)): T {\n if (value instanceof Function) {\n return value();\n } else {\n return value;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertNotEqual} from '../../util/assert';\nimport {CharCode} from '../../util/char_code';\n\n\n/**\n * Returns an index of `classToSearch` in `className` taking token boundaries into account.\n *\n * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)\n *\n * @param className A string containing classes (whitespace separated)\n * @param classToSearch A class name to locate\n * @param startingIndex Starting location of search\n * @returns an index of the located class (or -1 if not found)\n */\nexport function classIndexOf(\n className: string, classToSearch: string, startingIndex: number): number {\n ngDevMode && assertNotEqual(classToSearch, '', 'can not look for \"\" string.');\n let end = className.length;\n while (true) {\n const foundIndex = className.indexOf(classToSearch, startingIndex);\n if (foundIndex === -1) return foundIndex;\n if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= CharCode.SPACE) {\n // Ensure that it has leading whitespace\n const length = classToSearch.length;\n if (foundIndex + length === end ||\n className.charCodeAt(foundIndex + length) <= CharCode.SPACE) {\n // Ensure that it has trailing whitespace\n return foundIndex;\n }\n }\n // False positive, keep searching from where we left off.\n startingIndex = foundIndex + 1;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport '../util/ng_dev_mode';\n\nimport {assertDefined, assertEqual, assertNotEqual} from '../util/assert';\n\nimport {AttributeMarker, TAttributes, TNode, TNodeType} from './interfaces/node';\nimport {CssSelector, CssSelectorList, SelectorFlags} from './interfaces/projection';\nimport {classIndexOf} from './styling/class_differ';\nimport {isNameOnlyAttributeMarker} from './util/attrs_utils';\n\nconst NG_TEMPLATE_SELECTOR = 'ng-template';\n\n/**\n * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)\n *\n * @param attrs `TAttributes` to search through.\n * @param cssClassToMatch class to match (lowercase)\n * @param isProjectionMode Whether or not class matching should look into the attribute `class` in\n * addition to the `AttributeMarker.Classes`.\n */\nfunction isCssClassMatching(\n attrs: TAttributes, cssClassToMatch: string, isProjectionMode: boolean): boolean {\n // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.\n // It is strange to me that sometimes the class information comes in form of `class` attribute\n // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine\n // if that is the right behavior.\n ngDevMode &&\n assertEqual(\n cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');\n let i = 0;\n // Indicates whether we are processing value from the implicit\n // attribute section (i.e. before the first marker in the array).\n let isImplicitAttrsSection = true;\n while (i < attrs.length) {\n let item = attrs[i++];\n if (typeof item === 'string' && isImplicitAttrsSection) {\n const value = attrs[i++] as string;\n if (isProjectionMode && item === 'class') {\n // We found a `class` attribute in the implicit attribute section,\n // check if it matches the value of the `cssClassToMatch` argument.\n if (classIndexOf(value.toLowerCase(), cssClassToMatch, 0) !== -1) {\n return true;\n }\n }\n } else if (item === AttributeMarker.Classes) {\n // We found the classes section. Start searching for the class.\n while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {\n // while we have strings\n if (item.toLowerCase() === cssClassToMatch) return true;\n }\n return false;\n } else if (typeof item === 'number') {\n // We've came across a first marker, which indicates\n // that the implicit attribute section is over.\n isImplicitAttrsSection = false;\n }\n }\n return false;\n}\n\n/**\n * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).\n *\n * @param tNode current TNode\n */\nexport function isInlineTemplate(tNode: TNode): boolean {\n return tNode.type === TNodeType.Container && tNode.value !== NG_TEMPLATE_SELECTOR;\n}\n\n/**\n * Function that checks whether a given tNode matches tag-based selector and has a valid type.\n *\n * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular\n * directive matching mode:\n * - in the \"directive matching\" mode we do _not_ take TContainer's tagName into account if it is\n * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a\n * tag name was extracted from * syntax so we would match the same directive twice);\n * - in the \"projection\" mode, we use a tag name potentially extracted from the * syntax processing\n * (applicable to TNodeType.Container only).\n */\nfunction hasTagAndTypeMatch(\n tNode: TNode, currentSelector: string, isProjectionMode: boolean): boolean {\n const tagNameToCompare =\n tNode.type === TNodeType.Container && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;\n return currentSelector === tagNameToCompare;\n}\n\n/**\n * A utility function to match an Ivy node static data against a simple CSS selector\n *\n * @param node static data of the node to match\n * @param selector The selector to try matching against the node.\n * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing\n * directive matching.\n * @returns true if node matches the selector.\n */\nexport function isNodeMatchingSelector(\n tNode: TNode, selector: CssSelector, isProjectionMode: boolean): boolean {\n ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');\n let mode: SelectorFlags = SelectorFlags.ELEMENT;\n const nodeAttrs = tNode.attrs || [];\n\n // Find the index of first attribute that has no value, only a name.\n const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);\n\n // When processing \":not\" selectors, we skip to the next \":not\" if the\n // current one doesn't match\n let skipToNextSelector = false;\n\n for (let i = 0; i < selector.length; i++) {\n const current = selector[i];\n if (typeof current === 'number') {\n // If we finish processing a :not selector and it hasn't failed, return false\n if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {\n return false;\n }\n // If we are skipping to the next :not() and this mode flag is positive,\n // it's a part of the current :not() selector, and we should keep skipping\n if (skipToNextSelector && isPositive(current)) continue;\n skipToNextSelector = false;\n mode = (current as number) | (mode & SelectorFlags.NOT);\n continue;\n }\n\n if (skipToNextSelector) continue;\n\n if (mode & SelectorFlags.ELEMENT) {\n mode = SelectorFlags.ATTRIBUTE | mode & SelectorFlags.NOT;\n if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||\n current === '' && selector.length === 1) {\n if (isPositive(mode)) return false;\n skipToNextSelector = true;\n }\n } else {\n const selectorAttrValue = mode & SelectorFlags.CLASS ? current : selector[++i];\n\n // special case for matching against classes when a tNode has been instantiated with\n // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])\n if ((mode & SelectorFlags.CLASS) && tNode.attrs !== null) {\n if (!isCssClassMatching(tNode.attrs, selectorAttrValue as string, isProjectionMode)) {\n if (isPositive(mode)) return false;\n skipToNextSelector = true;\n }\n continue;\n }\n\n const attrName = (mode & SelectorFlags.CLASS) ? 'class' : current;\n const attrIndexInNode =\n findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);\n\n if (attrIndexInNode === -1) {\n if (isPositive(mode)) return false;\n skipToNextSelector = true;\n continue;\n }\n\n if (selectorAttrValue !== '') {\n let nodeAttrValue: string;\n if (attrIndexInNode > nameOnlyMarkerIdx) {\n nodeAttrValue = '';\n } else {\n ngDevMode &&\n assertNotEqual(\n nodeAttrs[attrIndexInNode], AttributeMarker.NamespaceURI,\n 'We do not match directives on namespaced attributes');\n // we lowercase the attribute value to be able to match\n // selectors without case-sensitivity\n // (selectors are already in lowercase when generated)\n nodeAttrValue = (nodeAttrs[attrIndexInNode + 1] as string).toLowerCase();\n }\n\n const compareAgainstClassName = mode & SelectorFlags.CLASS ? nodeAttrValue : null;\n if (compareAgainstClassName &&\n classIndexOf(compareAgainstClassName, selectorAttrValue as string, 0) !== -1 ||\n mode & SelectorFlags.ATTRIBUTE && selectorAttrValue !== nodeAttrValue) {\n if (isPositive(mode)) return false;\n skipToNextSelector = true;\n }\n }\n }\n }\n\n return isPositive(mode) || skipToNextSelector;\n}\n\nfunction isPositive(mode: SelectorFlags): boolean {\n return (mode & SelectorFlags.NOT) === 0;\n}\n\n/**\n * Examines the attribute's definition array for a node to find the index of the\n * attribute that matches the given `name`.\n *\n * NOTE: This will not match namespaced attributes.\n *\n * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.\n * The following table summarizes which types of attributes we attempt to match:\n *\n * ===========================================================================================================\n * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n\n * Attributes\n * ===========================================================================================================\n * Inline + Projection | YES | YES | NO | YES\n * -----------------------------------------------------------------------------------------------------------\n * Inline + Directive | NO | NO | YES | NO\n * -----------------------------------------------------------------------------------------------------------\n * Non-inline + Projection | YES | YES | NO | YES\n * -----------------------------------------------------------------------------------------------------------\n * Non-inline + Directive | YES | YES | NO | YES\n * ===========================================================================================================\n *\n * @param name the name of the attribute to find\n * @param attrs the attribute array to examine\n * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)\n * rather than a manually expanded template node (e.g `<ng-template>`).\n * @param isProjectionMode true if we are matching against content projection otherwise we are\n * matching against directives.\n */\nfunction findAttrIndexInNode(\n name: string, attrs: TAttributes|null, isInlineTemplate: boolean,\n isProjectionMode: boolean): number {\n if (attrs === null) return -1;\n\n let i = 0;\n\n if (isProjectionMode || !isInlineTemplate) {\n let bindingsMode = false;\n while (i < attrs.length) {\n const maybeAttrName = attrs[i];\n if (maybeAttrName === name) {\n return i;\n } else if (\n maybeAttrName === AttributeMarker.Bindings || maybeAttrName === AttributeMarker.I18n) {\n bindingsMode = true;\n } else if (\n maybeAttrName === AttributeMarker.Classes || maybeAttrName === AttributeMarker.Styles) {\n let value = attrs[++i];\n // We should skip classes here because we have a separate mechanism for\n // matching classes in projection mode.\n while (typeof value === 'string') {\n value = attrs[++i];\n }\n continue;\n } else if (maybeAttrName === AttributeMarker.Template) {\n // We do not care about Template attributes in this scenario.\n break;\n } else if (maybeAttrName === AttributeMarker.NamespaceURI) {\n // Skip the whole namespaced attribute and value. This is by design.\n i += 4;\n continue;\n }\n // In binding mode there are only names, rather than name-value pairs.\n i += bindingsMode ? 1 : 2;\n }\n // We did not match the attribute\n return -1;\n } else {\n return matchTemplateAttribute(attrs, name);\n }\n}\n\nexport function isNodeMatchingSelectorList(\n tNode: TNode, selector: CssSelectorList, isProjectionMode: boolean = false): boolean {\n for (let i = 0; i < selector.length; i++) {\n if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getProjectAsAttrValue(tNode: TNode): CssSelector|null {\n const nodeAttrs = tNode.attrs;\n if (nodeAttrs != null) {\n const ngProjectAsAttrIdx = nodeAttrs.indexOf(AttributeMarker.ProjectAs);\n // only check for ngProjectAs in attribute names, don't accidentally match attribute's value\n // (attribute names are stored at even indexes)\n if ((ngProjectAsAttrIdx & 1) === 0) {\n return nodeAttrs[ngProjectAsAttrIdx + 1] as CssSelector;\n }\n }\n return null;\n}\n\nfunction getNameOnlyMarkerIndex(nodeAttrs: TAttributes) {\n for (let i = 0; i < nodeAttrs.length; i++) {\n const nodeAttr = nodeAttrs[i];\n if (isNameOnlyAttributeMarker(nodeAttr)) {\n return i;\n }\n }\n return nodeAttrs.length;\n}\n\nfunction matchTemplateAttribute(attrs: TAttributes, name: string): number {\n let i = attrs.indexOf(AttributeMarker.Template);\n if (i > -1) {\n i++;\n while (i < attrs.length) {\n const attr = attrs[i];\n // Return in case we checked all template attrs and are switching to the next section in the\n // attrs array (that starts with a number that represents an attribute marker).\n if (typeof attr === 'number') return -1;\n if (attr === name) return i;\n i++;\n }\n }\n return -1;\n}\n\n/**\n * Checks whether a selector is inside a CssSelectorList\n * @param selector Selector to be checked.\n * @param list List in which to look for the selector.\n */\nexport function isSelectorInSelectorList(selector: CssSelector, list: CssSelectorList): boolean {\n selectorListLoop: for (let i = 0; i < list.length; i++) {\n const currentSelectorInList = list[i];\n if (selector.length !== currentSelectorInList.length) {\n continue;\n }\n for (let j = 0; j < selector.length; j++) {\n if (selector[j] !== currentSelectorInList[j]) {\n continue selectorListLoop;\n }\n }\n return true;\n }\n return false;\n}\n\nfunction maybeWrapInNotSelector(isNegativeMode: boolean, chunk: string): string {\n return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;\n}\n\nfunction stringifyCSSSelector(selector: CssSelector): string {\n let result = selector[0] as string;\n let i = 1;\n let mode = SelectorFlags.ATTRIBUTE;\n let currentChunk = '';\n let isNegativeMode = false;\n while (i < selector.length) {\n let valueOrMarker = selector[i];\n if (typeof valueOrMarker === 'string') {\n if (mode & SelectorFlags.ATTRIBUTE) {\n const attrValue = selector[++i] as string;\n currentChunk +=\n '[' + valueOrMarker + (attrValue.length > 0 ? '=\"' + attrValue + '\"' : '') + ']';\n } else if (mode & SelectorFlags.CLASS) {\n currentChunk += '.' + valueOrMarker;\n } else if (mode & SelectorFlags.ELEMENT) {\n currentChunk += ' ' + valueOrMarker;\n }\n } else {\n //\n // Append current chunk to the final result in case we come across SelectorFlag, which\n // indicates that the previous section of a selector is over. We need to accumulate content\n // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.\n // ```\n // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']\n // ```\n // should be transformed to `.classA :not(.classB .classC)`.\n //\n // Note: for negative selector part, we accumulate content between flags until we find the\n // next negative flag. This is needed to support a case where `:not()` rule contains more than\n // one chunk, e.g. the following selector:\n // ```\n // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']\n // ```\n // should be stringified to `:not(p.foo) :not(.bar)`\n //\n if (currentChunk !== '' && !isPositive(valueOrMarker)) {\n result += maybeWrapInNotSelector(isNegativeMode, currentChunk);\n currentChunk = '';\n }\n mode = valueOrMarker;\n // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative\n // mode is maintained for remaining chunks of a selector.\n isNegativeMode = isNegativeMode || !isPositive(mode);\n }\n i++;\n }\n if (currentChunk !== '') {\n result += maybeWrapInNotSelector(isNegativeMode, currentChunk);\n }\n return result;\n}\n\n/**\n * Generates string representation of CSS selector in parsed form.\n *\n * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing\n * additional parsing at runtime (for example, for directive matching). However in some cases (for\n * example, while bootstrapping a component), a string version of the selector is required to query\n * for the host element on the page. This function takes the parsed form of a selector and returns\n * its string representation.\n *\n * @param selectorList selector in parsed form\n * @returns string representation of a given selector\n */\nexport function stringifyCSSSelectorList(selectorList: CssSelectorList): string {\n return selectorList.map(stringifyCSSSelector).join(',');\n}\n\n/**\n * Extracts attributes and classes information from a given CSS selector.\n *\n * This function is used while creating a component dynamically. In this case, the host element\n * (that is created dynamically) should contain attributes and classes specified in component's CSS\n * selector.\n *\n * @param selector CSS selector in parsed form (in a form of array)\n * @returns object with `attrs` and `classes` fields that contain extracted information\n */\nexport function extractAttrsAndClassesFromSelector(selector: CssSelector):\n {attrs: string[], classes: string[]} {\n const attrs: string[] = [];\n const classes: string[] = [];\n let i = 1;\n let mode = SelectorFlags.ATTRIBUTE;\n while (i < selector.length) {\n let valueOrMarker = selector[i];\n if (typeof valueOrMarker === 'string') {\n if (mode === SelectorFlags.ATTRIBUTE) {\n if (valueOrMarker !== '') {\n attrs.push(valueOrMarker, selector[++i] as string);\n }\n } else if (mode === SelectorFlags.CLASS) {\n classes.push(valueOrMarker);\n }\n } else {\n // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative\n // mode is maintained for remaining chunks of a selector. Since attributes and classes are\n // extracted only for \"positive\" part of the selector, we can stop here.\n if (!isPositive(mode)) break;\n mode = valueOrMarker;\n }\n i++;\n }\n return {attrs, classes};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport interface NO_CHANGE {\n // This is a brand that ensures that this type can never match anything else\n __brand__: 'NO_CHANGE';\n}\n\n/** A special value which designates that a value has not changed. */\nexport const NO_CHANGE: NO_CHANGE =\n (typeof ngDevMode === 'undefined' || ngDevMode) ? {__brand__: 'NO_CHANGE'} : ({} as NO_CHANGE);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {assertGreaterThan} from '../../util/assert';\nimport {assertIndexInDeclRange} from '../assert';\nimport {executeCheckHooks, executeInitAndCheckHooks} from '../hooks';\nimport {FLAGS, InitPhaseState, LView, LViewFlags, TView} from '../interfaces/view';\nimport {getLView, getSelectedIndex, getTView, isInCheckNoChangesMode, setSelectedIndex} from '../state';\n\n\n/**\n * Advances to an element for later binding instructions.\n *\n * Used in conjunction with instructions like {@link property} to act on elements with specified\n * indices, for example those created with {@link element} or {@link elementStart}.\n *\n * ```ts\n * (rf: RenderFlags, ctx: any) => {\n * if (rf & 1) {\n * text(0, 'Hello');\n * text(1, 'Goodbye')\n * element(2, 'div');\n * }\n * if (rf & 2) {\n * advance(2); // Advance twice to the <div>.\n * property('title', 'test');\n * }\n * }\n * ```\n * @param delta Number of elements to advance forwards by.\n *\n * @codeGenApi\n */\nexport function ɵɵadvance(delta: number): void {\n ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward');\n selectIndexInternal(\n getTView(), getLView(), getSelectedIndex() + delta, !!ngDevMode && isInCheckNoChangesMode());\n}\n\nexport function selectIndexInternal(\n tView: TView, lView: LView, index: number, checkNoChangesMode: boolean) {\n ngDevMode && assertIndexInDeclRange(lView, index);\n\n // Flush the initial hooks for elements in the view that have been added up to this point.\n // PERF WARNING: do NOT extract this to a separate function without running benchmarks\n if (!checkNoChangesMode) {\n const hooksInitPhaseCompleted =\n (lView[FLAGS] & LViewFlags.InitPhaseStateMask) === InitPhaseState.InitPhaseCompleted;\n if (hooksInitPhaseCompleted) {\n const preOrderCheckHooks = tView.preOrderCheckHooks;\n if (preOrderCheckHooks !== null) {\n executeCheckHooks(lView, preOrderCheckHooks, index);\n }\n } else {\n const preOrderHooks = tView.preOrderHooks;\n if (preOrderHooks !== null) {\n executeInitAndCheckHooks(lView, preOrderHooks, InitPhaseState.OnInitHooksToBeRun, index);\n }\n }\n }\n\n // We must set the selected index *after* running the hooks, because hooks may have side-effects\n // that cause other template functions to run, thus updating the selected index, which is global\n // state. If we run `setSelectedIndex` *before* we run the hooks, in some cases the selected index\n // will be altered by the time we leave the `ɵɵadvance` instruction.\n setSelectedIndex(index);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EMPTY_ARRAY} from '../util/empty';\nimport {stringify} from '../util/stringify';\n\nimport {Injector} from './injector';\nimport {StaticProvider} from './interface/provider';\nimport {importProvidersFrom} from './provider_collection';\nimport {getNullInjector, R3Injector} from './r3_injector';\nimport {InjectorScope} from './scope';\n\n/**\n * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.\n *\n * @publicApi\n */\nexport function createInjector(\n defType: /* InjectorType<any> */ any, parent: Injector|null = null,\n additionalProviders: StaticProvider[]|null = null, name?: string): Injector {\n const injector =\n createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);\n injector.resolveInjectorInitializers();\n return injector;\n}\n\n/**\n * Creates a new injector without eagerly resolving its injector types. Can be used in places\n * where resolving the injector types immediately can lead to an infinite loop. The injector types\n * should be resolved at a later point by calling `_resolveInjectorDefTypes`.\n */\nexport function createInjectorWithoutInjectorInstances(\n defType: /* InjectorType<any> */ any, parent: Injector|null = null,\n additionalProviders: StaticProvider[]|null = null, name?: string,\n scopes = new Set<InjectorScope>()): R3Injector {\n const providers = [\n additionalProviders || EMPTY_ARRAY,\n importProvidersFrom(defType),\n ];\n name = name || (typeof defType === 'object' ? undefined : stringify(defType));\n\n return new R3Injector(providers, parent || getNullInjector(), name || null, scopes);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {createInjector} from './create_injector';\nimport {THROW_IF_NOT_FOUND, ɵɵinject} from './injector_compatibility';\nimport {InjectorMarkers} from './injector_marker';\nimport {INJECTOR} from './injector_token';\nimport {ɵɵdefineInjectable} from './interface/defs';\nimport {InjectFlags, InjectOptions} from './interface/injector';\nimport {StaticProvider} from './interface/provider';\nimport {NullInjector} from './null_injector';\nimport {ProviderToken} from './provider_token';\n\n/**\n * Concrete injectors implement this interface. Injectors are configured\n * with [providers](guide/glossary#provider) that associate\n * dependencies of various types with [injection tokens](guide/glossary#di-token).\n *\n * @see [\"DI Providers\"](guide/dependency-injection-providers).\n * @see `StaticProvider`\n *\n * @usageNotes\n *\n * The following example creates a service injector instance.\n *\n * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'}\n *\n * ### Usage example\n *\n * {@example core/di/ts/injector_spec.ts region='Injector'}\n *\n * `Injector` returns itself when given `Injector` as a token:\n *\n * {@example core/di/ts/injector_spec.ts region='injectInjector'}\n *\n * @publicApi\n */\nexport abstract class Injector {\n static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;\n static NULL: Injector = (/* @__PURE__ */ new NullInjector());\n\n /**\n * Internal note on the `options?: InjectOptions|InjectFlags` override of the `get`\n * method: consider dropping the `InjectFlags` part in one of the major versions.\n * It can **not** be done in minor/patch, since it's breaking for custom injectors\n * that only implement the old `InjectorFlags` interface.\n */\n\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue: undefined, options: InjectOptions&{\n optional?: false;\n }): T;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue: null|undefined, options: InjectOptions): T\n |null;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue?: T, options?: InjectOptions|InjectFlags):\n T;\n /**\n * Retrieves an instance from the injector based on the provided token.\n * @returns The instance from the injector if defined, otherwise the `notFoundValue`.\n * @throws When the `notFoundValue` is `undefined` or `Injector.THROW_IF_NOT_FOUND`.\n * @deprecated use object-based flags (`InjectOptions`) instead.\n */\n abstract get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T;\n /**\n * @deprecated from v4.0.0 use ProviderToken<T>\n * @suppress {duplicate}\n */\n abstract get(token: any, notFoundValue?: any): any;\n\n /**\n * @deprecated from v5 use the new signature Injector.create(options)\n */\n static create(providers: StaticProvider[], parent?: Injector): Injector;\n\n /**\n * Creates a new injector instance that provides one or more dependencies,\n * according to a given type or types of `StaticProvider`.\n *\n * @param options An object with the following properties:\n * * `providers`: An array of providers of the [StaticProvider type](api/core/StaticProvider).\n * * `parent`: (optional) A parent injector.\n * * `name`: (optional) A developer-defined identifying name for the new injector.\n *\n * @returns The new injector instance.\n *\n */\n static create(options: {providers: StaticProvider[], parent?: Injector, name?: string}): Injector;\n\n\n static create(\n options: StaticProvider[]|{providers: StaticProvider[], parent?: Injector, name?: string},\n parent?: Injector): Injector {\n if (Array.isArray(options)) {\n return createInjector({name: ''}, parent, options, '');\n } else {\n const name = options.name ?? '';\n return createInjector({name}, options.parent, options.providers, name);\n }\n }\n\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable({\n token: Injector,\n providedIn: 'any',\n factory: () => ɵɵinject(INJECTOR),\n });\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__ = InjectorMarkers.Injector;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {InjectFlags, resolveForwardRef} from '../../di';\nimport {assertInjectImplementationNotEqual} from '../../di/inject_switch';\nimport {ɵɵinject} from '../../di/injector_compatibility';\nimport {ProviderToken} from '../../di/provider_token';\nimport {getOrCreateInjectable} from '../di';\nimport {TDirectiveHostNode} from '../interfaces/node';\nimport {getCurrentTNode, getLView} from '../state';\n\n/**\n * Returns the value associated to the given token from the injectors.\n *\n * `directiveInject` is intended to be used for directive, component and pipe factories.\n * All other injection use `inject` which does not walk the node injector tree.\n *\n * Usage example (in factory function):\n *\n * ```ts\n * class SomeDirective {\n * constructor(directive: DirectiveA) {}\n *\n * static ɵdir = ɵɵdefineDirective({\n * type: SomeDirective,\n * factory: () => new SomeDirective(ɵɵdirectiveInject(DirectiveA))\n * });\n * }\n * ```\n * @param token the type or token to inject\n * @param flags Injection flags\n * @returns the value from the injector or `null` when not found\n *\n * @codeGenApi\n */\nexport function ɵɵdirectiveInject<T>(token: ProviderToken<T>): T;\nexport function ɵɵdirectiveInject<T>(token: ProviderToken<T>, flags: InjectFlags): T;\nexport function ɵɵdirectiveInject<T>(token: ProviderToken<T>, flags = InjectFlags.Default): T|null {\n const lView = getLView();\n // Fall back to inject() if view hasn't been created. This situation can happen in tests\n // if inject utilities are used before bootstrapping.\n if (lView === null) {\n // Verify that we will not get into infinite loop.\n ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);\n return ɵɵinject(token, flags);\n }\n const tNode = getCurrentTNode();\n return getOrCreateInjectable<T>(\n tNode as TDirectiveHostNode, lView, resolveForwardRef(token), flags);\n}\n\n/**\n * Throws an error indicating that a factory function could not be generated by the compiler for a\n * particular class.\n *\n * This instruction allows the actual error message to be optimized away when ngDevMode is turned\n * off, saving bytes of generated code while still providing a good experience in dev mode.\n *\n * The name of the class is not mentioned here, but will be in the generated factory function name\n * and thus in the stack trace.\n *\n * @codeGenApi\n */\nexport function ɵɵinvalidFactory(): never {\n const msg =\n ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';\n throw new Error(msg);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../../di/injector';\nimport {ErrorHandler} from '../../error_handler';\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {DoCheck, OnChanges, OnInit} from '../../interface/lifecycle_hooks';\nimport {SchemaMetadata} from '../../metadata/schema';\nimport {ViewEncapsulation} from '../../metadata/view';\nimport {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';\nimport {Sanitizer} from '../../sanitization/sanitizer';\nimport {assertDefined, assertEqual, assertGreaterThan, assertGreaterThanOrEqual, assertIndexInRange, assertNotEqual, assertNotSame, assertSame, assertString} from '../../util/assert';\nimport {escapeCommentText} from '../../util/dom';\nimport {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';\nimport {stringify} from '../../util/stringify';\nimport {assertFirstCreatePass, assertFirstUpdatePass, assertLContainer, assertLView, assertTNodeForLView, assertTNodeForTView} from '../assert';\nimport {attachPatchData} from '../context_discovery';\nimport {getFactoryDef} from '../definition_factory';\nimport {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';\nimport {throwMultipleComponentError} from '../errors';\nimport {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags} from '../hooks';\nimport {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS} from '../interfaces/container';\nimport {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, HostBindingsFunction, HostDirectiveBindingMap, HostDirectiveDefs, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition';\nimport {NodeInjectorFactory} from '../interfaces/injector';\nimport {getUniqueLViewId} from '../interfaces/lview_tracking';\nimport {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliases, PropertyAliasValue, TAttributes, TConstantsOrFactory, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from '../interfaces/node';\nimport {Renderer, RendererFactory} from '../interfaces/renderer';\nimport {RComment, RElement, RNode, RText} from '../interfaces/renderer_dom';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {isComponentDef, isComponentHost, isContentQueryHost, isRootView} from '../interfaces/type_checks';\nimport {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, EMBEDDED_VIEW_INJECTOR, FLAGS, HEADER_OFFSET, HOST, HostBindingOpCodes, ID, InitPhaseState, INJECTOR, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, SANITIZER, T_HOST, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TVIEW, TView, TViewType} from '../interfaces/view';\nimport {assertPureTNodeType, assertTNodeType} from '../node_assert';\nimport {updateTextNode} from '../node_manipulation';\nimport {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher';\nimport {profiler, ProfilerEvent} from '../profiler';\nimport {enterView, getBindingsEnabled, getCurrentDirectiveIndex, getCurrentParentTNode, getCurrentTNode, getCurrentTNodePlaceholderOk, getSelectedIndex, isCurrentTNodeParent, isInCheckNoChangesMode, isInI18nBlock, leaveView, setBindingIndex, setBindingRootForHostBindings, setCurrentDirectiveIndex, setCurrentQueryIndex, setCurrentTNode, setIsInCheckNoChangesMode, setSelectedIndex} from '../state';\nimport {NO_CHANGE} from '../tokens';\nimport {mergeHostAttrs} from '../util/attrs_utils';\nimport {INTERPOLATION_DELIMITER} from '../util/misc_utils';\nimport {renderStringify, stringifyForError} from '../util/stringify_utils';\nimport {getFirstLContainer, getLViewParent, getNextLContainer} from '../util/view_traversal_utils';\nimport {getComponentLViewByIndex, getNativeByIndex, getNativeByTNode, isCreationMode, resetPreOrderHookFlags, unwrapLView, updateTransplantedViewCount, viewAttachedToChangeDetector} from '../util/view_utils';\n\nimport {selectIndexInternal} from './advance';\nimport {ɵɵdirectiveInject} from './di';\nimport {handleUnknownPropertyError, isPropertyValid, matchingSchemas} from './element_validation';\n\n/**\n * Invoke `HostBindingsFunction`s for view.\n *\n * This methods executes `TView.hostBindingOpCodes`. It is used to execute the\n * `HostBindingsFunction`s associated with the current `LView`.\n *\n * @param tView Current `TView`.\n * @param lView Current `LView`.\n */\nexport function processHostBindingOpCodes(tView: TView, lView: LView): void {\n const hostBindingOpCodes = tView.hostBindingOpCodes;\n if (hostBindingOpCodes === null) return;\n try {\n for (let i = 0; i < hostBindingOpCodes.length; i++) {\n const opCode = hostBindingOpCodes[i] as number;\n if (opCode < 0) {\n // Negative numbers are element indexes.\n setSelectedIndex(~opCode);\n } else {\n // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex.\n const directiveIdx = opCode;\n const bindingRootIndx = hostBindingOpCodes[++i] as number;\n const hostBindingFn = hostBindingOpCodes[++i] as HostBindingsFunction<any>;\n setBindingRootForHostBindings(bindingRootIndx, directiveIdx);\n const context = lView[directiveIdx];\n hostBindingFn(RenderFlags.Update, context);\n }\n }\n } finally {\n setSelectedIndex(-1);\n }\n}\n\n\n/** Refreshes all content queries declared by directives in a given view */\nfunction refreshContentQueries(tView: TView, lView: LView): void {\n const contentQueries = tView.contentQueries;\n if (contentQueries !== null) {\n for (let i = 0; i < contentQueries.length; i += 2) {\n const queryStartIdx = contentQueries[i];\n const directiveDefIdx = contentQueries[i + 1];\n if (directiveDefIdx !== -1) {\n const directiveDef = tView.data[directiveDefIdx] as DirectiveDef<any>;\n ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.');\n ngDevMode &&\n assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined');\n setCurrentQueryIndex(queryStartIdx);\n directiveDef.contentQueries!(RenderFlags.Update, lView[directiveDefIdx], directiveDefIdx);\n }\n }\n }\n}\n\n/** Refreshes child components in the current view (update mode). */\nfunction refreshChildComponents(hostLView: LView, components: number[]): void {\n for (let i = 0; i < components.length; i++) {\n refreshComponent(hostLView, components[i]);\n }\n}\n\n/** Renders child components in the current view (creation mode). */\nfunction renderChildComponents(hostLView: LView, components: number[]): void {\n for (let i = 0; i < components.length; i++) {\n renderComponent(hostLView, components[i]);\n }\n}\n\nexport function createLView<T>(\n parentLView: LView|null, tView: TView, context: T|null, flags: LViewFlags, host: RElement|null,\n tHostNode: TNode|null, rendererFactory: RendererFactory|null, renderer: Renderer|null,\n sanitizer: Sanitizer|null, injector: Injector|null,\n embeddedViewInjector: Injector|null): LView {\n const lView = tView.blueprint.slice() as LView;\n lView[HOST] = host;\n lView[FLAGS] = flags | LViewFlags.CreationMode | LViewFlags.Attached | LViewFlags.FirstLViewPass;\n if (embeddedViewInjector !== null ||\n (parentLView && (parentLView[FLAGS] & LViewFlags.HasEmbeddedViewInjector))) {\n lView[FLAGS] |= LViewFlags.HasEmbeddedViewInjector;\n }\n resetPreOrderHookFlags(lView);\n ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);\n lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;\n lView[CONTEXT] = context;\n lView[RENDERER_FACTORY] = (rendererFactory || parentLView && parentLView[RENDERER_FACTORY])!;\n ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');\n lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER])!;\n ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');\n lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null!;\n lView[INJECTOR as any] = injector || parentLView && parentLView[INJECTOR] || null;\n lView[T_HOST] = tHostNode;\n lView[ID] = getUniqueLViewId();\n lView[EMBEDDED_VIEW_INJECTOR as any] = embeddedViewInjector;\n ngDevMode &&\n assertEqual(\n tView.type == TViewType.Embedded ? parentLView !== null : true, true,\n 'Embedded views must have parentLView');\n lView[DECLARATION_COMPONENT_VIEW] =\n tView.type == TViewType.Embedded ? parentLView![DECLARATION_COMPONENT_VIEW] : lView;\n return lView;\n}\n\n/**\n * Create and stores the TNode, and hooks it up to the tree.\n *\n * @param tView The current `TView`.\n * @param index The index at which the TNode should be saved (null if view, since they are not\n * saved).\n * @param type The type of TNode to create\n * @param native The native element for this node, if applicable\n * @param name The tag name of the associated native element, if applicable\n * @param attrs Any attrs for the native element, if applicable\n */\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType.Element|TNodeType.Text, name: string|null,\n attrs: TAttributes|null): TElementNode;\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType.Container, name: string|null,\n attrs: TAttributes|null): TContainerNode;\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType.Projection, name: null,\n attrs: TAttributes|null): TProjectionNode;\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType.ElementContainer, name: string|null,\n attrs: TAttributes|null): TElementContainerNode;\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType.Icu, name: null,\n attrs: TAttributes|null): TElementContainerNode;\nexport function getOrCreateTNode(\n tView: TView, index: number, type: TNodeType, name: string|null, attrs: TAttributes|null):\n TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {\n ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in\n // `view_engine_compatibility` for additional context.\n assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\\'t be in the LView header.');\n // Keep this function short, so that the VM will inline it.\n ngDevMode && assertPureTNodeType(type);\n let tNode = tView.data[index] as TNode;\n if (tNode === null) {\n tNode = createTNodeAtIndex(tView, index, type, name, attrs);\n if (isInI18nBlock()) {\n // If we are in i18n block then all elements should be pre declared through `Placeholder`\n // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.\n // If the `TNode` was not pre-declared than it means it was not mentioned which means it was\n // removed, so we mark it as detached.\n tNode.flags |= TNodeFlags.isDetached;\n }\n } else if (tNode.type & TNodeType.Placeholder) {\n tNode.type = type;\n tNode.value = name;\n tNode.attrs = attrs;\n const parent = getCurrentParentTNode();\n tNode.injectorIndex = parent === null ? -1 : parent.injectorIndex;\n ngDevMode && assertTNodeForTView(tNode, tView);\n ngDevMode && assertEqual(index, tNode.index, 'Expecting same index');\n }\n setCurrentTNode(tNode, true);\n return tNode as TElementNode & TContainerNode & TElementContainerNode & TProjectionNode &\n TIcuContainerNode;\n}\n\nexport function createTNodeAtIndex(\n tView: TView, index: number, type: TNodeType, name: string|null, attrs: TAttributes|null) {\n const currentTNode = getCurrentTNodePlaceholderOk();\n const isParent = isCurrentTNodeParent();\n const parent = isParent ? currentTNode : currentTNode && currentTNode.parent;\n // Parents cannot cross component boundaries because components will be used in multiple places.\n const tNode = tView.data[index] =\n createTNode(tView, parent as TElementNode | TContainerNode, type, index, name, attrs);\n // Assign a pointer to the first child node of a given view. The first node is not always the one\n // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has\n // the index 1 or more, so we can't just check node index.\n if (tView.firstChild === null) {\n tView.firstChild = tNode;\n }\n if (currentTNode !== null) {\n if (isParent) {\n // FIXME(misko): This logic looks unnecessarily complicated. Could we simplify?\n if (currentTNode.child == null && tNode.parent !== null) {\n // We are in the same view, which means we are adding content node to the parent view.\n currentTNode.child = tNode;\n }\n } else {\n if (currentTNode.next === null) {\n // In the case of i18n the `currentTNode` may already be linked, in which case we don't want\n // to break the links which i18n created.\n currentTNode.next = tNode;\n tNode.prev = currentTNode;\n }\n }\n }\n return tNode;\n}\n\n/**\n * When elements are created dynamically after a view blueprint is created (e.g. through\n * i18nApply()), we need to adjust the blueprint for future\n * template passes.\n *\n * @param tView `TView` associated with `LView`\n * @param lView The `LView` containing the blueprint to adjust\n * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0\n * @param initialValue Initial value to store in blueprint\n */\nexport function allocExpando(\n tView: TView, lView: LView, numSlotsToAlloc: number, initialValue: any): number {\n if (numSlotsToAlloc === 0) return -1;\n if (ngDevMode) {\n assertFirstCreatePass(tView);\n assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!');\n assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView');\n assertEqual(\n tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView');\n assertFirstUpdatePass(tView);\n }\n const allocIdx = lView.length;\n for (let i = 0; i < numSlotsToAlloc; i++) {\n lView.push(initialValue);\n tView.blueprint.push(initialValue);\n tView.data.push(null);\n }\n return allocIdx;\n}\n\n\n//////////////////////////\n//// Render\n//////////////////////////\n\n/**\n * Processes a view in the creation mode. This includes a number of steps in a specific order:\n * - creating view query functions (if any);\n * - executing a template function in the creation mode;\n * - updating static queries (if any);\n * - creating child components defined in a given view.\n */\nexport function renderView<T>(tView: TView, lView: LView<T>, context: T): void {\n ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');\n enterView(lView);\n try {\n const viewQuery = tView.viewQuery;\n if (viewQuery !== null) {\n executeViewQueryFn<T>(RenderFlags.Create, viewQuery, context);\n }\n\n // Execute a template associated with this view, if it exists. A template function might not be\n // defined for the root component views.\n const templateFn = tView.template;\n if (templateFn !== null) {\n executeTemplate<T>(tView, lView, templateFn, RenderFlags.Create, context);\n }\n\n // This needs to be set before children are processed to support recursive components.\n // This must be set to false immediately after the first creation run because in an\n // ngFor loop, all the views will be created together before update mode runs and turns\n // off firstCreatePass. If we don't set it here, instances will perform directive\n // matching, etc again and again.\n if (tView.firstCreatePass) {\n tView.firstCreatePass = false;\n }\n\n // We resolve content queries specifically marked as `static` in creation mode. Dynamic\n // content queries are resolved during change detection (i.e. update mode), after embedded\n // views are refreshed (see block above).\n if (tView.staticContentQueries) {\n refreshContentQueries(tView, lView);\n }\n\n // We must materialize query results before child components are processed\n // in case a child component has projected a container. The LContainer needs\n // to exist so the embedded views are properly attached by the container.\n if (tView.staticViewQueries) {\n executeViewQueryFn<T>(RenderFlags.Update, tView.viewQuery!, context);\n }\n\n // Render child component views.\n const components = tView.components;\n if (components !== null) {\n renderChildComponents(lView, components);\n }\n\n } catch (error) {\n // If we didn't manage to get past the first template pass due to\n // an error, mark the view as corrupted so we can try to recover.\n if (tView.firstCreatePass) {\n tView.incompleteFirstPass = true;\n tView.firstCreatePass = false;\n }\n\n throw error;\n } finally {\n lView[FLAGS] &= ~LViewFlags.CreationMode;\n leaveView();\n }\n}\n\n/**\n * Processes a view in update mode. This includes a number of steps in a specific order:\n * - executing a template function in update mode;\n * - executing hooks;\n * - refreshing queries;\n * - setting host bindings;\n * - refreshing child (embedded and component) views.\n */\nexport function refreshView<T>(\n tView: TView, lView: LView, templateFn: ComponentTemplate<{}>|null, context: T) {\n ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');\n const flags = lView[FLAGS];\n if ((flags & LViewFlags.Destroyed) === LViewFlags.Destroyed) return;\n enterView(lView);\n // Check no changes mode is a dev only mode used to verify that bindings have not changed\n // since they were assigned. We do not want to execute lifecycle hooks in that mode.\n const isInCheckNoChangesPass = ngDevMode && isInCheckNoChangesMode();\n try {\n resetPreOrderHookFlags(lView);\n\n setBindingIndex(tView.bindingStartIndex);\n if (templateFn !== null) {\n executeTemplate(tView, lView, templateFn, RenderFlags.Update, context);\n }\n\n const hooksInitPhaseCompleted =\n (flags & LViewFlags.InitPhaseStateMask) === InitPhaseState.InitPhaseCompleted;\n\n // execute pre-order hooks (OnInit, OnChanges, DoCheck)\n // PERF WARNING: do NOT extract this to a separate function without running benchmarks\n if (!isInCheckNoChangesPass) {\n if (hooksInitPhaseCompleted) {\n const preOrderCheckHooks = tView.preOrderCheckHooks;\n if (preOrderCheckHooks !== null) {\n executeCheckHooks(lView, preOrderCheckHooks, null);\n }\n } else {\n const preOrderHooks = tView.preOrderHooks;\n if (preOrderHooks !== null) {\n executeInitAndCheckHooks(lView, preOrderHooks, InitPhaseState.OnInitHooksToBeRun, null);\n }\n incrementInitPhaseFlags(lView, InitPhaseState.OnInitHooksToBeRun);\n }\n }\n\n // First mark transplanted views that are declared in this lView as needing a refresh at their\n // insertion points. This is needed to avoid the situation where the template is defined in this\n // `LView` but its declaration appears after the insertion component.\n markTransplantedViewsForRefresh(lView);\n refreshEmbeddedViews(lView);\n\n // Content query results must be refreshed before content hooks are called.\n if (tView.contentQueries !== null) {\n refreshContentQueries(tView, lView);\n }\n\n // execute content hooks (AfterContentInit, AfterContentChecked)\n // PERF WARNING: do NOT extract this to a separate function without running benchmarks\n if (!isInCheckNoChangesPass) {\n if (hooksInitPhaseCompleted) {\n const contentCheckHooks = tView.contentCheckHooks;\n if (contentCheckHooks !== null) {\n executeCheckHooks(lView, contentCheckHooks);\n }\n } else {\n const contentHooks = tView.contentHooks;\n if (contentHooks !== null) {\n executeInitAndCheckHooks(\n lView, contentHooks, InitPhaseState.AfterContentInitHooksToBeRun);\n }\n incrementInitPhaseFlags(lView, InitPhaseState.AfterContentInitHooksToBeRun);\n }\n }\n\n processHostBindingOpCodes(tView, lView);\n\n // Refresh child component views.\n const components = tView.components;\n if (components !== null) {\n refreshChildComponents(lView, components);\n }\n\n // View queries must execute after refreshing child components because a template in this view\n // could be inserted in a child component. If the view query executes before child component\n // refresh, the template might not yet be inserted.\n const viewQuery = tView.viewQuery;\n if (viewQuery !== null) {\n executeViewQueryFn<T>(RenderFlags.Update, viewQuery, context);\n }\n\n // execute view hooks (AfterViewInit, AfterViewChecked)\n // PERF WARNING: do NOT extract this to a separate function without running benchmarks\n if (!isInCheckNoChangesPass) {\n if (hooksInitPhaseCompleted) {\n const viewCheckHooks = tView.viewCheckHooks;\n if (viewCheckHooks !== null) {\n executeCheckHooks(lView, viewCheckHooks);\n }\n } else {\n const viewHooks = tView.viewHooks;\n if (viewHooks !== null) {\n executeInitAndCheckHooks(lView, viewHooks, InitPhaseState.AfterViewInitHooksToBeRun);\n }\n incrementInitPhaseFlags(lView, InitPhaseState.AfterViewInitHooksToBeRun);\n }\n }\n if (tView.firstUpdatePass === true) {\n // We need to make sure that we only flip the flag on successful `refreshView` only\n // Don't do this in `finally` block.\n // If we did this in `finally` block then an exception could block the execution of styling\n // instructions which in turn would be unable to insert themselves into the styling linked\n // list. The result of this would be that if the exception would not be throw on subsequent CD\n // the styling would be unable to process it data and reflect to the DOM.\n tView.firstUpdatePass = false;\n }\n\n // Do not reset the dirty state when running in check no changes mode. We don't want components\n // to behave differently depending on whether check no changes is enabled or not. For example:\n // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to\n // refresh a `NgClass` binding should work. If we would reset the dirty state in the check\n // no changes cycle, the component would be not be dirty for the next update pass. This would\n // be different in production mode where the component dirty state is not reset.\n if (!isInCheckNoChangesPass) {\n lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);\n }\n if (lView[FLAGS] & LViewFlags.RefreshTransplantedView) {\n lView[FLAGS] &= ~LViewFlags.RefreshTransplantedView;\n updateTransplantedViewCount(lView[PARENT] as LContainer, -1);\n }\n } finally {\n leaveView();\n }\n}\n\nfunction executeTemplate<T>(\n tView: TView, lView: LView<T>, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {\n const prevSelectedIndex = getSelectedIndex();\n const isUpdatePhase = rf & RenderFlags.Update;\n try {\n setSelectedIndex(-1);\n if (isUpdatePhase && lView.length > HEADER_OFFSET) {\n // When we're updating, inherently select 0 so we don't\n // have to generate that instruction for most update blocks.\n selectIndexInternal(tView, lView, HEADER_OFFSET, !!ngDevMode && isInCheckNoChangesMode());\n }\n\n const preHookType =\n isUpdatePhase ? ProfilerEvent.TemplateUpdateStart : ProfilerEvent.TemplateCreateStart;\n profiler(preHookType, context as unknown as {});\n templateFn(rf, context);\n } finally {\n setSelectedIndex(prevSelectedIndex);\n\n const postHookType =\n isUpdatePhase ? ProfilerEvent.TemplateUpdateEnd : ProfilerEvent.TemplateCreateEnd;\n profiler(postHookType, context as unknown as {});\n }\n}\n\n//////////////////////////\n//// Element\n//////////////////////////\n\nexport function executeContentQueries(tView: TView, tNode: TNode, lView: LView) {\n if (isContentQueryHost(tNode)) {\n const start = tNode.directiveStart;\n const end = tNode.directiveEnd;\n for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {\n const def = tView.data[directiveIndex] as DirectiveDef<any>;\n if (def.contentQueries) {\n def.contentQueries(RenderFlags.Create, lView[directiveIndex], directiveIndex);\n }\n }\n }\n}\n\n\n/**\n * Creates directive instances.\n */\nexport function createDirectivesInstances(tView: TView, lView: LView, tNode: TDirectiveHostNode) {\n if (!getBindingsEnabled()) return;\n instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));\n if ((tNode.flags & TNodeFlags.hasHostBindings) === TNodeFlags.hasHostBindings) {\n invokeDirectivesHostBindings(tView, lView, tNode);\n }\n}\n\n/**\n * Takes a list of local names and indices and pushes the resolved local variable values\n * to LView in the same order as they are loaded in the template with load().\n */\nexport function saveResolvedLocalsInData(\n viewData: LView, tNode: TDirectiveHostNode,\n localRefExtractor: LocalRefExtractor = getNativeByTNode): void {\n const localNames = tNode.localNames;\n if (localNames !== null) {\n let localIndex = tNode.index + 1;\n for (let i = 0; i < localNames.length; i += 2) {\n const index = localNames[i + 1] as number;\n const value = index === -1 ?\n localRefExtractor(\n tNode as TElementNode | TContainerNode | TElementContainerNode, viewData) :\n viewData[index];\n viewData[localIndex++] = value;\n }\n }\n}\n\n/**\n * Gets TView from a template function or creates a new TView\n * if it doesn't already exist.\n *\n * @param def ComponentDef\n * @returns TView\n */\nexport function getOrCreateComponentTView(def: ComponentDef<any>): TView {\n const tView = def.tView;\n\n // Create a TView if there isn't one, or recreate it if the first create pass didn't\n // complete successfully since we can't know for sure whether it's in a usable shape.\n if (tView === null || tView.incompleteFirstPass) {\n // Declaration node here is null since this function is called when we dynamically create a\n // component and hence there is no declaration.\n const declTNode = null;\n return def.tView = createTView(\n TViewType.Component, declTNode, def.template, def.decls, def.vars, def.directiveDefs,\n def.pipeDefs, def.viewQuery, def.schemas, def.consts);\n }\n\n return tView;\n}\n\n\n/**\n * Creates a TView instance\n *\n * @param type Type of `TView`.\n * @param declTNode Declaration location of this `TView`.\n * @param templateFn Template function\n * @param decls The number of nodes, local refs, and pipes in this template\n * @param directives Registry of directives for this view\n * @param pipes Registry of pipes for this view\n * @param viewQuery View queries for this view\n * @param schemas Schemas for this view\n * @param consts Constants for this view\n */\nexport function createTView(\n type: TViewType, declTNode: TNode|null, templateFn: ComponentTemplate<any>|null, decls: number,\n vars: number, directives: DirectiveDefListOrFactory|null, pipes: PipeDefListOrFactory|null,\n viewQuery: ViewQueriesFunction<any>|null, schemas: SchemaMetadata[]|null,\n constsOrFactory: TConstantsOrFactory|null): TView {\n ngDevMode && ngDevMode.tView++;\n const bindingStartIndex = HEADER_OFFSET + decls;\n // This length does not yet contain host bindings from child directives because at this point,\n // we don't know which directives are active on this template. As soon as a directive is matched\n // that has a host binding, we will update the blueprint with that def's hostVars count.\n const initialViewLength = bindingStartIndex + vars;\n const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);\n const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory;\n const tView = blueprint[TVIEW as any] = {\n type: type,\n blueprint: blueprint,\n template: templateFn,\n queries: null,\n viewQuery: viewQuery,\n declTNode: declTNode,\n data: blueprint.slice().fill(null, bindingStartIndex),\n bindingStartIndex: bindingStartIndex,\n expandoStartIndex: initialViewLength,\n hostBindingOpCodes: null,\n firstCreatePass: true,\n firstUpdatePass: true,\n staticViewQueries: false,\n staticContentQueries: false,\n preOrderHooks: null,\n preOrderCheckHooks: null,\n contentHooks: null,\n contentCheckHooks: null,\n viewHooks: null,\n viewCheckHooks: null,\n destroyHooks: null,\n cleanup: null,\n contentQueries: null,\n components: null,\n directiveRegistry: typeof directives === 'function' ? directives() : directives,\n pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,\n firstChild: null,\n schemas: schemas,\n consts: consts,\n incompleteFirstPass: false\n };\n if (ngDevMode) {\n // For performance reasons it is important that the tView retains the same shape during runtime.\n // (To make sure that all of the code is monomorphic.) For this reason we seal the object to\n // prevent class transitions.\n Object.seal(tView);\n }\n return tView;\n}\n\nfunction createViewBlueprint(bindingStartIndex: number, initialViewLength: number): LView {\n const blueprint = [];\n\n for (let i = 0; i < initialViewLength; i++) {\n blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);\n }\n\n return blueprint as LView;\n}\n\n/**\n * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.\n *\n * @param rendererFactory Factory function to create renderer instance.\n * @param elementOrSelector Render element or CSS selector to locate the element.\n * @param encapsulation View Encapsulation defined for component that requests host element.\n */\nexport function locateHostElement(\n renderer: Renderer, elementOrSelector: RElement|string,\n encapsulation: ViewEncapsulation): RElement {\n // When using native Shadow DOM, do not clear host element to allow native slot projection\n const preserveContent = encapsulation === ViewEncapsulation.ShadowDom;\n return renderer.selectRootElement(elementOrSelector, preserveContent);\n}\n\n/**\n * Saves context for this cleanup function in LView.cleanupInstances.\n *\n * On the first template pass, saves in TView:\n * - Cleanup function\n * - Index of context we just saved in LView.cleanupInstances\n *\n * This function can also be used to store instance specific cleanup fns. In that case the `context`\n * is `null` and the function is store in `LView` (rather than it `TView`).\n */\nexport function storeCleanupWithContext(\n tView: TView, lView: LView, context: any, cleanupFn: Function): void {\n const lCleanup = getOrCreateLViewCleanup(lView);\n if (context === null) {\n // If context is null that this is instance specific callback. These callbacks can only be\n // inserted after template shared instances. For this reason in ngDevMode we freeze the TView.\n if (ngDevMode) {\n Object.freeze(getOrCreateTViewCleanup(tView));\n }\n lCleanup.push(cleanupFn);\n } else {\n lCleanup.push(context);\n\n if (tView.firstCreatePass) {\n getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);\n }\n }\n}\n\n/**\n * Constructs a TNode object from the arguments.\n *\n * @param tView `TView` to which this `TNode` belongs\n * @param tParent Parent `TNode`\n * @param type The type of the node\n * @param index The index of the TNode in TView.data, adjusted for HEADER_OFFSET\n * @param tagName The tag name of the node\n * @param attrs The attributes defined on this node\n * @returns the TNode object\n */\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Container,\n index: number, tagName: string|null, attrs: TAttributes|null): TContainerNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Element|TNodeType.Text,\n index: number, tagName: string|null, attrs: TAttributes|null): TElementNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.ElementContainer,\n index: number, tagName: string|null, attrs: TAttributes|null): TElementContainerNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Icu, index: number,\n tagName: string|null, attrs: TAttributes|null): TIcuContainerNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Projection,\n index: number, tagName: string|null, attrs: TAttributes|null): TProjectionNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType, index: number,\n tagName: string|null, attrs: TAttributes|null): TNode;\nexport function createTNode(\n tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType, index: number,\n value: string|null, attrs: TAttributes|null): TNode {\n ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in\n // `view_engine_compatibility` for additional context.\n assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\\'t be in the LView header.');\n ngDevMode && assertNotSame(attrs, undefined, '\\'undefined\\' is not valid value for \\'attrs\\'');\n ngDevMode && ngDevMode.tNode++;\n ngDevMode && tParent && assertTNodeForTView(tParent, tView);\n let injectorIndex = tParent ? tParent.injectorIndex : -1;\n const tNode = {\n type,\n index,\n insertBeforeIndex: null,\n injectorIndex,\n directiveStart: -1,\n directiveEnd: -1,\n directiveStylingLast: -1,\n componentOffset: -1,\n propertyBindings: null,\n flags: 0,\n providerIndexes: 0,\n value: value,\n attrs: attrs,\n mergedAttrs: null,\n localNames: null,\n initialInputs: undefined,\n inputs: null,\n outputs: null,\n tView: null,\n next: null,\n prev: null,\n projectionNext: null,\n child: null,\n parent: tParent,\n projection: null,\n styles: null,\n stylesWithoutHost: null,\n residualStyles: undefined,\n classes: null,\n classesWithoutHost: null,\n residualClasses: undefined,\n classBindings: 0 as any,\n styleBindings: 0 as any,\n };\n if (ngDevMode) {\n // For performance reasons it is important that the tNode retains the same shape during runtime.\n // (To make sure that all of the code is monomorphic.) For this reason we seal the object to\n // prevent class transitions.\n Object.seal(tNode);\n }\n return tNode;\n}\n\n/**\n * Generates the `PropertyAliases` data structure from the provided input/output mapping.\n * @param aliasMap Input/output mapping from the directive definition.\n * @param directiveIndex Index of the directive.\n * @param propertyAliases Object in which to store the results.\n * @param hostDirectiveAliasMap Object used to alias or filter out properties for host directives.\n * If the mapping is provided, it'll act as an allowlist, as well as a mapping of what public\n * name inputs/outputs should be exposed under.\n */\nfunction generatePropertyAliases(\n aliasMap: {[publicName: string]: string}, directiveIndex: number,\n propertyAliases: PropertyAliases|null,\n hostDirectiveAliasMap: HostDirectiveBindingMap|null): PropertyAliases|null {\n for (let publicName in aliasMap) {\n if (aliasMap.hasOwnProperty(publicName)) {\n propertyAliases = propertyAliases === null ? {} : propertyAliases;\n const internalName = aliasMap[publicName];\n\n // If there are no host directive mappings, we want to remap using the alias map from the\n // definition itself. If there is an alias map, it has two functions:\n // 1. It serves as an allowlist of bindings that are exposed by the host directives. Only the\n // ones inside the host directive map will be exposed on the host.\n // 2. The public name of the property is aliased using the host directive alias map, rather\n // than the alias map from the definition.\n if (hostDirectiveAliasMap === null) {\n addPropertyAlias(propertyAliases, directiveIndex, publicName, internalName);\n } else if (hostDirectiveAliasMap.hasOwnProperty(publicName)) {\n addPropertyAlias(\n propertyAliases, directiveIndex, hostDirectiveAliasMap[publicName], internalName);\n }\n }\n }\n return propertyAliases;\n}\n\nfunction addPropertyAlias(\n propertyAliases: PropertyAliases, directiveIndex: number, publicName: string,\n internalName: string) {\n if (propertyAliases.hasOwnProperty(publicName)) {\n propertyAliases[publicName].push(directiveIndex, internalName);\n } else {\n propertyAliases[publicName] = [directiveIndex, internalName];\n }\n}\n\n/**\n * Initializes data structures required to work with directive inputs and outputs.\n * Initialization is done for all directives matched on a given TNode.\n */\nfunction initializeInputAndOutputAliases(\n tView: TView, tNode: TNode, hostDirectiveDefinitionMap: HostDirectiveDefs|null): void {\n ngDevMode && assertFirstCreatePass(tView);\n\n const start = tNode.directiveStart;\n const end = tNode.directiveEnd;\n const tViewData = tView.data;\n\n const tNodeAttrs = tNode.attrs;\n const inputsFromAttrs: InitialInputData = [];\n let inputsStore: PropertyAliases|null = null;\n let outputsStore: PropertyAliases|null = null;\n\n for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {\n const directiveDef = tViewData[directiveIndex] as DirectiveDef<any>;\n const aliasData =\n hostDirectiveDefinitionMap ? hostDirectiveDefinitionMap.get(directiveDef) : null;\n const aliasedInputs = aliasData ? aliasData.inputs : null;\n const aliasedOutputs = aliasData ? aliasData.outputs : null;\n\n inputsStore =\n generatePropertyAliases(directiveDef.inputs, directiveIndex, inputsStore, aliasedInputs);\n outputsStore =\n generatePropertyAliases(directiveDef.outputs, directiveIndex, outputsStore, aliasedOutputs);\n // Do not use unbound attributes as inputs to structural directives, since structural\n // directive inputs can only be set using microsyntax (e.g. `<div *dir=\"exp\">`).\n // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which\n // should be set for inline templates.\n const initialInputs =\n (inputsStore !== null && tNodeAttrs !== null && !isInlineTemplate(tNode)) ?\n generateInitialInputs(inputsStore, directiveIndex, tNodeAttrs) :\n null;\n inputsFromAttrs.push(initialInputs);\n }\n\n if (inputsStore !== null) {\n if (inputsStore.hasOwnProperty('class')) {\n tNode.flags |= TNodeFlags.hasClassInput;\n }\n if (inputsStore.hasOwnProperty('style')) {\n tNode.flags |= TNodeFlags.hasStyleInput;\n }\n }\n\n tNode.initialInputs = inputsFromAttrs;\n tNode.inputs = inputsStore;\n tNode.outputs = outputsStore;\n}\n\n/**\n * Mapping between attributes names that don't correspond to their element property names.\n *\n * Performance note: this function is written as a series of if checks (instead of, say, a property\n * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of\n * mapping property names. Do NOT change without benchmarking.\n *\n * Note: this mapping has to be kept in sync with the equally named mapping in the template\n * type-checking machinery of ngtsc.\n */\nfunction mapPropName(name: string): string {\n if (name === 'class') return 'className';\n if (name === 'for') return 'htmlFor';\n if (name === 'formaction') return 'formAction';\n if (name === 'innerHtml') return 'innerHTML';\n if (name === 'readonly') return 'readOnly';\n if (name === 'tabindex') return 'tabIndex';\n return name;\n}\n\nexport function elementPropertyInternal<T>(\n tView: TView, tNode: TNode, lView: LView, propName: string, value: T, renderer: Renderer,\n sanitizer: SanitizerFn|null|undefined, nativeOnly: boolean): void {\n ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');\n const element = getNativeByTNode(tNode, lView) as RElement | RComment;\n let inputData = tNode.inputs;\n let dataValue: PropertyAliasValue|undefined;\n if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {\n setInputsForProperty(tView, lView, dataValue, propName, value);\n if (isComponentHost(tNode)) markDirtyIfOnPush(lView, tNode.index);\n if (ngDevMode) {\n setNgReflectProperties(lView, element, tNode.type, dataValue, value);\n }\n } else if (tNode.type & TNodeType.AnyRNode) {\n propName = mapPropName(propName);\n\n if (ngDevMode) {\n validateAgainstEventProperties(propName);\n if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) {\n handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);\n }\n ngDevMode.rendererSetProperty++;\n }\n\n // It is assumed that the sanitizer is only added when the compiler determines that the\n // property is risky, so sanitization can be done without further checks.\n value = sanitizer != null ? (sanitizer(value, tNode.value || '', propName) as any) : value;\n renderer.setProperty(element as RElement, propName, value);\n } else if (tNode.type & TNodeType.AnyContainer) {\n // If the node is a container and the property didn't\n // match any of the inputs or schemas we should throw.\n if (ngDevMode && !matchingSchemas(tView.schemas, tNode.value)) {\n handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);\n }\n }\n}\n\n/** If node is an OnPush component, marks its LView dirty. */\nexport function markDirtyIfOnPush(lView: LView, viewIndex: number): void {\n ngDevMode && assertLView(lView);\n const childComponentLView = getComponentLViewByIndex(viewIndex, lView);\n if (!(childComponentLView[FLAGS] & LViewFlags.CheckAlways)) {\n childComponentLView[FLAGS] |= LViewFlags.Dirty;\n }\n}\n\nfunction setNgReflectProperty(\n lView: LView, element: RElement|RComment, type: TNodeType, attrName: string, value: any) {\n const renderer = lView[RENDERER];\n attrName = normalizeDebugBindingName(attrName);\n const debugValue = normalizeDebugBindingValue(value);\n if (type & TNodeType.AnyRNode) {\n if (value == null) {\n renderer.removeAttribute((element as RElement), attrName);\n } else {\n renderer.setAttribute((element as RElement), attrName, debugValue);\n }\n } else {\n const textContent =\n escapeCommentText(`bindings=${JSON.stringify({[attrName]: debugValue}, null, 2)}`);\n renderer.setValue((element as RComment), textContent);\n }\n}\n\nexport function setNgReflectProperties(\n lView: LView, element: RElement|RComment, type: TNodeType, dataValue: PropertyAliasValue,\n value: any) {\n if (type & (TNodeType.AnyRNode | TNodeType.Container)) {\n /**\n * dataValue is an array containing runtime input or output names for the directives:\n * i+0: directive instance index\n * i+1: privateName\n *\n * e.g. [0, 'change', 'change-minified']\n * we want to set the reflected property with the privateName: dataValue[i+1]\n */\n for (let i = 0; i < dataValue.length; i += 2) {\n setNgReflectProperty(lView, element, type, dataValue[i + 1] as string, value);\n }\n }\n}\n\n/**\n * Resolve the matched directives on a node.\n */\nexport function resolveDirectives(\n tView: TView, lView: LView, tNode: TElementNode|TContainerNode|TElementContainerNode,\n localRefs: string[]|null): void {\n // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in\n // tsickle.\n ngDevMode && assertFirstCreatePass(tView);\n\n if (getBindingsEnabled()) {\n const exportsMap: ({[key: string]: number}|null) = localRefs === null ? null : {'': -1};\n const matchResult = findDirectiveDefMatches(tView, tNode);\n let directiveDefs: DirectiveDef<unknown>[]|null;\n let hostDirectiveDefs: HostDirectiveDefs|null;\n\n if (matchResult === null) {\n directiveDefs = hostDirectiveDefs = null;\n } else {\n [directiveDefs, hostDirectiveDefs] = matchResult;\n }\n\n if (directiveDefs !== null) {\n initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap, hostDirectiveDefs);\n }\n if (exportsMap) cacheMatchingLocalNames(tNode, localRefs, exportsMap);\n }\n // Merge the template attrs last so that they have the highest priority.\n tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);\n}\n\n/** Initializes the data structures necessary for a list of directives to be instantiated. */\nexport function initializeDirectives(\n tView: TView, lView: LView<unknown>, tNode: TElementNode|TContainerNode|TElementContainerNode,\n directives: DirectiveDef<unknown>[], exportsMap: {[key: string]: number;}|null,\n hostDirectiveDefs: HostDirectiveDefs|null) {\n ngDevMode && assertFirstCreatePass(tView);\n\n // Publishes the directive types to DI so they can be injected. Needs to\n // happen in a separate pass before the TNode flags have been initialized.\n for (let i = 0; i < directives.length; i++) {\n diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, directives[i].type);\n }\n\n initTNodeFlags(tNode, tView.data.length, directives.length);\n\n // When the same token is provided by several directives on the same node, some rules apply in\n // the viewEngine:\n // - viewProviders have priority over providers\n // - the last directive in NgModule.declarations has priority over the previous one\n // So to match these rules, the order in which providers are added in the arrays is very\n // important.\n for (let i = 0; i < directives.length; i++) {\n const def = directives[i];\n if (def.providersResolver) def.providersResolver(def);\n }\n let preOrderHooksFound = false;\n let preOrderCheckHooksFound = false;\n let directiveIdx = allocExpando(tView, lView, directives.length, null);\n ngDevMode &&\n assertSame(\n directiveIdx, tNode.directiveStart,\n 'TNode.directiveStart should point to just allocated space');\n\n for (let i = 0; i < directives.length; i++) {\n const def = directives[i];\n // Merge the attrs in the order of matches. This assumes that the first directive is the\n // component itself, so that the component has the least priority.\n tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);\n\n configureViewWithDirective(tView, tNode, lView, directiveIdx, def);\n saveNameToExportMap(directiveIdx, def, exportsMap);\n\n if (def.contentQueries !== null) tNode.flags |= TNodeFlags.hasContentQuery;\n if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)\n tNode.flags |= TNodeFlags.hasHostBindings;\n\n const lifeCycleHooks: OnChanges&OnInit&DoCheck = def.type.prototype;\n // Only push a node index into the preOrderHooks array if this is the first\n // pre-order hook found on this node.\n if (!preOrderHooksFound &&\n (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngOnInit || lifeCycleHooks.ngDoCheck)) {\n // We will push the actual hook function into this array later during dir instantiation.\n // We cannot do it now because we must ensure hooks are registered in the same\n // order that directives are created (i.e. injection order).\n (tView.preOrderHooks ??= []).push(tNode.index);\n preOrderHooksFound = true;\n }\n\n if (!preOrderCheckHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngDoCheck)) {\n (tView.preOrderCheckHooks ??= []).push(tNode.index);\n preOrderCheckHooksFound = true;\n }\n\n directiveIdx++;\n }\n\n initializeInputAndOutputAliases(tView, tNode, hostDirectiveDefs);\n}\n\n/**\n * Add `hostBindings` to the `TView.hostBindingOpCodes`.\n *\n * @param tView `TView` to which the `hostBindings` should be added.\n * @param tNode `TNode` the element which contains the directive\n * @param directiveIdx Directive index in view.\n * @param directiveVarsIdx Where will the directive's vars be stored\n * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add.\n */\nexport function registerHostBindingOpCodes(\n tView: TView, tNode: TNode, directiveIdx: number, directiveVarsIdx: number,\n def: ComponentDef<any>|DirectiveDef<any>): void {\n ngDevMode && assertFirstCreatePass(tView);\n\n const hostBindings = def.hostBindings;\n if (hostBindings) {\n let hostBindingOpCodes = tView.hostBindingOpCodes;\n if (hostBindingOpCodes === null) {\n hostBindingOpCodes = tView.hostBindingOpCodes = [] as any as HostBindingOpCodes;\n }\n const elementIndx = ~tNode.index;\n if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) {\n // Conditionally add select element so that we are more efficient in execution.\n // NOTE: this is strictly not necessary and it trades code size for runtime perf.\n // (We could just always add it.)\n hostBindingOpCodes.push(elementIndx);\n }\n hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings);\n }\n}\n\n/**\n * Returns the last selected element index in the `HostBindingOpCodes`\n *\n * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only\n * if it changes. This method returns the last index (or '0' if not found.)\n *\n * Selected element index are only the ones which are negative.\n */\nfunction lastSelectedElementIdx(hostBindingOpCodes: HostBindingOpCodes): number {\n let i = hostBindingOpCodes.length;\n while (i > 0) {\n const value = hostBindingOpCodes[--i];\n if (typeof value === 'number' && value < 0) {\n return value;\n }\n }\n return 0;\n}\n\n\n/**\n * Instantiate all the directives that were previously resolved on the current node.\n */\nfunction instantiateAllDirectives(\n tView: TView, lView: LView, tNode: TDirectiveHostNode, native: RNode) {\n const start = tNode.directiveStart;\n const end = tNode.directiveEnd;\n\n // The component view needs to be created before creating the node injector\n // since it is used to inject some special symbols like `ChangeDetectorRef`.\n if (isComponentHost(tNode)) {\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode);\n addComponentLogic(\n lView, tNode as TElementNode,\n tView.data[start + tNode.componentOffset] as ComponentDef<unknown>);\n }\n\n if (!tView.firstCreatePass) {\n getOrCreateNodeInjectorForNode(tNode, lView);\n }\n\n attachPatchData(native, lView);\n\n const initialInputs = tNode.initialInputs;\n for (let i = start; i < end; i++) {\n const def = tView.data[i] as DirectiveDef<any>;\n const directive = getNodeInjectable(lView, tView, i, tNode);\n attachPatchData(directive, lView);\n\n if (initialInputs !== null) {\n setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs!);\n }\n\n if (isComponentDef(def)) {\n const componentView = getComponentLViewByIndex(tNode.index, lView);\n componentView[CONTEXT] = getNodeInjectable(lView, tView, i, tNode);\n }\n }\n}\n\nexport function invokeDirectivesHostBindings(tView: TView, lView: LView, tNode: TNode) {\n const start = tNode.directiveStart;\n const end = tNode.directiveEnd;\n const elementIndex = tNode.index;\n const currentDirectiveIndex = getCurrentDirectiveIndex();\n try {\n setSelectedIndex(elementIndex);\n for (let dirIndex = start; dirIndex < end; dirIndex++) {\n const def = tView.data[dirIndex] as DirectiveDef<unknown>;\n const directive = lView[dirIndex];\n setCurrentDirectiveIndex(dirIndex);\n if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {\n invokeHostBindingsInCreationMode(def, directive);\n }\n }\n } finally {\n setSelectedIndex(-1);\n setCurrentDirectiveIndex(currentDirectiveIndex);\n }\n}\n\n/**\n * Invoke the host bindings in creation mode.\n *\n * @param def `DirectiveDef` which may contain the `hostBindings` function.\n * @param directive Instance of directive.\n */\nexport function invokeHostBindingsInCreationMode(def: DirectiveDef<any>, directive: any) {\n if (def.hostBindings !== null) {\n def.hostBindings!(RenderFlags.Create, directive);\n }\n}\n\n/**\n * Matches the current node against all available selectors.\n * If a component is matched (at most one), it is returned in first position in the array.\n */\nfunction findDirectiveDefMatches(\n tView: TView, tNode: TElementNode|TContainerNode|TElementContainerNode):\n [matches: DirectiveDef<unknown>[], hostDirectiveDefs: HostDirectiveDefs|null]|null {\n ngDevMode && assertFirstCreatePass(tView);\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);\n\n const registry = tView.directiveRegistry;\n let matches: DirectiveDef<unknown>[]|null = null;\n let hostDirectiveDefs: HostDirectiveDefs|null = null;\n if (registry) {\n for (let i = 0; i < registry.length; i++) {\n const def = registry[i] as ComponentDef<any>| DirectiveDef<any>;\n if (isNodeMatchingSelectorList(tNode, def.selectors!, /* isProjectionMode */ false)) {\n matches || (matches = []);\n\n if (isComponentDef(def)) {\n if (ngDevMode) {\n assertTNodeType(\n tNode, TNodeType.Element,\n `\"${tNode.value}\" tags cannot be used as component hosts. ` +\n `Please use a different tag to activate the ${stringify(def.type)} component.`);\n\n if (isComponentHost(tNode)) {\n throwMultipleComponentError(tNode, matches.find(isComponentDef)!.type, def.type);\n }\n }\n\n // Components are inserted at the front of the matches array so that their lifecycle\n // hooks run before any directive lifecycle hooks. This appears to be for ViewEngine\n // compatibility. This logic doesn't make sense with host directives, because it\n // would allow the host directives to undo any overrides the host may have made.\n // To handle this case, the host directives of components are inserted at the beginning\n // of the array, followed by the component. As such, the insertion order is as follows:\n // 1. Host directives belonging to the selector-matched component.\n // 2. Selector-matched component.\n // 3. Host directives belonging to selector-matched directives.\n // 4. Selector-matched directives.\n if (def.findHostDirectiveDefs !== null) {\n const hostDirectiveMatches: DirectiveDef<unknown>[] = [];\n hostDirectiveDefs = hostDirectiveDefs || new Map();\n def.findHostDirectiveDefs(def, hostDirectiveMatches, hostDirectiveDefs);\n // Add all host directives declared on this component, followed by the component itself.\n // Host directives should execute first so the host has a chance to override changes\n // to the DOM made by them.\n matches.unshift(...hostDirectiveMatches, def);\n // Component is offset starting from the beginning of the host directives array.\n const componentOffset = hostDirectiveMatches.length;\n markAsComponentHost(tView, tNode, componentOffset);\n } else {\n // No host directives on this component, just add the\n // component def to the beginning of the matches.\n matches.unshift(def);\n markAsComponentHost(tView, tNode, 0);\n }\n } else {\n // Append any host directives to the matches first.\n hostDirectiveDefs = hostDirectiveDefs || new Map();\n def.findHostDirectiveDefs?.(def, matches, hostDirectiveDefs);\n matches.push(def);\n }\n }\n }\n }\n return matches === null ? null : [matches, hostDirectiveDefs];\n}\n\n/**\n * Marks a given TNode as a component's host. This consists of:\n * - setting the component offset on the TNode.\n * - storing index of component's host element so it will be queued for view refresh during CD.\n */\nexport function markAsComponentHost(tView: TView, hostTNode: TNode, componentOffset: number): void {\n ngDevMode && assertFirstCreatePass(tView);\n ngDevMode && assertGreaterThan(componentOffset, -1, 'componentOffset must be great than -1');\n hostTNode.componentOffset = componentOffset;\n (tView.components ??= []).push(hostTNode.index);\n}\n\n/** Caches local names and their matching directive indices for query and template lookups. */\nfunction cacheMatchingLocalNames(\n tNode: TNode, localRefs: string[]|null, exportsMap: {[key: string]: number}): void {\n if (localRefs) {\n const localNames: (string|number)[] = tNode.localNames = [];\n\n // Local names must be stored in tNode in the same order that localRefs are defined\n // in the template to ensure the data is loaded in the same slots as their refs\n // in the template (for template queries).\n for (let i = 0; i < localRefs.length; i += 2) {\n const index = exportsMap[localRefs[i + 1]];\n if (index == null)\n throw new RuntimeError(\n RuntimeErrorCode.EXPORT_NOT_FOUND,\n ngDevMode && `Export of name '${localRefs[i + 1]}' not found!`);\n localNames.push(localRefs[i], index);\n }\n }\n}\n\n/**\n * Builds up an export map as directives are created, so local refs can be quickly mapped\n * to their directive instances.\n */\nfunction saveNameToExportMap(\n directiveIdx: number, def: DirectiveDef<any>|ComponentDef<any>,\n exportsMap: {[key: string]: number}|null) {\n if (exportsMap) {\n if (def.exportAs) {\n for (let i = 0; i < def.exportAs.length; i++) {\n exportsMap[def.exportAs[i]] = directiveIdx;\n }\n }\n if (isComponentDef(def)) exportsMap[''] = directiveIdx;\n }\n}\n\n/**\n * Initializes the flags on the current node, setting all indices to the initial index,\n * the directive count to 0, and adding the isComponent flag.\n * @param index the initial index\n */\nexport function initTNodeFlags(tNode: TNode, index: number, numberOfDirectives: number) {\n ngDevMode &&\n assertNotEqual(\n numberOfDirectives, tNode.directiveEnd - tNode.directiveStart,\n 'Reached the max number of directives');\n tNode.flags |= TNodeFlags.isDirectiveHost;\n // When the first directive is created on a node, save the index\n tNode.directiveStart = index;\n tNode.directiveEnd = index + numberOfDirectives;\n tNode.providerIndexes = index;\n}\n\n/**\n * Setup directive for instantiation.\n *\n * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well\n * as `LView`. `TView` gets the `DirectiveDef`.\n *\n * @param tView `TView`\n * @param tNode `TNode`\n * @param lView `LView`\n * @param directiveIndex Index where the directive will be stored in the Expando.\n * @param def `DirectiveDef`\n */\nexport function configureViewWithDirective<T>(\n tView: TView, tNode: TNode, lView: LView, directiveIndex: number, def: DirectiveDef<T>): void {\n ngDevMode &&\n assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section');\n tView.data[directiveIndex] = def;\n const directiveFactory =\n def.factory || ((def as {factory: Function}).factory = getFactoryDef(def.type, true));\n // Even though `directiveFactory` will already be using `ɵɵdirectiveInject` in its generated code,\n // we also want to support `inject()` directly from the directive constructor context so we set\n // `ɵɵdirectiveInject` as the inject implementation here too.\n const nodeInjectorFactory =\n new NodeInjectorFactory(directiveFactory, isComponentDef(def), ɵɵdirectiveInject);\n tView.blueprint[directiveIndex] = nodeInjectorFactory;\n lView[directiveIndex] = nodeInjectorFactory;\n\n registerHostBindingOpCodes(\n tView, tNode, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), def);\n}\n\nfunction addComponentLogic<T>(lView: LView, hostTNode: TElementNode, def: ComponentDef<T>): void {\n const native = getNativeByTNode(hostTNode, lView) as RElement;\n const tView = getOrCreateComponentTView(def);\n\n // Only component views should be added to the view tree directly. Embedded views are\n // accessed through their containers because they may be removed / re-added later.\n const rendererFactory = lView[RENDERER_FACTORY];\n const componentView = addToViewTree(\n lView,\n createLView(\n lView, tView, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, native,\n hostTNode as TElementNode, rendererFactory, rendererFactory.createRenderer(native, def),\n null, null, null));\n\n // Component view will always be created before any injected LContainers,\n // so this is a regular element, wrap it with the component view\n lView[hostTNode.index] = componentView;\n}\n\nexport function elementAttributeInternal(\n tNode: TNode, lView: LView, name: string, value: any, sanitizer: SanitizerFn|null|undefined,\n namespace: string|null|undefined) {\n if (ngDevMode) {\n assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');\n validateAgainstEventAttributes(name);\n assertTNodeType(\n tNode, TNodeType.Element,\n `Attempted to set attribute \\`${name}\\` on a container node. ` +\n `Host bindings are not valid on ng-container or ng-template.`);\n }\n const element = getNativeByTNode(tNode, lView) as RElement;\n setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);\n}\n\nexport function setElementAttribute(\n renderer: Renderer, element: RElement, namespace: string|null|undefined, tagName: string|null,\n name: string, value: any, sanitizer: SanitizerFn|null|undefined) {\n if (value == null) {\n ngDevMode && ngDevMode.rendererRemoveAttribute++;\n renderer.removeAttribute(element, name, namespace);\n } else {\n ngDevMode && ngDevMode.rendererSetAttribute++;\n const strValue =\n sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);\n\n\n renderer.setAttribute(element, name, strValue as string, namespace);\n }\n}\n\n/**\n * Sets initial input properties on directive instances from attribute data\n *\n * @param lView Current LView that is being processed.\n * @param directiveIndex Index of the directive in directives array\n * @param instance Instance of the directive on which to set the initial inputs\n * @param def The directive def that contains the list of inputs\n * @param tNode The static data for this node\n */\nfunction setInputsFromAttrs<T>(\n lView: LView, directiveIndex: number, instance: T, def: DirectiveDef<T>, tNode: TNode,\n initialInputData: InitialInputData): void {\n const initialInputs: InitialInputs|null = initialInputData![directiveIndex];\n if (initialInputs !== null) {\n const setInput = def.setInput;\n for (let i = 0; i < initialInputs.length;) {\n const publicName = initialInputs[i++];\n const privateName = initialInputs[i++];\n const value = initialInputs[i++];\n if (setInput !== null) {\n def.setInput!(instance, value, publicName, privateName);\n } else {\n (instance as any)[privateName] = value;\n }\n if (ngDevMode) {\n const nativeElement = getNativeByTNode(tNode, lView) as RElement;\n setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value);\n }\n }\n }\n}\n\n/**\n * Generates initialInputData for a node and stores it in the template's static storage\n * so subsequent template invocations don't have to recalculate it.\n *\n * initialInputData is an array containing values that need to be set as input properties\n * for directives on this node, but only once on creation. We need this array to support\n * the case where you set an @Input property of a directive using attribute-like syntax.\n * e.g. if you have a `name` @Input, you can set it once like this:\n *\n * <my-component name=\"Bess\"></my-component>\n *\n * @param inputs Input alias map that was generated from the directive def inputs.\n * @param directiveIndex Index of the directive that is currently being processed.\n * @param attrs Static attrs on this node.\n */\nfunction generateInitialInputs(\n inputs: PropertyAliases, directiveIndex: number, attrs: TAttributes): InitialInputs|null {\n let inputsToStore: InitialInputs|null = null;\n let i = 0;\n while (i < attrs.length) {\n const attrName = attrs[i];\n if (attrName === AttributeMarker.NamespaceURI) {\n // We do not allow inputs on namespaced attributes.\n i += 4;\n continue;\n } else if (attrName === AttributeMarker.ProjectAs) {\n // Skip over the `ngProjectAs` value.\n i += 2;\n continue;\n }\n\n // If we hit any other attribute markers, we're done anyway. None of those are valid inputs.\n if (typeof attrName === 'number') break;\n\n if (inputs.hasOwnProperty(attrName as string)) {\n if (inputsToStore === null) inputsToStore = [];\n\n // Find the input's public name from the input store. Note that we can be found easier\n // through the directive def, but we want to do it using the inputs store so that it can\n // account for host directive aliases.\n const inputConfig = inputs[attrName as string];\n for (let j = 0; j < inputConfig.length; j += 2) {\n if (inputConfig[j] === directiveIndex) {\n inputsToStore.push(\n attrName as string, inputConfig[j + 1] as string, attrs[i + 1] as string);\n // A directive can't have multiple inputs with the same name so we can break here.\n break;\n }\n }\n }\n\n i += 2;\n }\n return inputsToStore;\n}\n\n//////////////////////////\n//// ViewContainer & View\n//////////////////////////\n\n/**\n * Creates a LContainer, either from a container instruction, or for a ViewContainerRef.\n *\n * @param hostNative The host element for the LContainer\n * @param hostTNode The host TNode for the LContainer\n * @param currentView The parent view of the LContainer\n * @param native The native comment element\n * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case\n * @returns LContainer\n */\nexport function createLContainer(\n hostNative: RElement|RComment|LView, currentView: LView, native: RComment,\n tNode: TNode): LContainer {\n ngDevMode && assertLView(currentView);\n const lContainer: LContainer = [\n hostNative, // host native\n true, // Boolean `true` in this position signifies that this is an `LContainer`\n false, // has transplanted views\n currentView, // parent\n null, // next\n 0, // transplanted views to refresh count\n tNode, // t_host\n native, // native,\n null, // view refs\n null, // moved views\n ];\n ngDevMode &&\n assertEqual(\n lContainer.length, CONTAINER_HEADER_OFFSET,\n 'Should allocate correct number of slots for LContainer header.');\n return lContainer;\n}\n\n/**\n * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes\n * them by executing an associated template function.\n */\nfunction refreshEmbeddedViews(lView: LView) {\n for (let lContainer = getFirstLContainer(lView); lContainer !== null;\n lContainer = getNextLContainer(lContainer)) {\n for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {\n const embeddedLView = lContainer[i];\n const embeddedTView = embeddedLView[TVIEW];\n ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');\n if (viewAttachedToChangeDetector(embeddedLView)) {\n refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]!);\n }\n }\n }\n}\n\n/**\n * Mark transplanted views as needing to be refreshed at their insertion points.\n *\n * @param lView The `LView` that may have transplanted views.\n */\nfunction markTransplantedViewsForRefresh(lView: LView) {\n for (let lContainer = getFirstLContainer(lView); lContainer !== null;\n lContainer = getNextLContainer(lContainer)) {\n if (!lContainer[HAS_TRANSPLANTED_VIEWS]) continue;\n\n const movedViews = lContainer[MOVED_VIEWS]!;\n ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS');\n for (let i = 0; i < movedViews.length; i++) {\n const movedLView = movedViews[i]!;\n const insertionLContainer = movedLView[PARENT] as LContainer;\n ngDevMode && assertLContainer(insertionLContainer);\n // We don't want to increment the counter if the moved LView was already marked for\n // refresh.\n if ((movedLView[FLAGS] & LViewFlags.RefreshTransplantedView) === 0) {\n updateTransplantedViewCount(insertionLContainer, 1);\n }\n // Note, it is possible that the `movedViews` is tracking views that are transplanted *and*\n // those that aren't (declaration component === insertion component). In the latter case,\n // it's fine to add the flag, as we will clear it immediately in\n // `refreshEmbeddedViews` for the view currently being refreshed.\n movedLView[FLAGS] |= LViewFlags.RefreshTransplantedView;\n }\n }\n}\n\n/////////////\n\n/**\n * Refreshes components by entering the component view and processing its bindings, queries, etc.\n *\n * @param componentHostIdx Element index in LView[] (adjusted for HEADER_OFFSET)\n */\nfunction refreshComponent(hostLView: LView, componentHostIdx: number): void {\n ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');\n const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);\n // Only attached components that are CheckAlways or OnPush and dirty should be refreshed\n if (viewAttachedToChangeDetector(componentView)) {\n const tView = componentView[TVIEW];\n if (componentView[FLAGS] & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {\n refreshView(tView, componentView, tView.template, componentView[CONTEXT]);\n } else if (componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {\n // Only attached components that are CheckAlways or OnPush and dirty should be refreshed\n refreshContainsDirtyView(componentView);\n }\n }\n}\n\n/**\n * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are\n * children or descendants of the given lView.\n *\n * @param lView The lView which contains descendant transplanted views that need to be refreshed.\n */\nfunction refreshContainsDirtyView(lView: LView) {\n for (let lContainer = getFirstLContainer(lView); lContainer !== null;\n lContainer = getNextLContainer(lContainer)) {\n for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {\n const embeddedLView = lContainer[i];\n if (viewAttachedToChangeDetector(embeddedLView)) {\n if (embeddedLView[FLAGS] & LViewFlags.RefreshTransplantedView) {\n const embeddedTView = embeddedLView[TVIEW];\n ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');\n refreshView(\n embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]!);\n\n } else if (embeddedLView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {\n refreshContainsDirtyView(embeddedLView);\n }\n }\n }\n }\n\n const tView = lView[TVIEW];\n // Refresh child component views.\n const components = tView.components;\n if (components !== null) {\n for (let i = 0; i < components.length; i++) {\n const componentView = getComponentLViewByIndex(components[i], lView);\n // Only attached components that are CheckAlways or OnPush and dirty should be refreshed\n if (viewAttachedToChangeDetector(componentView) &&\n componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {\n refreshContainsDirtyView(componentView);\n }\n }\n }\n}\n\nfunction renderComponent(hostLView: LView, componentHostIdx: number) {\n ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');\n const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);\n const componentTView = componentView[TVIEW];\n syncViewWithBlueprint(componentTView, componentView);\n renderView(componentTView, componentView, componentView[CONTEXT]);\n}\n\n/**\n * Syncs an LView instance with its blueprint if they have gotten out of sync.\n *\n * Typically, blueprints and their view instances should always be in sync, so the loop here\n * will be skipped. However, consider this case of two components side-by-side:\n *\n * App template:\n * ```\n * <comp></comp>\n * <comp></comp>\n * ```\n *\n * The following will happen:\n * 1. App template begins processing.\n * 2. First <comp> is matched as a component and its LView is created.\n * 3. Second <comp> is matched as a component and its LView is created.\n * 4. App template completes processing, so it's time to check child templates.\n * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.\n * 6. Second <comp> template is checked. Its blueprint has been updated by the first\n * <comp> template, but its LView was created before this update, so it is out of sync.\n *\n * Note that embedded views inside ngFor loops will never be out of sync because these views\n * are processed as soon as they are created.\n *\n * @param tView The `TView` that contains the blueprint for syncing\n * @param lView The view to sync\n */\nfunction syncViewWithBlueprint(tView: TView, lView: LView) {\n for (let i = lView.length; i < tView.blueprint.length; i++) {\n lView.push(tView.blueprint[i]);\n }\n}\n\n/**\n * Adds LView or LContainer to the end of the current view tree.\n *\n * This structure will be used to traverse through nested views to remove listeners\n * and call onDestroy callbacks.\n *\n * @param lView The view where LView or LContainer should be added\n * @param adjustedHostIndex Index of the view's host node in LView[], adjusted for header\n * @param lViewOrLContainer The LView or LContainer to add to the view tree\n * @returns The state passed in\n */\nexport function addToViewTree<T extends LView|LContainer>(lView: LView, lViewOrLContainer: T): T {\n // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer\n // to the end of the queue, which means if the developer retrieves the LContainers from RNodes out\n // of order, the change detection will run out of order, as the act of retrieving the the\n // LContainer from the RNode is what adds it to the queue.\n if (lView[CHILD_HEAD]) {\n lView[CHILD_TAIL]![NEXT] = lViewOrLContainer;\n } else {\n lView[CHILD_HEAD] = lViewOrLContainer;\n }\n lView[CHILD_TAIL] = lViewOrLContainer;\n return lViewOrLContainer;\n}\n\n///////////////////////////////\n//// Change detection\n///////////////////////////////\n\n\n/**\n * Marks current view and all ancestors dirty.\n *\n * Returns the root view because it is found as a byproduct of marking the view tree\n * dirty, and can be used by methods that consume markViewDirty() to easily schedule\n * change detection. Otherwise, such methods would need to traverse up the view tree\n * an additional time to get the root view and schedule a tick on it.\n *\n * @param lView The starting LView to mark dirty\n * @returns the root LView\n */\nexport function markViewDirty(lView: LView): LView|null {\n while (lView) {\n lView[FLAGS] |= LViewFlags.Dirty;\n const parent = getLViewParent(lView);\n // Stop traversing up as soon as you find a root view that wasn't attached to any container\n if (isRootView(lView) && !parent) {\n return lView;\n }\n // continue otherwise\n lView = parent!;\n }\n return null;\n}\n\nexport function detectChangesInternal<T>(\n tView: TView, lView: LView, context: T, notifyErrorHandler = true) {\n const rendererFactory = lView[RENDERER_FACTORY];\n\n // Check no changes mode is a dev only mode used to verify that bindings have not changed\n // since they were assigned. We do not want to invoke renderer factory functions in that mode\n // to avoid any possible side-effects.\n const checkNoChangesMode = !!ngDevMode && isInCheckNoChangesMode();\n\n if (!checkNoChangesMode && rendererFactory.begin) rendererFactory.begin();\n try {\n refreshView(tView, lView, tView.template, context);\n } catch (error) {\n if (notifyErrorHandler) {\n handleError(lView, error);\n }\n throw error;\n } finally {\n if (!checkNoChangesMode && rendererFactory.end) rendererFactory.end();\n }\n}\n\nexport function checkNoChangesInternal<T>(\n tView: TView, lView: LView, context: T, notifyErrorHandler = true) {\n setIsInCheckNoChangesMode(true);\n try {\n detectChangesInternal(tView, lView, context, notifyErrorHandler);\n } finally {\n setIsInCheckNoChangesMode(false);\n }\n}\n\nfunction executeViewQueryFn<T>(\n flags: RenderFlags, viewQueryFn: ViewQueriesFunction<T>, component: T): void {\n ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');\n setCurrentQueryIndex(0);\n viewQueryFn(flags, component);\n}\n\n///////////////////////////////\n//// Bindings & interpolations\n///////////////////////////////\n\n/**\n * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.\n *\n * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:\n * - a bound property name;\n * - a static parts of interpolated strings;\n *\n * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a\n * property binding metadata will be stored in `TView.data` at the same index as a bound value in\n * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the\n * following format:\n * - `propertyName` for bound properties;\n * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for\n * interpolated properties.\n *\n * @param tData `TData` where meta-data will be saved;\n * @param tNode `TNode` that is a target of the binding;\n * @param propertyName bound property name;\n * @param bindingIndex binding index in `LView`\n * @param interpolationParts static interpolation parts (for property interpolations)\n */\nexport function storePropertyBindingMetadata(\n tData: TData, tNode: TNode, propertyName: string, bindingIndex: number,\n ...interpolationParts: string[]) {\n // Binding meta-data are stored only the first time a given property instruction is processed.\n // Since we don't have a concept of the \"first update pass\" we need to check for presence of the\n // binding meta-data to decide if one should be stored (or if was stored already).\n if (tData[bindingIndex] === null) {\n if (tNode.inputs == null || !tNode.inputs[propertyName]) {\n const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);\n propBindingIdxs.push(bindingIndex);\n let bindingMetadata = propertyName;\n if (interpolationParts.length > 0) {\n bindingMetadata +=\n INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);\n }\n tData[bindingIndex] = bindingMetadata;\n }\n }\n}\n\nexport function getOrCreateLViewCleanup(view: LView): any[] {\n // top level variables should not be exported for performance reasons (PERF_NOTES.md)\n return view[CLEANUP] || (view[CLEANUP] = []);\n}\n\nexport function getOrCreateTViewCleanup(tView: TView): any[] {\n return tView.cleanup || (tView.cleanup = []);\n}\n\n/**\n * There are cases where the sub component's renderer needs to be included\n * instead of the current renderer (see the componentSyntheticHost* instructions).\n */\nexport function loadComponentRenderer(\n currentDef: DirectiveDef<any>|null, tNode: TNode, lView: LView): Renderer {\n // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root\n // component (see packages/core/src/render3/component.ts). This is not consistent with the process\n // of creating inner components, when current directive index is available in the state. In order\n // to avoid relying on current def being `null` (thus special-casing root component creation), the\n // process of creating root component should be unified with the process of creating inner\n // components.\n if (currentDef === null || isComponentDef(currentDef)) {\n lView = unwrapLView(lView[tNode.index])!;\n }\n return lView[RENDERER];\n}\n\n/** Handles an error thrown in an LView. */\nexport function handleError(lView: LView, error: any): void {\n const injector = lView[INJECTOR];\n const errorHandler = injector ? injector.get(ErrorHandler, null) : null;\n errorHandler && errorHandler.handleError(error);\n}\n\n/**\n * Set the inputs of directives at the current node to corresponding value.\n *\n * @param tView The current TView\n * @param lView the `LView` which contains the directives.\n * @param inputs mapping between the public \"input\" name and privately-known,\n * possibly minified, property names to write to.\n * @param value Value to set.\n */\nexport function setInputsForProperty(\n tView: TView, lView: LView, inputs: PropertyAliasValue, publicName: string, value: any): void {\n for (let i = 0; i < inputs.length;) {\n const index = inputs[i++] as number;\n const privateName = inputs[i++] as string;\n const instance = lView[index];\n ngDevMode && assertIndexInRange(lView, index);\n const def = tView.data[index] as DirectiveDef<any>;\n if (def.setInput !== null) {\n def.setInput!(instance, value, publicName, privateName);\n } else {\n instance[privateName] = value;\n }\n }\n}\n\n/**\n * Updates a text binding at a given index in a given LView.\n */\nexport function textBindingInternal(lView: LView, index: number, value: string): void {\n ngDevMode && assertString(value, 'Value should be a string');\n ngDevMode && assertNotSame(value, NO_CHANGE as any, 'value should not be NO_CHANGE');\n ngDevMode && assertIndexInRange(lView, index);\n const element = getNativeByIndex(index, lView) as any as RText;\n ngDevMode && assertDefined(element, 'native element should exist');\n updateTextNode(lView[RENDERER], element, value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {concatStringsWithSpace} from '../../util/stringify';\nimport {assertFirstCreatePass} from '../assert';\nimport {AttributeMarker, TAttributes, TNode} from '../interfaces/node';\nimport {getTView} from '../state';\n\n/**\n * Compute the static styling (class/style) from `TAttributes`.\n *\n * This function should be called during `firstCreatePass` only.\n *\n * @param tNode The `TNode` into which the styling information should be loaded.\n * @param attrs `TAttributes` containing the styling information.\n * @param writeToHost Where should the resulting static styles be written?\n * - `false` Write to `TNode.stylesWithoutHost` / `TNode.classesWithoutHost`\n * - `true` Write to `TNode.styles` / `TNode.classes`\n */\nexport function computeStaticStyling(\n tNode: TNode, attrs: TAttributes|null, writeToHost: boolean): void {\n ngDevMode &&\n assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');\n let styles: string|null = writeToHost ? tNode.styles : null;\n let classes: string|null = writeToHost ? tNode.classes : null;\n let mode: AttributeMarker|0 = 0;\n if (attrs !== null) {\n for (let i = 0; i < attrs.length; i++) {\n const value = attrs[i];\n if (typeof value === 'number') {\n mode = value;\n } else if (mode == AttributeMarker.Classes) {\n classes = concatStringsWithSpace(classes, value as string);\n } else if (mode == AttributeMarker.Styles) {\n const style = value as string;\n const styleValue = attrs[++i] as string;\n styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';');\n }\n }\n }\n writeToHost ? tNode.styles = styles : tNode.stylesWithoutHost = styles;\n writeToHost ? tNode.classes = classes : tNode.classesWithoutHost = classes;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertParentView} from './assert';\nimport {icuContainerIterate} from './i18n/i18n_tree_shaking';\nimport {CONTAINER_HEADER_OFFSET} from './interfaces/container';\nimport {TIcuContainerNode, TNode, TNodeType} from './interfaces/node';\nimport {RNode} from './interfaces/renderer_dom';\nimport {isLContainer} from './interfaces/type_checks';\nimport {DECLARATION_COMPONENT_VIEW, LView, T_HOST, TVIEW, TView} from './interfaces/view';\nimport {assertTNodeType} from './node_assert';\nimport {getProjectionNodes} from './node_manipulation';\nimport {getLViewParent} from './util/view_traversal_utils';\nimport {unwrapRNode} from './util/view_utils';\n\n\n\nexport function collectNativeNodes(\n tView: TView, lView: LView, tNode: TNode|null, result: any[],\n isProjection: boolean = false): any[] {\n while (tNode !== null) {\n ngDevMode &&\n assertTNodeType(\n tNode,\n TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Projection | TNodeType.Icu);\n\n const lNode = lView[tNode.index];\n if (lNode !== null) {\n result.push(unwrapRNode(lNode));\n }\n\n // A given lNode can represent either a native node or a LContainer (when it is a host of a\n // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes\n // from the views in this container.\n if (isLContainer(lNode)) {\n for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {\n const lViewInAContainer = lNode[i];\n const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;\n if (lViewFirstChildTNode !== null) {\n collectNativeNodes(\n lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);\n }\n }\n }\n\n const tNodeType = tNode.type;\n if (tNodeType & TNodeType.ElementContainer) {\n collectNativeNodes(tView, lView, tNode.child, result);\n } else if (tNodeType & TNodeType.Icu) {\n const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);\n let rNode: RNode|null;\n while (rNode = nextRNode()) {\n result.push(rNode);\n }\n } else if (tNodeType & TNodeType.Projection) {\n const nodesInSlot = getProjectionNodes(lView, tNode);\n if (Array.isArray(nodesInSlot)) {\n result.push(...nodesInSlot);\n } else {\n const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW])!;\n ngDevMode && assertParentView(parentView);\n collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true);\n }\n }\n tNode = isProjection ? tNode.projectionNext : tNode.next;\n }\n\n return result;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef} from '../change_detection/change_detector_ref';\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {EmbeddedViewRef, InternalViewRef, ViewRefTracker} from '../linker/view_ref';\nimport {removeFromArray} from '../util/array_utils';\nimport {assertEqual} from '../util/assert';\n\nimport {collectNativeNodes} from './collect_native_nodes';\nimport {checkNoChangesInternal, detectChangesInternal, markViewDirty, storeCleanupWithContext} from './instructions/shared';\nimport {CONTAINER_HEADER_OFFSET, VIEW_REFS} from './interfaces/container';\nimport {isLContainer} from './interfaces/type_checks';\nimport {CONTEXT, FLAGS, LView, LViewFlags, PARENT, TVIEW} from './interfaces/view';\nimport {destroyLView, detachView, renderDetachView} from './node_manipulation';\n\n\n// Needed due to tsickle downleveling where multiple `implements` with classes creates\n// multiple @extends in Closure annotations, which is illegal. This workaround fixes\n// the multiple @extends by making the annotation @implements instead\ninterface ChangeDetectorRefInterface extends ChangeDetectorRef {}\n\nexport class ViewRef<T> implements EmbeddedViewRef<T>, InternalViewRef, ChangeDetectorRefInterface {\n private _appRef: ViewRefTracker|null = null;\n private _attachedToViewContainer = false;\n\n get rootNodes(): any[] {\n const lView = this._lView;\n const tView = lView[TVIEW];\n return collectNativeNodes(tView, lView, tView.firstChild, []);\n }\n\n constructor(\n /**\n * This represents `LView` associated with the component when ViewRef is a ChangeDetectorRef.\n *\n * When ViewRef is created for a dynamic component, this also represents the `LView` for the\n * component.\n *\n * For a \"regular\" ViewRef created for an embedded view, this is the `LView` for the embedded\n * view.\n *\n * @internal\n */\n public _lView: LView,\n\n /**\n * This represents the `LView` associated with the point where `ChangeDetectorRef` was\n * requested.\n *\n * This may be different from `_lView` if the `_cdRefInjectingView` is an embedded view.\n */\n private _cdRefInjectingView?: LView) {}\n\n get context(): T {\n return this._lView[CONTEXT] as unknown as T;\n }\n\n set context(value: T) {\n this._lView[CONTEXT] = value as unknown as {};\n }\n\n get destroyed(): boolean {\n return (this._lView[FLAGS] & LViewFlags.Destroyed) === LViewFlags.Destroyed;\n }\n\n destroy(): void {\n if (this._appRef) {\n this._appRef.detachView(this);\n } else if (this._attachedToViewContainer) {\n const parent = this._lView[PARENT];\n if (isLContainer(parent)) {\n const viewRefs = parent[VIEW_REFS] as ViewRef<unknown>[] | null;\n const index = viewRefs ? viewRefs.indexOf(this) : -1;\n if (index > -1) {\n ngDevMode &&\n assertEqual(\n index, parent.indexOf(this._lView) - CONTAINER_HEADER_OFFSET,\n 'An attached view should be in the same position within its container as its ViewRef in the VIEW_REFS array.');\n detachView(parent, index);\n removeFromArray(viewRefs!, index);\n }\n }\n this._attachedToViewContainer = false;\n }\n destroyLView(this._lView[TVIEW], this._lView);\n }\n\n onDestroy(callback: Function) {\n storeCleanupWithContext(this._lView[TVIEW], this._lView, null, callback);\n }\n\n /**\n * Marks a view and all of its ancestors dirty.\n *\n * This can be used to ensure an {@link ChangeDetectionStrategy#OnPush OnPush} component is\n * checked when it needs to be re-rendered but the two normal triggers haven't marked it\n * dirty (i.e. inputs haven't changed and events haven't fired in the view).\n *\n * <!-- TODO: Add a link to a chapter on OnPush components -->\n *\n * @usageNotes\n * ### Example\n *\n * ```typescript\n * @Component({\n * selector: 'app-root',\n * template: `Number of ticks: {{numberOfTicks}}`\n * changeDetection: ChangeDetectionStrategy.OnPush,\n * })\n * class AppComponent {\n * numberOfTicks = 0;\n *\n * constructor(private ref: ChangeDetectorRef) {\n * setInterval(() => {\n * this.numberOfTicks++;\n * // the following is required, otherwise the view will not be updated\n * this.ref.markForCheck();\n * }, 1000);\n * }\n * }\n * ```\n */\n markForCheck(): void {\n markViewDirty(this._cdRefInjectingView || this._lView);\n }\n\n /**\n * Detaches the view from the change detection tree.\n *\n * Detached views will not be checked during change detection runs until they are\n * re-attached, even if they are dirty. `detach` can be used in combination with\n * {@link ChangeDetectorRef#detectChanges detectChanges} to implement local change\n * detection checks.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->\n *\n * @usageNotes\n * ### Example\n *\n * The following example defines a component with a large list of readonly data.\n * Imagine the data changes constantly, many times per second. For performance reasons,\n * we want to check and update the list every five seconds. We can do that by detaching\n * the component's change detector and doing a local check every five seconds.\n *\n * ```typescript\n * class DataProvider {\n * // in a real application the returned data will be different every time\n * get data() {\n * return [1,2,3,4,5];\n * }\n * }\n *\n * @Component({\n * selector: 'giant-list',\n * template: `\n * <li *ngFor=\"let d of dataProvider.data\">Data {{d}}</li>\n * `,\n * })\n * class GiantList {\n * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {\n * ref.detach();\n * setInterval(() => {\n * this.ref.detectChanges();\n * }, 5000);\n * }\n * }\n *\n * @Component({\n * selector: 'app',\n * providers: [DataProvider],\n * template: `\n * <giant-list><giant-list>\n * `,\n * })\n * class App {\n * }\n * ```\n */\n detach(): void {\n this._lView[FLAGS] &= ~LViewFlags.Attached;\n }\n\n /**\n * Re-attaches a view to the change detection tree.\n *\n * This can be used to re-attach views that were previously detached from the tree\n * using {@link ChangeDetectorRef#detach detach}. Views are attached to the tree by default.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n *\n * @usageNotes\n * ### Example\n *\n * The following example creates a component displaying `live` data. The component will detach\n * its change detector from the main change detector tree when the component's live property\n * is set to false.\n *\n * ```typescript\n * class DataProvider {\n * data = 1;\n *\n * constructor() {\n * setInterval(() => {\n * this.data = this.data * 2;\n * }, 500);\n * }\n * }\n *\n * @Component({\n * selector: 'live-data',\n * inputs: ['live'],\n * template: 'Data: {{dataProvider.data}}'\n * })\n * class LiveData {\n * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}\n *\n * set live(value) {\n * if (value) {\n * this.ref.reattach();\n * } else {\n * this.ref.detach();\n * }\n * }\n * }\n *\n * @Component({\n * selector: 'app-root',\n * providers: [DataProvider],\n * template: `\n * Live Update: <input type=\"checkbox\" [(ngModel)]=\"live\">\n * <live-data [live]=\"live\"><live-data>\n * `,\n * })\n * class AppComponent {\n * live = true;\n * }\n * ```\n */\n reattach(): void {\n this._lView[FLAGS] |= LViewFlags.Attached;\n }\n\n /**\n * Checks the view and its children.\n *\n * This can also be used in combination with {@link ChangeDetectorRef#detach detach} to implement\n * local change detection checks.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->\n *\n * @usageNotes\n * ### Example\n *\n * The following example defines a component with a large list of readonly data.\n * Imagine, the data changes constantly, many times per second. For performance reasons,\n * we want to check and update the list every five seconds.\n *\n * We can do that by detaching the component's change detector and doing a local change detection\n * check every five seconds.\n *\n * See {@link ChangeDetectorRef#detach detach} for more information.\n */\n detectChanges(): void {\n detectChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});\n }\n\n /**\n * Checks the change detector and its children, and throws if any changes are detected.\n *\n * This is used in development mode to verify that running change detection doesn't\n * introduce other changes.\n */\n checkNoChanges(): void {\n if (ngDevMode) {\n checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});\n }\n }\n\n attachToViewContainerRef() {\n if (this._appRef) {\n throw new RuntimeError(\n RuntimeErrorCode.VIEW_ALREADY_ATTACHED,\n ngDevMode && 'This view is already attached directly to the ApplicationRef!');\n }\n this._attachedToViewContainer = true;\n }\n\n detachFromAppRef() {\n this._appRef = null;\n renderDetachView(this._lView[TVIEW], this._lView);\n }\n\n attachToAppRef(appRef: ViewRefTracker) {\n if (this._attachedToViewContainer) {\n throw new RuntimeError(\n RuntimeErrorCode.VIEW_ALREADY_ATTACHED,\n ngDevMode && 'This view is already attached to a ViewContainer!');\n }\n this._appRef = appRef;\n }\n}\n\n/** @internal */\nexport class RootViewRef<T> extends ViewRef<T> {\n constructor(public _view: LView) {\n super(_view);\n }\n\n override detectChanges(): void {\n const lView = this._view;\n const tView = lView[TVIEW];\n const context = lView[CONTEXT];\n detectChangesInternal(tView, lView, context, false);\n }\n\n override checkNoChanges(): void {\n if (ngDevMode) {\n const lView = this._view;\n const tView = lView[TVIEW];\n const context = lView[CONTEXT];\n checkNoChangesInternal(tView, lView, context, false);\n }\n }\n\n override get context(): T {\n return null!;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef} from '../change_detection/change_detector_ref';\nimport {Injector} from '../di/injector';\nimport {convertToBitFlags} from '../di/injector_compatibility';\nimport {InjectFlags, InjectOptions} from '../di/interface/injector';\nimport {ProviderToken} from '../di/provider_token';\nimport {EnvironmentInjector} from '../di/r3_injector';\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {Type} from '../interface/type';\nimport {ComponentFactory as AbstractComponentFactory, ComponentRef as AbstractComponentRef} from '../linker/component_factory';\nimport {ComponentFactoryResolver as AbstractComponentFactoryResolver} from '../linker/component_factory_resolver';\nimport {createElementRef, ElementRef} from '../linker/element_ref';\nimport {NgModuleRef} from '../linker/ng_module_factory';\nimport {Renderer2, RendererFactory2} from '../render/api';\nimport {Sanitizer} from '../sanitization/sanitizer';\nimport {assertDefined, assertGreaterThan, assertIndexInRange} from '../util/assert';\nimport {VERSION} from '../version';\nimport {NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR} from '../view/provider_flags';\n\nimport {assertComponentType} from './assert';\nimport {attachPatchData} from './context_discovery';\nimport {getComponentDef} from './definition';\nimport {getNodeInjectable, NodeInjector} from './di';\nimport {throwProviderNotFoundError} from './errors_di';\nimport {registerPostOrderHooks} from './hooks';\nimport {reportUnknownPropertyError} from './instructions/element_validation';\nimport {addToViewTree, createLView, createTView, executeContentQueries, getOrCreateComponentTView, getOrCreateTNode, initializeDirectives, invokeDirectivesHostBindings, locateHostElement, markAsComponentHost, markViewDirty, renderView, setInputsForProperty} from './instructions/shared';\nimport {ComponentDef, DirectiveDef, HostDirectiveDefs} from './interfaces/definition';\nimport {PropertyAliasValue, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType} from './interfaces/node';\nimport {Renderer, RendererFactory} from './interfaces/renderer';\nimport {RElement, RNode} from './interfaces/renderer_dom';\nimport {CONTEXT, HEADER_OFFSET, LView, LViewFlags, TVIEW, TViewType} from './interfaces/view';\nimport {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';\nimport {createElementNode, setupStaticAttributes, writeDirectClass} from './node_manipulation';\nimport {extractAttrsAndClassesFromSelector, stringifyCSSSelectorList} from './node_selector_matcher';\nimport {enterView, getCurrentTNode, getLView, leaveView} from './state';\nimport {computeStaticStyling} from './styling/static_styling';\nimport {mergeHostAttrs, setUpAttributes} from './util/attrs_utils';\nimport {stringifyForError} from './util/stringify_utils';\nimport {getComponentLViewByIndex, getNativeByTNode, getTNode} from './util/view_utils';\nimport {RootViewRef, ViewRef} from './view_ref';\n\nexport class ComponentFactoryResolver extends AbstractComponentFactoryResolver {\n /**\n * @param ngModule The NgModuleRef to which all resolved factories are bound.\n */\n constructor(private ngModule?: NgModuleRef<any>) {\n super();\n }\n\n override resolveComponentFactory<T>(component: Type<T>): AbstractComponentFactory<T> {\n ngDevMode && assertComponentType(component);\n const componentDef = getComponentDef(component)!;\n return new ComponentFactory(componentDef, this.ngModule);\n }\n}\n\nfunction toRefArray(map: {[key: string]: string}): {propName: string; templateName: string;}[] {\n const array: {propName: string; templateName: string;}[] = [];\n for (let nonMinified in map) {\n if (map.hasOwnProperty(nonMinified)) {\n const minified = map[nonMinified];\n array.push({propName: minified, templateName: nonMinified});\n }\n }\n return array;\n}\n\nfunction getNamespace(elementName: string): string|null {\n const name = elementName.toLowerCase();\n return name === 'svg' ? SVG_NAMESPACE : (name === 'math' ? MATH_ML_NAMESPACE : null);\n}\n\n/**\n * Injector that looks up a value using a specific injector, before falling back to the module\n * injector. Used primarily when creating components or embedded views dynamically.\n */\nclass ChainedInjector implements Injector {\n constructor(private injector: Injector, private parentInjector: Injector) {}\n\n get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags|InjectOptions): T {\n flags = convertToBitFlags(flags);\n const value = this.injector.get<T|typeof NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR>(\n token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);\n\n if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||\n notFoundValue === (NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as unknown as T)) {\n // Return the value from the root element injector when\n // - it provides it\n // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)\n // - the module injector should not be checked\n // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)\n return value as T;\n }\n\n return this.parentInjector.get(token, notFoundValue, flags);\n }\n}\n\n/**\n * ComponentFactory interface implementation.\n */\nexport class ComponentFactory<T> extends AbstractComponentFactory<T> {\n override selector: string;\n override componentType: Type<any>;\n override ngContentSelectors: string[];\n isBoundToModule: boolean;\n\n override get inputs(): {propName: string; templateName: string;}[] {\n return toRefArray(this.componentDef.inputs);\n }\n\n override get outputs(): {propName: string; templateName: string;}[] {\n return toRefArray(this.componentDef.outputs);\n }\n\n /**\n * @param componentDef The component definition.\n * @param ngModule The NgModuleRef to which the factory is bound.\n */\n constructor(private componentDef: ComponentDef<any>, private ngModule?: NgModuleRef<any>) {\n super();\n this.componentType = componentDef.type;\n this.selector = stringifyCSSSelectorList(componentDef.selectors);\n this.ngContentSelectors =\n componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];\n this.isBoundToModule = !!ngModule;\n }\n\n override create(\n injector: Injector, projectableNodes?: any[][]|undefined, rootSelectorOrNode?: any,\n environmentInjector?: NgModuleRef<any>|EnvironmentInjector|\n undefined): AbstractComponentRef<T> {\n environmentInjector = environmentInjector || this.ngModule;\n\n let realEnvironmentInjector = environmentInjector instanceof EnvironmentInjector ?\n environmentInjector :\n environmentInjector?.injector;\n\n if (realEnvironmentInjector && this.componentDef.getStandaloneInjector !== null) {\n realEnvironmentInjector = this.componentDef.getStandaloneInjector(realEnvironmentInjector) ||\n realEnvironmentInjector;\n }\n\n const rootViewInjector =\n realEnvironmentInjector ? new ChainedInjector(injector, realEnvironmentInjector) : injector;\n\n const rendererFactory = rootViewInjector.get(RendererFactory2, null);\n if (rendererFactory === null) {\n throw new RuntimeError(\n RuntimeErrorCode.RENDERER_NOT_FOUND,\n ngDevMode &&\n 'Angular was not able to inject a renderer (RendererFactory2). ' +\n 'Likely this is due to a broken DI hierarchy. ' +\n 'Make sure that any injector used to create this component has a correct parent.');\n }\n const sanitizer = rootViewInjector.get(Sanitizer, null);\n\n const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);\n // Determine a tag name used for creating host elements when this component is created\n // dynamically. Default to 'div' if this component did not specify any tag name in its selector.\n const elementName = this.componentDef.selectors[0][0] as string || 'div';\n const hostRNode = rootSelectorOrNode ?\n locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :\n createElementNode(hostRenderer, elementName, getNamespace(elementName));\n\n const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :\n LViewFlags.CheckAlways | LViewFlags.IsRoot;\n\n // Create the root view. Uses empty TView and ContentTemplate.\n const rootTView = createTView(TViewType.Root, null, null, 1, 0, null, null, null, null, null);\n const rootLView = createLView(\n null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer,\n rootViewInjector, null);\n\n // rootView is the parent when bootstrapping\n // TODO(misko): it looks like we are entering view here but we don't really need to as\n // `renderView` does that. However as the code is written it is needed because\n // `createRootComponentView` and `createRootComponent` both read global state. Fixing those\n // issues would allow us to drop this.\n enterView(rootLView);\n\n let component: T;\n let tElementNode: TElementNode;\n\n try {\n const rootComponentDef = this.componentDef;\n let rootDirectives: DirectiveDef<unknown>[];\n let hostDirectiveDefs: HostDirectiveDefs|null = null;\n\n if (rootComponentDef.findHostDirectiveDefs) {\n rootDirectives = [];\n hostDirectiveDefs = new Map();\n rootComponentDef.findHostDirectiveDefs(rootComponentDef, rootDirectives, hostDirectiveDefs);\n rootDirectives.push(rootComponentDef);\n } else {\n rootDirectives = [rootComponentDef];\n }\n\n const hostTNode = createRootComponentTNode(rootLView, hostRNode);\n const componentView = createRootComponentView(\n hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView, rendererFactory,\n hostRenderer);\n\n tElementNode = getTNode(rootTView, HEADER_OFFSET) as TElementNode;\n\n // TODO(crisbeto): in practice `hostRNode` should always be defined, but there are some tests\n // where the renderer is mocked out and `undefined` is returned. We should update the tests so\n // that this check can be removed.\n if (hostRNode) {\n setRootNodeAttributes(hostRenderer, rootComponentDef, hostRNode, rootSelectorOrNode);\n }\n\n if (projectableNodes !== undefined) {\n projectNodes(tElementNode, this.ngContentSelectors, projectableNodes);\n }\n\n // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and\n // executed here?\n // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref\n component = createRootComponent(\n componentView, rootComponentDef, rootDirectives, hostDirectiveDefs, rootLView,\n [LifecycleHooksFeature]);\n renderView(rootTView, rootLView, null);\n } finally {\n leaveView();\n }\n\n return new ComponentRef(\n this.componentType, component, createElementRef(tElementNode, rootLView), rootLView,\n tElementNode);\n }\n}\n\n/**\n * Represents an instance of a Component created via a {@link ComponentFactory}.\n *\n * `ComponentRef` provides access to the Component Instance as well other objects related to this\n * Component Instance and allows you to destroy the Component Instance via the {@link #destroy}\n * method.\n *\n */\nexport class ComponentRef<T> extends AbstractComponentRef<T> {\n override instance: T;\n override hostView: ViewRef<T>;\n override changeDetectorRef: ChangeDetectorRef;\n override componentType: Type<T>;\n\n constructor(\n componentType: Type<T>, instance: T, public location: ElementRef, private _rootLView: LView,\n private _tNode: TElementNode|TContainerNode|TElementContainerNode) {\n super();\n this.instance = instance;\n this.hostView = this.changeDetectorRef = new RootViewRef<T>(_rootLView);\n this.componentType = componentType;\n }\n\n override setInput(name: string, value: unknown): void {\n const inputData = this._tNode.inputs;\n let dataValue: PropertyAliasValue|undefined;\n if (inputData !== null && (dataValue = inputData[name])) {\n const lView = this._rootLView;\n setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);\n const childComponentLView = getComponentLViewByIndex(this._tNode.index, lView);\n markViewDirty(childComponentLView);\n } else {\n if (ngDevMode) {\n const cmpNameForError = stringifyForError(this.componentType);\n let message =\n `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `;\n message += `Make sure that the '${\n name}' property is annotated with @Input() or a mapped @Input('${name}') exists.`;\n reportUnknownPropertyError(message);\n }\n }\n }\n\n override get injector(): Injector {\n return new NodeInjector(this._tNode, this._rootLView);\n }\n\n override destroy(): void {\n this.hostView.destroy();\n }\n\n override onDestroy(callback: () => void): void {\n this.hostView.onDestroy(callback);\n }\n}\n\n/** Represents a HostFeature function. */\ntype HostFeature = (<T>(component: T, componentDef: ComponentDef<T>) => void);\n\n// TODO: A hack to not pull in the NullInjector from @angular/core.\nexport const NULL_INJECTOR: Injector = {\n get: (token: any, notFoundValue?: any) => {\n throwProviderNotFoundError(token, 'NullInjector');\n }\n};\n\n/** Creates a TNode that can be used to instantiate a root component. */\nfunction createRootComponentTNode(lView: LView, rNode: RNode): TElementNode {\n const tView = lView[TVIEW];\n const index = HEADER_OFFSET;\n ngDevMode && assertIndexInRange(lView, index);\n lView[index] = rNode;\n\n // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at\n // the same time we want to communicate the debug `TNode` that this is a special `TNode`\n // representing a host element.\n return getOrCreateTNode(tView, index, TNodeType.Element, '#host', null);\n}\n\n/**\n * Creates the root component view and the root component node.\n *\n * @param rNode Render host element.\n * @param rootComponentDef ComponentDef\n * @param rootView The parent view where the host node is stored\n * @param rendererFactory Factory to be used for creating child renderers.\n * @param hostRenderer The current renderer\n * @param sanitizer The sanitizer, if provided\n *\n * @returns Component view created\n */\nfunction createRootComponentView(\n tNode: TElementNode, rNode: RElement|null, rootComponentDef: ComponentDef<any>,\n rootDirectives: DirectiveDef<any>[], rootView: LView, rendererFactory: RendererFactory,\n hostRenderer: Renderer, sanitizer?: Sanitizer|null): LView {\n const tView = rootView[TVIEW];\n applyRootComponentStyling(rootDirectives, tNode, rNode, hostRenderer);\n\n const viewRenderer = rendererFactory.createRenderer(rNode, rootComponentDef);\n const componentView = createLView(\n rootView, getOrCreateComponentTView(rootComponentDef), null,\n rootComponentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, rootView[tNode.index],\n tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);\n\n if (tView.firstCreatePass) {\n markAsComponentHost(tView, tNode, rootDirectives.length - 1);\n }\n\n addToViewTree(rootView, componentView);\n\n // Store component view at node index, with node as the HOST\n return rootView[tNode.index] = componentView;\n}\n\n/** Sets up the styling information on a root component. */\nfunction applyRootComponentStyling(\n rootDirectives: DirectiveDef<any>[], tNode: TElementNode, rNode: RElement|null,\n hostRenderer: Renderer): void {\n for (const def of rootDirectives) {\n tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);\n }\n\n if (tNode.mergedAttrs !== null) {\n computeStaticStyling(tNode, tNode.mergedAttrs, true);\n\n if (rNode !== null) {\n setupStaticAttributes(hostRenderer, rNode, tNode);\n }\n }\n}\n\n/**\n * Creates a root component and sets it up with features and host bindings.Shared by\n * renderComponent() and ViewContainerRef.createComponent().\n */\nfunction createRootComponent<T>(\n componentView: LView, rootComponentDef: ComponentDef<T>, rootDirectives: DirectiveDef<any>[],\n hostDirectiveDefs: HostDirectiveDefs|null, rootLView: LView,\n hostFeatures: HostFeature[]|null): any {\n const rootTNode = getCurrentTNode() as TElementNode;\n ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');\n const tView = rootLView[TVIEW];\n const native = getNativeByTNode(rootTNode, rootLView);\n\n initializeDirectives(tView, rootLView, rootTNode, rootDirectives, null, hostDirectiveDefs);\n\n for (let i = 0; i < rootDirectives.length; i++) {\n const directiveIndex = rootTNode.directiveStart + i;\n const directiveInstance = getNodeInjectable(rootLView, tView, directiveIndex, rootTNode);\n attachPatchData(directiveInstance, rootLView);\n }\n\n invokeDirectivesHostBindings(tView, rootLView, rootTNode);\n\n if (native) {\n attachPatchData(native, rootLView);\n }\n\n // We're guaranteed for the `componentOffset` to be positive here\n // since a root component always matches a component def.\n ngDevMode &&\n assertGreaterThan(rootTNode.componentOffset, -1, 'componentOffset must be great than -1');\n const component = getNodeInjectable(\n rootLView, tView, rootTNode.directiveStart + rootTNode.componentOffset, rootTNode);\n componentView[CONTEXT] = rootLView[CONTEXT] = component;\n\n if (hostFeatures !== null) {\n for (const feature of hostFeatures) {\n feature(component, rootComponentDef);\n }\n }\n\n // We want to generate an empty QueryList for root content queries for backwards\n // compatibility with ViewEngine.\n executeContentQueries(tView, rootTNode, componentView);\n\n return component;\n}\n\n/** Sets the static attributes on a root component. */\nfunction setRootNodeAttributes(\n hostRenderer: Renderer2, componentDef: ComponentDef<unknown>, hostRNode: RElement,\n rootSelectorOrNode: any) {\n if (rootSelectorOrNode) {\n setUpAttributes(hostRenderer, hostRNode, ['ng-version', VERSION.full]);\n } else {\n // If host element is created as a part of this function call (i.e. `rootSelectorOrNode`\n // is not defined), also apply attributes and classes extracted from component selector.\n // Extract attributes and classes from the first selector only to match VE behavior.\n const {attrs, classes} = extractAttrsAndClassesFromSelector(componentDef.selectors[0]);\n if (attrs) {\n setUpAttributes(hostRenderer, hostRNode, attrs);\n }\n if (classes && classes.length > 0) {\n writeDirectClass(hostRenderer, hostRNode, classes.join(' '));\n }\n }\n}\n\n/** Projects the `projectableNodes` that were specified when creating a root component. */\nfunction projectNodes(\n tNode: TElementNode, ngContentSelectors: string[], projectableNodes: any[][]) {\n const projection: (TNode|RNode[]|null)[] = tNode.projection = [];\n for (let i = 0; i < ngContentSelectors.length; i++) {\n const nodesforSlot = projectableNodes[i];\n // Projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade\n // case). Here we do normalize passed data structure to be an array of arrays to avoid\n // complex checks down the line.\n // We also normalize the length of the passed in projectable nodes (to match the number of\n // <ng-container> slots defined by a component).\n projection.push(nodesforSlot != null ? Array.from(nodesforSlot) : null);\n }\n}\n\n/**\n * Used to enable lifecycle hooks on the root component.\n *\n * Include this feature when calling `renderComponent` if the root component\n * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't\n * be called properly.\n *\n * Example:\n *\n * ```\n * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});\n * ```\n */\nexport function LifecycleHooksFeature(): void {\n const tNode = getCurrentTNode()!;\n ngDevMode && assertDefined(tNode, 'TNode is required');\n registerPostOrderHooks(getLView()[TVIEW], tNode);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {Type, Writable} from '../../interface/type';\nimport {EMPTY_ARRAY, EMPTY_OBJ} from '../../util/empty';\nimport {fillProperties} from '../../util/property';\nimport {ComponentDef, ContentQueriesFunction, DirectiveDef, DirectiveDefFeature, HostBindingsFunction, RenderFlags, ViewQueriesFunction} from '../interfaces/definition';\nimport {TAttributes} from '../interfaces/node';\nimport {isComponentDef} from '../interfaces/type_checks';\nimport {mergeHostAttrs} from '../util/attrs_utils';\nimport {stringifyForError} from '../util/stringify_utils';\n\nexport function getSuperType(type: Type<any>): Type<any>&\n {ɵcmp?: ComponentDef<any>, ɵdir?: DirectiveDef<any>} {\n return Object.getPrototypeOf(type.prototype).constructor;\n}\n\ntype WritableDef = Writable<DirectiveDef<any>|ComponentDef<any>>;\n\n/**\n * Merges the definition from a super class to a sub class.\n * @param definition The definition that is a SubClass of another directive of component\n *\n * @codeGenApi\n */\nexport function ɵɵInheritDefinitionFeature(definition: DirectiveDef<any>|ComponentDef<any>): void {\n let superType = getSuperType(definition.type);\n let shouldInheritFields = true;\n const inheritanceChain: WritableDef[] = [definition];\n\n while (superType) {\n let superDef: DirectiveDef<any>|ComponentDef<any>|undefined = undefined;\n if (isComponentDef(definition)) {\n // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.\n superDef = superType.ɵcmp || superType.ɵdir;\n } else {\n if (superType.ɵcmp) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_INHERITANCE,\n ngDevMode &&\n `Directives cannot inherit Components. Directive ${\n stringifyForError(definition.type)} is attempting to extend component ${\n stringifyForError(superType)}`);\n }\n // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.\n superDef = superType.ɵdir;\n }\n\n if (superDef) {\n if (shouldInheritFields) {\n inheritanceChain.push(superDef);\n // Some fields in the definition may be empty, if there were no values to put in them that\n // would've justified object creation. Unwrap them if necessary.\n const writeableDef = definition as WritableDef;\n writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);\n writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);\n writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);\n\n // Merge hostBindings\n const superHostBindings = superDef.hostBindings;\n superHostBindings && inheritHostBindings(definition, superHostBindings);\n\n // Merge queries\n const superViewQuery = superDef.viewQuery;\n const superContentQueries = superDef.contentQueries;\n superViewQuery && inheritViewQuery(definition, superViewQuery);\n superContentQueries && inheritContentQueries(definition, superContentQueries);\n\n // Merge inputs and outputs\n fillProperties(definition.inputs, superDef.inputs);\n fillProperties(definition.declaredInputs, superDef.declaredInputs);\n fillProperties(definition.outputs, superDef.outputs);\n\n // Merge animations metadata.\n // If `superDef` is a Component, the `data` field is present (defaults to an empty object).\n if (isComponentDef(superDef) && superDef.data.animation) {\n // If super def is a Component, the `definition` is also a Component, since Directives can\n // not inherit Components (we throw an error above and cannot reach this code).\n const defData = (definition as ComponentDef<any>).data;\n defData.animation = (defData.animation || []).concat(superDef.data.animation);\n }\n }\n\n // Run parent features\n const features = superDef.features;\n if (features) {\n for (let i = 0; i < features.length; i++) {\n const feature = features[i];\n if (feature && feature.ngInherit) {\n (feature as DirectiveDefFeature)(definition);\n }\n // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this\n // def already has all the necessary information inherited from its super class(es), so we\n // can stop merging fields from super classes. However we need to iterate through the\n // prototype chain to look for classes that might contain other \"features\" (like\n // NgOnChanges), which we should invoke for the original `definition`. We set the\n // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance\n // logic and only invoking functions from the \"features\" list.\n if (feature === ɵɵInheritDefinitionFeature) {\n shouldInheritFields = false;\n }\n }\n }\n }\n\n superType = Object.getPrototypeOf(superType);\n }\n mergeHostAttrsAcrossInheritance(inheritanceChain);\n}\n\n/**\n * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.\n *\n * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing\n * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child\n * type.\n */\nfunction mergeHostAttrsAcrossInheritance(inheritanceChain: WritableDef[]) {\n let hostVars: number = 0;\n let hostAttrs: TAttributes|null = null;\n // We process the inheritance order from the base to the leaves here.\n for (let i = inheritanceChain.length - 1; i >= 0; i--) {\n const def = inheritanceChain[i];\n // For each `hostVars`, we need to add the superclass amount.\n def.hostVars = (hostVars += def.hostVars);\n // for each `hostAttrs` we need to merge it with superclass.\n def.hostAttrs =\n mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));\n }\n}\n\nfunction maybeUnwrapEmpty<T>(value: T[]): T[];\nfunction maybeUnwrapEmpty<T>(value: T): T;\nfunction maybeUnwrapEmpty(value: any): any {\n if (value === EMPTY_OBJ) {\n return {};\n } else if (value === EMPTY_ARRAY) {\n return [];\n } else {\n return value;\n }\n}\n\nfunction inheritViewQuery(definition: WritableDef, superViewQuery: ViewQueriesFunction<any>) {\n const prevViewQuery = definition.viewQuery;\n if (prevViewQuery) {\n definition.viewQuery = (rf, ctx) => {\n superViewQuery(rf, ctx);\n prevViewQuery(rf, ctx);\n };\n } else {\n definition.viewQuery = superViewQuery;\n }\n}\n\nfunction inheritContentQueries(\n definition: WritableDef, superContentQueries: ContentQueriesFunction<any>) {\n const prevContentQueries = definition.contentQueries;\n if (prevContentQueries) {\n definition.contentQueries = (rf, ctx, directiveIndex) => {\n superContentQueries(rf, ctx, directiveIndex);\n prevContentQueries(rf, ctx, directiveIndex);\n };\n } else {\n definition.contentQueries = superContentQueries;\n }\n}\n\nfunction inheritHostBindings(\n definition: WritableDef, superHostBindings: HostBindingsFunction<any>) {\n const prevHostBindings = definition.hostBindings;\n if (prevHostBindings) {\n definition.hostBindings = (rf: RenderFlags, ctx: any) => {\n superHostBindings(rf, ctx);\n prevHostBindings(rf, ctx);\n };\n } else {\n definition.hostBindings = superHostBindings;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {resolveForwardRef} from '../../di';\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {Type} from '../../interface/type';\nimport {assertEqual} from '../../util/assert';\nimport {EMPTY_OBJ} from '../../util/empty';\nimport {getComponentDef, getDirectiveDef} from '../definition';\nimport {DirectiveDef, HostDirectiveBindingMap, HostDirectiveDef, HostDirectiveDefs} from '../interfaces/definition';\n\n/** Values that can be used to define a host directive through the `HostDirectivesFeature`. */\ntype HostDirectiveConfig = Type<unknown>|{\n directive: Type<unknown>;\n inputs?: string[];\n outputs?: string[];\n};\n\n/**\n * This feature adds the host directives behavior to a directive definition by patching a\n * function onto it. The expectation is that the runtime will invoke the function during\n * directive matching.\n *\n * For example:\n * ```ts\n * class ComponentWithHostDirective {\n * static ɵcmp = defineComponent({\n * type: ComponentWithHostDirective,\n * features: [ɵɵHostDirectivesFeature([\n * SimpleHostDirective,\n * {directive: AdvancedHostDirective, inputs: ['foo: alias'], outputs: ['bar']},\n * ])]\n * });\n * }\n * ```\n *\n * @codeGenApi\n */\nexport function ɵɵHostDirectivesFeature(rawHostDirectives: HostDirectiveConfig[]|\n (() => HostDirectiveConfig[])) {\n return (definition: DirectiveDef<unknown>) => {\n definition.findHostDirectiveDefs = findHostDirectiveDefs;\n definition.hostDirectives =\n (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => {\n return typeof dir === 'function' ?\n {directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ} :\n {\n directive: resolveForwardRef(dir.directive),\n inputs: bindingArrayToMap(dir.inputs),\n outputs: bindingArrayToMap(dir.outputs)\n };\n });\n };\n}\n\nfunction findHostDirectiveDefs(\n currentDef: DirectiveDef<unknown>, matchedDefs: DirectiveDef<unknown>[],\n hostDirectiveDefs: HostDirectiveDefs): void {\n if (currentDef.hostDirectives !== null) {\n for (const hostDirectiveConfig of currentDef.hostDirectives) {\n const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive)!;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n validateHostDirective(hostDirectiveConfig, hostDirectiveDef, matchedDefs);\n }\n\n // We need to patch the `declaredInputs` so that\n // `ngOnChanges` can map the properties correctly.\n patchDeclaredInputs(hostDirectiveDef.declaredInputs, hostDirectiveConfig.inputs);\n\n // Host directives execute before the host so that its host bindings can be overwritten.\n findHostDirectiveDefs(hostDirectiveDef, matchedDefs, hostDirectiveDefs);\n hostDirectiveDefs.set(hostDirectiveDef, hostDirectiveConfig);\n matchedDefs.push(hostDirectiveDef);\n }\n }\n}\n\n/**\n * Converts an array in the form of `['publicName', 'alias', 'otherPublicName', 'otherAlias']` into\n * a map in the form of `{publicName: 'alias', otherPublicName: 'otherAlias'}`.\n */\nfunction bindingArrayToMap(bindings: string[]|undefined): HostDirectiveBindingMap {\n if (bindings === undefined || bindings.length === 0) {\n return EMPTY_OBJ;\n }\n\n const result: HostDirectiveBindingMap = {};\n\n for (let i = 0; i < bindings.length; i += 2) {\n result[bindings[i]] = bindings[i + 1];\n }\n\n return result;\n}\n\n/**\n * `ngOnChanges` has some leftover legacy ViewEngine behavior where the keys inside the\n * `SimpleChanges` event refer to the *declared* name of the input, not its public name or its\n * minified name. E.g. in `@Input('alias') foo: string`, the name in the `SimpleChanges` object\n * will always be `foo`, and not `alias` or the minified name of `foo` in apps using property\n * minification.\n *\n * This is achieved through the `DirectiveDef.declaredInputs` map that is constructed when the\n * definition is declared. When a property is written to the directive instance, the\n * `NgOnChangesFeature` will try to remap the property name being written to using the\n * `declaredInputs`.\n *\n * Since the host directive input remapping happens during directive matching, `declaredInputs`\n * won't contain the new alias that the input is available under. This function addresses the\n * issue by patching the host directive aliases to the `declaredInputs`. There is *not* a risk of\n * this patching accidentally introducing new inputs to the host directive, because `declaredInputs`\n * is used *only* by the `NgOnChangesFeature` when determining what name is used in the\n * `SimpleChanges` object which won't be reached if an input doesn't exist.\n */\nfunction patchDeclaredInputs(\n declaredInputs: Record<string, string>, exposedInputs: HostDirectiveBindingMap): void {\n for (const publicName in exposedInputs) {\n if (exposedInputs.hasOwnProperty(publicName)) {\n const remappedPublicName = exposedInputs[publicName];\n const privateName = declaredInputs[publicName];\n\n // We *technically* shouldn't be able to hit this case because we can't have multiple\n // inputs on the same property and we have validations against conflicting aliases in\n // `validateMappings`. If we somehow did, it would lead to `ngOnChanges` being invoked\n // with the wrong name so we have a non-user-friendly assertion here just in case.\n if ((typeof ngDevMode === 'undefined' || ngDevMode) &&\n declaredInputs.hasOwnProperty(remappedPublicName)) {\n assertEqual(\n declaredInputs[remappedPublicName], declaredInputs[publicName],\n `Conflicting host directive input alias ${publicName}.`);\n }\n\n declaredInputs[remappedPublicName] = privateName;\n }\n }\n}\n\n/**\n * Verifies that the host directive has been configured correctly.\n * @param hostDirectiveConfig Host directive configuration object.\n * @param directiveDef Directive definition of the host directive.\n * @param matchedDefs Directives that have been matched so far.\n */\nfunction validateHostDirective(\n hostDirectiveConfig: HostDirectiveDef<unknown>, directiveDef: DirectiveDef<any>|null,\n matchedDefs: DirectiveDef<unknown>[]): asserts directiveDef is DirectiveDef<unknown> {\n const type = hostDirectiveConfig.directive;\n\n if (directiveDef === null) {\n if (getComponentDef(type) !== null) {\n throw new RuntimeError(\n RuntimeErrorCode.HOST_DIRECTIVE_COMPONENT,\n `Host directive ${type.name} cannot be a component.`);\n }\n\n throw new RuntimeError(\n RuntimeErrorCode.HOST_DIRECTIVE_UNRESOLVABLE,\n `Could not resolve metadata for host directive ${type.name}. ` +\n `Make sure that the ${type.name} class is annotated with an @Directive decorator.`);\n }\n\n if (!directiveDef.standalone) {\n throw new RuntimeError(\n RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE,\n `Host directive ${directiveDef.type.name} must be standalone.`);\n }\n\n if (matchedDefs.indexOf(directiveDef) > -1) {\n throw new RuntimeError(\n RuntimeErrorCode.DUPLICATE_DIRECTITVE,\n `Directive ${directiveDef.type.name} matches multiple times on the same element. ` +\n `Directives can only match an element once.`);\n }\n\n validateMappings('input', directiveDef, hostDirectiveConfig.inputs);\n validateMappings('output', directiveDef, hostDirectiveConfig.outputs);\n}\n\n/**\n * Checks that the host directive inputs/outputs configuration is valid.\n * @param bindingType Kind of binding that is being validated. Used in the error message.\n * @param def Definition of the host directive that is being validated against.\n * @param hostDirectiveBindings Host directive mapping object that shold be validated.\n */\nfunction validateMappings(\n bindingType: 'input'|'output', def: DirectiveDef<unknown>,\n hostDirectiveBindings: HostDirectiveBindingMap) {\n const className = def.type.name;\n const bindings: Record<string, string> = bindingType === 'input' ? def.inputs : def.outputs;\n\n for (const publicName in hostDirectiveBindings) {\n if (hostDirectiveBindings.hasOwnProperty(publicName)) {\n if (!bindings.hasOwnProperty(publicName)) {\n throw new RuntimeError(\n RuntimeErrorCode.HOST_DIRECTIVE_UNDEFINED_BINDING,\n `Directive ${className} does not have an ${bindingType} with a public name of ${\n publicName}.`);\n }\n\n const remappedPublicName = hostDirectiveBindings[publicName];\n\n if (bindings.hasOwnProperty(remappedPublicName) &&\n bindings[remappedPublicName] !== publicName) {\n throw new RuntimeError(\n RuntimeErrorCode.HOST_DIRECTIVE_CONFLICTING_ALIAS,\n `Cannot alias ${bindingType} ${publicName} of host directive ${className} to ${\n remappedPublicName}, because it already has a different ${\n bindingType} with the same public name.`);\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function isIterable(obj: any): obj is Iterable<any> {\n return obj !== null && typeof obj === 'object' && obj[Symbol.iterator] !== undefined;\n}\n\nexport function isListLikeIterable(obj: any): boolean {\n if (!isJsObject(obj)) return false;\n return Array.isArray(obj) ||\n (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]\n Symbol.iterator in obj); // JS Iterable have a Symbol.iterator prop\n}\n\nexport function areIterablesEqual<T>(\n a: Iterable<T>, b: Iterable<T>, comparator: (a: T, b: T) => boolean): boolean {\n const iterator1 = a[Symbol.iterator]();\n const iterator2 = b[Symbol.iterator]();\n\n while (true) {\n const item1 = iterator1.next();\n const item2 = iterator2.next();\n if (item1.done && item2.done) return true;\n if (item1.done || item2.done) return false;\n if (!comparator(item1.value, item2.value)) return false;\n }\n}\n\nexport function iterateListLike<T>(obj: Iterable<T>, fn: (p: T) => void) {\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n fn(obj[i]);\n }\n } else {\n const iterator = obj[Symbol.iterator]();\n let item: IteratorResult<T, any>;\n while (!((item = iterator.next()).done)) {\n fn(item.value);\n }\n }\n}\n\nexport function isJsObject(o: any): boolean {\n return o !== null && (typeof o === 'function' || typeof o === 'object');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertIndexInRange, assertLessThan, assertNotSame} from '../util/assert';\nimport {devModeEqual} from '../util/comparison';\n\nimport {getExpressionChangedErrorDetails, throwErrorIfNoChangesMode} from './errors';\nimport {LView} from './interfaces/view';\nimport {isInCheckNoChangesMode} from './state';\nimport {NO_CHANGE} from './tokens';\n\n\n// TODO(misko): consider inlining\n/** Updates binding and returns the value. */\nexport function updateBinding(lView: LView, bindingIndex: number, value: any): any {\n return lView[bindingIndex] = value;\n}\n\n\n/** Gets the current binding value. */\nexport function getBinding(lView: LView, bindingIndex: number): any {\n ngDevMode && assertIndexInRange(lView, bindingIndex);\n ngDevMode &&\n assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');\n return lView[bindingIndex];\n}\n\n/**\n * Updates binding if changed, then returns whether it was updated.\n *\n * This function also checks the `CheckNoChangesMode` and throws if changes are made.\n * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE\n * behavior.\n *\n * @param lView current `LView`\n * @param bindingIndex The binding in the `LView` to check\n * @param value New value to check against `lView[bindingIndex]`\n * @returns `true` if the bindings has changed. (Throws if binding has changed during\n * `CheckNoChangesMode`)\n */\nexport function bindingUpdated(lView: LView, bindingIndex: number, value: any): boolean {\n ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');\n ngDevMode &&\n assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);\n const oldValue = lView[bindingIndex];\n\n if (Object.is(oldValue, value)) {\n return false;\n } else {\n if (ngDevMode && isInCheckNoChangesMode()) {\n // View engine didn't report undefined values as changed on the first checkNoChanges pass\n // (before the change detection was run).\n const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;\n if (!devModeEqual(oldValueToCompare, value)) {\n const details =\n getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);\n throwErrorIfNoChangesMode(\n oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);\n }\n // There was a change, but the `devModeEqual` decided that the change is exempt from an error.\n // For this reason we exit as if no change. The early exit is needed to prevent the changed\n // value to be written into `LView` (If we would write the new value that we would not see it\n // as change on next CD.)\n return false;\n }\n lView[bindingIndex] = value;\n return true;\n }\n}\n\n/** Updates 2 bindings if changed, then returns whether either was updated. */\nexport function bindingUpdated2(lView: LView, bindingIndex: number, exp1: any, exp2: any): boolean {\n const different = bindingUpdated(lView, bindingIndex, exp1);\n return bindingUpdated(lView, bindingIndex + 1, exp2) || different;\n}\n\n/** Updates 3 bindings if changed, then returns whether any was updated. */\nexport function bindingUpdated3(\n lView: LView, bindingIndex: number, exp1: any, exp2: any, exp3: any): boolean {\n const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);\n return bindingUpdated(lView, bindingIndex + 2, exp3) || different;\n}\n\n/** Updates 4 bindings if changed, then returns whether any was updated. */\nexport function bindingUpdated4(\n lView: LView, bindingIndex: number, exp1: any, exp2: any, exp3: any, exp4: any): boolean {\n const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);\n return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {bindingUpdated} from '../bindings';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';\nimport {elementAttributeInternal, storePropertyBindingMetadata} from './shared';\n\n\n\n/**\n * Updates the value of or removes a bound attribute on an Element.\n *\n * Used in the case of `[attr.title]=\"value\"`\n *\n * @param name name The name of the attribute.\n * @param value value The attribute is removed when value is `null` or `undefined`.\n * Otherwise the attribute value is set to the stringified value.\n * @param sanitizer An optional function used to sanitize the value.\n * @param namespace Optional namespace to use when setting the attribute.\n *\n * @codeGenApi\n */\nexport function ɵɵattribute(\n name: string, value: any, sanitizer?: SanitizerFn|null,\n namespace?: string): typeof ɵɵattribute {\n const lView = getLView();\n const bindingIndex = nextBindingIndex();\n if (bindingUpdated(lView, bindingIndex, value)) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);\n ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);\n }\n return ɵɵattribute;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertEqual, assertLessThan} from '../../util/assert';\nimport {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings';\nimport {LView} from '../interfaces/view';\nimport {getBindingIndex, incrementBindingIndex, nextBindingIndex, setBindingIndex} from '../state';\nimport {NO_CHANGE} from '../tokens';\nimport {renderStringify} from '../util/stringify_utils';\n\n\n\n/**\n * Create interpolation bindings with a variable number of expressions.\n *\n * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.\n * Those are faster because there is no need to create an array of expressions and iterate over it.\n *\n * `values`:\n * - has static text at even indexes,\n * - has evaluated expressions at odd indexes.\n *\n * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.\n */\nexport function interpolationV(lView: LView, values: any[]): string|NO_CHANGE {\n ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');\n ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');\n let isBindingUpdated = false;\n let bindingIndex = getBindingIndex();\n\n for (let i = 1; i < values.length; i += 2) {\n // Check if bindings (odd indexes) have changed\n isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;\n }\n setBindingIndex(bindingIndex);\n\n if (!isBindingUpdated) {\n return NO_CHANGE;\n }\n\n // Build the updated content\n let content = values[0];\n for (let i = 1; i < values.length; i += 2) {\n content += renderStringify(values[i]) + values[i + 1];\n }\n\n return content;\n}\n\n/**\n * Creates an interpolation binding with 1 expression.\n *\n * @param prefix static value used for concatenation only.\n * @param v0 value checked for change.\n * @param suffix static value used for concatenation only.\n */\nexport function interpolation1(lView: LView, prefix: string, v0: any, suffix: string): string|\n NO_CHANGE {\n const different = bindingUpdated(lView, nextBindingIndex(), v0);\n return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 2 expressions.\n */\nexport function interpolation2(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n const different = bindingUpdated2(lView, bindingIndex, v0, v1);\n incrementBindingIndex(2);\n\n return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 3 expressions.\n */\nexport function interpolation3(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,\n suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);\n incrementBindingIndex(3);\n\n return different ?\n prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :\n NO_CHANGE;\n}\n\n/**\n * Create an interpolation binding with 4 expressions.\n */\nexport function interpolation4(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);\n incrementBindingIndex(4);\n\n return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +\n renderStringify(v2) + i2 + renderStringify(v3) + suffix :\n NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 5 expressions.\n */\nexport function interpolation5(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);\n different = bindingUpdated(lView, bindingIndex + 4, v4) || different;\n incrementBindingIndex(5);\n\n return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +\n renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix :\n NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 6 expressions.\n */\nexport function interpolation6(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);\n different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;\n incrementBindingIndex(6);\n\n return different ?\n prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +\n renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix :\n NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 7 expressions.\n */\nexport function interpolation7(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): string|\n NO_CHANGE {\n const bindingIndex = getBindingIndex();\n let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);\n different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;\n incrementBindingIndex(7);\n\n return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +\n renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +\n renderStringify(v5) + i5 + renderStringify(v6) + suffix :\n NO_CHANGE;\n}\n\n/**\n * Creates an interpolation binding with 8 expressions.\n */\nexport function interpolation8(\n lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,\n suffix: string): string|NO_CHANGE {\n const bindingIndex = getBindingIndex();\n let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);\n different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;\n incrementBindingIndex(8);\n\n return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +\n renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +\n renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix :\n NO_CHANGE;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {assertFirstCreatePass} from '../assert';\nimport {attachPatchData} from '../context_discovery';\nimport {registerPostOrderHooks} from '../hooks';\nimport {ComponentTemplate} from '../interfaces/definition';\nimport {LocalRefExtractor, TAttributes, TContainerNode, TNodeType} from '../interfaces/node';\nimport {isDirectiveHost} from '../interfaces/type_checks';\nimport {HEADER_OFFSET, LView, RENDERER, TView, TViewType} from '../interfaces/view';\nimport {appendChild} from '../node_manipulation';\nimport {getLView, getTView, setCurrentTNode} from '../state';\nimport {getConstant} from '../util/view_utils';\n\nimport {addToViewTree, createDirectivesInstances, createLContainer, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';\n\n\n\nfunction templateFirstCreatePass(\n index: number, tView: TView, lView: LView, templateFn: ComponentTemplate<any>|null,\n decls: number, vars: number, tagName?: string|null, attrsIndex?: number|null,\n localRefsIndex?: number|null): TContainerNode {\n ngDevMode && assertFirstCreatePass(tView);\n ngDevMode && ngDevMode.firstCreatePass++;\n const tViewConsts = tView.consts;\n // TODO(pk): refactor getOrCreateTNode to have the \"create\" only version\n const tNode = getOrCreateTNode(\n tView, index, TNodeType.Container, tagName || null,\n getConstant<TAttributes>(tViewConsts, attrsIndex));\n\n resolveDirectives(tView, lView, tNode, getConstant<string[]>(tViewConsts, localRefsIndex));\n registerPostOrderHooks(tView, tNode);\n\n const embeddedTView = tNode.tView = createTView(\n TViewType.Embedded, tNode, templateFn, decls, vars, tView.directiveRegistry,\n tView.pipeRegistry, null, tView.schemas, tViewConsts);\n\n if (tView.queries !== null) {\n tView.queries.template(tView, tNode);\n embeddedTView.queries = tView.queries.embeddedTView(tNode);\n }\n\n return tNode;\n}\n\n/**\n * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.\n *\n * <ng-template #foo>\n * <div></div>\n * </ng-template>\n *\n * @param index The index of the container in the data array\n * @param templateFn Inline template\n * @param decls The number of nodes, local refs, and pipes for this template\n * @param vars The number of bindings for this template\n * @param tagName The name of the container element, if applicable\n * @param attrsIndex Index of template attributes in the `consts` array.\n * @param localRefs Index of the local references in the `consts` array.\n * @param localRefExtractor A function which extracts local-refs values from the template.\n * Defaults to the current element associated with the local-ref.\n *\n * @codeGenApi\n */\nexport function ɵɵtemplate(\n index: number, templateFn: ComponentTemplate<any>|null, decls: number, vars: number,\n tagName?: string|null, attrsIndex?: number|null, localRefsIndex?: number|null,\n localRefExtractor?: LocalRefExtractor) {\n const lView = getLView();\n const tView = getTView();\n const adjustedIndex = index + HEADER_OFFSET;\n\n const tNode = tView.firstCreatePass ? templateFirstCreatePass(\n adjustedIndex, tView, lView, templateFn, decls, vars,\n tagName, attrsIndex, localRefsIndex) :\n tView.data[adjustedIndex] as TContainerNode;\n setCurrentTNode(tNode, false);\n\n const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');\n appendChild(tView, lView, comment, tNode);\n attachPatchData(comment, lView);\n\n addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));\n\n if (isDirectiveHost(tNode)) {\n createDirectivesInstances(tView, lView, tNode);\n }\n\n if (localRefsIndex != null) {\n saveResolvedLocalsInData(lView, tNode, localRefExtractor);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {HEADER_OFFSET, LView, TView} from '../interfaces/view';\nimport {getContextLView} from '../state';\nimport {load} from '../util/view_utils';\n\n\n/** Store a value in the `data` at a given `index`. */\nexport function store<T>(tView: TView, lView: LView, index: number, value: T): void {\n // We don't store any static data for local variables, so the first time\n // we see the template, we should store as null to avoid a sparse array\n if (index >= tView.data.length) {\n tView.data[index] = null;\n tView.blueprint[index] = null;\n }\n lView[index] = value;\n}\n\n/**\n * Retrieves a local reference from the current contextViewData.\n *\n * If the reference to retrieve is in a parent view, this instruction is used in conjunction\n * with a nextContext() call, which walks up the tree and updates the contextViewData instance.\n *\n * @param index The index of the local ref in contextViewData.\n *\n * @codeGenApi\n */\nexport function ɵɵreference<T>(index: number) {\n const contextLView = getContextLView();\n return load<T>(contextLView, HEADER_OFFSET + index);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {bindingUpdated} from '../bindings';\nimport {TNode} from '../interfaces/node';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {LView, RENDERER, TView} from '../interfaces/view';\nimport {getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';\n\nimport {elementPropertyInternal, setInputsForProperty, storePropertyBindingMetadata} from './shared';\n\n\n/**\n * Update a property on a selected element.\n *\n * Operates on the element selected by index via the {@link select} instruction.\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled\n *\n * @param propName Name of property. Because it is going to DOM, this is not subject to\n * renaming as part of minification.\n * @param value New value to write.\n * @param sanitizer An optional function used to sanitize the value.\n * @returns This function returns itself so that it may be chained\n * (e.g. `property('name', ctx.name)('title', ctx.title)`)\n *\n * @codeGenApi\n */\nexport function ɵɵproperty<T>(\n propName: string, value: T, sanitizer?: SanitizerFn|null): typeof ɵɵproperty {\n const lView = getLView();\n const bindingIndex = nextBindingIndex();\n if (bindingUpdated(lView, bindingIndex, value)) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false);\n ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);\n }\n return ɵɵproperty;\n}\n\n/**\n * Given `<div style=\"...\" my-dir>` and `MyDir` with `@Input('style')` we need to write to\n * directive input.\n */\nexport function setDirectiveInputsWhichShadowsStyling(\n tView: TView, tNode: TNode, lView: LView, value: any, isClassBased: boolean) {\n const inputs = tNode.inputs!;\n const property = isClassBased ? 'class' : 'style';\n // We support both 'class' and `className` hence the fallback.\n setInputsForProperty(tView, lView, inputs[property], property, value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertDefined, assertEqual, assertIndexInRange} from '../../util/assert';\nimport {assertFirstCreatePass, assertHasParent} from '../assert';\nimport {attachPatchData} from '../context_discovery';\nimport {registerPostOrderHooks} from '../hooks';\nimport {hasClassInput, hasStyleInput, TAttributes, TElementNode, TNodeFlags, TNodeType} from '../interfaces/node';\nimport {RElement} from '../interfaces/renderer_dom';\nimport {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';\nimport {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';\nimport {assertTNodeType} from '../node_assert';\nimport {appendChild, createElementNode, setupStaticAttributes} from '../node_manipulation';\nimport {decreaseElementDepthCount, getBindingIndex, getCurrentTNode, getElementDepthCount, getLView, getNamespace, getTView, increaseElementDepthCount, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';\nimport {computeStaticStyling} from '../styling/static_styling';\nimport {getConstant} from '../util/view_utils';\n\nimport {validateElementIsKnown} from './element_validation';\nimport {setDirectiveInputsWhichShadowsStyling} from './property';\nimport {createDirectivesInstances, executeContentQueries, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';\n\n\nfunction elementStartFirstCreatePass(\n index: number, tView: TView, lView: LView, name: string, attrsIndex?: number|null,\n localRefsIndex?: number): TElementNode {\n ngDevMode && assertFirstCreatePass(tView);\n ngDevMode && ngDevMode.firstCreatePass++;\n\n const tViewConsts = tView.consts;\n const attrs = getConstant<TAttributes>(tViewConsts, attrsIndex);\n const tNode = getOrCreateTNode(tView, index, TNodeType.Element, name, attrs);\n\n resolveDirectives(tView, lView, tNode, getConstant<string[]>(tViewConsts, localRefsIndex));\n\n if (tNode.attrs !== null) {\n computeStaticStyling(tNode, tNode.attrs, false);\n }\n\n if (tNode.mergedAttrs !== null) {\n computeStaticStyling(tNode, tNode.mergedAttrs, true);\n }\n\n if (tView.queries !== null) {\n tView.queries.elementStart(tView, tNode);\n }\n\n return tNode;\n}\n\n/**\n * Create DOM element. The instruction must later be followed by `elementEnd()` call.\n *\n * @param index Index of the element in the LView array\n * @param name Name of the DOM Node\n * @param attrsIndex Index of the element's attributes in the `consts` array.\n * @param localRefsIndex Index of the element's local references in the `consts` array.\n * @returns This function returns itself so that it may be chained.\n *\n * Attributes and localRefs are passed as an array of strings where elements with an even index\n * hold an attribute name and elements with an odd index hold an attribute value, ex.:\n * ['id', 'warning5', 'class', 'alert']\n *\n * @codeGenApi\n */\nexport function ɵɵelementStart(\n index: number, name: string, attrsIndex?: number|null,\n localRefsIndex?: number): typeof ɵɵelementStart {\n const lView = getLView();\n const tView = getTView();\n const adjustedIndex = HEADER_OFFSET + index;\n\n ngDevMode &&\n assertEqual(\n getBindingIndex(), tView.bindingStartIndex,\n 'elements should be created before any bindings');\n ngDevMode && assertIndexInRange(lView, adjustedIndex);\n\n const renderer = lView[RENDERER];\n const tNode = tView.firstCreatePass ?\n elementStartFirstCreatePass(adjustedIndex, tView, lView, name, attrsIndex, localRefsIndex) :\n tView.data[adjustedIndex] as TElementNode;\n const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace());\n const hasDirectives = isDirectiveHost(tNode);\n\n if (ngDevMode && tView.firstCreatePass) {\n validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);\n }\n\n setCurrentTNode(tNode, true);\n setupStaticAttributes(renderer, native, tNode);\n\n if ((tNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) {\n // In the i18n case, the translation may have removed this element, so only add it if it is not\n // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.\n appendChild(tView, lView, native, tNode);\n }\n\n // any immediate children of a component or template container must be pre-emptively\n // monkey-patched with the component view data so that the element can be inspected\n // later on using any element discovery utility methods (see `element_discovery.ts`)\n if (getElementDepthCount() === 0) {\n attachPatchData(native, lView);\n }\n increaseElementDepthCount();\n\n if (hasDirectives) {\n createDirectivesInstances(tView, lView, tNode);\n executeContentQueries(tView, tNode, lView);\n }\n if (localRefsIndex !== null) {\n saveResolvedLocalsInData(lView, tNode);\n }\n return ɵɵelementStart;\n}\n\n/**\n * Mark the end of the element.\n * @returns This function returns itself so that it may be chained.\n *\n * @codeGenApi\n */\nexport function ɵɵelementEnd(): typeof ɵɵelementEnd {\n let currentTNode = getCurrentTNode()!;\n ngDevMode && assertDefined(currentTNode, 'No parent node to close.');\n if (isCurrentTNodeParent()) {\n setCurrentTNodeAsNotParent();\n } else {\n ngDevMode && assertHasParent(getCurrentTNode());\n currentTNode = currentTNode.parent!;\n setCurrentTNode(currentTNode, false);\n }\n\n const tNode = currentTNode;\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode);\n\n\n decreaseElementDepthCount();\n\n const tView = getTView();\n if (tView.firstCreatePass) {\n registerPostOrderHooks(tView, currentTNode);\n if (isContentQueryHost(currentTNode)) {\n tView.queries!.elementEnd(currentTNode);\n }\n }\n\n if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {\n setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);\n }\n\n if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) {\n setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false);\n }\n return ɵɵelementEnd;\n}\n\n/**\n * Creates an empty element using {@link elementStart} and {@link elementEnd}\n *\n * @param index Index of the element in the data array\n * @param name Name of the DOM Node\n * @param attrsIndex Index of the element's attributes in the `consts` array.\n * @param localRefsIndex Index of the element's local references in the `consts` array.\n * @returns This function returns itself so that it may be chained.\n *\n * @codeGenApi\n */\nexport function ɵɵelement(\n index: number, name: string, attrsIndex?: number|null,\n localRefsIndex?: number): typeof ɵɵelement {\n ɵɵelementStart(index, name, attrsIndex, localRefsIndex);\n ɵɵelementEnd();\n return ɵɵelement;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {KeyValueArray} from '../../util/array_utils';\nimport {TStylingRange} from '../interfaces/styling';\n\nimport {TIcu} from './i18n';\nimport {CssSelector} from './projection';\nimport {RNode} from './renderer_dom';\nimport {LView, TView} from './view';\n\n\n/**\n * TNodeType corresponds to the {@link TNode} `type` property.\n *\n * NOTE: type IDs are such that we use each bit to denote a type. This is done so that we can easily\n * check if the `TNode` is of more than one type.\n *\n * `if (tNode.type === TNodeType.Text || tNode.type === TNode.Element)`\n * can be written as:\n * `if (tNode.type & (TNodeType.Text | TNodeType.Element))`\n *\n * However any given `TNode` can only be of one type.\n */\nexport const enum TNodeType {\n /**\n * The TNode contains information about a DOM element aka {@link RText}.\n */\n Text = 0b1,\n\n /**\n * The TNode contains information about a DOM element aka {@link RElement}.\n */\n Element = 0b10,\n\n /**\n * The TNode contains information about an {@link LContainer} for embedded views.\n */\n Container = 0b100,\n\n /**\n * The TNode contains information about an `<ng-container>` element {@link RNode}.\n */\n ElementContainer = 0b1000,\n\n /**\n * The TNode contains information about an `<ng-content>` projection\n */\n Projection = 0b10000,\n\n /**\n * The TNode contains information about an ICU comment used in `i18n`.\n */\n Icu = 0b100000,\n\n /**\n * Special node type representing a placeholder for future `TNode` at this location.\n *\n * I18n translation blocks are created before the element nodes which they contain. (I18n blocks\n * can span over many elements.) Because i18n `TNode`s (representing text) are created first they\n * often may need to point to element `TNode`s which are not yet created. In such a case we create\n * a `Placeholder` `TNode`. This allows the i18n to structurally link the `TNode`s together\n * without knowing any information about the future nodes which will be at that location.\n *\n * On `firstCreatePass` When element instruction executes it will try to create a `TNode` at that\n * location. Seeing a `Placeholder` `TNode` already there tells the system that it should reuse\n * existing `TNode` (rather than create a new one) and just update the missing information.\n */\n Placeholder = 0b1000000,\n\n // Combined Types These should never be used for `TNode.type` only as a useful way to check\n // if `TNode.type` is one of several choices.\n\n // See: https://github.com/microsoft/TypeScript/issues/35875 why we can't refer to existing enum.\n AnyRNode = 0b11, // Text | Element,\n AnyContainer = 0b1100, // Container | ElementContainer, // See:\n}\n\n/**\n * Converts `TNodeType` into human readable text.\n * Make sure this matches with `TNodeType`\n */\nexport function toTNodeTypeAsString(tNodeType: TNodeType): string {\n let text = '';\n (tNodeType & TNodeType.Text) && (text += '|Text');\n (tNodeType & TNodeType.Element) && (text += '|Element');\n (tNodeType & TNodeType.Container) && (text += '|Container');\n (tNodeType & TNodeType.ElementContainer) && (text += '|ElementContainer');\n (tNodeType & TNodeType.Projection) && (text += '|Projection');\n (tNodeType & TNodeType.Icu) && (text += '|IcuContainer');\n (tNodeType & TNodeType.Placeholder) && (text += '|Placeholder');\n return text.length > 0 ? text.substring(1) : text;\n}\n\n/**\n * Corresponds to the TNode.flags property.\n */\nexport const enum TNodeFlags {\n /** Bit #1 - This bit is set if the node is a host for any directive (including a component) */\n isDirectiveHost = 0x1,\n\n /** Bit #2 - This bit is set if the node has been projected */\n isProjected = 0x2,\n\n /** Bit #3 - This bit is set if any directive on this node has content queries */\n hasContentQuery = 0x4,\n\n /** Bit #4 - This bit is set if the node has any \"class\" inputs */\n hasClassInput = 0x8,\n\n /** Bit #5 - This bit is set if the node has any \"style\" inputs */\n hasStyleInput = 0x10,\n\n /** Bit #6 This bit is set if the node has been detached by i18n */\n isDetached = 0x20,\n\n /**\n * Bit #7 - This bit is set if the node has directives with host bindings.\n *\n * This flags allows us to guard host-binding logic and invoke it only on nodes\n * that actually have directives with host bindings.\n */\n hasHostBindings = 0x40,\n}\n\n/**\n * Corresponds to the TNode.providerIndexes property.\n */\nexport const enum TNodeProviderIndexes {\n /** The index of the first provider on this node is encoded on the least significant bits. */\n ProvidersStartIndexMask = 0b00000000000011111111111111111111,\n\n /**\n * The count of view providers from the component on this node is\n * encoded on the 20 most significant bits.\n */\n CptViewProvidersCountShift = 20,\n CptViewProvidersCountShifter = 0b00000000000100000000000000000000,\n}\n\n/**\n * A set of marker values to be used in the attributes arrays. These markers indicate that some\n * items are not regular attributes and the processing should be adapted accordingly.\n */\nexport const enum AttributeMarker {\n /**\n * An implicit marker which indicates that the value in the array are of `attributeKey`,\n * `attributeValue` format.\n *\n * NOTE: This is implicit as it is the type when no marker is present in array. We indicate that\n * it should not be present at runtime by the negative number.\n */\n ImplicitAttributes = -1,\n\n /**\n * Marker indicates that the following 3 values in the attributes array are:\n * namespaceUri, attributeName, attributeValue\n * in that order.\n */\n NamespaceURI = 0,\n\n /**\n * Signals class declaration.\n *\n * Each value following `Classes` designates a class name to include on the element.\n * ## Example:\n *\n * Given:\n * ```\n * <div class=\"foo bar baz\">...<d/vi>\n * ```\n *\n * the generated code is:\n * ```\n * var _c1 = [AttributeMarker.Classes, 'foo', 'bar', 'baz'];\n * ```\n */\n Classes = 1,\n\n /**\n * Signals style declaration.\n *\n * Each pair of values following `Styles` designates a style name and value to include on the\n * element.\n * ## Example:\n *\n * Given:\n * ```\n * <div style=\"width:100px; height:200px; color:red\">...</div>\n * ```\n *\n * the generated code is:\n * ```\n * var _c1 = [AttributeMarker.Styles, 'width', '100px', 'height'. '200px', 'color', 'red'];\n * ```\n */\n Styles = 2,\n\n /**\n * Signals that the following attribute names were extracted from input or output bindings.\n *\n * For example, given the following HTML:\n *\n * ```\n * <div moo=\"car\" [foo]=\"exp\" (bar)=\"doSth()\">\n * ```\n *\n * the generated code is:\n *\n * ```\n * var _c1 = ['moo', 'car', AttributeMarker.Bindings, 'foo', 'bar'];\n * ```\n */\n Bindings = 3,\n\n /**\n * Signals that the following attribute names were hoisted from an inline-template declaration.\n *\n * For example, given the following HTML:\n *\n * ```\n * <div *ngFor=\"let value of values; trackBy:trackBy\" dirA [dirB]=\"value\">\n * ```\n *\n * the generated code for the `template()` instruction would include:\n *\n * ```\n * ['dirA', '', AttributeMarker.Bindings, 'dirB', AttributeMarker.Template, 'ngFor', 'ngForOf',\n * 'ngForTrackBy', 'let-value']\n * ```\n *\n * while the generated code for the `element()` instruction inside the template function would\n * include:\n *\n * ```\n * ['dirA', '', AttributeMarker.Bindings, 'dirB']\n * ```\n */\n Template = 4,\n\n /**\n * Signals that the following attribute is `ngProjectAs` and its value is a parsed\n * `CssSelector`.\n *\n * For example, given the following HTML:\n *\n * ```\n * <h1 attr=\"value\" ngProjectAs=\"[title]\">\n * ```\n *\n * the generated code for the `element()` instruction would include:\n *\n * ```\n * ['attr', 'value', AttributeMarker.ProjectAs, ['', 'title', '']]\n * ```\n */\n ProjectAs = 5,\n\n /**\n * Signals that the following attribute will be translated by runtime i18n\n *\n * For example, given the following HTML:\n *\n * ```\n * <div moo=\"car\" foo=\"value\" i18n-foo [bar]=\"binding\" i18n-bar>\n * ```\n *\n * the generated code is:\n *\n * ```\n * var _c1 = ['moo', 'car', AttributeMarker.I18n, 'foo', 'bar'];\n */\n I18n = 6,\n}\n\n/**\n * A combination of:\n * - Attribute names and values.\n * - Special markers acting as flags to alter attributes processing.\n * - Parsed ngProjectAs selectors.\n */\nexport type TAttributes = (string|AttributeMarker|CssSelector)[];\n\n/**\n * Constants that are associated with a view. Includes:\n * - Attribute arrays.\n * - Local definition arrays.\n * - Translated messages (i18n).\n */\nexport type TConstants = (TAttributes|string)[];\n\n/**\n * Factory function that returns an array of consts. Consts can be represented as a function in\n * case any additional statements are required to define consts in the list. An example is i18n\n * where additional i18n calls are generated, which should be executed when consts are requested\n * for the first time.\n */\nexport type TConstantsFactory = () => TConstants;\n\n/**\n * TConstants type that describes how the `consts` field is generated on ComponentDef: it can be\n * either an array or a factory function that returns that array.\n */\nexport type TConstantsOrFactory = TConstants|TConstantsFactory;\n\n/**\n * Binding data (flyweight) for a particular node that is shared between all templates\n * of a specific type.\n *\n * If a property is:\n * - PropertyAliases: that property's data was generated and this is it\n * - Null: that property's data was already generated and nothing was found.\n * - Undefined: that property's data has not yet been generated\n *\n * see: https://en.wikipedia.org/wiki/Flyweight_pattern for more on the Flyweight pattern\n */\nexport interface TNode {\n /** The type of the TNode. See TNodeType. */\n type: TNodeType;\n\n /**\n * Index of the TNode in TView.data and corresponding native element in LView.\n *\n * This is necessary to get from any TNode to its corresponding native element when\n * traversing the node tree.\n *\n * If index is -1, this is a dynamically created container node or embedded view node.\n */\n index: number;\n\n /**\n * Insert before existing DOM node index.\n *\n * When DOM nodes are being inserted, normally they are being appended as they are created.\n * Under i18n case, the translated text nodes are created ahead of time as part of the\n * `ɵɵi18nStart` instruction which means that this `TNode` can't just be appended and instead\n * needs to be inserted using `insertBeforeIndex` semantics.\n *\n * Additionally sometimes it is necessary to insert new text nodes as a child of this `TNode`. In\n * such a case the value stores an array of text nodes to insert.\n *\n * Example:\n * ```\n * <div i18n>\n * Hello <span>World</span>!\n * </div>\n * ```\n * In the above example the `ɵɵi18nStart` instruction can create `Hello `, `World` and `!` text\n * nodes. It can also insert `Hello ` and `!` text node as a child of `<div>`, but it can't\n * insert `World` because the `<span>` node has not yet been created. In such a case the\n * `<span>` `TNode` will have an array which will direct the `<span>` to not only insert\n * itself in front of `!` but also to insert the `World` (created by `ɵɵi18nStart`) into\n * `<span>` itself.\n *\n * Pseudo code:\n * ```\n * if (insertBeforeIndex === null) {\n * // append as normal\n * } else if (Array.isArray(insertBeforeIndex)) {\n * // First insert current `TNode` at correct location\n * const currentNode = lView[this.index];\n * parentNode.insertBefore(currentNode, lView[this.insertBeforeIndex[0]]);\n * // Now append all of the children\n * for(let i=1; i<this.insertBeforeIndex; i++) {\n * currentNode.appendChild(lView[this.insertBeforeIndex[i]]);\n * }\n * } else {\n * parentNode.insertBefore(lView[this.index], lView[this.insertBeforeIndex])\n * }\n * ```\n * - null: Append as normal using `parentNode.appendChild`\n * - `number`: Append using\n * `parentNode.insertBefore(lView[this.index], lView[this.insertBeforeIndex])`\n *\n * *Initialization*\n *\n * Because `ɵɵi18nStart` executes before nodes are created, on `TView.firstCreatePass` it is not\n * possible for `ɵɵi18nStart` to set the `insertBeforeIndex` value as the corresponding `TNode`\n * has not yet been created. For this reason the `ɵɵi18nStart` creates a `TNodeType.Placeholder`\n * `TNode` at that location. See `TNodeType.Placeholder` for more information.\n */\n insertBeforeIndex: InsertBeforeIndex;\n\n /**\n * The index of the closest injector in this node's LView.\n *\n * If the index === -1, there is no injector on this node or any ancestor node in this view.\n *\n * If the index !== -1, it is the index of this node's injector OR the index of a parent\n * injector in the same view. We pass the parent injector index down the node tree of a view so\n * it's possible to find the parent injector without walking a potentially deep node tree.\n * Injector indices are not set across view boundaries because there could be multiple component\n * hosts.\n *\n * If tNode.injectorIndex === tNode.parent.injectorIndex, then the index belongs to a parent\n * injector.\n */\n injectorIndex: number;\n\n /** Stores starting index of the directives. */\n directiveStart: number;\n\n /**\n * Stores final exclusive index of the directives.\n *\n * The area right behind the `directiveStart-directiveEnd` range is used to allocate the\n * `HostBindingFunction` `vars` (or null if no bindings.) Therefore `directiveEnd` is used to set\n * `LFrame.bindingRootIndex` before `HostBindingFunction` is executed.\n */\n directiveEnd: number;\n\n /**\n * Offset from the `directiveStart` at which the component (one at most) of the node is stored.\n * Set to -1 if no components have been applied to the node. Component index can be found using\n * `directiveStart + componentOffset`.\n */\n componentOffset: number;\n\n /**\n * Stores the last directive which had a styling instruction.\n *\n * Initial value of this is `-1` which means that no `hostBindings` styling instruction has\n * executed. As `hostBindings` instructions execute they set the value to the index of the\n * `DirectiveDef` which contained the last `hostBindings` styling instruction.\n *\n * Valid values are:\n * - `-1` No `hostBindings` instruction has executed.\n * - `directiveStart <= directiveStylingLast < directiveEnd`: Points to the `DirectiveDef` of\n * the last styling instruction which executed in the `hostBindings`.\n *\n * This data is needed so that styling instructions know which static styling data needs to be\n * collected from the `DirectiveDef.hostAttrs`. A styling instruction needs to collect all data\n * since last styling instruction.\n */\n directiveStylingLast: number;\n\n /**\n * Stores indexes of property bindings. This field is only set in the ngDevMode and holds\n * indexes of property bindings so TestBed can get bound property metadata for a given node.\n */\n propertyBindings: number[]|null;\n\n /**\n * Stores if Node isComponent, isProjected, hasContentQuery, hasClassInput and hasStyleInput\n * etc.\n */\n flags: TNodeFlags;\n\n /**\n * This number stores two values using its bits:\n *\n * - the index of the first provider on that node (first 16 bits)\n * - the count of view providers from the component on this node (last 16 bits)\n */\n // TODO(misko): break this into actual vars.\n providerIndexes: TNodeProviderIndexes;\n\n /**\n * The value name associated with this node.\n * if type:\n * `TNodeType.Text`: text value\n * `TNodeType.Element`: tag name\n * `TNodeType.ICUContainer`: `TIcu`\n */\n value: any;\n\n /**\n * Attributes associated with an element. We need to store attributes to support various\n * use-cases (attribute injection, content projection with selectors, directives matching).\n * Attributes are stored statically because reading them from the DOM would be way too slow for\n * content projection and queries.\n *\n * Since attrs will always be calculated first, they will never need to be marked undefined by\n * other instructions.\n *\n * For regular attributes a name of an attribute and its value alternate in the array.\n * e.g. ['role', 'checkbox']\n * This array can contain flags that will indicate \"special attributes\" (attributes with\n * namespaces, attributes extracted from bindings and outputs).\n */\n attrs: TAttributes|null;\n\n /**\n * Same as `TNode.attrs` but contains merged data across all directive host bindings.\n *\n * We need to keep `attrs` as unmerged so that it can be used for attribute selectors.\n * We merge attrs here so that it can be used in a performant way for initial rendering.\n *\n * The `attrs` are merged in first pass in following order:\n * - Component's `hostAttrs`\n * - Directives' `hostAttrs`\n * - Template `TNode.attrs` associated with the current `TNode`.\n */\n mergedAttrs: TAttributes|null;\n\n /**\n * A set of local names under which a given element is exported in a template and\n * visible to queries. An entry in this array can be created for different reasons:\n * - an element itself is referenced, ex.: `<div #foo>`\n * - a component is referenced, ex.: `<my-cmpt #foo>`\n * - a directive is referenced, ex.: `<my-cmpt #foo=\"directiveExportAs\">`.\n *\n * A given element might have different local names and those names can be associated\n * with a directive. We store local names at even indexes while odd indexes are reserved\n * for directive index in a view (or `-1` if there is no associated directive).\n *\n * Some examples:\n * - `<div #foo>` => `[\"foo\", -1]`\n * - `<my-cmpt #foo>` => `[\"foo\", myCmptIdx]`\n * - `<my-cmpt #foo #bar=\"directiveExportAs\">` => `[\"foo\", myCmptIdx, \"bar\", directiveIdx]`\n * - `<div #foo #bar=\"directiveExportAs\">` => `[\"foo\", -1, \"bar\", directiveIdx]`\n */\n localNames: (string|number)[]|null;\n\n /** Information about input properties that need to be set once from attribute data. */\n initialInputs: InitialInputData|null|undefined;\n\n /**\n * Input data for all directives on this node. `null` means that there are no directives with\n * inputs on this node.\n */\n inputs: PropertyAliases|null;\n\n /**\n * Output data for all directives on this node. `null` means that there are no directives with\n * outputs on this node.\n */\n outputs: PropertyAliases|null;\n\n /**\n * The TView attached to this node.\n *\n * If this TNode corresponds to an LContainer with a template (e.g. structural\n * directive), the template's TView will be stored here.\n *\n * If this TNode corresponds to an element, tView will be `null`.\n */\n tView: TView|null;\n\n /**\n * The next sibling node. Necessary so we can propagate through the root nodes of a view\n * to insert them or remove them from the DOM.\n */\n next: TNode|null;\n\n /**\n * The previous sibling node.\n * This simplifies operations when we need a pointer to the previous node.\n */\n prev: TNode|null;\n\n /**\n * The next projected sibling. Since in Angular content projection works on the node-by-node\n * basis the act of projecting nodes might change nodes relationship at the insertion point\n * (target view). At the same time we need to keep initial relationship between nodes as\n * expressed in content view.\n */\n projectionNext: TNode|null;\n\n /**\n * First child of the current node.\n *\n * For component nodes, the child will always be a ContentChild (in same view).\n * For embedded view nodes, the child will be in their child view.\n */\n child: TNode|null;\n\n /**\n * Parent node (in the same view only).\n *\n * We need a reference to a node's parent so we can append the node to its parent's native\n * element at the appropriate time.\n *\n * If the parent would be in a different view (e.g. component host), this property will be null.\n * It's important that we don't try to cross component boundaries when retrieving the parent\n * because the parent will change (e.g. index, attrs) depending on where the component was\n * used (and thus shouldn't be stored on TNode). In these cases, we retrieve the parent through\n * LView.node instead (which will be instance-specific).\n *\n * If this is an inline view node (V), the parent will be its container.\n */\n parent: TElementNode|TContainerNode|null;\n\n /**\n * List of projected TNodes for a given component host element OR index into the said nodes.\n *\n * For easier discussion assume this example:\n * `<parent>`'s view definition:\n * ```\n * <child id=\"c1\">content1</child>\n * <child id=\"c2\"><span>content2</span></child>\n * ```\n * `<child>`'s view definition:\n * ```\n * <ng-content id=\"cont1\"></ng-content>\n * ```\n *\n * If `Array.isArray(projection)` then `TNode` is a host element:\n * - `projection` stores the content nodes which are to be projected.\n * - The nodes represent categories defined by the selector: For example:\n * `<ng-content/><ng-content select=\"abc\"/>` would represent the heads for `<ng-content/>`\n * and `<ng-content select=\"abc\"/>` respectively.\n * - The nodes we store in `projection` are heads only, we used `.next` to get their\n * siblings.\n * - The nodes `.next` is sorted/rewritten as part of the projection setup.\n * - `projection` size is equal to the number of projections `<ng-content>`. The size of\n * `c1` will be `1` because `<child>` has only one `<ng-content>`.\n * - we store `projection` with the host (`c1`, `c2`) rather than the `<ng-content>` (`cont1`)\n * because the same component (`<child>`) can be used in multiple locations (`c1`, `c2`) and\n * as a result have different set of nodes to project.\n * - without `projection` it would be difficult to efficiently traverse nodes to be projected.\n *\n * If `typeof projection == 'number'` then `TNode` is a `<ng-content>` element:\n * - `projection` is an index of the host's `projection`Nodes.\n * - This would return the first head node to project:\n * `getHost(currentTNode).projection[currentTNode.projection]`.\n * - When projecting nodes the parent node retrieved may be a `<ng-content>` node, in which case\n * the process is recursive in nature.\n *\n * If `projection` is of type `RNode[][]` than we have a collection of native nodes passed as\n * projectable nodes during dynamic component creation.\n */\n projection: (TNode|RNode[])[]|number|null;\n\n /**\n * A collection of all `style` static values for an element (including from host).\n *\n * This field will be populated if and when:\n *\n * - There are one or more initial `style`s on an element (e.g. `<div style=\"width:200px;\">`)\n * - There are one or more initial `style`s on a directive/component host\n * (e.g. `@Directive({host: {style: \"width:200px;\" } }`)\n */\n styles: string|null;\n\n\n /**\n * A collection of all `style` static values for an element excluding host sources.\n *\n * Populated when there are one or more initial `style`s on an element\n * (e.g. `<div style=\"width:200px;\">`)\n * Must be stored separately from `tNode.styles` to facilitate setting directive\n * inputs that shadow the `style` property. If we used `tNode.styles` as is for shadowed inputs,\n * we would feed host styles back into directives as \"inputs\". If we used `tNode.attrs`, we\n * would have to concatenate the attributes on every template pass. Instead, we process once on\n * first create pass and store here.\n */\n stylesWithoutHost: string|null;\n\n /**\n * A `KeyValueArray` version of residual `styles`.\n *\n * When there are styling instructions than each instruction stores the static styling\n * which is of lower priority than itself. This means that there may be a higher priority\n * styling than the instruction.\n *\n * Imagine:\n * ```\n * <div style=\"color: highest;\" my-dir>\n *\n * @Directive({\n * host: {\n * style: 'color: lowest; ',\n * '[styles.color]': 'exp' // ɵɵstyleProp('color', ctx.exp);\n * }\n * })\n * ```\n *\n * In the above case:\n * - `color: lowest` is stored with `ɵɵstyleProp('color', ctx.exp);` instruction\n * - `color: highest` is the residual and is stored here.\n *\n * - `undefined': not initialized.\n * - `null`: initialized but `styles` is `null`\n * - `KeyValueArray`: parsed version of `styles`.\n */\n residualStyles: KeyValueArray<any>|undefined|null;\n\n /**\n * A collection of all class static values for an element (including from host).\n *\n * This field will be populated if and when:\n *\n * - There are one or more initial classes on an element (e.g. `<div class=\"one two three\">`)\n * - There are one or more initial classes on an directive/component host\n * (e.g. `@Directive({host: {class: \"SOME_CLASS\" } }`)\n */\n classes: string|null;\n\n /**\n * A collection of all class static values for an element excluding host sources.\n *\n * Populated when there are one or more initial classes on an element\n * (e.g. `<div class=\"SOME_CLASS\">`)\n * Must be stored separately from `tNode.classes` to facilitate setting directive\n * inputs that shadow the `class` property. If we used `tNode.classes` as is for shadowed\n * inputs, we would feed host classes back into directives as \"inputs\". If we used\n * `tNode.attrs`, we would have to concatenate the attributes on every template pass. Instead,\n * we process once on first create pass and store here.\n */\n classesWithoutHost: string|null;\n\n /**\n * A `KeyValueArray` version of residual `classes`.\n *\n * Same as `TNode.residualStyles` but for classes.\n *\n * - `undefined': not initialized.\n * - `null`: initialized but `classes` is `null`\n * - `KeyValueArray`: parsed version of `classes`.\n */\n residualClasses: KeyValueArray<any>|undefined|null;\n\n /**\n * Stores the head/tail index of the class bindings.\n *\n * - If no bindings, the head and tail will both be 0.\n * - If there are template bindings, stores the head/tail of the class bindings in the template.\n * - If no template bindings but there are host bindings, the head value will point to the last\n * host binding for \"class\" (not the head of the linked list), tail will be 0.\n *\n * See: `style_binding_list.ts` for details.\n *\n * This is used by `insertTStylingBinding` to know where the next styling binding should be\n * inserted so that they can be sorted in priority order.\n */\n classBindings: TStylingRange;\n\n /**\n * Stores the head/tail index of the class bindings.\n *\n * - If no bindings, the head and tail will both be 0.\n * - If there are template bindings, stores the head/tail of the style bindings in the template.\n * - If no template bindings but there are host bindings, the head value will point to the last\n * host binding for \"style\" (not the head of the linked list), tail will be 0.\n *\n * See: `style_binding_list.ts` for details.\n *\n * This is used by `insertTStylingBinding` to know where the next styling binding should be\n * inserted so that they can be sorted in priority order.\n */\n styleBindings: TStylingRange;\n}\n\n/**\n * See `TNode.insertBeforeIndex`\n */\nexport type InsertBeforeIndex = null|number|number[];\n\n/** Static data for an element */\nexport interface TElementNode extends TNode {\n /** Index in the data[] array */\n index: number;\n child: TElementNode|TTextNode|TElementContainerNode|TContainerNode|TProjectionNode|null;\n /**\n * Element nodes will have parents unless they are the first node of a component or\n * embedded view (which means their parent is in a different view and must be\n * retrieved using viewData[HOST_NODE]).\n */\n parent: TElementNode|TElementContainerNode|null;\n tView: null;\n\n /**\n * If this is a component TNode with projection, this will be an array of projected\n * TNodes or native nodes (see TNode.projection for more info). If it's a regular element node\n * or a component without projection, it will be null.\n */\n projection: (TNode|RNode[])[]|null;\n\n /**\n * Stores TagName\n */\n value: string;\n}\n\n/** Static data for a text node */\nexport interface TTextNode extends TNode {\n /** Index in the data[] array */\n index: number;\n child: null;\n /**\n * Text nodes will have parents unless they are the first node of a component or\n * embedded view (which means their parent is in a different view and must be\n * retrieved using LView.node).\n */\n parent: TElementNode|TElementContainerNode|null;\n tView: null;\n projection: null;\n}\n\n/** Static data for an LContainer */\nexport interface TContainerNode extends TNode {\n /**\n * Index in the data[] array.\n *\n * If it's -1, this is a dynamically created container node that isn't stored in\n * data[] (e.g. when you inject ViewContainerRef) .\n */\n index: number;\n child: null;\n\n /**\n * Container nodes will have parents unless:\n *\n * - They are the first node of a component or embedded view\n * - They are dynamically created\n */\n parent: TElementNode|TElementContainerNode|null;\n tView: TView|null;\n projection: null;\n value: null;\n}\n\n/** Static data for an <ng-container> */\nexport interface TElementContainerNode extends TNode {\n /** Index in the LView[] array. */\n index: number;\n child: TElementNode|TTextNode|TContainerNode|TElementContainerNode|TProjectionNode|null;\n parent: TElementNode|TElementContainerNode|null;\n tView: null;\n projection: null;\n}\n\n/** Static data for an ICU expression */\nexport interface TIcuContainerNode extends TNode {\n /** Index in the LView[] array. */\n index: number;\n child: null;\n parent: TElementNode|TElementContainerNode|null;\n tView: null;\n projection: null;\n value: TIcu;\n}\n\n/** Static data for an LProjectionNode */\nexport interface TProjectionNode extends TNode {\n /** Index in the data[] array */\n child: null;\n /**\n * Projection nodes will have parents unless they are the first node of a component\n * or embedded view (which means their parent is in a different view and must be\n * retrieved using LView.node).\n */\n parent: TElementNode|TElementContainerNode|null;\n tView: null;\n\n /** Index of the projection node. (See TNode.projection for more info.) */\n projection: number;\n value: null;\n}\n\n/**\n * A union type representing all TNode types that can host a directive.\n */\nexport type TDirectiveHostNode = TElementNode|TContainerNode|TElementContainerNode;\n\n/**\n * This mapping is necessary so we can set input properties and output listeners\n * properly at runtime when property names are minified or aliased.\n *\n * Key: unminified / public input or output name\n * Value: array containing minified / internal name and related directive index\n *\n * The value must be an array to support inputs and outputs with the same name\n * on the same node.\n */\nexport type PropertyAliases = {\n // This uses an object map because using the Map type would be too slow\n [key: string]: PropertyAliasValue\n};\n\n/**\n * Store the runtime input or output names for all the directives.\n *\n * i+0: directive instance index\n * i+1: privateName\n *\n * e.g. [0, 'change-minified']\n */\nexport type PropertyAliasValue = (number|string)[];\n\n/**\n * This array contains information about input properties that\n * need to be set once from attribute data. It's ordered by\n * directive index (relative to element) so it's simple to\n * look up a specific directive's initial input data.\n *\n * Within each sub-array:\n *\n * i+0: attribute name\n * i+1: minified/internal input name\n * i+2: initial value\n *\n * If a directive on a node does not have any input properties\n * that should be set from attributes, its index is set to null\n * to avoid a sparse array.\n *\n * e.g. [null, ['role-min', 'minified-input', 'button']]\n */\nexport type InitialInputData = (InitialInputs|null)[];\n\n/**\n * Used by InitialInputData to store input properties\n * that should be set once from attributes.\n *\n * i+0: attribute name\n * i+1: minified/internal input name\n * i+2: initial value\n *\n * e.g. ['role-min', 'minified-input', 'button']\n */\nexport type InitialInputs = string[];\n\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nexport const unusedValueExportToPlacateAjd = 1;\n\n/**\n * Type representing a set of TNodes that can have local refs (`#foo`) placed on them.\n */\nexport type TNodeWithLocalRefs = TContainerNode|TElementNode|TElementContainerNode;\n\n/**\n * Type for a function that extracts a value for a local refs.\n * Example:\n * - `<div #nativeDivEl>` - `nativeDivEl` should point to the native `<div>` element;\n * - `<ng-template #tplRef>` - `tplRef` should point to the `TemplateRef` instance;\n */\nexport type LocalRefExtractor = (tNode: TNodeWithLocalRefs, currentView: LView) => any;\n\n/**\n * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.\n *\n * ```\n * <div my-dir [class]=\"exp\"></div>\n * ```\n * and\n * ```\n * @Directive({\n * })\n * class MyDirective {\n * @Input()\n * class: string;\n * }\n * ```\n *\n * In the above case it is necessary to write the reconciled styling information into the\n * directive's input.\n *\n * @param tNode\n */\nexport function hasClassInput(tNode: TNode) {\n return (tNode.flags & TNodeFlags.hasClassInput) !== 0;\n}\n\n/**\n * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.\n *\n * ```\n * <div my-dir [style]=\"exp\"></div>\n * ```\n * and\n * ```\n * @Directive({\n * })\n * class MyDirective {\n * @Input()\n * class: string;\n * }\n * ```\n *\n * In the above case it is necessary to write the reconciled styling information into the\n * directive's input.\n *\n * @param tNode\n */\nexport function hasStyleInput(tNode: TNode) {\n return (tNode.flags & TNodeFlags.hasStyleInput) !== 0;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {assertEqual, assertIndexInRange} from '../../util/assert';\nimport {assertHasParent} from '../assert';\nimport {attachPatchData} from '../context_discovery';\nimport {registerPostOrderHooks} from '../hooks';\nimport {TAttributes, TElementContainerNode, TNodeType} from '../interfaces/node';\nimport {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';\nimport {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';\nimport {assertTNodeType} from '../node_assert';\nimport {appendChild} from '../node_manipulation';\nimport {getBindingIndex, getCurrentTNode, getLView, getTView, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';\nimport {computeStaticStyling} from '../styling/static_styling';\nimport {getConstant} from '../util/view_utils';\n\nimport {createDirectivesInstances, executeContentQueries, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';\n\nfunction elementContainerStartFirstCreatePass(\n index: number, tView: TView, lView: LView, attrsIndex?: number|null,\n localRefsIndex?: number): TElementContainerNode {\n ngDevMode && ngDevMode.firstCreatePass++;\n\n const tViewConsts = tView.consts;\n const attrs = getConstant<TAttributes>(tViewConsts, attrsIndex);\n const tNode = getOrCreateTNode(tView, index, TNodeType.ElementContainer, 'ng-container', attrs);\n\n // While ng-container doesn't necessarily support styling, we use the style context to identify\n // and execute directives on the ng-container.\n if (attrs !== null) {\n computeStaticStyling(tNode, attrs, true);\n }\n\n const localRefs = getConstant<string[]>(tViewConsts, localRefsIndex);\n resolveDirectives(tView, lView, tNode, localRefs);\n\n if (tView.queries !== null) {\n tView.queries.elementStart(tView, tNode);\n }\n\n return tNode;\n}\n\n/**\n * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.\n * The instruction must later be followed by `elementContainerEnd()` call.\n *\n * @param index Index of the element in the LView array\n * @param attrsIndex Index of the container attributes in the `consts` array.\n * @param localRefsIndex Index of the container's local references in the `consts` array.\n * @returns This function returns itself so that it may be chained.\n *\n * Even if this instruction accepts a set of attributes no actual attribute values are propagated to\n * the DOM (as a comment node can't have attributes). Attributes are here only for directive\n * matching purposes and setting initial inputs of directives.\n *\n * @codeGenApi\n */\nexport function ɵɵelementContainerStart(\n index: number, attrsIndex?: number|null,\n localRefsIndex?: number): typeof ɵɵelementContainerStart {\n const lView = getLView();\n const tView = getTView();\n const adjustedIndex = index + HEADER_OFFSET;\n\n ngDevMode && assertIndexInRange(lView, adjustedIndex);\n ngDevMode &&\n assertEqual(\n getBindingIndex(), tView.bindingStartIndex,\n 'element containers should be created before any bindings');\n\n const tNode = tView.firstCreatePass ?\n elementContainerStartFirstCreatePass(\n adjustedIndex, tView, lView, attrsIndex, localRefsIndex) :\n tView.data[adjustedIndex] as TElementContainerNode;\n setCurrentTNode(tNode, true);\n\n ngDevMode && ngDevMode.rendererCreateComment++;\n const native = lView[adjustedIndex] =\n lView[RENDERER].createComment(ngDevMode ? 'ng-container' : '');\n appendChild(tView, lView, native, tNode);\n attachPatchData(native, lView);\n\n if (isDirectiveHost(tNode)) {\n createDirectivesInstances(tView, lView, tNode);\n executeContentQueries(tView, tNode, lView);\n }\n\n if (localRefsIndex != null) {\n saveResolvedLocalsInData(lView, tNode);\n }\n\n return ɵɵelementContainerStart;\n}\n\n/**\n * Mark the end of the <ng-container>.\n * @returns This function returns itself so that it may be chained.\n *\n * @codeGenApi\n */\nexport function ɵɵelementContainerEnd(): typeof ɵɵelementContainerEnd {\n let currentTNode = getCurrentTNode()!;\n const tView = getTView();\n if (isCurrentTNodeParent()) {\n setCurrentTNodeAsNotParent();\n } else {\n ngDevMode && assertHasParent(currentTNode);\n currentTNode = currentTNode.parent!;\n setCurrentTNode(currentTNode, false);\n }\n\n ngDevMode && assertTNodeType(currentTNode, TNodeType.ElementContainer);\n\n if (tView.firstCreatePass) {\n registerPostOrderHooks(tView, currentTNode);\n if (isContentQueryHost(currentTNode)) {\n tView.queries!.elementEnd(currentTNode);\n }\n }\n return ɵɵelementContainerEnd;\n}\n\n/**\n * Creates an empty logical container using {@link elementContainerStart}\n * and {@link elementContainerEnd}\n *\n * @param index Index of the element in the LView array\n * @param attrsIndex Index of the container attributes in the `consts` array.\n * @param localRefsIndex Index of the container's local references in the `consts` array.\n * @returns This function returns itself so that it may be chained.\n *\n * @codeGenApi\n */\nexport function ɵɵelementContainer(\n index: number, attrsIndex?: number|null, localRefsIndex?: number): typeof ɵɵelementContainer {\n ɵɵelementContainerStart(index, attrsIndex, localRefsIndex);\n ɵɵelementContainerEnd();\n return ɵɵelementContainer;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {OpaqueViewState} from '../interfaces/view';\nimport {getLView} from '../state';\n\n/**\n * Returns the current OpaqueViewState instance.\n *\n * Used in conjunction with the restoreView() instruction to save a snapshot\n * of the current view and restore it when listeners are invoked. This allows\n * walking the declaration view tree in listeners to get vars from parent views.\n *\n * @codeGenApi\n */\nexport function ɵɵgetCurrentView(): OpaqueViewState {\n return getLView() as any as OpaqueViewState;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Observable, Subscribable} from 'rxjs';\n\n/**\n * Determine if the argument is shaped like a Promise\n */\nexport function isPromise<T = any>(obj: any): obj is Promise<T> {\n // allow any Promise/A+ compliant thenable.\n // It's up to the caller to ensure that obj.then conforms to the spec\n return !!obj && typeof obj.then === 'function';\n}\n\n/**\n * Determine if the argument is a Subscribable\n */\nexport function isSubscribable(obj: any|Subscribable<any>): obj is Subscribable<any> {\n return !!obj && typeof obj.subscribe === 'function';\n}\n\n/**\n * Determine if the argument is an Observable\n *\n * Strictly this tests that the `obj` is `Subscribable`, since `Observable`\n * types need additional methods, such as `lift()`. But it is adequate for our\n * needs since within the Angular framework code we only ever need to use the\n * `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects\n * into `Observable` as needed.\n */\nexport const isObservable =\n isSubscribable as ((obj: any|Observable<any>) => obj is Observable<any>);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {assertIndexInRange} from '../../util/assert';\nimport {isObservable} from '../../util/lang';\nimport {PropertyAliasValue, TNode, TNodeType} from '../interfaces/node';\nimport {GlobalTargetResolver, Renderer} from '../interfaces/renderer';\nimport {RElement} from '../interfaces/renderer_dom';\nimport {isDirectiveHost} from '../interfaces/type_checks';\nimport {CLEANUP, CONTEXT, LView, RENDERER, TView} from '../interfaces/view';\nimport {assertTNodeType} from '../node_assert';\nimport {profiler, ProfilerEvent} from '../profiler';\nimport {getCurrentDirectiveDef, getCurrentTNode, getLView, getTView} from '../state';\nimport {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';\n\nimport {getOrCreateLViewCleanup, getOrCreateTViewCleanup, handleError, loadComponentRenderer, markViewDirty} from './shared';\n\n\n\n/**\n * Adds an event listener to the current node.\n *\n * If an output exists on one of the node's directives, it also subscribes to the output\n * and saves the subscription for later cleanup.\n *\n * @param eventName Name of the event\n * @param listenerFn The function to be called when event emits\n * @param useCapture Whether or not to use capture in event listener - this argument is a reminder\n * from the Renderer3 infrastructure and should be removed from the instruction arguments\n * @param eventTargetResolver Function that returns global target information in case this listener\n * should be attached to a global object like window, document or body\n *\n * @codeGenApi\n */\nexport function ɵɵlistener(\n eventName: string, listenerFn: (e?: any) => any, useCapture?: boolean,\n eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {\n const lView = getLView<{}|null>();\n const tView = getTView();\n const tNode = getCurrentTNode()!;\n listenerInternal(\n tView, lView, lView[RENDERER], tNode, eventName, listenerFn, eventTargetResolver);\n return ɵɵlistener;\n}\n\n/**\n * Registers a synthetic host listener (e.g. `(@foo.start)`) on a component or directive.\n *\n * This instruction is for compatibility purposes and is designed to ensure that a\n * synthetic host listener (e.g. `@HostListener('@foo.start')`) properly gets rendered\n * in the component's renderer. Normally all host listeners are evaluated with the\n * parent component's renderer, but, in the case of animation @triggers, they need\n * to be evaluated with the sub component's renderer (because that's where the\n * animation triggers are defined).\n *\n * Do not use this instruction as a replacement for `listener`. This instruction\n * only exists to ensure compatibility with the ViewEngine's host binding behavior.\n *\n * @param eventName Name of the event\n * @param listenerFn The function to be called when event emits\n * @param useCapture Whether or not to use capture in event listener\n * @param eventTargetResolver Function that returns global target information in case this listener\n * should be attached to a global object like window, document or body\n *\n * @codeGenApi\n */\nexport function ɵɵsyntheticHostListener(\n eventName: string, listenerFn: (e?: any) => any): typeof ɵɵsyntheticHostListener {\n const tNode = getCurrentTNode()!;\n const lView = getLView<{}|null>();\n const tView = getTView();\n const currentDef = getCurrentDirectiveDef(tView.data);\n const renderer = loadComponentRenderer(currentDef, tNode, lView);\n listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn);\n return ɵɵsyntheticHostListener;\n}\n\n/**\n * A utility function that checks if a given element has already an event handler registered for an\n * event with a specified name. The TView.cleanup data structure is used to find out which events\n * are registered for a given element.\n */\nfunction findExistingListener(\n tView: TView, lView: LView, eventName: string, tNodeIdx: number): ((e?: any) => any)|null {\n const tCleanup = tView.cleanup;\n if (tCleanup != null) {\n for (let i = 0; i < tCleanup.length - 1; i += 2) {\n const cleanupEventName = tCleanup[i];\n if (cleanupEventName === eventName && tCleanup[i + 1] === tNodeIdx) {\n // We have found a matching event name on the same node but it might not have been\n // registered yet, so we must explicitly verify entries in the LView cleanup data\n // structures.\n const lCleanup = lView[CLEANUP]!;\n const listenerIdxInLCleanup = tCleanup[i + 2];\n return lCleanup.length > listenerIdxInLCleanup ? lCleanup[listenerIdxInLCleanup] : null;\n }\n // TView.cleanup can have a mix of 4-elements entries (for event handler cleanups) or\n // 2-element entries (for directive and queries destroy hooks). As such we can encounter\n // blocks of 4 or 2 items in the tView.cleanup and this is why we iterate over 2 elements\n // first and jump another 2 elements if we detect listeners cleanup (4 elements). Also check\n // documentation of TView.cleanup for more details of this data structure layout.\n if (typeof cleanupEventName === 'string') {\n i += 2;\n }\n }\n }\n return null;\n}\n\nfunction listenerInternal(\n tView: TView, lView: LView<{}|null>, renderer: Renderer, tNode: TNode, eventName: string,\n listenerFn: (e?: any) => any, eventTargetResolver?: GlobalTargetResolver): void {\n const isTNodeDirectiveHost = isDirectiveHost(tNode);\n const firstCreatePass = tView.firstCreatePass;\n const tCleanup: false|any[] = firstCreatePass && getOrCreateTViewCleanup(tView);\n const context = lView[CONTEXT];\n\n // When the ɵɵlistener instruction was generated and is executed we know that there is either a\n // native listener or a directive output on this element. As such we we know that we will have to\n // register a listener and store its cleanup function on LView.\n const lCleanup = getOrCreateLViewCleanup(lView);\n\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);\n\n let processOutputs = true;\n\n // Adding a native event listener is applicable when:\n // - The corresponding TNode represents a DOM element.\n // - The event target has a resolver (usually resulting in a global object,\n // such as `window` or `document`).\n if ((tNode.type & TNodeType.AnyRNode) || eventTargetResolver) {\n const native = getNativeByTNode(tNode, lView) as RElement;\n const target = eventTargetResolver ? eventTargetResolver(native) : native;\n const lCleanupIndex = lCleanup.length;\n const idxOrTargetGetter = eventTargetResolver ?\n (_lView: LView) => eventTargetResolver(unwrapRNode(_lView[tNode.index])) :\n tNode.index;\n\n // In order to match current behavior, native DOM event listeners must be added for all\n // events (including outputs).\n\n // There might be cases where multiple directives on the same element try to register an event\n // handler function for the same event. In this situation we want to avoid registration of\n // several native listeners as each registration would be intercepted by NgZone and\n // trigger change detection. This would mean that a single user action would result in several\n // change detections being invoked. To avoid this situation we want to have only one call to\n // native handler registration (for the same element and same type of event).\n //\n // In order to have just one native event handler in presence of multiple handler functions,\n // we just register a first handler function as a native event listener and then chain\n // (coalesce) other handler functions on top of the first native handler function.\n let existingListener = null;\n // Please note that the coalescing described here doesn't happen for events specifying an\n // alternative target (ex. (document:click)) - this is to keep backward compatibility with the\n // view engine.\n // Also, we don't have to search for existing listeners is there are no directives\n // matching on a given node as we can't register multiple event handlers for the same event in\n // a template (this would mean having duplicate attributes).\n if (!eventTargetResolver && isTNodeDirectiveHost) {\n existingListener = findExistingListener(tView, lView, eventName, tNode.index);\n }\n if (existingListener !== null) {\n // Attach a new listener to coalesced listeners list, maintaining the order in which\n // listeners are registered. For performance reasons, we keep a reference to the last\n // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through\n // the entire set each time we need to add a new listener.\n const lastListenerFn = (<any>existingListener).__ngLastListenerFn__ || existingListener;\n lastListenerFn.__ngNextListenerFn__ = listenerFn;\n (<any>existingListener).__ngLastListenerFn__ = listenerFn;\n processOutputs = false;\n } else {\n listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);\n const cleanupFn = renderer.listen(target as RElement, eventName, listenerFn);\n ngDevMode && ngDevMode.rendererAddEventListener++;\n\n lCleanup.push(listenerFn, cleanupFn);\n tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);\n }\n\n } else {\n // Even if there is no native listener to add, we still need to wrap the listener so that OnPush\n // ancestors are marked dirty when an event occurs.\n listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);\n }\n\n // subscribe to directive outputs\n const outputs = tNode.outputs;\n let props: PropertyAliasValue|undefined;\n if (processOutputs && outputs !== null && (props = outputs[eventName])) {\n const propsLength = props.length;\n if (propsLength) {\n for (let i = 0; i < propsLength; i += 2) {\n const index = props[i] as number;\n ngDevMode && assertIndexInRange(lView, index);\n const minifiedName = props[i + 1];\n const directiveInstance = lView[index];\n const output = directiveInstance[minifiedName];\n\n if (ngDevMode && !isObservable(output)) {\n throw new Error(`@Output ${minifiedName} not initialized in '${\n directiveInstance.constructor.name}'.`);\n }\n\n const subscription = output.subscribe(listenerFn);\n const idx = lCleanup.length;\n lCleanup.push(listenerFn, subscription);\n tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));\n }\n }\n }\n}\n\nfunction executeListenerWithErrorHandling(\n lView: LView, context: {}|null, listenerFn: (e?: any) => any, e: any): boolean {\n try {\n profiler(ProfilerEvent.OutputStart, context, listenerFn);\n // Only explicitly returning false from a listener should preventDefault\n return listenerFn(e) !== false;\n } catch (error) {\n handleError(lView, error);\n return false;\n } finally {\n profiler(ProfilerEvent.OutputEnd, context, listenerFn);\n }\n}\n\n/**\n * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior,\n * if applicable.\n *\n * @param tNode The TNode associated with this listener\n * @param lView The LView that contains this listener\n * @param listenerFn The listener function to call\n * @param wrapWithPreventDefault Whether or not to prevent default behavior\n * (the procedural renderer does this already, so in those cases, we should skip)\n */\nfunction wrapListener(\n tNode: TNode, lView: LView<{}|null>, context: {}|null, listenerFn: (e?: any) => any,\n wrapWithPreventDefault: boolean): EventListener {\n // Note: we are performing most of the work in the listener function itself\n // to optimize listener registration.\n return function wrapListenerIn_markDirtyAndPreventDefault(e: any) {\n // Ivy uses `Function` as a special token that allows us to unwrap the function\n // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.\n if (e === Function) {\n return listenerFn;\n }\n\n // In order to be backwards compatible with View Engine, events on component host nodes\n // must also mark the component view itself dirty (i.e. the view that it owns).\n const startView =\n tNode.componentOffset > -1 ? getComponentLViewByIndex(tNode.index, lView) : lView;\n markViewDirty(startView);\n\n let result = executeListenerWithErrorHandling(lView, context, listenerFn, e);\n // A just-invoked listener function might have coalesced listeners so we need to check for\n // their presence and invoke as needed.\n let nextListenerFn = (<any>wrapListenerIn_markDirtyAndPreventDefault).__ngNextListenerFn__;\n while (nextListenerFn) {\n // We should prevent default if any of the listeners explicitly return false\n result = executeListenerWithErrorHandling(lView, context, nextListenerFn, e) && result;\n nextListenerFn = (<any>nextListenerFn).__ngNextListenerFn__;\n }\n\n if (wrapWithPreventDefault && result === false) {\n e.preventDefault();\n // Necessary for legacy browsers that don't support preventDefault (e.g. IE)\n e.returnValue = false;\n }\n\n return result;\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {nextContextImpl} from '../state';\n\n/**\n * Retrieves a context at the level specified and saves it as the global, contextViewData.\n * Will get the next level up if level is not specified.\n *\n * This is used to save contexts of parent views so they can be bound in embedded views, or\n * in conjunction with reference() to bind a ref from a parent view.\n *\n * @param level The relative level of the view from which to grab context compared to contextVewData\n * @returns context\n *\n * @codeGenApi\n */\nexport function ɵɵnextContext<T = any>(level: number = 1): T {\n return nextContextImpl(level);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {newArray} from '../../util/array_utils';\nimport {TAttributes, TElementNode, TNode, TNodeFlags, TNodeType} from '../interfaces/node';\nimport {ProjectionSlots} from '../interfaces/projection';\nimport {DECLARATION_COMPONENT_VIEW, HEADER_OFFSET, T_HOST} from '../interfaces/view';\nimport {applyProjection} from '../node_manipulation';\nimport {getProjectAsAttrValue, isNodeMatchingSelectorList, isSelectorInSelectorList} from '../node_selector_matcher';\nimport {getLView, getTView, setCurrentTNodeAsNotParent} from '../state';\nimport {getOrCreateTNode} from './shared';\n\n\n\n/**\n * Checks a given node against matching projection slots and returns the\n * determined slot index. Returns \"null\" if no slot matched the given node.\n *\n * This function takes into account the parsed ngProjectAs selector from the\n * node's attributes. If present, it will check whether the ngProjectAs selector\n * matches any of the projection slot selectors.\n */\nexport function matchingProjectionSlotIndex(tNode: TNode, projectionSlots: ProjectionSlots): number|\n null {\n let wildcardNgContentIndex = null;\n const ngProjectAsAttrVal = getProjectAsAttrValue(tNode);\n for (let i = 0; i < projectionSlots.length; i++) {\n const slotValue = projectionSlots[i];\n // The last wildcard projection slot should match all nodes which aren't matching\n // any selector. This is necessary to be backwards compatible with view engine.\n if (slotValue === '*') {\n wildcardNgContentIndex = i;\n continue;\n }\n // If we ran into an `ngProjectAs` attribute, we should match its parsed selector\n // to the list of selectors, otherwise we fall back to matching against the node.\n if (ngProjectAsAttrVal === null ?\n isNodeMatchingSelectorList(tNode, slotValue, /* isProjectionMode */ true) :\n isSelectorInSelectorList(ngProjectAsAttrVal, slotValue)) {\n return i; // first matching selector \"captures\" a given node\n }\n }\n return wildcardNgContentIndex;\n}\n\n/**\n * Instruction to distribute projectable nodes among <ng-content> occurrences in a given template.\n * It takes all the selectors from the entire component's template and decides where\n * each projected node belongs (it re-distributes nodes among \"buckets\" where each \"bucket\" is\n * backed by a selector).\n *\n * This function requires CSS selectors to be provided in 2 forms: parsed (by a compiler) and text,\n * un-parsed form.\n *\n * The parsed form is needed for efficient matching of a node against a given CSS selector.\n * The un-parsed, textual form is needed for support of the ngProjectAs attribute.\n *\n * Having a CSS selector in 2 different formats is not ideal, but alternatives have even more\n * drawbacks:\n * - having only a textual form would require runtime parsing of CSS selectors;\n * - we can't have only a parsed as we can't re-construct textual form from it (as entered by a\n * template author).\n *\n * @param projectionSlots? A collection of projection slots. A projection slot can be based\n * on a parsed CSS selectors or set to the wildcard selector (\"*\") in order to match\n * all nodes which do not match any selector. If not specified, a single wildcard\n * selector projection slot will be defined.\n *\n * @codeGenApi\n */\nexport function ɵɵprojectionDef(projectionSlots?: ProjectionSlots): void {\n const componentNode = getLView()[DECLARATION_COMPONENT_VIEW][T_HOST] as TElementNode;\n\n if (!componentNode.projection) {\n // If no explicit projection slots are defined, fall back to a single\n // projection slot with the wildcard selector.\n const numProjectionSlots = projectionSlots ? projectionSlots.length : 1;\n const projectionHeads: (TNode|null)[] = componentNode.projection =\n newArray(numProjectionSlots, null! as TNode);\n const tails: (TNode|null)[] = projectionHeads.slice();\n\n let componentChild: TNode|null = componentNode.child;\n\n while (componentChild !== null) {\n const slotIndex =\n projectionSlots ? matchingProjectionSlotIndex(componentChild, projectionSlots) : 0;\n\n if (slotIndex !== null) {\n if (tails[slotIndex]) {\n tails[slotIndex]!.projectionNext = componentChild;\n } else {\n projectionHeads[slotIndex] = componentChild;\n }\n tails[slotIndex] = componentChild;\n }\n\n componentChild = componentChild.next;\n }\n }\n}\n\n\n/**\n * Inserts previously re-distributed projected nodes. This instruction must be preceded by a call\n * to the projectionDef instruction.\n *\n * @param nodeIndex\n * @param selectorIndex:\n * - 0 when the selector is `*` (or unspecified as this is the default value),\n * - 1 based index of the selector from the {@link projectionDef}\n *\n * @codeGenApi\n */\nexport function ɵɵprojection(\n nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void {\n const lView = getLView();\n const tView = getTView();\n const tProjectionNode =\n getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, TNodeType.Projection, null, attrs || null);\n\n // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.\n if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex;\n\n // `<ng-content>` has no content\n setCurrentTNodeAsNotParent();\n\n if ((tProjectionNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) {\n // re-distribution of projectable nodes is stored on a component's view level\n applyProjection(tView, lView, tProjectionNode);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {RENDERER} from '../interfaces/view';\nimport {getBindingIndex, getLView, getSelectedTNode, getTView} from '../state';\nimport {NO_CHANGE} from '../tokens';\n\nimport {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';\nimport {elementPropertyInternal, storePropertyBindingMetadata} from './shared';\n\n\n/**\n *\n * Update an interpolated property on an element with a lone bound value\n *\n * Used when the value passed to a property has 1 interpolated value in it, an no additional text\n * surrounds that interpolated value:\n *\n * ```html\n * <div title=\"{{v0}}\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate('title', v0);\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate(\n propName: string, v0: any, sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate {\n ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);\n return ɵɵpropertyInterpolate;\n}\n\n\n/**\n *\n * Update an interpolated property on an element with single bound value surrounded by text.\n *\n * Used when the value passed to a property has 1 interpolated value in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate1(\n propName: string, prefix: string, v0: any, suffix: string,\n sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate1 {\n const lView = getLView();\n const interpolatedValue = interpolation1(lView, prefix, v0, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix);\n }\n return ɵɵpropertyInterpolate1;\n}\n\n/**\n *\n * Update an interpolated property on an element with 2 bound values surrounded by text.\n *\n * Used when the value passed to a property has 2 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate2(\n propName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string,\n sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate2 {\n const lView = getLView();\n const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix);\n }\n return ɵɵpropertyInterpolate2;\n}\n\n/**\n *\n * Update an interpolated property on an element with 3 bound values surrounded by text.\n *\n * Used when the value passed to a property has 3 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate3(\n * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate3(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,\n suffix: string, sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate3 {\n const lView = getLView();\n const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);\n }\n return ɵɵpropertyInterpolate3;\n}\n\n/**\n *\n * Update an interpolated property on an element with 4 bound values surrounded by text.\n *\n * Used when the value passed to a property has 4 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate4(\n * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate4(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, suffix: string, sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate4 {\n const lView = getLView();\n const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);\n }\n return ɵɵpropertyInterpolate4;\n}\n\n/**\n *\n * Update an interpolated property on an element with 5 bound values surrounded by text.\n *\n * Used when the value passed to a property has 5 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate5(\n * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate5(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, suffix: string,\n sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate5 {\n const lView = getLView();\n const interpolatedValue =\n interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);\n }\n return ɵɵpropertyInterpolate5;\n}\n\n/**\n *\n * Update an interpolated property on an element with 6 bound values surrounded by text.\n *\n * Used when the value passed to a property has 6 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate6(\n * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate6(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string,\n sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate6 {\n const lView = getLView();\n const interpolatedValue =\n interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);\n }\n return ɵɵpropertyInterpolate6;\n}\n\n/**\n *\n * Update an interpolated property on an element with 7 bound values surrounded by text.\n *\n * Used when the value passed to a property has 7 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate7(\n * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param i5 Static value used for concatenation only.\n * @param v6 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate7(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string,\n sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate7 {\n const lView = getLView();\n const interpolatedValue =\n interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5,\n suffix);\n }\n return ɵɵpropertyInterpolate7;\n}\n\n/**\n *\n * Update an interpolated property on an element with 8 bound values surrounded by text.\n *\n * Used when the value passed to a property has 8 interpolated values in it:\n *\n * ```html\n * <div title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolate8(\n * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param i5 Static value used for concatenation only.\n * @param v6 Value checked for change.\n * @param i6 Static value used for concatenation only.\n * @param v7 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolate8(\n propName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,\n v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,\n suffix: string, sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolate8 {\n const lView = getLView();\n const interpolatedValue = interpolation8(\n lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n ngDevMode &&\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6,\n suffix);\n }\n return ɵɵpropertyInterpolate8;\n}\n\n/**\n * Update an interpolated property on an element with 9 or more bound values surrounded by text.\n *\n * Used when the number of interpolated values exceeds 8.\n *\n * ```html\n * <div\n * title=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix\"></div>\n * ```\n *\n * Its compiled representation is::\n *\n * ```ts\n * ɵɵpropertyInterpolateV(\n * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,\n * 'suffix']);\n * ```\n *\n * If the property name also exists as an input property on one of the element's directives,\n * the component property will be set instead of the element property. This check must\n * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.\n *\n * @param propName The name of the property to update.\n * @param values The collection of values and the strings in between those values, beginning with a\n * string prefix and ending with a string suffix.\n * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)\n * @param sanitizer An optional sanitizer function\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵpropertyInterpolateV(\n propName: string, values: any[], sanitizer?: SanitizerFn): typeof ɵɵpropertyInterpolateV {\n const lView = getLView();\n const interpolatedValue = interpolationV(lView, values);\n if (interpolatedValue !== NO_CHANGE) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(\n tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);\n if (ngDevMode) {\n const interpolationInBetween = [values[0]]; // prefix\n for (let i = 2; i < values.length; i += 2) {\n interpolationInBetween.push(values[i]);\n }\n storePropertyBindingMetadata(\n tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1,\n ...interpolationInBetween);\n }\n }\n return ɵɵpropertyInterpolateV;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {KeyValueArray} from '../../util/array_utils';\nimport {assertNumber, assertNumberInRange} from '../../util/assert';\n\n/**\n * Value stored in the `TData` which is needed to re-concatenate the styling.\n *\n * See: `TStylingKeyPrimitive` and `TStylingStatic`\n */\nexport type TStylingKey = TStylingKeyPrimitive|TStylingStatic;\n\n\n/**\n * The primitive portion (`TStylingStatic` removed) of the value stored in the `TData` which is\n * needed to re-concatenate the styling.\n *\n * - `string`: Stores the property name. Used with `ɵɵstyleProp`/`ɵɵclassProp` instruction.\n * - `null`: Represents map, so there is no name. Used with `ɵɵstyleMap`/`ɵɵclassMap`.\n * - `false`: Represents an ignore case. This happens when `ɵɵstyleProp`/`ɵɵclassProp` instruction\n * is combined with directive which shadows its input `@Input('class')`. That way the binding\n * should not participate in the styling resolution.\n */\nexport type TStylingKeyPrimitive = string|null|false;\n\n/**\n * Store the static values for the styling binding.\n *\n * The `TStylingStatic` is just `KeyValueArray` where key `\"\"` (stored at location 0) contains the\n * `TStylingKey` (stored at location 1). In other words this wraps the `TStylingKey` such that the\n * `\"\"` contains the wrapped value.\n *\n * When instructions are resolving styling they may need to look forward or backwards in the linked\n * list to resolve the value. For this reason we have to make sure that he linked list also contains\n * the static values. However the list only has space for one item per styling instruction. For this\n * reason we store the static values here as part of the `TStylingKey`. This means that the\n * resolution function when looking for a value needs to first look at the binding value, and than\n * at `TStylingKey` (if it exists).\n *\n * Imagine we have:\n *\n * ```\n * <div class=\"TEMPLATE\" my-dir>\n *\n * @Directive({\n * host: {\n * class: 'DIR',\n * '[class.dynamic]': 'exp' // ɵɵclassProp('dynamic', ctx.exp);\n * }\n * })\n * ```\n *\n * In the above case the linked list will contain one item:\n *\n * ```\n * // assume binding location: 10 for `ɵɵclassProp('dynamic', ctx.exp);`\n * tData[10] = <TStylingStatic>[\n * '': 'dynamic', // This is the wrapped value of `TStylingKey`\n * 'DIR': true, // This is the default static value of directive binding.\n * ];\n * tData[10 + 1] = 0; // We don't have prev/next.\n *\n * lView[10] = undefined; // assume `ctx.exp` is `undefined`\n * lView[10 + 1] = undefined; // Just normalized `lView[10]`\n * ```\n *\n * So when the function is resolving styling value, it first needs to look into the linked list\n * (there is none) and than into the static `TStylingStatic` too see if there is a default value for\n * `dynamic` (there is not). Therefore it is safe to remove it.\n *\n * If setting `true` case:\n * ```\n * lView[10] = true; // assume `ctx.exp` is `true`\n * lView[10 + 1] = true; // Just normalized `lView[10]`\n * ```\n * So when the function is resolving styling value, it first needs to look into the linked list\n * (there is none) and than into `TNode.residualClass` (TNode.residualStyle) which contains\n * ```\n * tNode.residualClass = [\n * 'TEMPLATE': true,\n * ];\n * ```\n *\n * This means that it is safe to add class.\n */\nexport interface TStylingStatic extends KeyValueArray<any> {}\n\n/**\n * This is a branded number which contains previous and next index.\n *\n * When we come across styling instructions we need to store the `TStylingKey` in the correct\n * order so that we can re-concatenate the styling value in the desired priority.\n *\n * The insertion can happen either at the:\n * - end of template as in the case of coming across additional styling instruction in the template\n * - in front of the template in the case of coming across additional instruction in the\n * `hostBindings`.\n *\n * We use `TStylingRange` to store the previous and next index into the `TData` where the template\n * bindings can be found.\n *\n * - bit 0 is used to mark that the previous index has a duplicate for current value.\n * - bit 1 is used to mark that the next index has a duplicate for the current value.\n * - bits 2-16 are used to encode the next/tail of the template.\n * - bits 17-32 are used to encode the previous/head of template.\n *\n * NODE: *duplicate* false implies that it is statically known that this binding will not collide\n * with other bindings and therefore there is no need to check other bindings. For example the\n * bindings in `<div [style.color]=\"exp\" [style.width]=\"exp\">` will never collide and will have\n * their bits set accordingly. Previous duplicate means that we may need to check previous if the\n * current binding is `null`. Next duplicate means that we may need to check next bindings if the\n * current binding is not `null`.\n *\n * NOTE: `0` has special significance and represents `null` as in no additional pointer.\n */\nexport interface TStylingRange {\n __brand__: 'TStylingRange';\n}\n\n/**\n * Shift and masks constants for encoding two numbers into and duplicate info into a single number.\n */\nexport const enum StylingRange {\n /// Number of bits to shift for the previous pointer\n PREV_SHIFT = 17,\n /// Previous pointer mask.\n PREV_MASK = 0xFFFE0000,\n\n /// Number of bits to shift for the next pointer\n NEXT_SHIFT = 2,\n /// Next pointer mask.\n NEXT_MASK = 0x001FFFC,\n\n // Mask to remove negative bit. (interpret number as positive)\n UNSIGNED_MASK = 0x7FFF,\n\n /**\n * This bit is set if the previous bindings contains a binding which could possibly cause a\n * duplicate. For example: `<div [style]=\"map\" [style.width]=\"width\">`, the `width` binding will\n * have previous duplicate set. The implication is that if `width` binding becomes `null`, it is\n * necessary to defer the value to `map.width`. (Because `width` overwrites `map.width`.)\n */\n PREV_DUPLICATE = 0x02,\n\n /**\n * This bit is set to if the next binding contains a binding which could possibly cause a\n * duplicate. For example: `<div [style]=\"map\" [style.width]=\"width\">`, the `map` binding will\n * have next duplicate set. The implication is that if `map.width` binding becomes not `null`, it\n * is necessary to defer the value to `width`. (Because `width` overwrites `map.width`.)\n */\n NEXT_DUPLICATE = 0x01,\n}\n\n\nexport function toTStylingRange(prev: number, next: number): TStylingRange {\n ngDevMode && assertNumberInRange(prev, 0, StylingRange.UNSIGNED_MASK);\n ngDevMode && assertNumberInRange(next, 0, StylingRange.UNSIGNED_MASK);\n return (prev << StylingRange.PREV_SHIFT | next << StylingRange.NEXT_SHIFT) as any;\n}\n\nexport function getTStylingRangePrev(tStylingRange: TStylingRange): number {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) >> StylingRange.PREV_SHIFT) & StylingRange.UNSIGNED_MASK;\n}\n\nexport function getTStylingRangePrevDuplicate(tStylingRange: TStylingRange): boolean {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) & StylingRange.PREV_DUPLICATE) ==\n StylingRange.PREV_DUPLICATE;\n}\n\nexport function setTStylingRangePrev(\n tStylingRange: TStylingRange, previous: number): TStylingRange {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n ngDevMode && assertNumberInRange(previous, 0, StylingRange.UNSIGNED_MASK);\n return (((tStylingRange as any as number) & ~StylingRange.PREV_MASK) |\n (previous << StylingRange.PREV_SHIFT)) as any;\n}\n\nexport function setTStylingRangePrevDuplicate(tStylingRange: TStylingRange): TStylingRange {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) | StylingRange.PREV_DUPLICATE) as any;\n}\n\nexport function getTStylingRangeNext(tStylingRange: TStylingRange): number {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) & StylingRange.NEXT_MASK) >> StylingRange.NEXT_SHIFT;\n}\n\nexport function setTStylingRangeNext(tStylingRange: TStylingRange, next: number): TStylingRange {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n ngDevMode && assertNumberInRange(next, 0, StylingRange.UNSIGNED_MASK);\n return (((tStylingRange as any as number) & ~StylingRange.NEXT_MASK) | //\n next << StylingRange.NEXT_SHIFT) as any;\n}\n\nexport function getTStylingRangeNextDuplicate(tStylingRange: TStylingRange): boolean {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) & StylingRange.NEXT_DUPLICATE) ===\n StylingRange.NEXT_DUPLICATE;\n}\n\nexport function setTStylingRangeNextDuplicate(tStylingRange: TStylingRange): TStylingRange {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n return ((tStylingRange as any as number) | StylingRange.NEXT_DUPLICATE) as any;\n}\n\nexport function getTStylingRangeTail(tStylingRange: TStylingRange): number {\n ngDevMode && assertNumber(tStylingRange, 'expected number');\n const next = getTStylingRangeNext(tStylingRange);\n return next === 0 ? getTStylingRangePrev(tStylingRange) : next;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {KeyValueArray, keyValueArrayIndexOf} from '../../util/array_utils';\nimport {assertEqual, assertIndexInRange, assertNotEqual} from '../../util/assert';\nimport {assertFirstUpdatePass} from '../assert';\nimport {TNode} from '../interfaces/node';\nimport {getTStylingRangeNext, getTStylingRangePrev, setTStylingRangeNext, setTStylingRangeNextDuplicate, setTStylingRangePrev, setTStylingRangePrevDuplicate, toTStylingRange, TStylingKey, TStylingKeyPrimitive, TStylingRange} from '../interfaces/styling';\nimport {TData} from '../interfaces/view';\nimport {getTView} from '../state';\n\n\n/**\n * NOTE: The word `styling` is used interchangeably as style or class styling.\n *\n * This file contains code to link styling instructions together so that they can be replayed in\n * priority order. The file exists because Ivy styling instruction execution order does not match\n * that of the priority order. The purpose of this code is to create a linked list so that the\n * instructions can be traversed in priority order when computing the styles.\n *\n * Assume we are dealing with the following code:\n * ```\n * @Component({\n * template: `\n * <my-cmp [style]=\" {color: '#001'} \"\n * [style.color]=\" #002 \"\n * dir-style-color-1\n * dir-style-color-2> `\n * })\n * class ExampleComponent {\n * static ngComp = ... {\n * ...\n * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`\n * ɵɵstyleMap({color: '#001'});\n * ɵɵstyleProp('color', '#002');\n * ...\n * }\n * }\n *\n * @Directive({\n * selector: `[dir-style-color-1]',\n * })\n * class Style1Directive {\n * @HostBinding('style') style = {color: '#005'};\n * @HostBinding('style.color') color = '#006';\n *\n * static ngDir = ... {\n * ...\n * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`\n * ɵɵstyleMap({color: '#005'});\n * ɵɵstyleProp('color', '#006');\n * ...\n * }\n * }\n *\n * @Directive({\n * selector: `[dir-style-color-2]',\n * })\n * class Style2Directive {\n * @HostBinding('style') style = {color: '#007'};\n * @HostBinding('style.color') color = '#008';\n *\n * static ngDir = ... {\n * ...\n * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`\n * ɵɵstyleMap({color: '#007'});\n * ɵɵstyleProp('color', '#008');\n * ...\n * }\n * }\n *\n * @Directive({\n * selector: `my-cmp',\n * })\n * class MyComponent {\n * @HostBinding('style') style = {color: '#003'};\n * @HostBinding('style.color') color = '#004';\n *\n * static ngComp = ... {\n * ...\n * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`\n * ɵɵstyleMap({color: '#003'});\n * ɵɵstyleProp('color', '#004');\n * ...\n * }\n * }\n * ```\n *\n * The Order of instruction execution is:\n *\n * NOTE: the comment binding location is for illustrative purposes only.\n *\n * ```\n * // Template: (ExampleComponent)\n * ɵɵstyleMap({color: '#001'}); // Binding index: 10\n * ɵɵstyleProp('color', '#002'); // Binding index: 12\n * // MyComponent\n * ɵɵstyleMap({color: '#003'}); // Binding index: 20\n * ɵɵstyleProp('color', '#004'); // Binding index: 22\n * // Style1Directive\n * ɵɵstyleMap({color: '#005'}); // Binding index: 24\n * ɵɵstyleProp('color', '#006'); // Binding index: 26\n * // Style2Directive\n * ɵɵstyleMap({color: '#007'}); // Binding index: 28\n * ɵɵstyleProp('color', '#008'); // Binding index: 30\n * ```\n *\n * The correct priority order of concatenation is:\n *\n * ```\n * // MyComponent\n * ɵɵstyleMap({color: '#003'}); // Binding index: 20\n * ɵɵstyleProp('color', '#004'); // Binding index: 22\n * // Style1Directive\n * ɵɵstyleMap({color: '#005'}); // Binding index: 24\n * ɵɵstyleProp('color', '#006'); // Binding index: 26\n * // Style2Directive\n * ɵɵstyleMap({color: '#007'}); // Binding index: 28\n * ɵɵstyleProp('color', '#008'); // Binding index: 30\n * // Template: (ExampleComponent)\n * ɵɵstyleMap({color: '#001'}); // Binding index: 10\n * ɵɵstyleProp('color', '#002'); // Binding index: 12\n * ```\n *\n * What color should be rendered?\n *\n * Once the items are correctly sorted in the list, the answer is simply the last item in the\n * concatenation list which is `#002`.\n *\n * To do so we keep a linked list of all of the bindings which pertain to this element.\n * Notice that the bindings are inserted in the order of execution, but the `TView.data` allows\n * us to traverse them in the order of priority.\n *\n * |Idx|`TView.data`|`LView` | Notes\n * |---|------------|-----------------|--------------\n * |...| | |\n * |10 |`null` |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})`\n * |11 |`30 | 12` | ... |\n * |12 |`color` |`'#002'` | `ɵɵstyleProp('color', '#002')`\n * |13 |`10 | 0` | ... |\n * |...| | |\n * |20 |`null` |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})`\n * |21 |`0 | 22` | ... |\n * |22 |`color` |`'#004'` | `ɵɵstyleProp('color', '#004')`\n * |23 |`20 | 24` | ... |\n * |24 |`null` |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})`\n * |25 |`22 | 26` | ... |\n * |26 |`color` |`'#006'` | `ɵɵstyleProp('color', '#006')`\n * |27 |`24 | 28` | ... |\n * |28 |`null` |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})`\n * |29 |`26 | 30` | ... |\n * |30 |`color` |`'#008'` | `ɵɵstyleProp('color', '#008')`\n * |31 |`28 | 10` | ... |\n *\n * The above data structure allows us to re-concatenate the styling no matter which data binding\n * changes.\n *\n * NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next\n * duplicate bit. The duplicate bit if true says there either is a binding with the same name or\n * there is a map (which may contain the name). This information is useful in knowing if other\n * styles with higher priority need to be searched for overwrites.\n *\n * NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in\n * `tnode_linked_list_spec.ts` for working example.\n */\nlet __unused_const_as_closure_does_not_like_standalone_comment_blocks__: undefined;\n\n/**\n * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked\n * list of styles and compute the duplicate flag.\n *\n * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.\n *\n * The function works by keeping track of `tStylingRange` which contains two pointers pointing to\n * the head/tail of the template portion of the styles.\n * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`\n * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`\n *\n * @param tData The `TData` to insert into.\n * @param tNode `TNode` associated with the styling element.\n * @param tStylingKey See `TStylingKey`.\n * @param index location of where `tStyleValue` should be stored (and linked into list.)\n * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of\n * template.)\n * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.\n * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)\n */\nexport function insertTStylingBinding(\n tData: TData, tNode: TNode, tStylingKeyWithStatic: TStylingKey, index: number,\n isHostBinding: boolean, isClassBinding: boolean): void {\n ngDevMode && assertFirstUpdatePass(getTView());\n let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;\n let tmplHead = getTStylingRangePrev(tBindings);\n let tmplTail = getTStylingRangeNext(tBindings);\n\n tData[index] = tStylingKeyWithStatic;\n let isKeyDuplicateOfStatic = false;\n let tStylingKey: TStylingKeyPrimitive;\n if (Array.isArray(tStylingKeyWithStatic)) {\n // We are case when the `TStylingKey` contains static fields as well.\n const staticKeyValueArray = tStylingKeyWithStatic as KeyValueArray<any>;\n tStylingKey = staticKeyValueArray[1]; // unwrap.\n // We need to check if our key is present in the static so that we can mark it as duplicate.\n if (tStylingKey === null ||\n keyValueArrayIndexOf(staticKeyValueArray, tStylingKey as string) > 0) {\n // tStylingKey is present in the statics, need to mark it as duplicate.\n isKeyDuplicateOfStatic = true;\n }\n } else {\n tStylingKey = tStylingKeyWithStatic;\n }\n if (isHostBinding) {\n // We are inserting host bindings\n\n // If we don't have template bindings then `tail` is 0.\n const hasTemplateBindings = tmplTail !== 0;\n // This is important to know because that means that the `head` can't point to the first\n // template bindings (there are none.) Instead the head points to the tail of the template.\n if (hasTemplateBindings) {\n // template head's \"prev\" will point to last host binding or to 0 if no host bindings yet\n const previousNode = getTStylingRangePrev(tData[tmplHead + 1] as TStylingRange);\n tData[index + 1] = toTStylingRange(previousNode, tmplHead);\n // if a host binding has already been registered, we need to update the next of that host\n // binding to point to this one\n if (previousNode !== 0) {\n // We need to update the template-tail value to point to us.\n tData[previousNode + 1] =\n setTStylingRangeNext(tData[previousNode + 1] as TStylingRange, index);\n }\n // The \"previous\" of the template binding head should point to this host binding\n tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1] as TStylingRange, index);\n } else {\n tData[index + 1] = toTStylingRange(tmplHead, 0);\n // if a host binding has already been registered, we need to update the next of that host\n // binding to point to this one\n if (tmplHead !== 0) {\n // We need to update the template-tail value to point to us.\n tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1] as TStylingRange, index);\n }\n // if we don't have template, the head points to template-tail, and needs to be advanced.\n tmplHead = index;\n }\n } else {\n // We are inserting in template section.\n // We need to set this binding's \"previous\" to the current template tail\n tData[index + 1] = toTStylingRange(tmplTail, 0);\n ngDevMode &&\n assertEqual(\n tmplHead !== 0 && tmplTail === 0, false,\n 'Adding template bindings after hostBindings is not allowed.');\n if (tmplHead === 0) {\n tmplHead = index;\n } else {\n // We need to update the previous value \"next\" to point to this binding\n tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1] as TStylingRange, index);\n }\n tmplTail = index;\n }\n\n // Now we need to update / compute the duplicates.\n // Starting with our location search towards head (least priority)\n if (isKeyDuplicateOfStatic) {\n tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1] as TStylingRange);\n }\n markDuplicates(tData, tStylingKey, index, true, isClassBinding);\n markDuplicates(tData, tStylingKey, index, false, isClassBinding);\n markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);\n\n tBindings = toTStylingRange(tmplHead, tmplTail);\n if (isClassBinding) {\n tNode.classBindings = tBindings;\n } else {\n tNode.styleBindings = tBindings;\n }\n}\n\n/**\n * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.\n *\n * @param tNode `TNode` where the residual is stored.\n * @param tStylingKey `TStylingKey` to store.\n * @param tData `TData` associated with the current `LView`.\n * @param index location of where `tStyleValue` should be stored (and linked into list.)\n * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.\n * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)\n */\nfunction markDuplicateOfResidualStyling(\n tNode: TNode, tStylingKey: TStylingKey, tData: TData, index: number, isClassBinding: boolean) {\n const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;\n if (residual != null /* or undefined */ && typeof tStylingKey == 'string' &&\n keyValueArrayIndexOf(residual, tStylingKey) >= 0) {\n // We have duplicate in the residual so mark ourselves as duplicate.\n tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1] as TStylingRange);\n }\n}\n\n\n/**\n * Marks `TStyleValue`s as duplicates if another style binding in the list has the same\n * `TStyleValue`.\n *\n * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once\n * with it set to `false` to search both the previous as well as next items in the list.\n *\n * No duplicate case\n * ```\n * [style.color]\n * [style.width.px] <<- index\n * [style.height.px]\n * ```\n *\n * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no\n * duplicates because `width` is not found in any other part of the linked list.\n *\n * Duplicate case\n * ```\n * [style.color]\n * [style.width.em]\n * [style.width.px] <<- index\n * ```\n * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`\n * because `width` is found in the chain.\n *\n * Map case 1\n * ```\n * [style.width.px]\n * [style.color]\n * [style] <<- index\n * ```\n * In the above case adding `[style]` will produce a duplicate with any other bindings because\n * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.\n *\n * Map case 2\n * ```\n * [style]\n * [style.width.px]\n * [style.color] <<- index\n * ```\n * In the above case adding `[style.color]` will produce a duplicate because there is already a\n * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or\n * `width`.\n *\n * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.\n * NOTE: We use `style` as example, but same logic is applied to `class`es as well.\n *\n * @param tData `TData` where the linked list is stored.\n * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in\n * the linked list.\n * @param index Starting location in the linked list to search from\n * @param isPrevDir Direction.\n * - `true` for previous (lower priority);\n * - `false` for next (higher priority).\n */\nfunction markDuplicates(\n tData: TData, tStylingKey: TStylingKeyPrimitive, index: number, isPrevDir: boolean,\n isClassBinding: boolean) {\n const tStylingAtIndex = tData[index + 1] as TStylingRange;\n const isMap = tStylingKey === null;\n let cursor =\n isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);\n let foundDuplicate = false;\n // We keep iterating as long as we have a cursor\n // AND either:\n // - we found what we are looking for, OR\n // - we are a map in which case we have to continue searching even after we find what we were\n // looking for since we are a wild card and everything needs to be flipped to duplicate.\n while (cursor !== 0 && (foundDuplicate === false || isMap)) {\n ngDevMode && assertIndexInRange(tData, cursor);\n const tStylingValueAtCursor = tData[cursor] as TStylingKey;\n const tStyleRangeAtCursor = tData[cursor + 1] as TStylingRange;\n if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {\n foundDuplicate = true;\n tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) :\n setTStylingRangePrevDuplicate(tStyleRangeAtCursor);\n }\n cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) :\n getTStylingRangeNext(tStyleRangeAtCursor);\n }\n if (foundDuplicate) {\n // if we found a duplicate, than mark ourselves.\n tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) :\n setTStylingRangeNextDuplicate(tStylingAtIndex);\n }\n}\n\n/**\n * Determines if two `TStylingKey`s are a match.\n *\n * When computing whether a binding contains a duplicate, we need to compare if the instruction\n * `TStylingKey` has a match.\n *\n * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:\n * - `color`\n * - `color` // Match another color\n * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction\n * - `['', 'color', 'other', true]` // wrapped `color` so match\n * - `['', null, 'other', true]` // wrapped `null` so match\n * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`\n * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction\n *\n * @param tStylingKeyCursor\n * @param tStylingKey\n */\nfunction isStylingMatch(tStylingKeyCursor: TStylingKey, tStylingKey: TStylingKeyPrimitive) {\n ngDevMode &&\n assertNotEqual(\n Array.isArray(tStylingKey), true, 'Expected that \\'tStylingKey\\' has been unwrapped');\n if (\n tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that\n // location so we must assume that we have a match.\n tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it\n // contains a match.\n (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) ===\n tStylingKey // If the keys match explicitly than we are a match.\n ) {\n return true;\n } else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {\n // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has\n // statics and we need to check those as well.\n return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >=\n 0; // see if we are matching the key\n }\n return false;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertEqual, throwError} from '../../util/assert';\nimport {CharCode} from '../../util/char_code';\n\n/**\n * Stores the locations of key/value indexes while parsing styling.\n *\n * In case of `cssText` parsing the indexes are like so:\n * ```\n * \"key1: value1; key2: value2; key3: value3\"\n * ^ ^ ^ ^ ^\n * | | | | +-- textEnd\n * | | | +---------------- valueEnd\n * | | +---------------------- value\n * | +------------------------ keyEnd\n * +---------------------------- key\n * ```\n *\n * In case of `className` parsing the indexes are like so:\n * ```\n * \"key1 key2 key3\"\n * ^ ^ ^\n * | | +-- textEnd\n * | +------------------------ keyEnd\n * +---------------------------- key\n * ```\n * NOTE: `value` and `valueEnd` are used only for styles, not classes.\n */\ninterface ParserState {\n textEnd: number;\n key: number;\n keyEnd: number;\n value: number;\n valueEnd: number;\n}\n// Global state of the parser. (This makes parser non-reentrant, but that is not an issue)\nconst parserState: ParserState = {\n textEnd: 0,\n key: 0,\n keyEnd: 0,\n value: 0,\n valueEnd: 0,\n};\n\n/**\n * Retrieves the last parsed `key` of style.\n * @param text the text to substring the key from.\n */\nexport function getLastParsedKey(text: string): string {\n return text.substring(parserState.key, parserState.keyEnd);\n}\n\n/**\n * Retrieves the last parsed `value` of style.\n * @param text the text to substring the key from.\n */\nexport function getLastParsedValue(text: string): string {\n return text.substring(parserState.value, parserState.valueEnd);\n}\n\n/**\n * Initializes `className` string for parsing and parses the first token.\n *\n * This function is intended to be used in this format:\n * ```\n * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {\n * const key = getLastParsedKey();\n * ...\n * }\n * ```\n * @param text `className` to parse\n * @returns index where the next invocation of `parseClassNameNext` should resume.\n */\nexport function parseClassName(text: string): number {\n resetParserState(text);\n return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));\n}\n\n/**\n * Parses next `className` token.\n *\n * This function is intended to be used in this format:\n * ```\n * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {\n * const key = getLastParsedKey();\n * ...\n * }\n * ```\n *\n * @param text `className` to parse\n * @param index where the parsing should resume.\n * @returns index where the next invocation of `parseClassNameNext` should resume.\n */\nexport function parseClassNameNext(text: string, index: number): number {\n const end = parserState.textEnd;\n if (end === index) {\n return -1;\n }\n index = parserState.keyEnd = consumeClassToken(text, parserState.key = index, end);\n return consumeWhitespace(text, index, end);\n}\n\n/**\n * Initializes `cssText` string for parsing and parses the first key/values.\n *\n * This function is intended to be used in this format:\n * ```\n * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {\n * const key = getLastParsedKey();\n * const value = getLastParsedValue();\n * ...\n * }\n * ```\n * @param text `cssText` to parse\n * @returns index where the next invocation of `parseStyleNext` should resume.\n */\nexport function parseStyle(text: string): number {\n resetParserState(text);\n return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));\n}\n\n/**\n * Parses the next `cssText` key/values.\n *\n * This function is intended to be used in this format:\n * ```\n * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {\n * const key = getLastParsedKey();\n * const value = getLastParsedValue();\n * ...\n * }\n *\n * @param text `cssText` to parse\n * @param index where the parsing should resume.\n * @returns index where the next invocation of `parseStyleNext` should resume.\n */\nexport function parseStyleNext(text: string, startIndex: number): number {\n const end = parserState.textEnd;\n let index = parserState.key = consumeWhitespace(text, startIndex, end);\n if (end === index) {\n // we reached an end so just quit\n return -1;\n }\n index = parserState.keyEnd = consumeStyleKey(text, index, end);\n index = consumeSeparator(text, index, end, CharCode.COLON);\n index = parserState.value = consumeWhitespace(text, index, end);\n index = parserState.valueEnd = consumeStyleValue(text, index, end);\n return consumeSeparator(text, index, end, CharCode.SEMI_COLON);\n}\n\n/**\n * Reset the global state of the styling parser.\n * @param text The styling text to parse.\n */\nexport function resetParserState(text: string): void {\n parserState.key = 0;\n parserState.keyEnd = 0;\n parserState.value = 0;\n parserState.valueEnd = 0;\n parserState.textEnd = text.length;\n}\n\n/**\n * Returns index of next non-whitespace character.\n *\n * @param text Text to scan\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at\n * that location.)\n */\nexport function consumeWhitespace(text: string, startIndex: number, endIndex: number): number {\n while (startIndex < endIndex && text.charCodeAt(startIndex) <= CharCode.SPACE) {\n startIndex++;\n }\n return startIndex;\n}\n\n/**\n * Returns index of last char in class token.\n *\n * @param text Text to scan\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index after last char in class token.\n */\nexport function consumeClassToken(text: string, startIndex: number, endIndex: number): number {\n while (startIndex < endIndex && text.charCodeAt(startIndex) > CharCode.SPACE) {\n startIndex++;\n }\n return startIndex;\n}\n\n/**\n * Consumes all of the characters belonging to style key and token.\n *\n * @param text Text to scan\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index after last style key character.\n */\nexport function consumeStyleKey(text: string, startIndex: number, endIndex: number): number {\n let ch: number;\n while (startIndex < endIndex &&\n ((ch = text.charCodeAt(startIndex)) === CharCode.DASH || ch === CharCode.UNDERSCORE ||\n ((ch & CharCode.UPPER_CASE) >= CharCode.A && (ch & CharCode.UPPER_CASE) <= CharCode.Z) ||\n (ch >= CharCode.ZERO && ch <= CharCode.NINE))) {\n startIndex++;\n }\n return startIndex;\n}\n\n/**\n * Consumes all whitespace and the separator `:` after the style key.\n *\n * @param text Text to scan\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index after separator and surrounding whitespace.\n */\nexport function consumeSeparator(\n text: string, startIndex: number, endIndex: number, separator: number): number {\n startIndex = consumeWhitespace(text, startIndex, endIndex);\n if (startIndex < endIndex) {\n if (ngDevMode && text.charCodeAt(startIndex) !== separator) {\n malformedStyleError(text, String.fromCharCode(separator), startIndex);\n }\n startIndex++;\n }\n return startIndex;\n}\n\n\n/**\n * Consumes style value honoring `url()` and `\"\"` text.\n *\n * @param text Text to scan\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index after last style value character.\n */\nexport function consumeStyleValue(text: string, startIndex: number, endIndex: number): number {\n let ch1 = -1; // 1st previous character\n let ch2 = -1; // 2nd previous character\n let ch3 = -1; // 3rd previous character\n let i = startIndex;\n let lastChIndex = i;\n while (i < endIndex) {\n const ch: number = text.charCodeAt(i++);\n if (ch === CharCode.SEMI_COLON) {\n return lastChIndex;\n } else if (ch === CharCode.DOUBLE_QUOTE || ch === CharCode.SINGLE_QUOTE) {\n lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);\n } else if (\n startIndex ===\n i - 4 && // We have seen only 4 characters so far \"URL(\" (Ignore \"foo_URL()\")\n ch3 === CharCode.U &&\n ch2 === CharCode.R && ch1 === CharCode.L && ch === CharCode.OPEN_PAREN) {\n lastChIndex = i = consumeQuotedText(text, CharCode.CLOSE_PAREN, i, endIndex);\n } else if (ch > CharCode.SPACE) {\n // if we have a non-whitespace character then capture its location\n lastChIndex = i;\n }\n ch3 = ch2;\n ch2 = ch1;\n ch1 = ch & CharCode.UPPER_CASE;\n }\n return lastChIndex;\n}\n\n/**\n * Consumes all of the quoted characters.\n *\n * @param text Text to scan\n * @param quoteCharCode CharCode of either `\"` or `'` quote or `)` for `url(...)`.\n * @param startIndex Starting index of character where the scan should start.\n * @param endIndex Ending index of character where the scan should end.\n * @returns Index after quoted characters.\n */\nexport function consumeQuotedText(\n text: string, quoteCharCode: number, startIndex: number, endIndex: number): number {\n let ch1 = -1; // 1st previous character\n let index = startIndex;\n while (index < endIndex) {\n const ch = text.charCodeAt(index++);\n if (ch == quoteCharCode && ch1 !== CharCode.BACK_SLASH) {\n return index;\n }\n if (ch == CharCode.BACK_SLASH && ch1 === CharCode.BACK_SLASH) {\n // two back slashes cancel each other out. For example `\"\\\\\"` should properly end the\n // quotation. (It should not assume that the last `\"` is escaped.)\n ch1 = 0;\n } else {\n ch1 = ch;\n }\n }\n throw ngDevMode ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex) :\n new Error();\n}\n\nfunction malformedStyleError(text: string, expecting: string, index: number): never {\n ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');\n throw throwError(\n `Malformed style at location ${index} in string '` + text.substring(0, index) + '[>>' +\n text.substring(index, index + 1) + '<<]' + text.slice(index + 1) +\n `'. Expecting '${expecting}'.`);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {SafeValue, unwrapSafeValue} from '../../sanitization/bypass';\nimport {KeyValueArray, keyValueArrayGet, keyValueArraySet} from '../../util/array_utils';\nimport {assertDefined, assertEqual, assertLessThan, assertNotEqual, throwError} from '../../util/assert';\nimport {EMPTY_ARRAY} from '../../util/empty';\nimport {concatStringsWithSpace, stringify} from '../../util/stringify';\nimport {assertFirstUpdatePass} from '../assert';\nimport {bindingUpdated} from '../bindings';\nimport {DirectiveDef} from '../interfaces/definition';\nimport {AttributeMarker, TAttributes, TNode, TNodeFlags, TNodeType} from '../interfaces/node';\nimport {Renderer} from '../interfaces/renderer';\nimport {RElement} from '../interfaces/renderer_dom';\nimport {getTStylingRangeNext, getTStylingRangeNextDuplicate, getTStylingRangePrev, getTStylingRangePrevDuplicate, TStylingKey, TStylingRange} from '../interfaces/styling';\nimport {LView, RENDERER, TData, TView} from '../interfaces/view';\nimport {applyStyling} from '../node_manipulation';\nimport {getCurrentDirectiveDef, getLView, getSelectedIndex, getTView, incrementBindingIndex} from '../state';\nimport {insertTStylingBinding} from '../styling/style_binding_list';\nimport {getLastParsedKey, getLastParsedValue, parseClassName, parseClassNameNext, parseStyle, parseStyleNext} from '../styling/styling_parser';\nimport {NO_CHANGE} from '../tokens';\nimport {getNativeByIndex} from '../util/view_utils';\n\nimport {setDirectiveInputsWhichShadowsStyling} from './property';\n\n\n/**\n * Update a style binding on an element with the provided value.\n *\n * If the style value is falsy then it will be removed from the element\n * (or assigned a different value depending if there are any styles placed\n * on the element with `styleMap` or any static styles that are\n * present from when the element was created with `styling`).\n *\n * Note that the styling element is updated as part of `stylingApply`.\n *\n * @param prop A valid CSS property.\n * @param value New value to write (`null` or an empty string to remove).\n * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.\n *\n * Note that this will apply the provided style value to the host element if this function is called\n * within a host binding function.\n *\n * @codeGenApi\n */\nexport function ɵɵstyleProp(\n prop: string, value: string|number|SafeValue|undefined|null,\n suffix?: string|null): typeof ɵɵstyleProp {\n checkStylingProperty(prop, value, suffix, false);\n return ɵɵstyleProp;\n}\n\n/**\n * Update a class binding on an element with the provided value.\n *\n * This instruction is meant to handle the `[class.foo]=\"exp\"` case and,\n * therefore, the class binding itself must already be allocated using\n * `styling` within the creation block.\n *\n * @param prop A valid CSS class (only one).\n * @param value A true/false value which will turn the class on or off.\n *\n * Note that this will apply the provided class value to the host element if this function\n * is called within a host binding function.\n *\n * @codeGenApi\n */\nexport function ɵɵclassProp(className: string, value: boolean|undefined|null): typeof ɵɵclassProp {\n checkStylingProperty(className, value, null, true);\n return ɵɵclassProp;\n}\n\n\n/**\n * Update style bindings using an object literal on an element.\n *\n * This instruction is meant to apply styling via the `[style]=\"exp\"` template bindings.\n * When styles are applied to the element they will then be updated with respect to\n * any styles/classes set via `styleProp`. If any styles are set to falsy\n * then they will be removed from the element.\n *\n * Note that the styling instruction will not be applied until `stylingApply` is called.\n *\n * @param styles A key/value style map of the styles that will be applied to the given element.\n * Any missing styles (that have already been applied to the element beforehand) will be\n * removed (unset) from the element's styling.\n *\n * Note that this will apply the provided styleMap value to the host element if this function\n * is called within a host binding.\n *\n * @codeGenApi\n */\nexport function ɵɵstyleMap(styles: {[styleName: string]: any}|string|undefined|null): void {\n checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);\n}\n\n\n/**\n * Parse text as style and add values to KeyValueArray.\n *\n * This code is pulled out to a separate function so that it can be tree shaken away if it is not\n * needed. It is only referenced from `ɵɵstyleMap`.\n *\n * @param keyValueArray KeyValueArray to add parsed values to.\n * @param text text to parse.\n */\nexport function styleStringParser(keyValueArray: KeyValueArray<any>, text: string): void {\n for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {\n styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));\n }\n}\n\n\n/**\n * Update class bindings using an object literal or class-string on an element.\n *\n * This instruction is meant to apply styling via the `[class]=\"exp\"` template bindings.\n * When classes are applied to the element they will then be updated with\n * respect to any styles/classes set via `classProp`. If any\n * classes are set to falsy then they will be removed from the element.\n *\n * Note that the styling instruction will not be applied until `stylingApply` is called.\n * Note that this will the provided classMap value to the host element if this function is called\n * within a host binding.\n *\n * @param classes A key/value map or string of CSS classes that will be added to the\n * given element. Any missing classes (that have already been applied to the element\n * beforehand) will be removed (unset) from the element's list of CSS classes.\n *\n * @codeGenApi\n */\nexport function ɵɵclassMap(classes: {[className: string]: boolean|undefined|null}|string|undefined|\n null): void {\n checkStylingMap(classKeyValueArraySet, classStringParser, classes, true);\n}\n\n/**\n * Parse text as class and add values to KeyValueArray.\n *\n * This code is pulled out to a separate function so that it can be tree shaken away if it is not\n * needed. It is only referenced from `ɵɵclassMap`.\n *\n * @param keyValueArray KeyValueArray to add parsed values to.\n * @param text text to parse.\n */\nexport function classStringParser(keyValueArray: KeyValueArray<any>, text: string): void {\n for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {\n keyValueArraySet(keyValueArray, getLastParsedKey(text), true);\n }\n}\n\n/**\n * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.\n *\n * @param prop property name.\n * @param value binding value.\n * @param suffix suffix for the property (e.g. `em` or `px`)\n * @param isClassBased `true` if `class` change (`false` if `style`)\n */\nexport function checkStylingProperty(\n prop: string, value: any|NO_CHANGE, suffix: string|undefined|null,\n isClassBased: boolean): void {\n const lView = getLView();\n const tView = getTView();\n // Styling instructions use 2 slots per binding.\n // 1. one for the value / TStylingKey\n // 2. one for the intermittent-value / TStylingRange\n const bindingIndex = incrementBindingIndex(2);\n if (tView.firstUpdatePass) {\n stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);\n }\n if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {\n const tNode = tView.data[getSelectedIndex()] as TNode;\n updateStyling(\n tView, tNode, lView, lView[RENDERER], prop,\n lView[bindingIndex + 1] = normalizeSuffix(value, suffix), isClassBased, bindingIndex);\n }\n}\n\n/**\n * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.\n *\n * @param keyValueArraySet (See `keyValueArraySet` in \"util/array_utils\") Gets passed in as a\n * function so that `style` can be processed. This is done for tree shaking purposes.\n * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`\n * have different parsers.)\n * @param value bound value from application\n * @param isClassBased `true` if `class` change (`false` if `style`)\n */\nexport function checkStylingMap(\n keyValueArraySet: (keyValueArray: KeyValueArray<any>, key: string, value: any) => void,\n stringParser: (styleKeyValueArray: KeyValueArray<any>, text: string) => void,\n value: any|NO_CHANGE, isClassBased: boolean): void {\n const tView = getTView();\n const bindingIndex = incrementBindingIndex(2);\n if (tView.firstUpdatePass) {\n stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);\n }\n const lView = getLView();\n if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {\n // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the\n // if so as not to read unnecessarily.\n const tNode = tView.data[getSelectedIndex()] as TNode;\n if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {\n if (ngDevMode) {\n // verify that if we are shadowing then `TData` is appropriately marked so that we skip\n // processing this binding in styling resolution.\n const tStylingKey = tView.data[bindingIndex];\n assertEqual(\n Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false,\n 'Styling linked list shadow input should be marked as \\'false\\'');\n }\n // VE does not concatenate the static portion like we are doing here.\n // Instead VE just ignores the static completely if dynamic binding is present.\n // Because of locality we have already set the static portion because we don't know if there\n // is a dynamic portion until later. If we would ignore the static portion it would look like\n // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong\n // thing as it would think that the static portion was removed. For this reason we\n // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed.\n let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;\n ngDevMode && isClassBased === false && staticPrefix !== null &&\n assertEqual(\n staticPrefix.endsWith(';'), true, 'Expecting static portion to end with \\';\\'');\n if (staticPrefix !== null) {\n // We want to make sure that falsy values of `value` become empty strings.\n value = concatStringsWithSpace(staticPrefix, value ? value : '');\n }\n // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.\n // This takes over the `[style]` binding. (Same for `[class]`)\n setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);\n } else {\n updateStylingMap(\n tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1],\n lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value),\n isClassBased, bindingIndex);\n }\n }\n}\n\n/**\n * Determines when the binding is in `hostBindings` section\n *\n * @param tView Current `TView`\n * @param bindingIndex index of binding which we would like if it is in `hostBindings`\n */\nfunction isInHostBindings(tView: TView, bindingIndex: number): boolean {\n // All host bindings are placed after the expando section.\n return bindingIndex >= tView.expandoStartIndex;\n}\n\n/**\n * Collects the necessary information to insert the binding into a linked list of style bindings\n * using `insertTStylingBinding`.\n *\n * @param tView `TView` where the binding linked list will be stored.\n * @param tStylingKey Property/key of the binding.\n * @param bindingIndex Index of binding associated with the `prop`\n * @param isClassBased `true` if `class` change (`false` if `style`)\n */\nfunction stylingFirstUpdatePass(\n tView: TView, tStylingKey: TStylingKey, bindingIndex: number, isClassBased: boolean): void {\n ngDevMode && assertFirstUpdatePass(tView);\n const tData = tView.data;\n if (tData[bindingIndex + 1] === null) {\n // The above check is necessary because we don't clear first update pass until first successful\n // (no exception) template execution. This prevents the styling instruction from double adding\n // itself to the list.\n // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the\n // if so as not to read unnecessarily.\n const tNode = tData[getSelectedIndex()] as TNode;\n ngDevMode && assertDefined(tNode, 'TNode expected');\n const isHostBindings = isInHostBindings(tView, bindingIndex);\n if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {\n // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.\n // If there is a directive which uses `@Input('style')` or `@Input('class')` than\n // we need to neutralize this binding since that directive is shadowing it.\n // We turn this into a noop by setting the key to `false`\n tStylingKey = false;\n }\n tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);\n insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);\n }\n}\n\n/**\n * Adds static styling information to the binding if applicable.\n *\n * The linked list of styles not only stores the list and keys, but also stores static styling\n * information on some of the keys. This function determines if the key should contain the styling\n * information and computes it.\n *\n * See `TStylingStatic` for more details.\n *\n * @param tData `TData` where the linked list is stored.\n * @param tNode `TNode` for which the styling is being computed.\n * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nexport function wrapInStaticStylingKey(\n tData: TData, tNode: TNode, stylingKey: TStylingKey, isClassBased: boolean): TStylingKey {\n const hostDirectiveDef = getCurrentDirectiveDef(tData);\n let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;\n if (hostDirectiveDef === null) {\n // We are in template node.\n // If template node already had styling instruction then it has already collected the static\n // styling and there is no need to collect them again. We know that we are the first styling\n // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).\n const isFirstStylingInstructionInTemplate =\n (isClassBased ? tNode.classBindings : tNode.styleBindings) as any as number === 0;\n if (isFirstStylingInstructionInTemplate) {\n // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point\n // they are already merged and it would not be possible to figure which property belongs where\n // in the priority.\n stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);\n stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased);\n // We know that if we have styling binding in template we can't have residual.\n residual = null;\n }\n } else {\n // We are in host binding node and there was no binding instruction in template node.\n // This means that we need to compute the residual.\n const directiveStylingLast = tNode.directiveStylingLast;\n const isFirstStylingInstructionInHostBinding =\n directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;\n if (isFirstStylingInstructionInHostBinding) {\n stylingKey =\n collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);\n if (residual === null) {\n // - If `null` than either:\n // - Template styling instruction already ran and it has consumed the static\n // styling into its `TStylingKey` and so there is no need to update residual. Instead\n // we need to update the `TStylingKey` associated with the first template node\n // instruction. OR\n // - Some other styling instruction ran and determined that there are no residuals\n let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);\n if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {\n // Only recompute if `templateStylingKey` had static values. (If no static value found\n // then there is nothing to do since this operation can only produce less static keys, not\n // more.)\n templateStylingKey = collectStylingFromDirectives(\n null, tData, tNode, templateStylingKey[1] /* unwrap previous statics */,\n isClassBased);\n templateStylingKey =\n collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);\n setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);\n }\n } else {\n // We only need to recompute residual if it is not `null`.\n // - If existing residual (implies there was no template styling). This means that some of\n // the statics may have moved from the residual to the `stylingKey` and so we have to\n // recompute.\n // - If `undefined` this is the first time we are running.\n residual = collectResidual(tData, tNode, isClassBased);\n }\n }\n }\n if (residual !== undefined) {\n isClassBased ? (tNode.residualClasses = residual) : (tNode.residualStyles = residual);\n }\n return stylingKey;\n}\n\n/**\n * Retrieve the `TStylingKey` for the template styling instruction.\n *\n * This is needed since `hostBinding` styling instructions are inserted after the template\n * instruction. While the template instruction needs to update the residual in `TNode` the\n * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because\n * the template instruction is downstream from the `hostBindings` instructions.\n *\n * @param tData `TData` where the linked list is stored.\n * @param tNode `TNode` for which the styling is being computed.\n * @param isClassBased `true` if `class` (`false` if `style`)\n * @return `TStylingKey` if found or `undefined` if not found.\n */\nfunction getTemplateHeadTStylingKey(tData: TData, tNode: TNode, isClassBased: boolean): TStylingKey|\n undefined {\n const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;\n if (getTStylingRangeNext(bindings) === 0) {\n // There does not seem to be a styling instruction in the `template`.\n return undefined;\n }\n return tData[getTStylingRangePrev(bindings)] as TStylingKey;\n}\n\n/**\n * Update the `TStylingKey` of the first template instruction in `TNode`.\n *\n * Logically `hostBindings` styling instructions are of lower priority than that of the template.\n * However, they execute after the template styling instructions. This means that they get inserted\n * in front of the template styling instructions.\n *\n * If we have a template styling instruction and a new `hostBindings` styling instruction is\n * executed it means that it may need to steal static fields from the template instruction. This\n * method allows us to update the first template instruction `TStylingKey` with a new value.\n *\n * Assume:\n * ```\n * <div my-dir style=\"color: red\" [style.color]=\"tmplExp\"></div>\n *\n * @Directive({\n * host: {\n * 'style': 'width: 100px',\n * '[style.color]': 'dirExp',\n * }\n * })\n * class MyDir {}\n * ```\n *\n * when `[style.color]=\"tmplExp\"` executes it creates this data structure.\n * ```\n * ['', 'color', 'color', 'red', 'width', '100px'],\n * ```\n *\n * The reason for this is that the template instruction does not know if there are styling\n * instructions and must assume that there are none and must collect all of the static styling.\n * (both\n * `color' and 'width`)\n *\n * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.\n * ```\n * ['', 'color', 'width', '100px'], // newly inserted\n * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong\n * ```\n *\n * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to\n * update it like so:\n * ```\n * ['', 'color', 'width', '100px'],\n * ['', 'color', 'color', 'red'], // UPDATE\n * ```\n *\n * @param tData `TData` where the linked list is stored.\n * @param tNode `TNode` for which the styling is being computed.\n * @param isClassBased `true` if `class` (`false` if `style`)\n * @param tStylingKey New `TStylingKey` which is replacing the old one.\n */\nfunction setTemplateHeadTStylingKey(\n tData: TData, tNode: TNode, isClassBased: boolean, tStylingKey: TStylingKey): void {\n const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;\n ngDevMode &&\n assertNotEqual(\n getTStylingRangeNext(bindings), 0,\n 'Expecting to have at least one template styling binding.');\n tData[getTStylingRangePrev(bindings)] = tStylingKey;\n}\n\n/**\n * Collect all static values after the current `TNode.directiveStylingLast` index.\n *\n * Collect the remaining styling information which has not yet been collected by an existing\n * styling instruction.\n *\n * @param tData `TData` where the `DirectiveDefs` are stored.\n * @param tNode `TNode` which contains the directive range.\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nfunction collectResidual(tData: TData, tNode: TNode, isClassBased: boolean): KeyValueArray<any>|\n null {\n let residual: KeyValueArray<any>|null|undefined = undefined;\n const directiveEnd = tNode.directiveEnd;\n ngDevMode &&\n assertNotEqual(\n tNode.directiveStylingLast, -1,\n 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.');\n // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are\n // collecting things after the last `hostBindings` directive which had a styling instruction.)\n for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {\n const attrs = (tData[i] as DirectiveDef<any>).hostAttrs;\n residual = collectStylingFromTAttrs(residual, attrs, isClassBased) as KeyValueArray<any>| null;\n }\n return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased) as KeyValueArray<any>| null;\n}\n\n/**\n * Collect the static styling information with lower priority than `hostDirectiveDef`.\n *\n * (This is opposite of residual styling.)\n *\n * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static\n * styling. (Or `null` if template styling)\n * @param tData `TData` where the linked list is stored.\n * @param tNode `TNode` for which the styling is being computed.\n * @param stylingKey Existing `TStylingKey` to update or wrap.\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nfunction collectStylingFromDirectives(\n hostDirectiveDef: DirectiveDef<any>|null, tData: TData, tNode: TNode, stylingKey: TStylingKey,\n isClassBased: boolean): TStylingKey {\n // We need to loop because there can be directives which have `hostAttrs` but don't have\n // `hostBindings` so this loop catches up to the current directive..\n let currentDirective: DirectiveDef<any>|null = null;\n const directiveEnd = tNode.directiveEnd;\n let directiveStylingLast = tNode.directiveStylingLast;\n if (directiveStylingLast === -1) {\n directiveStylingLast = tNode.directiveStart;\n } else {\n directiveStylingLast++;\n }\n while (directiveStylingLast < directiveEnd) {\n currentDirective = tData[directiveStylingLast] as DirectiveDef<any>;\n ngDevMode && assertDefined(currentDirective, 'expected to be defined');\n stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);\n if (currentDirective === hostDirectiveDef) break;\n directiveStylingLast++;\n }\n if (hostDirectiveDef !== null) {\n // we only advance the styling cursor if we are collecting data from host bindings.\n // Template executes before host bindings and so if we would update the index,\n // host bindings would not get their statics.\n tNode.directiveStylingLast = directiveStylingLast;\n }\n return stylingKey;\n}\n\n/**\n * Convert `TAttrs` into `TStylingStatic`.\n *\n * @param stylingKey existing `TStylingKey` to update or wrap.\n * @param attrs `TAttributes` to process.\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nfunction collectStylingFromTAttrs(\n stylingKey: TStylingKey|undefined, attrs: TAttributes|null,\n isClassBased: boolean): TStylingKey {\n const desiredMarker = isClassBased ? AttributeMarker.Classes : AttributeMarker.Styles;\n let currentMarker = AttributeMarker.ImplicitAttributes;\n if (attrs !== null) {\n for (let i = 0; i < attrs.length; i++) {\n const item = attrs[i] as number | string;\n if (typeof item === 'number') {\n currentMarker = item;\n } else {\n if (currentMarker === desiredMarker) {\n if (!Array.isArray(stylingKey)) {\n stylingKey = stylingKey === undefined ? [] : ['', stylingKey] as any;\n }\n keyValueArraySet(\n stylingKey as KeyValueArray<any>, item, isClassBased ? true : attrs[++i]);\n }\n }\n }\n }\n return stylingKey === undefined ? null : stylingKey;\n}\n\n/**\n * Convert user input to `KeyValueArray`.\n *\n * This function takes user input which could be `string`, Object literal, or iterable and converts\n * it into a consistent representation. The output of this is `KeyValueArray` (which is an array\n * where\n * even indexes contain keys and odd indexes contain values for those keys).\n *\n * The advantage of converting to `KeyValueArray` is that we can perform diff in an input\n * independent\n * way.\n * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be\n * applied)\n *\n * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the\n * difference in linear fashion without the need to allocate any additional data.\n *\n * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine\n * which values need to be deleted, over the new `Map` to determine additions, and we would have to\n * keep additional `Map` to keep track of duplicates or items which have not yet been visited.\n *\n * @param keyValueArraySet (See `keyValueArraySet` in \"util/array_utils\") Gets passed in as a\n * function so that `style` can be processed. This is done\n * for tree shaking purposes.\n * @param stringParser The parser is passed in so that it will be tree shakable. See\n * `styleStringParser` and `classStringParser`\n * @param value The value to parse/convert to `KeyValueArray`\n */\nexport function toStylingKeyValueArray(\n keyValueArraySet: (keyValueArray: KeyValueArray<any>, key: string, value: any) => void,\n stringParser: (styleKeyValueArray: KeyValueArray<any>, text: string) => void,\n value: string|string[]|{[key: string]: any}|SafeValue|null|undefined): KeyValueArray<any> {\n if (value == null /*|| value === undefined */ || value === '') return EMPTY_ARRAY as any;\n const styleKeyValueArray: KeyValueArray<any> = [] as any;\n const unwrappedValue = unwrapSafeValue(value) as string | string[] | {[key: string]: any};\n if (Array.isArray(unwrappedValue)) {\n for (let i = 0; i < unwrappedValue.length; i++) {\n keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);\n }\n } else if (typeof unwrappedValue === 'object') {\n for (const key in unwrappedValue) {\n if (unwrappedValue.hasOwnProperty(key)) {\n keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);\n }\n }\n } else if (typeof unwrappedValue === 'string') {\n stringParser(styleKeyValueArray, unwrappedValue);\n } else {\n ngDevMode &&\n throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue);\n }\n return styleKeyValueArray;\n}\n\n/**\n * Set a `value` for a `key`.\n *\n * See: `keyValueArraySet` for details\n *\n * @param keyValueArray KeyValueArray to add to.\n * @param key Style key to add.\n * @param value The value to set.\n */\nexport function styleKeyValueArraySet(keyValueArray: KeyValueArray<any>, key: string, value: any) {\n keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));\n}\n\n/**\n * Class-binding-specific function for setting the `value` for a `key`.\n *\n * See: `keyValueArraySet` for details\n *\n * @param keyValueArray KeyValueArray to add to.\n * @param key Style key to add.\n * @param value The value to set.\n */\nexport function classKeyValueArraySet(keyValueArray: KeyValueArray<any>, key: unknown, value: any) {\n // We use `classList.add` to eventually add the CSS classes to the DOM node. Any value passed into\n // `add` is stringified and added to the `class` attribute, e.g. even null, undefined or numbers\n // will be added. Stringify the key here so that our internal data structure matches the value in\n // the DOM. The only exceptions are empty strings and strings that contain spaces for which\n // the browser throws an error. We ignore such values, because the error is somewhat cryptic.\n const stringKey = String(key);\n if (stringKey !== '' && !stringKey.includes(' ')) {\n keyValueArraySet(keyValueArray, stringKey, value);\n }\n}\n\n/**\n * Update map based styling.\n *\n * Map based styling could be anything which contains more than one binding. For example `string`,\n * or object literal. Dealing with all of these types would complicate the logic so\n * instead this function expects that the complex input is first converted into normalized\n * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it\n * very cheap to compute deltas between the previous and current value.\n *\n * @param tView Associated `TView.data` contains the linked list of binding priorities.\n * @param tNode `TNode` where the binding is located.\n * @param lView `LView` contains the values associated with other styling binding at this `TNode`.\n * @param renderer Renderer to use if any updates.\n * @param oldKeyValueArray Previous value represented as `KeyValueArray`\n * @param newKeyValueArray Current value represented as `KeyValueArray`\n * @param isClassBased `true` if `class` (`false` if `style`)\n * @param bindingIndex Binding index of the binding.\n */\nfunction updateStylingMap(\n tView: TView, tNode: TNode, lView: LView, renderer: Renderer,\n oldKeyValueArray: KeyValueArray<any>, newKeyValueArray: KeyValueArray<any>,\n isClassBased: boolean, bindingIndex: number) {\n if (oldKeyValueArray as KeyValueArray<any>| NO_CHANGE === NO_CHANGE) {\n // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.\n oldKeyValueArray = EMPTY_ARRAY as any;\n }\n let oldIndex = 0;\n let newIndex = 0;\n let oldKey: string|null = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;\n let newKey: string|null = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;\n while (oldKey !== null || newKey !== null) {\n ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');\n ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');\n const oldValue =\n oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;\n const newValue =\n newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;\n let setKey: string|null = null;\n let setValue: any = undefined;\n if (oldKey === newKey) {\n // UPDATE: Keys are equal => new value is overwriting old value.\n oldIndex += 2;\n newIndex += 2;\n if (oldValue !== newValue) {\n setKey = newKey;\n setValue = newValue;\n }\n } else if (newKey === null || oldKey !== null && oldKey < newKey!) {\n // DELETE: oldKey key is missing or we did not find the oldKey in the newValue\n // (because the keyValueArray is sorted and `newKey` is found later alphabetically).\n // `\"background\" < \"color\"` so we need to delete `\"background\"` because it is not found in the\n // new array.\n oldIndex += 2;\n setKey = oldKey;\n } else {\n // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.\n // `\"color\" > \"background\"` so we need to add `color` because it is in new array but not in\n // old array.\n ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');\n newIndex += 2;\n setKey = newKey;\n setValue = newValue;\n }\n if (setKey !== null) {\n updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);\n }\n oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;\n newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;\n }\n}\n\n/**\n * Update a simple (property name) styling.\n *\n * This function takes `prop` and updates the DOM to that value. The function takes the binding\n * value as well as binding priority into consideration to determine which value should be written\n * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks\n * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)\n *\n * @param tView Associated `TView.data` contains the linked list of binding priorities.\n * @param tNode `TNode` where the binding is located.\n * @param lView `LView` contains the values associated with other styling binding at this `TNode`.\n * @param renderer Renderer to use if any updates.\n * @param prop Either style property name or a class name.\n * @param value Either style value for `prop` or `true`/`false` if `prop` is class.\n * @param isClassBased `true` if `class` (`false` if `style`)\n * @param bindingIndex Binding index of the binding.\n */\nfunction updateStyling(\n tView: TView, tNode: TNode, lView: LView, renderer: Renderer, prop: string,\n value: string|undefined|null|boolean, isClassBased: boolean, bindingIndex: number) {\n if (!(tNode.type & TNodeType.AnyRNode)) {\n // It is possible to have styling on non-elements (such as ng-container).\n // This is rare, but it does happen. In such a case, just ignore the binding.\n return;\n }\n const tData = tView.data;\n const tRange = tData[bindingIndex + 1] as TStylingRange;\n const higherPriorityValue = getTStylingRangeNextDuplicate(tRange) ?\n findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased) :\n undefined;\n if (!isStylingValuePresent(higherPriorityValue)) {\n // We don't have a next duplicate, or we did not find a duplicate value.\n if (!isStylingValuePresent(value)) {\n // We should delete current value or restore to lower priority value.\n if (getTStylingRangePrevDuplicate(tRange)) {\n // We have a possible prev duplicate, let's retrieve it.\n value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);\n }\n }\n const rNode = getNativeByIndex(getSelectedIndex(), lView) as RElement;\n applyStyling(renderer, isClassBased, rNode, prop, value);\n }\n}\n\n/**\n * Search for styling value with higher priority which is overwriting current value, or a\n * value of lower priority to which we should fall back if the value is `undefined`.\n *\n * When value is being applied at a location, related values need to be consulted.\n * - If there is a higher priority binding, we should be using that one instead.\n * For example `<div [style]=\"{color:exp1}\" [style.color]=\"exp2\">` change to `exp1`\n * requires that we check `exp2` to see if it is set to value other than `undefined`.\n * - If there is a lower priority binding and we are changing to `undefined`\n * For example `<div [style]=\"{color:exp1}\" [style.color]=\"exp2\">` change to `exp2` to\n * `undefined` requires that we check `exp1` (and static values) and use that as new value.\n *\n * NOTE: The styling stores two values.\n * 1. The raw value which came from the application is stored at `index + 0` location. (This value\n * is used for dirty checking).\n * 2. The normalized value is stored at `index + 1`.\n *\n * @param tData `TData` used for traversing the priority.\n * @param tNode `TNode` to use for resolving static styling. Also controls search direction.\n * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.\n * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.\n * - `null` search prev and go all the way to end. Return last value where\n * `isStylingValuePresent(value)` is true.\n * @param lView `LView` used for retrieving the actual values.\n * @param prop Property which we are interested in.\n * @param index Starting index in the linked list of styling bindings where the search should start.\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nfunction findStylingValue(\n tData: TData, tNode: TNode|null, lView: LView, prop: string, index: number,\n isClassBased: boolean): any {\n // `TNode` to use for resolving static styling. Also controls search direction.\n // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.\n // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.\n // - `null` search prev and go all the way to end. Return last value where\n // `isStylingValuePresent(value)` is true.\n const isPrevDirection = tNode === null;\n let value: any = undefined;\n while (index > 0) {\n const rawKey = tData[index] as TStylingKey;\n const containsStatics = Array.isArray(rawKey);\n // Unwrap the key if we contain static values.\n const key = containsStatics ? (rawKey as string[])[1] : rawKey;\n const isStylingMap = key === null;\n let valueAtLViewIndex = lView[index + 1];\n if (valueAtLViewIndex === NO_CHANGE) {\n // In firstUpdatePass the styling instructions create a linked list of styling.\n // On subsequent passes it is possible for a styling instruction to try to read a binding\n // which\n // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that\n // we have `undefined` (or empty array in case of styling-map instruction) instead. This\n // allows the resolution to apply the value (which may later be overwritten when the\n // binding actually executes.)\n valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;\n }\n let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) :\n (key === prop ? valueAtLViewIndex : undefined);\n if (containsStatics && !isStylingValuePresent(currentValue)) {\n currentValue = keyValueArrayGet(rawKey as KeyValueArray<any>, prop);\n }\n if (isStylingValuePresent(currentValue)) {\n value = currentValue;\n if (isPrevDirection) {\n return value;\n }\n }\n const tRange = tData[index + 1] as TStylingRange;\n index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);\n }\n if (tNode !== null) {\n // in case where we are going in next direction AND we did not find anything, we need to\n // consult residual styling\n let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;\n if (residual != null /** OR residual !=== undefined */) {\n value = keyValueArrayGet(residual!, prop);\n }\n }\n return value;\n}\n\n/**\n * Determines if the binding value should be used (or if the value is 'undefined' and hence priority\n * resolution should be used.)\n *\n * @param value Binding style value.\n */\nfunction isStylingValuePresent(value: any): boolean {\n // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't\n // have an opinion as to what this binding should be and you should consult other bindings by\n // priority to determine the valid value.\n // This is extracted into a single function so that we have a single place to control this.\n return value !== undefined;\n}\n\n/**\n * Normalizes and/or adds a suffix to the value.\n *\n * If value is `null`/`undefined` no suffix is added\n * @param value\n * @param suffix\n */\nfunction normalizeSuffix(value: any, suffix: string|undefined|null): string|null|undefined|boolean {\n if (value == null || value === '') {\n // do nothing\n // Do not add the suffix if the value is going to be empty.\n // As it produce invalid CSS, which the browsers will automatically omit but Domino will not.\n // Example: `\"left\": \"px;\"` instead of `\"left\": \"\"`.\n } else if (typeof suffix === 'string') {\n value = value + suffix;\n } else if (typeof value === 'object') {\n value = stringify(unwrapSafeValue(value));\n }\n return value;\n}\n\n\n/**\n * Tests if the `TNode` has input shadow.\n *\n * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or\n * `@Input('class')` as input.\n *\n * @param tNode `TNode` which we would like to see if it has shadow.\n * @param isClassBased `true` if `class` (`false` if `style`)\n */\nexport function hasStylingInputShadow(tNode: TNode, isClassBased: boolean) {\n return (tNode.flags & (isClassBased ? TNodeFlags.hasClassInput : TNodeFlags.hasStyleInput)) !== 0;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {assertEqual, assertIndexInRange} from '../../util/assert';\nimport {TElementNode, TNodeType} from '../interfaces/node';\nimport {HEADER_OFFSET, RENDERER, T_HOST} from '../interfaces/view';\nimport {appendChild, createTextNode} from '../node_manipulation';\nimport {getBindingIndex, getLView, getTView, setCurrentTNode} from '../state';\n\nimport {getOrCreateTNode} from './shared';\n\n\n\n/**\n * Create static text node\n *\n * @param index Index of the node in the data array\n * @param value Static string value to write.\n *\n * @codeGenApi\n */\nexport function ɵɵtext(index: number, value: string = ''): void {\n const lView = getLView();\n const tView = getTView();\n const adjustedIndex = index + HEADER_OFFSET;\n\n ngDevMode &&\n assertEqual(\n getBindingIndex(), tView.bindingStartIndex,\n 'text nodes should be created before any bindings');\n ngDevMode && assertIndexInRange(lView, adjustedIndex);\n\n const tNode = tView.firstCreatePass ?\n getOrCreateTNode(tView, adjustedIndex, TNodeType.Text, value, null) :\n tView.data[adjustedIndex] as TElementNode;\n\n const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);\n appendChild(tView, lView, textNative, tNode);\n\n // Text nodes are self closing.\n setCurrentTNode(tNode, false);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {getLView, getSelectedIndex} from '../state';\nimport {NO_CHANGE} from '../tokens';\n\nimport {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';\nimport {textBindingInternal} from './shared';\n\n\n/**\n *\n * Update text content with a lone bound value\n *\n * Used when a text node has 1 interpolated value in it, an no additional text\n * surrounds that interpolated value:\n *\n * ```html\n * <div>{{v0}}</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate(v0);\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate(v0: any): typeof ɵɵtextInterpolate {\n ɵɵtextInterpolate1('', v0, '');\n return ɵɵtextInterpolate;\n}\n\n\n/**\n *\n * Update text content with single bound value surrounded by other text.\n *\n * Used when a text node has 1 interpolated value in it:\n *\n * ```html\n * <div>prefix{{v0}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate1('prefix', v0, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate1(\n prefix: string, v0: any, suffix: string): typeof ɵɵtextInterpolate1 {\n const lView = getLView();\n const interpolated = interpolation1(lView, prefix, v0, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate1;\n}\n\n/**\n *\n * Update text content with 2 bound values surrounded by other text.\n *\n * Used when a text node has 2 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate2(\n prefix: string, v0: any, i0: string, v1: any, suffix: string): typeof ɵɵtextInterpolate2 {\n const lView = getLView();\n const interpolated = interpolation2(lView, prefix, v0, i0, v1, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate2;\n}\n\n/**\n *\n * Update text content with 3 bound values surrounded by other text.\n *\n * Used when a text node has 3 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate3(\n * 'prefix', v0, '-', v1, '-', v2, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate3(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,\n suffix: string): typeof ɵɵtextInterpolate3 {\n const lView = getLView();\n const interpolated = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate3;\n}\n\n/**\n *\n * Update text content with 4 bound values surrounded by other text.\n *\n * Used when a text node has 4 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate4(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see ɵɵtextInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate4(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n suffix: string): typeof ɵɵtextInterpolate4 {\n const lView = getLView();\n const interpolated = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate4;\n}\n\n/**\n *\n * Update text content with 5 bound values surrounded by other text.\n *\n * Used when a text node has 5 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate5(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate5(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, suffix: string): typeof ɵɵtextInterpolate5 {\n const lView = getLView();\n const interpolated = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate5;\n}\n\n/**\n *\n * Update text content with 6 bound values surrounded by other text.\n *\n * Used when a text node has 6 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate6(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');\n * ```\n *\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change. @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate6(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, suffix: string): typeof ɵɵtextInterpolate6 {\n const lView = getLView();\n const interpolated =\n interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate6;\n}\n\n/**\n *\n * Update text content with 7 bound values surrounded by other text.\n *\n * Used when a text node has 7 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate7(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate7(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, i5: string, v6: any,\n suffix: string): typeof ɵɵtextInterpolate7 {\n const lView = getLView();\n const interpolated =\n interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate7;\n}\n\n/**\n *\n * Update text content with 8 bound values surrounded by other text.\n *\n * Used when a text node has 8 interpolated values in it:\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolate8(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');\n * ```\n * @returns itself, so that it may be chained.\n * @see textInterpolateV\n * @codeGenApi\n */\nexport function ɵɵtextInterpolate8(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,\n suffix: string): typeof ɵɵtextInterpolate8 {\n const lView = getLView();\n const interpolated = interpolation8(\n lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolate8;\n}\n\n/**\n * Update text content with 9 or more bound values other surrounded by text.\n *\n * Used when the number of interpolated values exceeds 8.\n *\n * ```html\n * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵtextInterpolateV(\n * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,\n * 'suffix']);\n * ```\n *.\n * @param values The collection of values and the strings in between those values, beginning with\n * a string prefix and ending with a string suffix.\n * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)\n *\n * @returns itself, so that it may be chained.\n * @codeGenApi\n */\nexport function ɵɵtextInterpolateV(values: any[]): typeof ɵɵtextInterpolateV {\n const lView = getLView();\n const interpolated = interpolationV(lView, values);\n if (interpolated !== NO_CHANGE) {\n textBindingInternal(lView, getSelectedIndex(), interpolated as string);\n }\n return ɵɵtextInterpolateV;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {keyValueArraySet} from '../../util/array_utils';\nimport {getLView} from '../state';\nimport {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';\nimport {checkStylingMap, classStringParser} from './styling';\n\n\n\n/**\n *\n * Update an interpolated class on an element with single bound value surrounded by text.\n *\n * Used when the value passed to a property has 1 interpolated value in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate1('prefix', v0, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate1(prefix: string, v0: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue = interpolation1(lView, prefix, v0, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 2 bound values surrounded by text.\n *\n * Used when the value passed to a property has 2 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate2(\n prefix: string, v0: any, i0: string, v1: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 3 bound values surrounded by text.\n *\n * Used when the value passed to a property has 3 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate3(\n * 'prefix', v0, '-', v1, '-', v2, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate3(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 4 bound values surrounded by text.\n *\n * Used when the value passed to a property has 4 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate4(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate4(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n suffix: string): void {\n const lView = getLView();\n const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 5 bound values surrounded by text.\n *\n * Used when the value passed to a property has 5 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate5(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate5(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue =\n interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 6 bound values surrounded by text.\n *\n * Used when the value passed to a property has 6 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate6(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate6(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue =\n interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 7 bound values surrounded by text.\n *\n * Used when the value passed to a property has 7 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate7(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param i5 Static value used for concatenation only.\n * @param v6 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate7(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): void {\n const lView = getLView();\n const interpolatedValue =\n interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n *\n * Update an interpolated class on an element with 8 bound values surrounded by text.\n *\n * Used when the value passed to a property has 8 interpolated values in it:\n *\n * ```html\n * <div class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolate8(\n * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');\n * ```\n *\n * @param prefix Static value used for concatenation only.\n * @param v0 Value checked for change.\n * @param i0 Static value used for concatenation only.\n * @param v1 Value checked for change.\n * @param i1 Static value used for concatenation only.\n * @param v2 Value checked for change.\n * @param i2 Static value used for concatenation only.\n * @param v3 Value checked for change.\n * @param i3 Static value used for concatenation only.\n * @param v4 Value checked for change.\n * @param i4 Static value used for concatenation only.\n * @param v5 Value checked for change.\n * @param i5 Static value used for concatenation only.\n * @param v6 Value checked for change.\n * @param i6 Static value used for concatenation only.\n * @param v7 Value checked for change.\n * @param suffix Static value used for concatenation only.\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolate8(\n prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,\n i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,\n suffix: string): void {\n const lView = getLView();\n const interpolatedValue = interpolation8(\n lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n\n/**\n * Update an interpolated class on an element with 9 or more bound values surrounded by text.\n *\n * Used when the number of interpolated values exceeds 8.\n *\n * ```html\n * <div\n * class=\"prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix\"></div>\n * ```\n *\n * Its compiled representation is:\n *\n * ```ts\n * ɵɵclassMapInterpolateV(\n * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,\n * 'suffix']);\n * ```\n *.\n * @param values The collection of values and the strings in-between those values, beginning with\n * a string prefix and ending with a string suffix.\n * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)\n * @codeGenApi\n */\nexport function ɵɵclassMapInterpolateV(values: any[]): void {\n const lView = getLView();\n const interpolatedValue = interpolationV(lView, values);\n checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {bindingUpdated} from '../bindings';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {RENDERER} from '../interfaces/view';\nimport {getCurrentDirectiveDef, getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';\nimport {NO_CHANGE} from '../tokens';\n\nimport {elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared';\n\n/**\n * Update a property on a host element. Only applies to native node properties, not inputs.\n *\n * Operates on the element selected by index via the {@link select} instruction.\n *\n * @param propName Name of property. Because it is going to DOM, this is not subject to\n * renaming as part of minification.\n * @param value New value to write.\n * @param sanitizer An optional function used to sanitize the value.\n * @returns This function returns itself so that it may be chained\n * (e.g. `property('name', ctx.name)('title', ctx.title)`)\n *\n * @codeGenApi\n */\nexport function ɵɵhostProperty<T>(\n propName: string, value: T, sanitizer?: SanitizerFn|null): typeof ɵɵhostProperty {\n const lView = getLView();\n const bindingIndex = nextBindingIndex();\n if (bindingUpdated(lView, bindingIndex, value)) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true);\n ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);\n }\n return ɵɵhostProperty;\n}\n\n\n/**\n * Updates a synthetic host binding (e.g. `[@foo]`) on a component or directive.\n *\n * This instruction is for compatibility purposes and is designed to ensure that a\n * synthetic host binding (e.g. `@HostBinding('@foo')`) properly gets rendered in\n * the component's renderer. Normally all host bindings are evaluated with the parent\n * component's renderer, but, in the case of animation @triggers, they need to be\n * evaluated with the sub component's renderer (because that's where the animation\n * triggers are defined).\n *\n * Do not use this instruction as a replacement for `elementProperty`. This instruction\n * only exists to ensure compatibility with the ViewEngine's host binding behavior.\n *\n * @param index The index of the element to update in the data array\n * @param propName Name of property. Because it is going to DOM, this is not subject to\n * renaming as part of minification.\n * @param value New value to write.\n * @param sanitizer An optional function used to sanitize the value.\n *\n * @codeGenApi\n */\nexport function ɵɵsyntheticHostProperty<T>(\n propName: string, value: T|NO_CHANGE,\n sanitizer?: SanitizerFn|null): typeof ɵɵsyntheticHostProperty {\n const lView = getLView();\n const bindingIndex = nextBindingIndex();\n if (bindingUpdated(lView, bindingIndex, value)) {\n const tView = getTView();\n const tNode = getSelectedTNode();\n const currentDef = getCurrentDirectiveDef(tView.data);\n const renderer = loadComponentRenderer(currentDef, tNode, lView);\n elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);\n ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);\n }\n return ɵɵsyntheticHostProperty;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// THIS CODE IS GENERATED - DO NOT MODIFY.\nconst u = undefined;\n\nfunction plural(val: number): number {\nconst n = val, i = Math.floor(Math.abs(val)), v = val.toString().replace(/^[^.]*\\.?/, '').length;\n\nif (i === 1 && v === 0)\n return 1;\nreturn 5;\n}\n\nexport default [\"en\",[[\"a\",\"p\"],[\"AM\",\"PM\"],u],[[\"AM\",\"PM\"],u,u],[[\"S\",\"M\",\"T\",\"W\",\"T\",\"F\",\"S\"],[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"],[\"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\"]],u,[[\"J\",\"F\",\"M\",\"A\",\"M\",\"J\",\"J\",\"A\",\"S\",\"O\",\"N\",\"D\"],[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"]],u,[[\"B\",\"A\"],[\"BC\",\"AD\"],[\"Before Christ\",\"Anno Domini\"]],0,[6,0],[\"M/d/yy\",\"MMM d, y\",\"MMMM d, y\",\"EEEE, MMMM d, y\"],[\"h:mm a\",\"h:mm:ss a\",\"h:mm:ss a z\",\"h:mm:ss a zzzz\"],[\"{1}, {0}\",u,\"{1} 'at' {0}\",u],[\".\",\",\",\";\",\"%\",\"+\",\"-\",\"E\",\"×\",\"‰\",\"∞\",\"NaN\",\":\"],[\"#,##0.###\",\"#,##0%\",\"¤#,##0.00\",\"#E0\"],\"USD\",\"$\",\"US Dollar\",{},\"ltr\", plural];\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {global} from '../util/global';\n\nimport localeEn from './locale_en';\n\n/**\n * This const is used to store the locale data registered with `registerLocaleData`\n */\nlet LOCALE_DATA: {[localeId: string]: any} = {};\n\n/**\n * Register locale data to be used internally by Angular. See the\n * [\"I18n guide\"](guide/i18n-common-format-data-locale) to know how to import additional locale\n * data.\n *\n * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1\n */\nexport function registerLocaleData(data: any, localeId?: string|any, extraData?: any): void {\n if (typeof localeId !== 'string') {\n extraData = localeId;\n localeId = data[LocaleDataIndex.LocaleId];\n }\n\n localeId = localeId.toLowerCase().replace(/_/g, '-');\n\n LOCALE_DATA[localeId] = data;\n\n if (extraData) {\n LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData;\n }\n}\n\n/**\n * Finds the locale data for a given locale.\n *\n * @param locale The locale code.\n * @returns The locale data.\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n */\nexport function findLocaleData(locale: string): any {\n const normalizedLocale = normalizeLocale(locale);\n\n let match = getLocaleData(normalizedLocale);\n if (match) {\n return match;\n }\n\n // let's try to find a parent locale\n const parentLocale = normalizedLocale.split('-')[0];\n match = getLocaleData(parentLocale);\n if (match) {\n return match;\n }\n\n if (parentLocale === 'en') {\n return localeEn;\n }\n\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_LOCALE_DATA,\n ngDevMode && `Missing locale data for the locale \"${locale}\".`);\n}\n\n/**\n * Retrieves the default currency code for the given locale.\n *\n * The default is defined as the first currency which is still in use.\n *\n * @param locale The code of the locale whose currency code we want.\n * @returns The code of the default currency for the given locale.\n *\n */\nexport function getLocaleCurrencyCode(locale: string): string|null {\n const data = findLocaleData(locale);\n return data[LocaleDataIndex.CurrencyCode] || null;\n}\n\n/**\n * Retrieves the plural function used by ICU expressions to determine the plural case to use\n * for a given locale.\n * @param locale A locale code for the locale format rules to use.\n * @returns The plural function for the locale.\n * @see `NgPlural`\n * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)\n */\nexport function getLocalePluralCase(locale: string): (value: number) => number {\n const data = findLocaleData(locale);\n return data[LocaleDataIndex.PluralCase];\n}\n\n\n\n/**\n * Helper function to get the given `normalizedLocale` from `LOCALE_DATA`\n * or from the global `ng.common.locale`.\n */\nexport function getLocaleData(normalizedLocale: string): any {\n if (!(normalizedLocale in LOCALE_DATA)) {\n LOCALE_DATA[normalizedLocale] = global.ng && global.ng.common && global.ng.common.locales &&\n global.ng.common.locales[normalizedLocale];\n }\n return LOCALE_DATA[normalizedLocale];\n}\n\n/**\n * Helper function to remove all the locale data from `LOCALE_DATA`.\n */\nexport function unregisterAllLocaleData() {\n LOCALE_DATA = {};\n}\n\n/**\n * Index of each type of locale data from the locale data array\n */\nexport enum LocaleDataIndex {\n LocaleId = 0,\n DayPeriodsFormat,\n DayPeriodsStandalone,\n DaysFormat,\n DaysStandalone,\n MonthsFormat,\n MonthsStandalone,\n Eras,\n FirstDayOfWeek,\n WeekendRange,\n DateFormat,\n TimeFormat,\n DateTimeFormat,\n NumberSymbols,\n NumberFormats,\n CurrencyCode,\n CurrencySymbol,\n CurrencyName,\n Currencies,\n Directionality,\n PluralCase,\n ExtraData\n}\n\n/**\n * Index of each type of locale data from the extra locale data array\n */\nexport const enum ExtraLocaleDataIndex {\n ExtraDayPeriodFormats = 0,\n ExtraDayPeriodStandalone,\n ExtraDayPeriodsRules\n}\n\n/**\n * Index of each value in currency data (used to describe CURRENCIES_EN in currencies.ts)\n */\nexport const enum CurrencyIndex {\n Symbol = 0,\n SymbolNarrow,\n NbOfDigits\n}\n\n/**\n * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.\n */\nfunction normalizeLocale(locale: string): string {\n return locale.toLowerCase().replace(/_/g, '-');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {getLocalePluralCase} from './locale_data_api';\n\nconst pluralMapping = ['zero', 'one', 'two', 'few', 'many'];\n\n/**\n * Returns the plural case based on the locale\n */\nexport function getPluralCase(value: string, locale: string): string {\n const plural = getLocalePluralCase(locale)(parseInt(value, 10));\n const result = pluralMapping[plural];\n return (result !== undefined) ? result : 'other';\n}\n\n/**\n * The locale id that the application is using by default (for translations and ICU expressions).\n */\nexport const DEFAULT_LOCALE_ID = 'en-US';\n\n/**\n * USD currency code that the application uses by default for CurrencyPipe when no\n * DEFAULT_CURRENCY_CODE is provided.\n */\nexport const USD_CURRENCY_CODE = 'USD';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {SanitizerFn} from './sanitization';\n\n\n/**\n * Stores a list of nodes which need to be removed.\n *\n * Numbers are indexes into the `LView`\n * - index > 0: `removeRNode(lView[0])`\n * - index < 0: `removeICU(~lView[0])`\n */\nexport interface I18nRemoveOpCodes extends Array<number> {\n __brand__: 'I18nRemoveOpCodes';\n}\n\n/**\n * `I18nMutateOpCode` defines OpCodes for `I18nMutateOpCodes` array.\n *\n * OpCodes are efficient operations which can be applied to the DOM to update it. (For example to\n * update to a new ICU case requires that we clean up previous elements and create new ones.)\n *\n * OpCodes contain three parts:\n * 1) Parent node index offset. (p)\n * 2) Reference node index offset. (r)\n * 3) The instruction to execute. (i)\n *\n * pppp pppp pppp pppp rrrr rrrr rrrr riii\n * 3322 2222 2222 1111 1111 1110 0000 0000\n * 1098 7654 3210 9876 5432 1098 7654 3210\n *\n * ```\n * var parent = lView[opCode >>> SHIFT_PARENT];\n * var refNode = lView[((opCode & MASK_REF) >>> SHIFT_REF)];\n * var instruction = opCode & MASK_OPCODE;\n * ```\n *\n * See: `I18nCreateOpCodes` for example of usage.\n */\nexport const enum IcuCreateOpCode {\n /**\n * Stores shift amount for bits 17-3 that contain reference index.\n */\n SHIFT_REF = 1,\n /**\n * Stores shift amount for bits 31-17 that contain parent index.\n */\n SHIFT_PARENT = 17,\n /**\n * Mask for OpCode\n */\n MASK_INSTRUCTION = 0b1,\n\n /**\n * Mask for the Reference node (bits 16-3)\n */\n MASK_REF = 0b11111111111111110,\n // 11111110000000000\n // 65432109876543210\n\n /**\n * Instruction to append the current node to `PARENT`.\n */\n AppendChild = 0b0,\n\n /**\n * Instruction to set the attribute of a node.\n */\n Attr = 0b1,\n}\n\n\n/**\n * Array storing OpCode for dynamically creating `i18n` blocks.\n *\n * Example:\n * ```ts\n * <I18nCreateOpCode>[\n * // For adding text nodes\n * // ---------------------\n * // Equivalent to:\n * // lView[1].appendChild(lView[0] = document.createTextNode('xyz'));\n * 'xyz', 0, 1 << SHIFT_PARENT | 0 << SHIFT_REF | AppendChild,\n *\n * // For adding element nodes\n * // ---------------------\n * // Equivalent to:\n * // lView[1].appendChild(lView[0] = document.createElement('div'));\n * ELEMENT_MARKER, 'div', 0, 1 << SHIFT_PARENT | 0 << SHIFT_REF | AppendChild,\n *\n * // For adding comment nodes\n * // ---------------------\n * // Equivalent to:\n * // lView[1].appendChild(lView[0] = document.createComment(''));\n * ICU_MARKER, '', 0, 1 << SHIFT_PARENT | 0 << SHIFT_REF | AppendChild,\n *\n * // For moving existing nodes to a different location\n * // --------------------------------------------------\n * // Equivalent to:\n * // const node = lView[1];\n * // lView[2].appendChild(node);\n * 1 << SHIFT_REF | Select, 2 << SHIFT_PARENT | 0 << SHIFT_REF | AppendChild,\n *\n * // For removing existing nodes\n * // --------------------------------------------------\n * // const node = lView[1];\n * // removeChild(tView.data(1), node, lView);\n * 1 << SHIFT_REF | Remove,\n *\n * // For writing attributes\n * // --------------------------------------------------\n * // const node = lView[1];\n * // node.setAttribute('attr', 'value');\n * 1 << SHIFT_REF | Attr, 'attr', 'value'\n * ];\n * ```\n */\nexport interface IcuCreateOpCodes extends Array<number|string|ELEMENT_MARKER|ICU_MARKER|null>,\n I18nDebug {\n __brand__: 'I18nCreateOpCodes';\n}\n\nexport const enum I18nUpdateOpCode {\n /**\n * Stores shift amount for bits 17-2 that contain reference index.\n */\n SHIFT_REF = 2,\n /**\n * Mask for OpCode\n */\n MASK_OPCODE = 0b11,\n\n /**\n * Instruction to update a text node.\n */\n Text = 0b00,\n /**\n * Instruction to update a attribute of a node.\n */\n Attr = 0b01,\n /**\n * Instruction to switch the current ICU case.\n */\n IcuSwitch = 0b10,\n /**\n * Instruction to update the current ICU case.\n */\n IcuUpdate = 0b11,\n}\n\n/**\n * Marks that the next string is an element name.\n *\n * See `I18nMutateOpCodes` documentation.\n */\nexport const ELEMENT_MARKER: ELEMENT_MARKER = {\n marker: 'element'\n};\nexport interface ELEMENT_MARKER {\n marker: 'element';\n}\n\n/**\n * Marks that the next string is comment text need for ICU.\n *\n * See `I18nMutateOpCodes` documentation.\n */\nexport const ICU_MARKER: ICU_MARKER = {\n marker: 'ICU'\n};\n\nexport interface ICU_MARKER {\n marker: 'ICU';\n}\n\nexport interface I18nDebug {\n /**\n * Human readable representation of the OpCode arrays.\n *\n * NOTE: This property only exists if `ngDevMode` is set to `true` and it is not present in\n * production. Its presence is purely to help debug issue in development, and should not be relied\n * on in production application.\n */\n debug?: string[];\n}\n\n/**\n * Array storing OpCode for dynamically creating `i18n` translation DOM elements.\n *\n * This array creates a sequence of `Text` and `Comment` (as ICU anchor) DOM elements. It consists\n * of a pair of `number` and `string` pairs which encode the operations for the creation of the\n * translated block.\n *\n * The number is shifted and encoded according to `I18nCreateOpCode`\n *\n * Pseudocode:\n * ```\n * const i18nCreateOpCodes = [\n * 10 << I18nCreateOpCode.SHIFT, \"Text Node add to DOM\",\n * 11 << I18nCreateOpCode.SHIFT | I18nCreateOpCode.COMMENT, \"Comment Node add to DOM\",\n * 12 << I18nCreateOpCode.SHIFT | I18nCreateOpCode.APPEND_LATER, \"Text Node added later\"\n * ];\n *\n * for(var i=0; i<i18nCreateOpCodes.length; i++) {\n * const opcode = i18NCreateOpCodes[i++];\n * const index = opcode >> I18nCreateOpCode.SHIFT;\n * const text = i18NCreateOpCodes[i];\n * let node: Text|Comment;\n * if (opcode & I18nCreateOpCode.COMMENT === I18nCreateOpCode.COMMENT) {\n * node = lView[~index] = document.createComment(text);\n * } else {\n * node = lView[index] = document.createText(text);\n * }\n * if (opcode & I18nCreateOpCode.APPEND_EAGERLY !== I18nCreateOpCode.APPEND_EAGERLY) {\n * parentNode.appendChild(node);\n * }\n * }\n * ```\n */\nexport interface I18nCreateOpCodes extends Array<number|string>, I18nDebug {\n __brand__: 'I18nCreateOpCodes';\n}\n\n/**\n * See `I18nCreateOpCodes`\n */\nexport enum I18nCreateOpCode {\n /**\n * Number of bits to shift index so that it can be combined with the `APPEND_EAGERLY` and\n * `COMMENT`.\n */\n SHIFT = 2,\n\n /**\n * Should the node be appended to parent immediately after creation.\n */\n APPEND_EAGERLY = 0b01,\n\n /**\n * If set the node should be comment (rather than a text) node.\n */\n COMMENT = 0b10,\n}\n\n\n/**\n * Stores DOM operations which need to be applied to update DOM render tree due to changes in\n * expressions.\n *\n * The basic idea is that `i18nExp` OpCodes capture expression changes and update a change\n * mask bit. (Bit 1 for expression 1, bit 2 for expression 2 etc..., bit 32 for expression 32 and\n * higher.) The OpCodes then compare its own change mask against the expression change mask to\n * determine if the OpCodes should execute.\n *\n * NOTE: 32nd bit is special as it says 32nd or higher. This way if we have more than 32 bindings\n * the code still works, but with lower efficiency. (it is unlikely that a translation would have\n * more than 32 bindings.)\n *\n * These OpCodes can be used by both the i18n block as well as ICU sub-block.\n *\n * ## Example\n *\n * Assume\n * ```ts\n * if (rf & RenderFlags.Update) {\n * i18nExp(ctx.exp1); // If changed set mask bit 1\n * i18nExp(ctx.exp2); // If changed set mask bit 2\n * i18nExp(ctx.exp3); // If changed set mask bit 3\n * i18nExp(ctx.exp4); // If changed set mask bit 4\n * i18nApply(0); // Apply all changes by executing the OpCodes.\n * }\n * ```\n * We can assume that each call to `i18nExp` sets an internal `changeMask` bit depending on the\n * index of `i18nExp`.\n *\n * ### OpCodes\n * ```ts\n * <I18nUpdateOpCodes>[\n * // The following OpCodes represent: `<div i18n-title=\"pre{{exp1}}in{{exp2}}post\">`\n * // If `changeMask & 0b11`\n * // has changed then execute update OpCodes.\n * // has NOT changed then skip `8` values and start processing next OpCodes.\n * 0b11, 8,\n * // Concatenate `newValue = 'pre'+lView[bindIndex-4]+'in'+lView[bindIndex-3]+'post';`.\n * 'pre', -4, 'in', -3, 'post',\n * // Update attribute: `elementAttribute(1, 'title', sanitizerFn(newValue));`\n * 1 << SHIFT_REF | Attr, 'title', sanitizerFn,\n *\n * // The following OpCodes represent: `<div i18n>Hello {{exp3}}!\">`\n * // If `changeMask & 0b100`\n * // has changed then execute update OpCodes.\n * // has NOT changed then skip `4` values and start processing next OpCodes.\n * 0b100, 4,\n * // Concatenate `newValue = 'Hello ' + lView[bindIndex -2] + '!';`.\n * 'Hello ', -2, '!',\n * // Update text: `lView[1].textContent = newValue;`\n * 1 << SHIFT_REF | Text,\n *\n * // The following OpCodes represent: `<div i18n>{exp4, plural, ... }\">`\n * // If `changeMask & 0b1000`\n * // has changed then execute update OpCodes.\n * // has NOT changed then skip `2` values and start processing next OpCodes.\n * 0b1000, 2,\n * // Concatenate `newValue = lView[bindIndex -1];`.\n * -1,\n * // Switch ICU: `icuSwitchCase(lView[1], 0, newValue);`\n * 0 << SHIFT_ICU | 1 << SHIFT_REF | IcuSwitch,\n *\n * // Note `changeMask & -1` is always true, so the IcuUpdate will always execute.\n * -1, 1,\n * // Update ICU: `icuUpdateCase(lView[1], 0);`\n * 0 << SHIFT_ICU | 1 << SHIFT_REF | IcuUpdate,\n *\n * ];\n * ```\n *\n */\nexport interface I18nUpdateOpCodes extends Array<string|number|SanitizerFn|null>, I18nDebug {\n __brand__: 'I18nUpdateOpCodes';\n}\n\n/**\n * Store information for the i18n translation block.\n */\nexport interface TI18n {\n /**\n * A set of OpCodes which will create the Text Nodes and ICU anchors for the translation blocks.\n *\n * NOTE: The ICU anchors are filled in with ICU Update OpCode.\n */\n create: I18nCreateOpCodes;\n\n /**\n * A set of OpCodes which will be executed on each change detection to determine if any changes to\n * DOM are required.\n */\n update: I18nUpdateOpCodes;\n}\n\n/**\n * Defines the ICU type of `select` or `plural`\n */\nexport const enum IcuType {\n select = 0,\n plural = 1,\n}\n\nexport interface TIcu {\n /**\n * Defines the ICU type of `select` or `plural`\n */\n type: IcuType;\n\n /**\n * Index in `LView` where the anchor node is stored. `<!-- ICU 0:0 -->`\n */\n anchorIdx: number;\n\n /**\n * Currently selected ICU case pointer.\n *\n * `lView[currentCaseLViewIndex]` stores the currently selected case. This is needed to know how\n * to clean up the current case when transitioning no the new case.\n *\n * If the value stored is:\n * `null`: No current case selected.\n * `<0`: A flag which means that the ICU just switched and that `icuUpdate` must be executed\n * regardless of the `mask`. (After the execution the flag is cleared)\n * `>=0` A currently selected case index.\n */\n currentCaseLViewIndex: number;\n\n /**\n * A list of case values which the current ICU will try to match.\n *\n * The last value is `other`\n */\n cases: any[];\n\n /**\n * A set of OpCodes to apply in order to build up the DOM render tree for the ICU\n */\n create: IcuCreateOpCodes[];\n\n /**\n * A set of OpCodes to apply in order to destroy the DOM render tree for the ICU.\n */\n remove: I18nRemoveOpCodes[];\n\n /**\n * A set of OpCodes to apply in order to update the DOM render tree for the ICU bindings.\n */\n update: I18nUpdateOpCodes[];\n}\n\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nexport const unusedValueExportToPlacateAjd = 1;\n\n/**\n * Parsed ICU expression\n */\nexport interface IcuExpression {\n type: IcuType;\n mainBinding: number;\n cases: string[];\n values: (string|IcuExpression)[][];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DEFAULT_LOCALE_ID} from '../../i18n/localization';\nimport {assertDefined} from '../../util/assert';\n\n\n/**\n * The locale id that the application is currently using (for translations and ICU expressions).\n * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine\n * but is now defined as a global value.\n */\nlet LOCALE_ID = DEFAULT_LOCALE_ID;\n\n/**\n * Sets the locale id that will be used for translations and ICU expressions.\n * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine\n * but is now defined as a global value.\n *\n * @param localeId\n */\nexport function setLocaleId(localeId: string) {\n assertDefined(localeId, `Expected localeId to be defined`);\n if (typeof localeId === 'string') {\n LOCALE_ID = localeId.toLowerCase().replace(/_/g, '-');\n }\n}\n\n/**\n * Gets the locale id that will be used for translations and ICU expressions.\n * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine\n * but is now defined as a global value.\n */\nexport function getLocaleId(): string {\n return LOCALE_ID;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertDomNode, assertIndexInRange} from '../util/assert';\n\nimport {TNode, TNodeFlags, TNodeType} from './interfaces/node';\nimport {Renderer} from './interfaces/renderer';\nimport {RElement, RNode} from './interfaces/renderer_dom';\nimport {LView} from './interfaces/view';\nimport {getInsertInFrontOfRNodeWithNoI18n, nativeInsertBefore} from './node_manipulation';\nimport {unwrapRNode} from './util/view_utils';\n\n\n/**\n * Find a node in front of which `currentTNode` should be inserted (takes i18n into account).\n *\n * This method determines the `RNode` in front of which we should insert the `currentRNode`. This\n * takes `TNode.insertBeforeIndex` into account.\n *\n * @param parentTNode parent `TNode`\n * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)\n * @param lView current `LView`\n */\nexport function getInsertInFrontOfRNodeWithI18n(\n parentTNode: TNode, currentTNode: TNode, lView: LView): RNode|null {\n const tNodeInsertBeforeIndex = currentTNode.insertBeforeIndex;\n const insertBeforeIndex =\n Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;\n if (insertBeforeIndex === null) {\n return getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView);\n } else {\n ngDevMode && assertIndexInRange(lView, insertBeforeIndex);\n return unwrapRNode(lView[insertBeforeIndex]);\n }\n}\n\n\n/**\n * Process `TNode.insertBeforeIndex` by adding i18n text nodes.\n *\n * See `TNode.insertBeforeIndex`\n */\nexport function processI18nInsertBefore(\n renderer: Renderer, childTNode: TNode, lView: LView, childRNode: RNode|RNode[],\n parentRElement: RElement|null): void {\n const tNodeInsertBeforeIndex = childTNode.insertBeforeIndex;\n if (Array.isArray(tNodeInsertBeforeIndex)) {\n // An array indicates that there are i18n nodes that need to be added as children of this\n // `childRNode`. These i18n nodes were created before this `childRNode` was available and so\n // only now can be added. The first element of the array is the normal index where we should\n // insert the `childRNode`. Additional elements are the extra nodes to be added as children of\n // `childRNode`.\n ngDevMode && assertDomNode(childRNode);\n let i18nParent: RElement|null = childRNode as RElement;\n let anchorRNode: RNode|null = null;\n if (!(childTNode.type & TNodeType.AnyRNode)) {\n anchorRNode = i18nParent;\n i18nParent = parentRElement;\n }\n if (i18nParent !== null && childTNode.componentOffset === -1) {\n for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) {\n // No need to `unwrapRNode` because all of the indexes point to i18n text nodes.\n // see `assertDomNode` below.\n const i18nChild = lView[tNodeInsertBeforeIndex[i]];\n nativeInsertBefore(renderer, i18nParent, i18nChild, anchorRNode, false);\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertEqual} from '../../util/assert';\nimport {TNode, TNodeType} from '../interfaces/node';\nimport {setI18nHandling} from '../node_manipulation';\nimport {getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore} from '../node_manipulation_i18n';\n\n/**\n * Add `tNode` to `previousTNodes` list and update relevant `TNode`s in `previousTNodes` list\n * `tNode.insertBeforeIndex`.\n *\n * Things to keep in mind:\n * 1. All i18n text nodes are encoded as `TNodeType.Element` and are created eagerly by the\n * `ɵɵi18nStart` instruction.\n * 2. All `TNodeType.Placeholder` `TNodes` are elements which will be created later by\n * `ɵɵelementStart` instruction.\n * 3. `ɵɵelementStart` instruction will create `TNode`s in the ascending `TNode.index` order. (So a\n * smaller index `TNode` is guaranteed to be created before a larger one)\n *\n * We use the above three invariants to determine `TNode.insertBeforeIndex`.\n *\n * In an ideal world `TNode.insertBeforeIndex` would always be `TNode.next.index`. However,\n * this will not work because `TNode.next.index` may be larger than `TNode.index` which means that\n * the next node is not yet created and therefore we can't insert in front of it.\n *\n * Rule1: `TNode.insertBeforeIndex = null` if `TNode.next === null` (Initial condition, as we don't\n * know if there will be further `TNode`s inserted after.)\n * Rule2: If `previousTNode` is created after the `tNode` being inserted, then\n * `previousTNode.insertBeforeNode = tNode.index` (So when a new `tNode` is added we check\n * previous to see if we can update its `insertBeforeTNode`)\n *\n * See `TNode.insertBeforeIndex` for more context.\n *\n * @param previousTNodes A list of previous TNodes so that we can easily traverse `TNode`s in\n * reverse order. (If `TNode` would have `previous` this would not be necessary.)\n * @param newTNode A TNode to add to the `previousTNodes` list.\n */\nexport function addTNodeAndUpdateInsertBeforeIndex(previousTNodes: TNode[], newTNode: TNode) {\n // Start with Rule1\n ngDevMode &&\n assertEqual(newTNode.insertBeforeIndex, null, 'We expect that insertBeforeIndex is not set');\n\n previousTNodes.push(newTNode);\n if (previousTNodes.length > 1) {\n for (let i = previousTNodes.length - 2; i >= 0; i--) {\n const existingTNode = previousTNodes[i];\n // Text nodes are created eagerly and so they don't need their `indexBeforeIndex` updated.\n // It is safe to ignore them.\n if (!isI18nText(existingTNode)) {\n if (isNewTNodeCreatedBefore(existingTNode, newTNode) &&\n getInsertBeforeIndex(existingTNode) === null) {\n // If it was created before us in time, (and it does not yet have `insertBeforeIndex`)\n // then add the `insertBeforeIndex`.\n setInsertBeforeIndex(existingTNode, newTNode.index);\n }\n }\n }\n }\n}\n\nfunction isI18nText(tNode: TNode): boolean {\n return !(tNode.type & TNodeType.Placeholder);\n}\n\nfunction isNewTNodeCreatedBefore(existingTNode: TNode, newTNode: TNode): boolean {\n return isI18nText(newTNode) || existingTNode.index > newTNode.index;\n}\n\nfunction getInsertBeforeIndex(tNode: TNode): number|null {\n const index = tNode.insertBeforeIndex;\n return Array.isArray(index) ? index[0] : index;\n}\n\nfunction setInsertBeforeIndex(tNode: TNode, value: number): void {\n const index = tNode.insertBeforeIndex;\n if (Array.isArray(index)) {\n // Array is stored if we have to insert child nodes. See `TNode.insertBeforeIndex`\n index[0] = value;\n } else {\n setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);\n tNode.insertBeforeIndex = value;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertEqual, assertGreaterThan, assertGreaterThanOrEqual, throwError} from '../../util/assert';\nimport {assertTIcu, assertTNode} from '../assert';\nimport {createTNodeAtIndex} from '../instructions/shared';\nimport {IcuCreateOpCode, TIcu} from '../interfaces/i18n';\nimport {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';\nimport {LView, TView} from '../interfaces/view';\nimport {assertTNodeType} from '../node_assert';\nimport {setI18nHandling} from '../node_manipulation';\nimport {getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore} from '../node_manipulation_i18n';\n\nimport {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';\n\n\n/**\n * Retrieve `TIcu` at a given `index`.\n *\n * The `TIcu` can be stored either directly (if it is nested ICU) OR\n * it is stored inside tho `TIcuContainer` if it is top level ICU.\n *\n * The reason for this is that the top level ICU need a `TNode` so that they are part of the render\n * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is\n * expressed (parent ICU may have selected a case which does not contain it.)\n *\n * @param tView Current `TView`.\n * @param index Index where the value should be read from.\n */\nexport function getTIcu(tView: TView, index: number): TIcu|null {\n const value = tView.data[index] as null | TIcu | TIcuContainerNode | string;\n if (value === null || typeof value === 'string') return null;\n if (ngDevMode &&\n !(value.hasOwnProperty('tView') || value.hasOwnProperty('currentCaseLViewIndex'))) {\n throwError('We expect to get \\'null\\'|\\'TIcu\\'|\\'TIcuContainer\\', but got: ' + value);\n }\n // Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be\n // either TIcu or TIcuContainerNode. This is not ideal, but we still think it is OK because it\n // will be just two cases which fits into the browser inline cache (inline cache can take up to\n // 4)\n const tIcu = value.hasOwnProperty('currentCaseLViewIndex') ? value as TIcu :\n (value as TIcuContainerNode).value;\n ngDevMode && assertTIcu(tIcu);\n return tIcu;\n}\n\n/**\n * Store `TIcu` at a give `index`.\n *\n * The `TIcu` can be stored either directly (if it is nested ICU) OR\n * it is stored inside tho `TIcuContainer` if it is top level ICU.\n *\n * The reason for this is that the top level ICU need a `TNode` so that they are part of the render\n * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is\n * expressed (parent ICU may have selected a case which does not contain it.)\n *\n * @param tView Current `TView`.\n * @param index Index where the value should be stored at in `Tview.data`\n * @param tIcu The TIcu to store.\n */\nexport function setTIcu(tView: TView, index: number, tIcu: TIcu): void {\n const tNode = tView.data[index] as null | TIcuContainerNode;\n ngDevMode &&\n assertEqual(\n tNode === null || tNode.hasOwnProperty('tView'), true,\n 'We expect to get \\'null\\'|\\'TIcuContainer\\'');\n if (tNode === null) {\n tView.data[index] = tIcu;\n } else {\n ngDevMode && assertTNodeType(tNode, TNodeType.Icu);\n tNode.value = tIcu;\n }\n}\n\n/**\n * Set `TNode.insertBeforeIndex` taking the `Array` into account.\n *\n * See `TNode.insertBeforeIndex`\n */\nexport function setTNodeInsertBeforeIndex(tNode: TNode, index: number) {\n ngDevMode && assertTNode(tNode);\n let insertBeforeIndex = tNode.insertBeforeIndex;\n if (insertBeforeIndex === null) {\n setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);\n insertBeforeIndex = tNode.insertBeforeIndex =\n [null!/* may be updated to number later */, index];\n } else {\n assertEqual(Array.isArray(insertBeforeIndex), true, 'Expecting array here');\n (insertBeforeIndex as number[]).push(index);\n }\n}\n\n/**\n * Create `TNode.type=TNodeType.Placeholder` node.\n *\n * See `TNodeType.Placeholder` for more information.\n */\nexport function createTNodePlaceholder(\n tView: TView, previousTNodes: TNode[], index: number): TNode {\n const tNode = createTNodeAtIndex(tView, index, TNodeType.Placeholder, null, null);\n addTNodeAndUpdateInsertBeforeIndex(previousTNodes, tNode);\n return tNode;\n}\n\n\n/**\n * Returns current ICU case.\n *\n * ICU cases are stored as index into the `TIcu.cases`.\n * At times it is necessary to communicate that the ICU case just switched and that next ICU update\n * should update all bindings regardless of the mask. In such a case the we store negative numbers\n * for cases which have just been switched. This function removes the negative flag.\n */\nexport function getCurrentICUCaseIndex(tIcu: TIcu, lView: LView) {\n const currentCase: number|null = lView[tIcu.currentCaseLViewIndex];\n return currentCase === null ? currentCase : (currentCase < 0 ? ~currentCase : currentCase);\n}\n\nexport function getParentFromIcuCreateOpCode(mergedCode: number): number {\n return mergedCode >>> IcuCreateOpCode.SHIFT_PARENT;\n}\n\nexport function getRefFromIcuCreateOpCode(mergedCode: number): number {\n return (mergedCode & IcuCreateOpCode.MASK_REF) >>> IcuCreateOpCode.SHIFT_REF;\n}\n\nexport function getInstructionFromIcuCreateOpCode(mergedCode: number): number {\n return mergedCode & IcuCreateOpCode.MASK_INSTRUCTION;\n}\n\nexport function icuCreateOpCode(opCode: IcuCreateOpCode, parentIdx: number, refIdx: number) {\n ngDevMode && assertGreaterThanOrEqual(parentIdx, 0, 'Missing parent index');\n ngDevMode && assertGreaterThan(refIdx, 0, 'Missing ref index');\n return opCode | parentIdx << IcuCreateOpCode.SHIFT_PARENT | refIdx << IcuCreateOpCode.SHIFT_REF;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {getPluralCase} from '../../i18n/localization';\nimport {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertIndexInRange, throwError} from '../../util/assert';\nimport {assertIndexInExpandoRange, assertTIcu} from '../assert';\nimport {attachPatchData} from '../context_discovery';\nimport {elementPropertyInternal, setElementAttribute} from '../instructions/shared';\nimport {ELEMENT_MARKER, I18nCreateOpCode, I18nCreateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, ICU_MARKER, IcuCreateOpCode, IcuCreateOpCodes, IcuType, TI18n, TIcu} from '../interfaces/i18n';\nimport {TNode} from '../interfaces/node';\nimport {RElement, RNode, RText} from '../interfaces/renderer_dom';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';\nimport {createCommentNode, createElementNode, createTextNode, nativeInsertBefore, nativeParentNode, nativeRemoveNode, updateTextNode} from '../node_manipulation';\nimport {getBindingIndex} from '../state';\nimport {renderStringify} from '../util/stringify_utils';\nimport {getNativeByIndex, unwrapRNode} from '../util/view_utils';\n\nimport {getLocaleId} from './i18n_locale_id';\nimport {getCurrentICUCaseIndex, getParentFromIcuCreateOpCode, getRefFromIcuCreateOpCode, getTIcu} from './i18n_util';\n\n\n\n/**\n * Keep track of which input bindings in `ɵɵi18nExp` have changed.\n *\n * This is used to efficiently update expressions in i18n only when the corresponding input has\n * changed.\n *\n * 1) Each bit represents which of the `ɵɵi18nExp` has changed.\n * 2) There are 32 bits allowed in JS.\n * 3) Bit 32 is special as it is shared for all changes past 32. (In other words if you have more\n * than 32 `ɵɵi18nExp` then all changes past 32nd `ɵɵi18nExp` will be mapped to same bit. This means\n * that we may end up changing more than we need to. But i18n expressions with 32 bindings is rare\n * so in practice it should not be an issue.)\n */\nlet changeMask = 0b0;\n\n/**\n * Keeps track of which bit needs to be updated in `changeMask`\n *\n * This value gets incremented on every call to `ɵɵi18nExp`\n */\nlet changeMaskCounter = 0;\n\n/**\n * Keep track of which input bindings in `ɵɵi18nExp` have changed.\n *\n * `setMaskBit` gets invoked by each call to `ɵɵi18nExp`.\n *\n * @param hasChange did `ɵɵi18nExp` detect a change.\n */\nexport function setMaskBit(hasChange: boolean) {\n if (hasChange) {\n changeMask = changeMask | (1 << Math.min(changeMaskCounter, 31));\n }\n changeMaskCounter++;\n}\n\nexport function applyI18n(tView: TView, lView: LView, index: number) {\n if (changeMaskCounter > 0) {\n ngDevMode && assertDefined(tView, `tView should be defined`);\n const tI18n = tView.data[index] as TI18n | I18nUpdateOpCodes;\n // When `index` points to an `ɵɵi18nAttributes` then we have an array otherwise `TI18n`\n const updateOpCodes: I18nUpdateOpCodes =\n Array.isArray(tI18n) ? tI18n as I18nUpdateOpCodes : (tI18n as TI18n).update;\n const bindingsStartIndex = getBindingIndex() - changeMaskCounter - 1;\n applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask);\n }\n // Reset changeMask & maskBit to default for the next update cycle\n changeMask = 0b0;\n changeMaskCounter = 0;\n}\n\n\n/**\n * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`.\n *\n * Creates text (and comment) nodes which are internationalized.\n *\n * @param lView Current lView\n * @param createOpCodes Set of op-codes to apply\n * @param parentRNode Parent node (so that direct children can be added eagerly) or `null` if it is\n * a root node.\n * @param insertInFrontOf DOM node that should be used as an anchor.\n */\nexport function applyCreateOpCodes(\n lView: LView, createOpCodes: I18nCreateOpCodes, parentRNode: RElement|null,\n insertInFrontOf: RElement|null): void {\n const renderer = lView[RENDERER];\n for (let i = 0; i < createOpCodes.length; i++) {\n const opCode = createOpCodes[i++] as any;\n const text = createOpCodes[i] as string;\n const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;\n const appendNow =\n (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;\n const index = opCode >>> I18nCreateOpCode.SHIFT;\n let rNode = lView[index];\n if (rNode === null) {\n // We only create new DOM nodes if they don't already exist: If ICU switches case back to a\n // case which was already instantiated, no need to create new DOM nodes.\n rNode = lView[index] =\n isComment ? renderer.createComment(text) : createTextNode(renderer, text);\n }\n if (appendNow && parentRNode !== null) {\n nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false);\n }\n }\n}\n\n/**\n * Apply `I18nMutateOpCodes` OpCodes.\n *\n * @param tView Current `TView`\n * @param mutableOpCodes Mutable OpCodes to process\n * @param lView Current `LView`\n * @param anchorRNode place where the i18n node should be inserted.\n */\nexport function applyMutableOpCodes(\n tView: TView, mutableOpCodes: IcuCreateOpCodes, lView: LView, anchorRNode: RNode): void {\n ngDevMode && assertDomNode(anchorRNode);\n const renderer = lView[RENDERER];\n // `rootIdx` represents the node into which all inserts happen.\n let rootIdx: number|null = null;\n // `rootRNode` represents the real node into which we insert. This can be different from\n // `lView[rootIdx]` if we have projection.\n // - null we don't have a parent (as can be the case in when we are inserting into a root of\n // LView which has no parent.)\n // - `RElement` The element representing the root after taking projection into account.\n let rootRNode!: RElement|null;\n for (let i = 0; i < mutableOpCodes.length; i++) {\n const opCode = mutableOpCodes[i];\n if (typeof opCode == 'string') {\n const textNodeIndex = mutableOpCodes[++i] as number;\n if (lView[textNodeIndex] === null) {\n ngDevMode && ngDevMode.rendererCreateTextNode++;\n ngDevMode && assertIndexInRange(lView, textNodeIndex);\n lView[textNodeIndex] = createTextNode(renderer, opCode);\n }\n } else if (typeof opCode == 'number') {\n switch (opCode & IcuCreateOpCode.MASK_INSTRUCTION) {\n case IcuCreateOpCode.AppendChild:\n const parentIdx = getParentFromIcuCreateOpCode(opCode);\n if (rootIdx === null) {\n // The first operation should save the `rootIdx` because the first operation\n // must insert into the root. (Only subsequent operations can insert into a dynamic\n // parent)\n rootIdx = parentIdx;\n rootRNode = nativeParentNode(renderer, anchorRNode);\n }\n let insertInFrontOf: RNode|null;\n let parentRNode: RElement|null;\n if (parentIdx === rootIdx) {\n insertInFrontOf = anchorRNode;\n parentRNode = rootRNode;\n } else {\n insertInFrontOf = null;\n parentRNode = unwrapRNode(lView[parentIdx]) as RElement;\n }\n // FIXME(misko): Refactor with `processI18nText`\n if (parentRNode !== null) {\n // This can happen if the `LView` we are adding to is not attached to a parent `LView`.\n // In such a case there is no \"root\" we can attach to. This is fine, as we still need to\n // create the elements. When the `LView` gets later added to a parent these \"root\" nodes\n // get picked up and added.\n ngDevMode && assertDomNode(parentRNode);\n const refIdx = getRefFromIcuCreateOpCode(opCode);\n ngDevMode && assertGreaterThan(refIdx, HEADER_OFFSET, 'Missing ref');\n // `unwrapRNode` is not needed here as all of these point to RNodes as part of the i18n\n // which can't have components.\n const child = lView[refIdx] as RElement;\n ngDevMode && assertDomNode(child);\n nativeInsertBefore(renderer, parentRNode, child, insertInFrontOf, false);\n const tIcu = getTIcu(tView, refIdx);\n if (tIcu !== null && typeof tIcu === 'object') {\n // If we just added a comment node which has ICU then that ICU may have already been\n // rendered and therefore we need to re-add it here.\n ngDevMode && assertTIcu(tIcu);\n const caseIndex = getCurrentICUCaseIndex(tIcu, lView);\n if (caseIndex !== null) {\n applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, lView[tIcu.anchorIdx]);\n }\n }\n }\n break;\n case IcuCreateOpCode.Attr:\n const elementNodeIndex = opCode >>> IcuCreateOpCode.SHIFT_REF;\n const attrName = mutableOpCodes[++i] as string;\n const attrValue = mutableOpCodes[++i] as string;\n // This code is used for ICU expressions only, since we don't support\n // directives/components in ICUs, we don't need to worry about inputs here\n setElementAttribute(\n renderer, getNativeByIndex(elementNodeIndex, lView) as RElement, null, null, attrName,\n attrValue, null);\n break;\n default:\n if (ngDevMode) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_I18N_STRUCTURE,\n `Unable to determine the type of mutate operation for \"${opCode}\"`);\n }\n }\n } else {\n switch (opCode) {\n case ICU_MARKER:\n const commentValue = mutableOpCodes[++i] as string;\n const commentNodeIndex = mutableOpCodes[++i] as number;\n if (lView[commentNodeIndex] === null) {\n ngDevMode &&\n assertEqual(\n typeof commentValue, 'string',\n `Expected \"${commentValue}\" to be a comment node value`);\n ngDevMode && ngDevMode.rendererCreateComment++;\n ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex);\n const commentRNode = lView[commentNodeIndex] =\n createCommentNode(renderer, commentValue);\n // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)\n attachPatchData(commentRNode, lView);\n }\n break;\n case ELEMENT_MARKER:\n const tagName = mutableOpCodes[++i] as string;\n const elementNodeIndex = mutableOpCodes[++i] as number;\n if (lView[elementNodeIndex] === null) {\n ngDevMode &&\n assertEqual(\n typeof tagName, 'string',\n `Expected \"${tagName}\" to be an element node tag name`);\n\n ngDevMode && ngDevMode.rendererCreateElement++;\n ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex);\n const elementRNode = lView[elementNodeIndex] =\n createElementNode(renderer, tagName, null);\n // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)\n attachPatchData(elementRNode, lView);\n }\n break;\n default:\n ngDevMode &&\n throwError(`Unable to determine the type of mutate operation for \"${opCode}\"`);\n }\n }\n }\n}\n\n\n/**\n * Apply `I18nUpdateOpCodes` OpCodes\n *\n * @param tView Current `TView`\n * @param lView Current `LView`\n * @param updateOpCodes OpCodes to process\n * @param bindingsStartIndex Location of the first `ɵɵi18nApply`\n * @param changeMask Each bit corresponds to a `ɵɵi18nExp` (Counting backwards from\n * `bindingsStartIndex`)\n */\nexport function applyUpdateOpCodes(\n tView: TView, lView: LView, updateOpCodes: I18nUpdateOpCodes, bindingsStartIndex: number,\n changeMask: number) {\n for (let i = 0; i < updateOpCodes.length; i++) {\n // bit code to check if we should apply the next update\n const checkBit = updateOpCodes[i] as number;\n // Number of opCodes to skip until next set of update codes\n const skipCodes = updateOpCodes[++i] as number;\n if (checkBit & changeMask) {\n // The value has been updated since last checked\n let value = '';\n for (let j = i + 1; j <= (i + skipCodes); j++) {\n const opCode = updateOpCodes[j];\n if (typeof opCode == 'string') {\n value += opCode;\n } else if (typeof opCode == 'number') {\n if (opCode < 0) {\n // Negative opCode represent `i18nExp` values offset.\n value += renderStringify(lView[bindingsStartIndex - opCode]);\n } else {\n const nodeIndex = (opCode >>> I18nUpdateOpCode.SHIFT_REF);\n switch (opCode & I18nUpdateOpCode.MASK_OPCODE) {\n case I18nUpdateOpCode.Attr:\n const propName = updateOpCodes[++j] as string;\n const sanitizeFn = updateOpCodes[++j] as SanitizerFn | null;\n const tNodeOrTagName = tView.data[nodeIndex] as TNode | string;\n ngDevMode && assertDefined(tNodeOrTagName, 'Experting TNode or string');\n if (typeof tNodeOrTagName === 'string') {\n // IF we don't have a `TNode`, then we are an element in ICU (as ICU content does\n // not have TNode), in which case we know that there are no directives, and hence\n // we use attribute setting.\n setElementAttribute(\n lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value,\n sanitizeFn);\n } else {\n elementPropertyInternal(\n tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn,\n false);\n }\n break;\n case I18nUpdateOpCode.Text:\n const rText = lView[nodeIndex] as RText | null;\n rText !== null && updateTextNode(lView[RENDERER], rText, value);\n break;\n case I18nUpdateOpCode.IcuSwitch:\n applyIcuSwitchCase(tView, getTIcu(tView, nodeIndex)!, lView, value);\n break;\n case I18nUpdateOpCode.IcuUpdate:\n applyIcuUpdateCase(tView, getTIcu(tView, nodeIndex)!, bindingsStartIndex, lView);\n break;\n }\n }\n }\n }\n } else {\n const opCode = updateOpCodes[i + 1] as number;\n if (opCode > 0 && (opCode & I18nUpdateOpCode.MASK_OPCODE) === I18nUpdateOpCode.IcuUpdate) {\n // Special case for the `icuUpdateCase`. It could be that the mask did not match, but\n // we still need to execute `icuUpdateCase` because the case has changed recently due to\n // previous `icuSwitchCase` instruction. (`icuSwitchCase` and `icuUpdateCase` always come in\n // pairs.)\n const nodeIndex = (opCode >>> I18nUpdateOpCode.SHIFT_REF);\n const tIcu = getTIcu(tView, nodeIndex)!;\n const currentIndex = lView[tIcu.currentCaseLViewIndex];\n if (currentIndex < 0) {\n applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView);\n }\n }\n }\n i += skipCodes;\n }\n}\n\n/**\n * Apply OpCodes associated with updating an existing ICU.\n *\n * @param tView Current `TView`\n * @param tIcu Current `TIcu`\n * @param bindingsStartIndex Location of the first `ɵɵi18nApply`\n * @param lView Current `LView`\n */\nfunction applyIcuUpdateCase(tView: TView, tIcu: TIcu, bindingsStartIndex: number, lView: LView) {\n ngDevMode && assertIndexInRange(lView, tIcu.currentCaseLViewIndex);\n let activeCaseIndex = lView[tIcu.currentCaseLViewIndex];\n if (activeCaseIndex !== null) {\n let mask = changeMask;\n if (activeCaseIndex < 0) {\n // Clear the flag.\n // Negative number means that the ICU was freshly created and we need to force the update.\n activeCaseIndex = lView[tIcu.currentCaseLViewIndex] = ~activeCaseIndex;\n // -1 is same as all bits on, which simulates creation since it marks all bits dirty\n mask = -1;\n }\n applyUpdateOpCodes(tView, lView, tIcu.update[activeCaseIndex], bindingsStartIndex, mask);\n }\n}\n\n/**\n * Apply OpCodes associated with switching a case on ICU.\n *\n * This involves tearing down existing case and than building up a new case.\n *\n * @param tView Current `TView`\n * @param tIcu Current `TIcu`\n * @param lView Current `LView`\n * @param value Value of the case to update to.\n */\nfunction applyIcuSwitchCase(tView: TView, tIcu: TIcu, lView: LView, value: string) {\n // Rebuild a new case for this ICU\n const caseIndex = getCaseIndex(tIcu, value);\n let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);\n if (activeCaseIndex !== caseIndex) {\n applyIcuSwitchCaseRemove(tView, tIcu, lView);\n lView[tIcu.currentCaseLViewIndex] = caseIndex === null ? null : ~caseIndex;\n if (caseIndex !== null) {\n // Add the nodes for the new case\n const anchorRNode = lView[tIcu.anchorIdx];\n if (anchorRNode) {\n ngDevMode && assertDomNode(anchorRNode);\n applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, anchorRNode);\n }\n }\n }\n}\n\n/**\n * Apply OpCodes associated with tearing ICU case.\n *\n * This involves tearing down existing case and than building up a new case.\n *\n * @param tView Current `TView`\n * @param tIcu Current `TIcu`\n * @param lView Current `LView`\n */\nfunction applyIcuSwitchCaseRemove(tView: TView, tIcu: TIcu, lView: LView) {\n let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);\n if (activeCaseIndex !== null) {\n const removeCodes = tIcu.remove[activeCaseIndex];\n for (let i = 0; i < removeCodes.length; i++) {\n const nodeOrIcuIndex = removeCodes[i] as number;\n if (nodeOrIcuIndex > 0) {\n // Positive numbers are `RNode`s.\n const rNode = getNativeByIndex(nodeOrIcuIndex, lView);\n rNode !== null && nativeRemoveNode(lView[RENDERER], rNode);\n } else {\n // Negative numbers are ICUs\n applyIcuSwitchCaseRemove(tView, getTIcu(tView, ~nodeOrIcuIndex)!, lView);\n }\n }\n }\n}\n\n\n/**\n * Returns the index of the current case of an ICU expression depending on the main binding value\n *\n * @param icuExpression\n * @param bindingValue The value of the main binding used by this ICU expression\n */\nfunction getCaseIndex(icuExpression: TIcu, bindingValue: string): number|null {\n let index = icuExpression.cases.indexOf(bindingValue);\n if (index === -1) {\n switch (icuExpression.type) {\n case IcuType.plural: {\n const resolvedCase = getPluralCase(bindingValue, getLocaleId());\n index = icuExpression.cases.indexOf(resolvedCase);\n if (index === -1 && resolvedCase !== 'other') {\n index = icuExpression.cases.indexOf('other');\n }\n break;\n }\n case IcuType.select: {\n index = icuExpression.cases.indexOf('other');\n break;\n }\n }\n }\n return index === -1 ? null : index;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertDomNode, assertNumber, assertNumberInRange} from '../../util/assert';\nimport {EMPTY_ARRAY} from '../../util/empty';\nimport {assertTIcu, assertTNodeForLView} from '../assert';\nimport {getCurrentICUCaseIndex} from '../i18n/i18n_util';\nimport {I18nRemoveOpCodes, TIcu} from '../interfaces/i18n';\nimport {TIcuContainerNode} from '../interfaces/node';\nimport {RNode} from '../interfaces/renderer_dom';\nimport {LView, TVIEW} from '../interfaces/view';\n\nexport function loadIcuContainerVisitor() {\n const _stack: any[] = [];\n let _index: number = -1;\n let _lView: LView;\n let _removes: I18nRemoveOpCodes;\n\n /**\n * Retrieves a set of root nodes from `TIcu.remove`. Used by `TNodeType.ICUContainer`\n * to determine which root belong to the ICU.\n *\n * Example of usage.\n * ```\n * const nextRNode = icuContainerIteratorStart(tIcuContainerNode, lView);\n * let rNode: RNode|null;\n * while(rNode = nextRNode()) {\n * console.log(rNode);\n * }\n * ```\n *\n * @param tIcuContainerNode Current `TIcuContainerNode`\n * @param lView `LView` where the `RNode`s should be looked up.\n */\n function icuContainerIteratorStart(tIcuContainerNode: TIcuContainerNode, lView: LView): () =>\n RNode | null {\n _lView = lView;\n while (_stack.length) _stack.pop();\n ngDevMode && assertTNodeForLView(tIcuContainerNode, lView);\n enterIcu(tIcuContainerNode.value, lView);\n return icuContainerIteratorNext;\n }\n\n function enterIcu(tIcu: TIcu, lView: LView) {\n _index = 0;\n const currentCase = getCurrentICUCaseIndex(tIcu, lView);\n if (currentCase !== null) {\n ngDevMode && assertNumberInRange(currentCase, 0, tIcu.cases.length - 1);\n _removes = tIcu.remove[currentCase];\n } else {\n _removes = EMPTY_ARRAY as any;\n }\n }\n\n\n function icuContainerIteratorNext(): RNode|null {\n if (_index < _removes.length) {\n const removeOpCode = _removes[_index++] as number;\n ngDevMode && assertNumber(removeOpCode, 'Expecting OpCode number');\n if (removeOpCode > 0) {\n const rNode = _lView[removeOpCode];\n ngDevMode && assertDomNode(rNode);\n return rNode;\n } else {\n _stack.push(_index, _removes);\n // ICUs are represented by negative indices\n const tIcuIndex = ~removeOpCode;\n const tIcu = _lView[TVIEW].data[tIcuIndex] as TIcu;\n ngDevMode && assertTIcu(tIcu);\n enterIcu(tIcu, _lView);\n return icuContainerIteratorNext();\n }\n } else {\n if (_stack.length === 0) {\n return null;\n } else {\n _removes = _stack.pop();\n _index = _stack.pop();\n return icuContainerIteratorNext();\n }\n }\n }\n\n return icuContainerIteratorStart;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport '../../util/ng_dev_mode';\nimport '../../util/ng_i18n_closure_mode';\n\nimport {XSS_SECURITY_URL} from '../../error_details_base_url';\nimport {getTemplateContent, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS} from '../../sanitization/html_sanitizer';\nimport {getInertBodyHelper} from '../../sanitization/inert_body';\nimport {_sanitizeUrl} from '../../sanitization/url_sanitizer';\nimport {assertDefined, assertEqual, assertGreaterThanOrEqual, assertOneOf, assertString} from '../../util/assert';\nimport {CharCode} from '../../util/char_code';\nimport {loadIcuContainerVisitor} from '../instructions/i18n_icu_container_visitor';\nimport {allocExpando, createTNodeAtIndex} from '../instructions/shared';\nimport {getDocument} from '../interfaces/document';\nimport {ELEMENT_MARKER, I18nCreateOpCode, I18nCreateOpCodes, I18nRemoveOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, ICU_MARKER, IcuCreateOpCode, IcuCreateOpCodes, IcuExpression, IcuType, TI18n, TIcu} from '../interfaces/i18n';\nimport {TNode, TNodeType} from '../interfaces/node';\nimport {SanitizerFn} from '../interfaces/sanitization';\nimport {HEADER_OFFSET, LView, TView} from '../interfaces/view';\nimport {getCurrentParentTNode, getCurrentTNode, setCurrentTNode} from '../state';\n\nimport {i18nCreateOpCodesToString, i18nRemoveOpCodesToString, i18nUpdateOpCodesToString, icuCreateOpCodesToString} from './i18n_debug';\nimport {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';\nimport {ensureIcuContainerVisitorLoaded} from './i18n_tree_shaking';\nimport {createTNodePlaceholder, icuCreateOpCode, setTIcu, setTNodeInsertBeforeIndex} from './i18n_util';\n\n\n\nconst BINDING_REGEXP = /�(\\d+):?\\d*�/gi;\nconst ICU_REGEXP = /({\\s*�\\d+:?\\d*�\\s*,\\s*\\S{6}\\s*,[\\s\\S]*})/gi;\nconst NESTED_ICU = /�(\\d+)�/;\nconst ICU_BLOCK_REGEXP = /^\\s*(�\\d+:?\\d*�)\\s*,\\s*(select|plural)\\s*,/;\n\nconst MARKER = `�`;\nconst SUBTEMPLATE_REGEXP = /�\\/?\\*(\\d+:\\d+)�/gi;\nconst PH_REGEXP = /�(\\/?[#*]\\d+):?\\d*�/gi;\n\n/**\n * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:\n * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32\n * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character\n * and later on replaced by a space. We are re-implementing the same idea here, since translations\n * might contain this special character.\n */\nconst NGSP_UNICODE_REGEXP = /\\uE500/g;\nfunction replaceNgsp(value: string): string {\n return value.replace(NGSP_UNICODE_REGEXP, ' ');\n}\n\n/**\n * Patch a `debug` property getter on top of the existing object.\n *\n * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`\n *\n * @param obj Object to patch\n * @param debugGetter Getter returning a value to patch\n */\nfunction attachDebugGetter<T>(obj: T, debugGetter: (this: T) => any): void {\n if (ngDevMode) {\n Object.defineProperty(obj, 'debug', {get: debugGetter, enumerable: false});\n } else {\n throw new Error(\n 'This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');\n }\n}\n\n/**\n * Create dynamic nodes from i18n translation block.\n *\n * - Text nodes are created synchronously\n * - TNodes are linked into tree lazily\n *\n * @param tView Current `TView`\n * @parentTNodeIndex index to the parent TNode of this i18n block\n * @param lView Current `LView`\n * @param index Index of `ɵɵi18nStart` instruction.\n * @param message Message to translate.\n * @param subTemplateIndex Index into the sub template of message translation. (ie in case of\n * `ngIf`) (-1 otherwise)\n */\nexport function i18nStartFirstCreatePass(\n tView: TView, parentTNodeIndex: number, lView: LView, index: number, message: string,\n subTemplateIndex: number) {\n const rootTNode = getCurrentParentTNode();\n const createOpCodes: I18nCreateOpCodes = [] as any;\n const updateOpCodes: I18nUpdateOpCodes = [] as any;\n const existingTNodeStack: TNode[][] = [[]];\n if (ngDevMode) {\n attachDebugGetter(createOpCodes, i18nCreateOpCodesToString);\n attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);\n }\n\n message = getTranslationForTemplate(message, subTemplateIndex);\n const msgParts = replaceNgsp(message).split(PH_REGEXP);\n for (let i = 0; i < msgParts.length; i++) {\n let value = msgParts[i];\n if ((i & 1) === 0) {\n // Even indexes are text (including bindings & ICU expressions)\n const parts = i18nParseTextIntoPartsAndICU(value);\n for (let j = 0; j < parts.length; j++) {\n let part = parts[j];\n if ((j & 1) === 0) {\n // `j` is odd therefore `part` is string\n const text = part as string;\n ngDevMode && assertString(text, 'Parsed ICU part should be string');\n if (text !== '') {\n i18nStartFirstCreatePassProcessTextNode(\n tView, rootTNode, existingTNodeStack[0], createOpCodes, updateOpCodes, lView, text);\n }\n } else {\n // `j` is Even therefor `part` is an `ICUExpression`\n const icuExpression: IcuExpression = part as IcuExpression;\n // Verify that ICU expression has the right shape. Translations might contain invalid\n // constructions (while original messages were correct), so ICU parsing at runtime may\n // not succeed (thus `icuExpression` remains a string).\n // Note: we intentionally retain the error here by not using `ngDevMode`, because\n // the value can change based on the locale and users aren't guaranteed to hit\n // an invalid string while they're developing.\n if (typeof icuExpression !== 'object') {\n throw new Error(`Unable to parse ICU expression in \"${message}\" message.`);\n }\n const icuContainerTNode = createTNodeAndAddOpCode(\n tView, rootTNode, existingTNodeStack[0], lView, createOpCodes,\n ngDevMode ? `ICU ${index}:${icuExpression.mainBinding}` : '', true);\n const icuNodeIndex = icuContainerTNode.index;\n ngDevMode &&\n assertGreaterThanOrEqual(\n icuNodeIndex, HEADER_OFFSET, 'Index must be in absolute LView offset');\n icuStart(tView, lView, updateOpCodes, parentTNodeIndex, icuExpression, icuNodeIndex);\n }\n }\n } else {\n // Odd indexes are placeholders (elements and sub-templates)\n // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�')\n const isClosing = value.charCodeAt(0) === CharCode.SLASH;\n const type = value.charCodeAt(isClosing ? 1 : 0);\n ngDevMode && assertOneOf(type, CharCode.STAR, CharCode.HASH);\n const index = HEADER_OFFSET + Number.parseInt(value.substring((isClosing ? 2 : 1)));\n if (isClosing) {\n existingTNodeStack.shift();\n setCurrentTNode(getCurrentParentTNode()!, false);\n } else {\n const tNode = createTNodePlaceholder(tView, existingTNodeStack[0], index);\n existingTNodeStack.unshift([]);\n setCurrentTNode(tNode, true);\n }\n }\n }\n\n tView.data[index] = <TI18n>{\n create: createOpCodes,\n update: updateOpCodes,\n };\n}\n\n/**\n * Allocate space in i18n Range add create OpCode instruction to create a text or comment node.\n *\n * @param tView Current `TView` needed to allocate space in i18n range.\n * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will be\n * added as part of the `i18nStart` instruction or as part of the `TNode.insertBeforeIndex`.\n * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.\n * @param lView Current `LView` needed to allocate space in i18n range.\n * @param createOpCodes Array storing `I18nCreateOpCodes` where new opCodes will be added.\n * @param text Text to be added when the `Text` or `Comment` node will be created.\n * @param isICU true if a `Comment` node for ICU (instead of `Text`) node should be created.\n */\nfunction createTNodeAndAddOpCode(\n tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], lView: LView,\n createOpCodes: I18nCreateOpCodes, text: string|null, isICU: boolean): TNode {\n const i18nNodeIdx = allocExpando(tView, lView, 1, null);\n let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;\n let parentTNode = getCurrentParentTNode();\n\n if (rootTNode === parentTNode) {\n // FIXME(misko): A null `parentTNode` should represent when we fall of the `LView` boundary.\n // (there is no parent), but in some circumstances (because we are inconsistent about how we set\n // `previousOrParentTNode`) it could point to `rootTNode` So this is a work around.\n parentTNode = null;\n }\n if (parentTNode === null) {\n // If we don't have a parent that means that we can eagerly add nodes.\n // If we have a parent than these nodes can't be added now (as the parent has not been created\n // yet) and instead the `parentTNode` is responsible for adding it. See\n // `TNode.insertBeforeIndex`\n opCode |= I18nCreateOpCode.APPEND_EAGERLY;\n }\n if (isICU) {\n opCode |= I18nCreateOpCode.COMMENT;\n ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);\n }\n createOpCodes.push(opCode, text === null ? '' : text);\n // We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the\n // bindings are.\n const tNode = createTNodeAtIndex(\n tView, i18nNodeIdx, isICU ? TNodeType.Icu : TNodeType.Text,\n text === null ? (ngDevMode ? '{{?}}' : '') : text, null);\n addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);\n const tNodeIdx = tNode.index;\n setCurrentTNode(tNode, false /* Text nodes are self closing */);\n if (parentTNode !== null && rootTNode !== parentTNode) {\n // We are a child of deeper node (rather than a direct child of `i18nStart` instruction.)\n // We have to make sure to add ourselves to the parent.\n setTNodeInsertBeforeIndex(parentTNode, tNodeIdx);\n }\n return tNode;\n}\n\n/**\n * Processes text node in i18n block.\n *\n * Text nodes can have:\n * - Create instruction in `createOpCodes` for creating the text node.\n * - Allocate spec for text node in i18n range of `LView`\n * - If contains binding:\n * - bindings => allocate space in i18n range of `LView` to store the binding value.\n * - populate `updateOpCodes` with update instructions.\n *\n * @param tView Current `TView`\n * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will\n * be added as part of the `i18nStart` instruction or as part of the\n * `TNode.insertBeforeIndex`.\n * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.\n * @param createOpCodes Location where the creation OpCodes will be stored.\n * @param lView Current `LView`\n * @param text The translated text (which may contain binding)\n */\nfunction i18nStartFirstCreatePassProcessTextNode(\n tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], createOpCodes: I18nCreateOpCodes,\n updateOpCodes: I18nUpdateOpCodes, lView: LView, text: string): void {\n const hasBinding = text.match(BINDING_REGEXP);\n const tNode = createTNodeAndAddOpCode(\n tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);\n if (hasBinding) {\n generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index, null, 0, null);\n }\n}\n\n/**\n * See `i18nAttributes` above.\n */\nexport function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) {\n const previousElement = getCurrentTNode()!;\n const previousElementIndex = previousElement.index;\n const updateOpCodes: I18nUpdateOpCodes = [] as any;\n if (ngDevMode) {\n attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);\n }\n if (tView.firstCreatePass && tView.data[index] === null) {\n for (let i = 0; i < values.length; i += 2) {\n const attrName = values[i];\n const message = values[i + 1];\n\n if (message !== '') {\n // Check if attribute value contains an ICU and throw an error if that's the case.\n // ICUs in element attributes are not supported.\n // Note: we intentionally retain the error here by not using `ngDevMode`, because\n // the `value` can change based on the locale and users aren't guaranteed to hit\n // an invalid string while they're developing.\n if (ICU_REGEXP.test(message)) {\n throw new Error(\n `ICU expressions are not supported in attributes. Message: \"${message}\".`);\n }\n\n // i18n attributes that hit this code path are guaranteed to have bindings, because\n // the compiler treats static i18n attributes as regular attribute bindings.\n // Since this may not be the first i18n attribute on this element we need to pass in how\n // many previous bindings there have already been.\n generateBindingUpdateOpCodes(\n updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes),\n null);\n }\n }\n tView.data[index] = updateOpCodes;\n }\n}\n\n\n/**\n * Generate the OpCodes to update the bindings of a string.\n *\n * @param updateOpCodes Place where the update opcodes will be stored.\n * @param str The string containing the bindings.\n * @param destinationNode Index of the destination node which will receive the binding.\n * @param attrName Name of the attribute, if the string belongs to an attribute.\n * @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary.\n * @param bindingStart The lView index of the next expression that can be bound via an opCode.\n * @returns The mask value for these bindings\n */\nfunction generateBindingUpdateOpCodes(\n updateOpCodes: I18nUpdateOpCodes, str: string, destinationNode: number, attrName: string|null,\n bindingStart: number, sanitizeFn: SanitizerFn|null): number {\n ngDevMode &&\n assertGreaterThanOrEqual(\n destinationNode, HEADER_OFFSET, 'Index must be in absolute LView offset');\n const maskIndex = updateOpCodes.length; // Location of mask\n const sizeIndex = maskIndex + 1; // location of size for skipping\n updateOpCodes.push(null, null); // Alloc space for mask and size\n const startIndex = maskIndex + 2; // location of first allocation.\n if (ngDevMode) {\n attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);\n }\n const textParts = str.split(BINDING_REGEXP);\n let mask = 0;\n\n for (let j = 0; j < textParts.length; j++) {\n const textValue = textParts[j];\n\n if (j & 1) {\n // Odd indexes are bindings\n const bindingIndex = bindingStart + parseInt(textValue, 10);\n updateOpCodes.push(-1 - bindingIndex);\n mask = mask | toMaskBit(bindingIndex);\n } else if (textValue !== '') {\n // Even indexes are text\n updateOpCodes.push(textValue);\n }\n }\n\n updateOpCodes.push(\n destinationNode << I18nUpdateOpCode.SHIFT_REF |\n (attrName ? I18nUpdateOpCode.Attr : I18nUpdateOpCode.Text));\n if (attrName) {\n updateOpCodes.push(attrName, sanitizeFn);\n }\n updateOpCodes[maskIndex] = mask;\n updateOpCodes[sizeIndex] = updateOpCodes.length - startIndex;\n return mask;\n}\n\n/**\n * Count the number of bindings in the given `opCodes`.\n *\n * It could be possible to speed this up, by passing the number of bindings found back from\n * `generateBindingUpdateOpCodes()` to `i18nAttributesFirstPass()` but this would then require more\n * complexity in the code and/or transient objects to be created.\n *\n * Since this function is only called once when the template is instantiated, is trivial in the\n * first instance (since `opCodes` will be an empty array), and it is not common for elements to\n * contain multiple i18n bound attributes, it seems like this is a reasonable compromise.\n */\nfunction countBindings(opCodes: I18nUpdateOpCodes): number {\n let count = 0;\n for (let i = 0; i < opCodes.length; i++) {\n const opCode = opCodes[i];\n // Bindings are negative numbers.\n if (typeof opCode === 'number' && opCode < 0) {\n count++;\n }\n }\n return count;\n}\n\n/**\n * Convert binding index to mask bit.\n *\n * Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make\n * the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to\n * have more than 32 bindings this will be hit very rarely. The downside of hitting this corner\n * case is that we will execute binding code more often than necessary. (penalty of performance)\n */\nfunction toMaskBit(bindingIndex: number): number {\n return 1 << Math.min(bindingIndex, 31);\n}\n\nexport function isRootTemplateMessage(subTemplateIndex: number): subTemplateIndex is - 1 {\n return subTemplateIndex === -1;\n}\n\n\n/**\n * Removes everything inside the sub-templates of a message.\n */\nfunction removeInnerTemplateTranslation(message: string): string {\n let match;\n let res = '';\n let index = 0;\n let inTemplate = false;\n let tagMatched;\n\n while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) {\n if (!inTemplate) {\n res += message.substring(index, match.index + match[0].length);\n tagMatched = match[1];\n inTemplate = true;\n } else {\n if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) {\n index = match.index;\n inTemplate = false;\n }\n }\n }\n\n ngDevMode &&\n assertEqual(\n inTemplate, false,\n `Tag mismatch: unable to find the end of the sub-template in the translation \"${\n message}\"`);\n\n res += message.slice(index);\n return res;\n}\n\n\n/**\n * Extracts a part of a message and removes the rest.\n *\n * This method is used for extracting a part of the message associated with a template. A\n * translated message can span multiple templates.\n *\n * Example:\n * ```\n * <div i18n>Translate <span *ngIf>me</span>!</div>\n * ```\n *\n * @param message The message to crop\n * @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the\n * external template and removes all sub-templates.\n */\nexport function getTranslationForTemplate(message: string, subTemplateIndex: number) {\n if (isRootTemplateMessage(subTemplateIndex)) {\n // We want the root template message, ignore all sub-templates\n return removeInnerTemplateTranslation(message);\n } else {\n // We want a specific sub-template\n const start =\n message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length;\n const end = message.search(new RegExp(`${MARKER}\\\\/\\\\*\\\\d+:${subTemplateIndex}${MARKER}`));\n return removeInnerTemplateTranslation(message.substring(start, end));\n }\n}\n\n/**\n * Generate the OpCodes for ICU expressions.\n *\n * @param icuExpression\n * @param index Index where the anchor is stored and an optional `TIcuContainerNode`\n * - `lView[anchorIdx]` points to a `Comment` node representing the anchor for the ICU.\n * - `tView.data[anchorIdx]` points to the `TIcuContainerNode` if ICU is root (`null` otherwise)\n */\nexport function icuStart(\n tView: TView, lView: LView, updateOpCodes: I18nUpdateOpCodes, parentIdx: number,\n icuExpression: IcuExpression, anchorIdx: number) {\n ngDevMode && assertDefined(icuExpression, 'ICU expression must be defined');\n let bindingMask = 0;\n const tIcu: TIcu = {\n type: icuExpression.type,\n currentCaseLViewIndex: allocExpando(tView, lView, 1, null),\n anchorIdx,\n cases: [],\n create: [],\n remove: [],\n update: []\n };\n addUpdateIcuSwitch(updateOpCodes, icuExpression, anchorIdx);\n setTIcu(tView, anchorIdx, tIcu);\n const values = icuExpression.values;\n for (let i = 0; i < values.length; i++) {\n // Each value is an array of strings & other ICU expressions\n const valueArr = values[i];\n const nestedIcus: IcuExpression[] = [];\n for (let j = 0; j < valueArr.length; j++) {\n const value = valueArr[j];\n if (typeof value !== 'string') {\n // It is an nested ICU expression\n const icuIndex = nestedIcus.push(value as IcuExpression) - 1;\n // Replace nested ICU expression by a comment node\n valueArr[j] = `<!--�${icuIndex}�-->`;\n }\n }\n bindingMask = parseIcuCase(\n tView, tIcu, lView, updateOpCodes, parentIdx, icuExpression.cases[i],\n valueArr.join(''), nestedIcus) |\n bindingMask;\n }\n if (bindingMask) {\n addUpdateIcuUpdate(updateOpCodes, bindingMask, anchorIdx);\n }\n}\n\n/**\n * Parses text containing an ICU expression and produces a JSON object for it.\n * Original code from closure library, modified for Angular.\n *\n * @param pattern Text containing an ICU expression that needs to be parsed.\n *\n */\nexport function parseICUBlock(pattern: string): IcuExpression {\n const cases = [];\n const values: (string|IcuExpression)[][] = [];\n let icuType = IcuType.plural;\n let mainBinding = 0;\n pattern = pattern.replace(ICU_BLOCK_REGEXP, function(str: string, binding: string, type: string) {\n if (type === 'select') {\n icuType = IcuType.select;\n } else {\n icuType = IcuType.plural;\n }\n mainBinding = parseInt(binding.slice(1), 10);\n return '';\n });\n\n const parts = i18nParseTextIntoPartsAndICU(pattern) as string[];\n // Looking for (key block)+ sequence. One of the keys has to be \"other\".\n for (let pos = 0; pos < parts.length;) {\n let key = parts[pos++].trim();\n if (icuType === IcuType.plural) {\n // Key can be \"=x\", we just want \"x\"\n key = key.replace(/\\s*(?:=)?(\\w+)\\s*/, '$1');\n }\n if (key.length) {\n cases.push(key);\n }\n\n const blocks = i18nParseTextIntoPartsAndICU(parts[pos++]) as string[];\n if (cases.length > values.length) {\n values.push(blocks);\n }\n }\n\n // TODO(ocombe): support ICU expressions in attributes, see #21615\n return {type: icuType, mainBinding: mainBinding, cases, values};\n}\n\n\n/**\n * Breaks pattern into strings and top level {...} blocks.\n * Can be used to break a message into text and ICU expressions, or to break an ICU expression\n * into keys and cases. Original code from closure library, modified for Angular.\n *\n * @param pattern (sub)Pattern to be broken.\n * @returns An `Array<string|IcuExpression>` where:\n * - odd positions: `string` => text between ICU expressions\n * - even positions: `ICUExpression` => ICU expression parsed into `ICUExpression` record.\n */\nexport function i18nParseTextIntoPartsAndICU(pattern: string): (string|IcuExpression)[] {\n if (!pattern) {\n return [];\n }\n\n let prevPos = 0;\n const braceStack = [];\n const results: (string|IcuExpression)[] = [];\n const braces = /[{}]/g;\n // lastIndex doesn't get set to 0 so we have to.\n braces.lastIndex = 0;\n\n let match;\n while (match = braces.exec(pattern)) {\n const pos = match.index;\n if (match[0] == '}') {\n braceStack.pop();\n\n if (braceStack.length == 0) {\n // End of the block.\n const block = pattern.substring(prevPos, pos);\n if (ICU_BLOCK_REGEXP.test(block)) {\n results.push(parseICUBlock(block));\n } else {\n results.push(block);\n }\n\n prevPos = pos + 1;\n }\n } else {\n if (braceStack.length == 0) {\n const substring = pattern.substring(prevPos, pos);\n results.push(substring);\n prevPos = pos + 1;\n }\n braceStack.push('{');\n }\n }\n\n const substring = pattern.substring(prevPos);\n results.push(substring);\n return results;\n}\n\n\n/**\n * Parses a node, its children and its siblings, and generates the mutate & update OpCodes.\n *\n */\nexport function parseIcuCase(\n tView: TView, tIcu: TIcu, lView: LView, updateOpCodes: I18nUpdateOpCodes, parentIdx: number,\n caseName: string, unsafeCaseHtml: string, nestedIcus: IcuExpression[]): number {\n const create: IcuCreateOpCodes = [] as any;\n const remove: I18nRemoveOpCodes = [] as any;\n const update: I18nUpdateOpCodes = [] as any;\n if (ngDevMode) {\n attachDebugGetter(create, icuCreateOpCodesToString);\n attachDebugGetter(remove, i18nRemoveOpCodesToString);\n attachDebugGetter(update, i18nUpdateOpCodesToString);\n }\n tIcu.cases.push(caseName);\n tIcu.create.push(create);\n tIcu.remove.push(remove);\n tIcu.update.push(update);\n\n const inertBodyHelper = getInertBodyHelper(getDocument());\n const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeCaseHtml);\n ngDevMode && assertDefined(inertBodyElement, 'Unable to generate inert body element');\n const inertRootNode = getTemplateContent(inertBodyElement!) as Element || inertBodyElement;\n if (inertRootNode) {\n return walkIcuTree(\n tView, tIcu, lView, updateOpCodes, create, remove, update, inertRootNode, parentIdx,\n nestedIcus, 0);\n } else {\n return 0;\n }\n}\n\nfunction walkIcuTree(\n tView: TView, tIcu: TIcu, lView: LView, sharedUpdateOpCodes: I18nUpdateOpCodes,\n create: IcuCreateOpCodes, remove: I18nRemoveOpCodes, update: I18nUpdateOpCodes,\n parentNode: Element, parentIdx: number, nestedIcus: IcuExpression[], depth: number): number {\n let bindingMask = 0;\n let currentNode = parentNode.firstChild;\n while (currentNode) {\n const newIndex = allocExpando(tView, lView, 1, null);\n switch (currentNode.nodeType) {\n case Node.ELEMENT_NODE:\n const element = currentNode as Element;\n const tagName = element.tagName.toLowerCase();\n if (VALID_ELEMENTS.hasOwnProperty(tagName)) {\n addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex);\n tView.data[newIndex] = tagName;\n const elAttrs = element.attributes;\n for (let i = 0; i < elAttrs.length; i++) {\n const attr = elAttrs.item(i)!;\n const lowerAttrName = attr.name.toLowerCase();\n const hasBinding = !!attr.value.match(BINDING_REGEXP);\n // we assume the input string is safe, unless it's using a binding\n if (hasBinding) {\n if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {\n if (URI_ATTRS[lowerAttrName]) {\n generateBindingUpdateOpCodes(\n update, attr.value, newIndex, attr.name, 0, _sanitizeUrl);\n } else {\n generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, null);\n }\n } else {\n ngDevMode &&\n console.warn(\n `WARNING: ignoring unsafe attribute value ` +\n `${lowerAttrName} on element ${tagName} ` +\n `(see ${XSS_SECURITY_URL})`);\n }\n } else {\n addCreateAttribute(create, newIndex, attr);\n }\n }\n // Parse the children of this node (if any)\n bindingMask = walkIcuTree(\n tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update,\n currentNode as Element, newIndex, nestedIcus, depth + 1) |\n bindingMask;\n addRemoveNode(remove, newIndex, depth);\n }\n break;\n case Node.TEXT_NODE:\n const value = currentNode.textContent || '';\n const hasBinding = value.match(BINDING_REGEXP);\n addCreateNodeAndAppend(create, null, hasBinding ? '' : value, parentIdx, newIndex);\n addRemoveNode(remove, newIndex, depth);\n if (hasBinding) {\n bindingMask =\n generateBindingUpdateOpCodes(update, value, newIndex, null, 0, null) | bindingMask;\n }\n break;\n case Node.COMMENT_NODE:\n // Check if the comment node is a placeholder for a nested ICU\n const isNestedIcu = NESTED_ICU.exec(currentNode.textContent || '');\n if (isNestedIcu) {\n const nestedIcuIndex = parseInt(isNestedIcu[1], 10);\n const icuExpression: IcuExpression = nestedIcus[nestedIcuIndex];\n // Create the comment node that will anchor the ICU expression\n addCreateNodeAndAppend(\n create, ICU_MARKER, ngDevMode ? `nested ICU ${nestedIcuIndex}` : '', parentIdx,\n newIndex);\n icuStart(tView, lView, sharedUpdateOpCodes, parentIdx, icuExpression, newIndex);\n addRemoveNestedIcu(remove, newIndex, depth);\n }\n break;\n }\n currentNode = currentNode.nextSibling;\n }\n return bindingMask;\n}\n\nfunction addRemoveNode(remove: I18nRemoveOpCodes, index: number, depth: number) {\n if (depth === 0) {\n remove.push(index);\n }\n}\n\nfunction addRemoveNestedIcu(remove: I18nRemoveOpCodes, index: number, depth: number) {\n if (depth === 0) {\n remove.push(~index); // remove ICU at `index`\n remove.push(index); // remove ICU comment at `index`\n }\n}\n\nfunction addUpdateIcuSwitch(\n update: I18nUpdateOpCodes, icuExpression: IcuExpression, index: number) {\n update.push(\n toMaskBit(icuExpression.mainBinding), 2, -1 - icuExpression.mainBinding,\n index << I18nUpdateOpCode.SHIFT_REF | I18nUpdateOpCode.IcuSwitch);\n}\n\nfunction addUpdateIcuUpdate(update: I18nUpdateOpCodes, bindingMask: number, index: number) {\n update.push(bindingMask, 1, index << I18nUpdateOpCode.SHIFT_REF | I18nUpdateOpCode.IcuUpdate);\n}\n\nfunction addCreateNodeAndAppend(\n create: IcuCreateOpCodes, marker: null|ICU_MARKER|ELEMENT_MARKER, text: string,\n appendToParentIdx: number, createAtIdx: number) {\n if (marker !== null) {\n create.push(marker);\n }\n create.push(\n text, createAtIdx,\n icuCreateOpCode(IcuCreateOpCode.AppendChild, appendToParentIdx, createAtIdx));\n}\n\nfunction addCreateAttribute(create: IcuCreateOpCodes, newIndex: number, attr: Attr) {\n create.push(newIndex << IcuCreateOpCode.SHIFT_REF | IcuCreateOpCode.Attr, attr.name, attr.value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport '../../util/ng_dev_mode';\nimport '../../util/ng_i18n_closure_mode';\n\nimport {assertDefined} from '../../util/assert';\nimport {bindingUpdated} from '../bindings';\nimport {applyCreateOpCodes, applyI18n, setMaskBit} from '../i18n/i18n_apply';\nimport {i18nAttributesFirstPass, i18nStartFirstCreatePass} from '../i18n/i18n_parse';\nimport {i18nPostprocess} from '../i18n/i18n_postprocess';\nimport {TI18n} from '../interfaces/i18n';\nimport {TElementNode, TNodeType} from '../interfaces/node';\nimport {HEADER_OFFSET, T_HOST} from '../interfaces/view';\nimport {getClosestRElement} from '../node_manipulation';\nimport {getCurrentParentTNode, getLView, getTView, nextBindingIndex, setInI18nBlock} from '../state';\nimport {getConstant} from '../util/view_utils';\n\n/**\n * Marks a block of text as translatable.\n *\n * The instructions `i18nStart` and `i18nEnd` mark the translation block in the template.\n * The translation `message` is the value which is locale specific. The translation string may\n * contain placeholders which associate inner elements and sub-templates within the translation.\n *\n * The translation `message` placeholders are:\n * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be\n * interpolated into. The placeholder `index` points to the expression binding index. An optional\n * `block` that matches the sub-template in which it was declared.\n * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning\n * and end of DOM element that were embedded in the original translation block. The placeholder\n * `index` points to the element index in the template instructions set. An optional `block` that\n * matches the sub-template in which it was declared.\n * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be\n * split up and translated separately in each angular template function. The `index` points to the\n * `template` instruction index. A `block` that matches the sub-template in which it was declared.\n *\n * @param index A unique index of the translation in the static block.\n * @param messageIndex An index of the translation message from the `def.consts` array.\n * @param subTemplateIndex Optional sub-template index in the `message`.\n *\n * @codeGenApi\n */\nexport function ɵɵi18nStart(\n index: number, messageIndex: number, subTemplateIndex: number = -1): void {\n const tView = getTView();\n const lView = getLView();\n const adjustedIndex = HEADER_OFFSET + index;\n ngDevMode && assertDefined(tView, `tView should be defined`);\n const message = getConstant<string>(tView.consts, messageIndex)!;\n const parentTNode = getCurrentParentTNode() as TElementNode | null;\n if (tView.firstCreatePass) {\n i18nStartFirstCreatePass(\n tView, parentTNode === null ? 0 : parentTNode.index, lView, adjustedIndex, message,\n subTemplateIndex);\n }\n const tI18n = tView.data[adjustedIndex] as TI18n;\n const sameViewParentTNode = parentTNode === lView[T_HOST] ? null : parentTNode;\n const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);\n // If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.\n // When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.\n const insertInFrontOf = parentTNode && (parentTNode.type & TNodeType.ElementContainer) ?\n lView[parentTNode.index] :\n null;\n applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);\n setInI18nBlock(true);\n}\n\n\n\n/**\n * Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes\n * into the render tree, moves the placeholder nodes and removes the deleted nodes.\n *\n * @codeGenApi\n */\nexport function ɵɵi18nEnd(): void {\n setInI18nBlock(false);\n}\n\n/**\n *\n * Use this instruction to create a translation block that doesn't contain any placeholder.\n * It calls both {@link i18nStart} and {@link i18nEnd} in one instruction.\n *\n * The translation `message` is the value which is locale specific. The translation string may\n * contain placeholders which associate inner elements and sub-templates within the translation.\n *\n * The translation `message` placeholders are:\n * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be\n * interpolated into. The placeholder `index` points to the expression binding index. An optional\n * `block` that matches the sub-template in which it was declared.\n * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning\n * and end of DOM element that were embedded in the original translation block. The placeholder\n * `index` points to the element index in the template instructions set. An optional `block` that\n * matches the sub-template in which it was declared.\n * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be\n * split up and translated separately in each angular template function. The `index` points to the\n * `template` instruction index. A `block` that matches the sub-template in which it was declared.\n *\n * @param index A unique index of the translation in the static block.\n * @param messageIndex An index of the translation message from the `def.consts` array.\n * @param subTemplateIndex Optional sub-template index in the `message`.\n *\n * @codeGenApi\n */\nexport function ɵɵi18n(index: number, messageIndex: number, subTemplateIndex?: number): void {\n ɵɵi18nStart(index, messageIndex, subTemplateIndex);\n ɵɵi18nEnd();\n}\n\n/**\n * Marks a list of attributes as translatable.\n *\n * @param index A unique index in the static block\n * @param values\n *\n * @codeGenApi\n */\nexport function ɵɵi18nAttributes(index: number, attrsIndex: number): void {\n const tView = getTView();\n ngDevMode && assertDefined(tView, `tView should be defined`);\n const attrs = getConstant<string[]>(tView.consts, attrsIndex)!;\n i18nAttributesFirstPass(tView, index + HEADER_OFFSET, attrs);\n}\n\n\n/**\n * Stores the values of the bindings during each update cycle in order to determine if we need to\n * update the translated nodes.\n *\n * @param value The binding's value\n * @returns This function returns itself so that it may be chained\n * (e.g. `i18nExp(ctx.name)(ctx.title)`)\n *\n * @codeGenApi\n */\nexport function ɵɵi18nExp<T>(value: T): typeof ɵɵi18nExp {\n const lView = getLView();\n setMaskBit(bindingUpdated(lView, nextBindingIndex(), value));\n return ɵɵi18nExp;\n}\n\n/**\n * Updates a translation block or an i18n attribute when the bindings have changed.\n *\n * @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes}\n * (i18n attribute) on which it should update the content.\n *\n * @codeGenApi\n */\nexport function ɵɵi18nApply(index: number) {\n applyI18n(getTView(), getLView(), index + HEADER_OFFSET);\n}\n\n/**\n * Handles message string post-processing for internationalization.\n *\n * Handles message string post-processing by transforming it from intermediate\n * format (that might contain some markers that we need to replace) to the final\n * form, consumable by i18nStart instruction. Post processing steps include:\n *\n * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])\n * 2. Replace all ICU vars (like \"VAR_PLURAL\")\n * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}\n * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)\n * in case multiple ICUs have the same placeholder name\n *\n * @param message Raw translation string for post processing\n * @param replacements Set of replacements that should be applied\n *\n * @returns Transformed string that can be consumed by i18nStart instruction\n *\n * @codeGenApi\n */\nexport function ɵɵi18nPostprocess(\n message: string, replacements: {[key: string]: (string|string[])} = {}): string {\n return i18nPostprocess(message, replacements);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {resolveForwardRef} from '../di/forward_ref';\nimport {ClassProvider, Provider} from '../di/interface/provider';\nimport {isClassProvider, isTypeProvider} from '../di/provider_collection';\nimport {providerToFactory} from '../di/r3_injector';\nimport {assertDefined} from '../util/assert';\n\nimport {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from './di';\nimport {ɵɵdirectiveInject} from './instructions/all';\nimport {DirectiveDef} from './interfaces/definition';\nimport {NodeInjectorFactory} from './interfaces/injector';\nimport {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNodeProviderIndexes} from './interfaces/node';\nimport {isComponentDef} from './interfaces/type_checks';\nimport {DestroyHookData, LView, TData, TVIEW, TView} from './interfaces/view';\nimport {getCurrentTNode, getLView, getTView} from './state';\n\n\n\n/**\n * Resolves the providers which are defined in the DirectiveDef.\n *\n * When inserting the tokens and the factories in their respective arrays, we can assume that\n * this method is called first for the component (if any), and then for other directives on the same\n * node.\n * As a consequence,the providers are always processed in that order:\n * 1) The view providers of the component\n * 2) The providers of the component\n * 3) The providers of the other directives\n * This matches the structure of the injectables arrays of a view (for each node).\n * So the tokens and the factories can be pushed at the end of the arrays, except\n * in one case for multi providers.\n *\n * @param def the directive definition\n * @param providers: Array of `providers`.\n * @param viewProviders: Array of `viewProviders`.\n */\nexport function providersResolver<T>(\n def: DirectiveDef<T>, providers: Provider[], viewProviders: Provider[]): void {\n const tView = getTView();\n if (tView.firstCreatePass) {\n const isComponent = isComponentDef(def);\n\n // The list of view providers is processed first, and the flags are updated\n resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true);\n\n // Then, the list of providers is processed, and the flags are updated\n resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);\n }\n}\n\n/**\n * Resolves a provider and publishes it to the DI system.\n */\nfunction resolveProvider(\n provider: Provider, tInjectables: TData, lInjectablesBlueprint: NodeInjectorFactory[],\n isComponent: boolean, isViewProvider: boolean): void {\n provider = resolveForwardRef(provider);\n if (Array.isArray(provider)) {\n // Recursively call `resolveProvider`\n // Recursion is OK in this case because this code will not be in hot-path once we implement\n // cloning of the initial state.\n for (let i = 0; i < provider.length; i++) {\n resolveProvider(\n provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);\n }\n } else {\n const tView = getTView();\n const lView = getLView();\n let token: any = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);\n let providerFactory: () => any = providerToFactory(provider);\n\n const tNode = getCurrentTNode()!;\n const beginIndex = tNode.providerIndexes & TNodeProviderIndexes.ProvidersStartIndexMask;\n const endIndex = tNode.directiveStart;\n const cptViewProvidersCount =\n tNode.providerIndexes >> TNodeProviderIndexes.CptViewProvidersCountShift;\n\n if (isTypeProvider(provider) || !provider.multi) {\n // Single provider case: the factory is created and pushed immediately\n const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);\n const existingFactoryIndex = indexOf(\n token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount,\n endIndex);\n if (existingFactoryIndex === -1) {\n diPublicInInjector(\n getOrCreateNodeInjectorForNode(\n tNode as TElementNode | TContainerNode | TElementContainerNode, lView),\n tView, token);\n registerDestroyHooksIfSupported(tView, provider, tInjectables.length);\n tInjectables.push(token);\n tNode.directiveStart++;\n tNode.directiveEnd++;\n if (isViewProvider) {\n tNode.providerIndexes += TNodeProviderIndexes.CptViewProvidersCountShifter;\n }\n lInjectablesBlueprint.push(factory);\n lView.push(factory);\n } else {\n lInjectablesBlueprint[existingFactoryIndex] = factory;\n lView[existingFactoryIndex] = factory;\n }\n } else {\n // Multi provider case:\n // We create a multi factory which is going to aggregate all the values.\n // Since the output of such a factory depends on content or view injection,\n // we create two of them, which are linked together.\n //\n // The first one (for view providers) is always in the first block of the injectables array,\n // and the second one (for providers) is always in the second block.\n // This is important because view providers have higher priority. When a multi token\n // is being looked up, the view providers should be found first.\n // Note that it is not possible to have a multi factory in the third block (directive block).\n //\n // The algorithm to process multi providers is as follows:\n // 1) If the multi provider comes from the `viewProviders` of the component:\n // a) If the special view providers factory doesn't exist, it is created and pushed.\n // b) Else, the multi provider is added to the existing multi factory.\n // 2) If the multi provider comes from the `providers` of the component or of another\n // directive:\n // a) If the multi factory doesn't exist, it is created and provider pushed into it.\n // It is also linked to the multi factory for view providers, if it exists.\n // b) Else, the multi provider is added to the existing multi factory.\n\n const existingProvidersFactoryIndex =\n indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);\n const existingViewProvidersFactoryIndex =\n indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);\n const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&\n lInjectablesBlueprint[existingProvidersFactoryIndex];\n const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&\n lInjectablesBlueprint[existingViewProvidersFactoryIndex];\n\n if (isViewProvider && !doesViewProvidersFactoryExist ||\n !isViewProvider && !doesProvidersFactoryExist) {\n // Cases 1.a and 2.a\n diPublicInInjector(\n getOrCreateNodeInjectorForNode(\n tNode as TElementNode | TContainerNode | TElementContainerNode, lView),\n tView, token);\n const factory = multiFactory(\n isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver,\n lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);\n if (!isViewProvider && doesViewProvidersFactoryExist) {\n lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;\n }\n registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0);\n tInjectables.push(token);\n tNode.directiveStart++;\n tNode.directiveEnd++;\n if (isViewProvider) {\n tNode.providerIndexes += TNodeProviderIndexes.CptViewProvidersCountShifter;\n }\n lInjectablesBlueprint.push(factory);\n lView.push(factory);\n } else {\n // Cases 1.b and 2.b\n const indexInFactory = multiFactoryAdd(\n lInjectablesBlueprint!\n [isViewProvider ? existingViewProvidersFactoryIndex :\n existingProvidersFactoryIndex],\n providerFactory, !isViewProvider && isComponent);\n registerDestroyHooksIfSupported(\n tView, provider,\n existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex :\n existingViewProvidersFactoryIndex,\n indexInFactory);\n }\n if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {\n lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders!++;\n }\n }\n }\n}\n\n/**\n * Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks.\n * @param tView `TView` in which to register the hook.\n * @param provider Provider whose hook should be registered.\n * @param contextIndex Index under which to find the context for the hook when it's being invoked.\n * @param indexInFactory Only required for `multi` providers. Index of the provider in the multi\n * provider factory.\n */\nfunction registerDestroyHooksIfSupported(\n tView: TView, provider: Exclude<Provider, any[]>, contextIndex: number,\n indexInFactory?: number) {\n const providerIsTypeProvider = isTypeProvider(provider);\n const providerIsClassProvider = isClassProvider(provider);\n\n if (providerIsTypeProvider || providerIsClassProvider) {\n // Resolve forward references as `useClass` can hold a forward reference.\n const classToken = providerIsClassProvider ? resolveForwardRef(provider.useClass) : provider;\n const prototype = classToken.prototype;\n const ngOnDestroy = prototype.ngOnDestroy;\n\n if (ngOnDestroy) {\n const hooks = tView.destroyHooks || (tView.destroyHooks = []);\n\n if (!providerIsTypeProvider && ((provider as ClassProvider)).multi) {\n ngDevMode &&\n assertDefined(\n indexInFactory, 'indexInFactory when registering multi factory destroy hook');\n const existingCallbacksIndex = hooks.indexOf(contextIndex);\n\n if (existingCallbacksIndex === -1) {\n hooks.push(contextIndex, [indexInFactory, ngOnDestroy]);\n } else {\n (hooks[existingCallbacksIndex + 1] as DestroyHookData).push(indexInFactory!, ngOnDestroy);\n }\n } else {\n hooks.push(contextIndex, ngOnDestroy);\n }\n }\n }\n}\n\n/**\n * Add a factory in a multi factory.\n * @returns Index at which the factory was inserted.\n */\nfunction multiFactoryAdd(\n multiFactory: NodeInjectorFactory, factory: () => any, isComponentProvider: boolean): number {\n if (isComponentProvider) {\n multiFactory.componentProviders!++;\n }\n return multiFactory.multi!.push(factory) - 1;\n}\n\n/**\n * Returns the index of item in the array, but only in the begin to end range.\n */\nfunction indexOf(item: any, arr: any[], begin: number, end: number) {\n for (let i = begin; i < end; i++) {\n if (arr[i] === item) return i;\n }\n return -1;\n}\n\n/**\n * Use this with `multi` `providers`.\n */\nfunction multiProvidersFactoryResolver(\n this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView,\n tNode: TDirectiveHostNode): any[] {\n return multiResolve(this.multi!, []);\n}\n\n/**\n * Use this with `multi` `viewProviders`.\n *\n * This factory knows how to concatenate itself with the existing `multi` `providers`.\n */\nfunction multiViewProvidersFactoryResolver(\n this: NodeInjectorFactory, _: undefined, tData: TData, lView: LView,\n tNode: TDirectiveHostNode): any[] {\n const factories = this.multi!;\n let result: any[];\n if (this.providerFactory) {\n const componentCount = this.providerFactory.componentProviders!;\n const multiProviders =\n getNodeInjectable(lView, lView[TVIEW], this.providerFactory!.index!, tNode);\n // Copy the section of the array which contains `multi` `providers` from the component\n result = multiProviders.slice(0, componentCount);\n // Insert the `viewProvider` instances.\n multiResolve(factories, result);\n // Copy the section of the array which contains `multi` `providers` from other directives\n for (let i = componentCount; i < multiProviders.length; i++) {\n result.push(multiProviders[i]);\n }\n } else {\n result = [];\n // Insert the `viewProvider` instances.\n multiResolve(factories, result);\n }\n return result;\n}\n\n/**\n * Maps an array of factories into an array of values.\n */\nfunction multiResolve(factories: Array<() => any>, result: any[]): any[] {\n for (let i = 0; i < factories.length; i++) {\n const factory = factories[i]! as () => null;\n result.push(factory());\n }\n return result;\n}\n\n/**\n * Creates a multi factory.\n */\nfunction multiFactory(\n factoryFn: (\n this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView,\n tNode: TDirectiveHostNode) => any,\n index: number, isViewProvider: boolean, isComponent: boolean,\n f: () => any): NodeInjectorFactory {\n const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);\n factory.multi = [];\n factory.index = index;\n factory.componentProviders = 0;\n multiFactoryAdd(factory, f, isComponent && !isViewProvider);\n return factory;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ProcessProvidersFunction, Provider} from '../../di/interface/provider';\nimport {providersResolver} from '../di_setup';\nimport {DirectiveDef} from '../interfaces/definition';\n\n/**\n * This feature resolves the providers of a directive (or component),\n * and publish them into the DI system, making it visible to others for injection.\n *\n * For example:\n * ```ts\n * class ComponentWithProviders {\n * constructor(private greeter: GreeterDE) {}\n *\n * static ɵcmp = defineComponent({\n * type: ComponentWithProviders,\n * selectors: [['component-with-providers']],\n * factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)),\n * decls: 1,\n * vars: 1,\n * template: function(fs: RenderFlags, ctx: ComponentWithProviders) {\n * if (fs & RenderFlags.Create) {\n * ɵɵtext(0);\n * }\n * if (fs & RenderFlags.Update) {\n * ɵɵtextInterpolate(ctx.greeter.greet());\n * }\n * },\n * features: [ɵɵProvidersFeature([GreeterDE])]\n * });\n * }\n * ```\n *\n * @param definition\n *\n * @codeGenApi\n */\nexport function ɵɵProvidersFeature<T>(providers: Provider[], viewProviders: Provider[] = []) {\n return (definition: DirectiveDef<T>) => {\n definition.providersResolver =\n (def: DirectiveDef<T>, processProvidersFn?: ProcessProvidersFunction) => {\n return providersResolver(\n def, //\n processProvidersFn ? processProvidersFn(providers) : providers, //\n viewProviders);\n };\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../di/injector';\nimport {EnvironmentInjector} from '../di/r3_injector';\nimport {Type} from '../interface/type';\n\nimport {ComponentFactoryResolver} from './component_factory_resolver';\n\n\n/**\n * Represents an instance of an `NgModule` created by an `NgModuleFactory`.\n * Provides access to the `NgModule` instance and related objects.\n *\n * @publicApi\n */\nexport abstract class NgModuleRef<T> {\n /**\n * The injector that contains all of the providers of the `NgModule`.\n */\n abstract get injector(): EnvironmentInjector;\n\n /**\n * The resolver that can retrieve component factories in a context of this module.\n *\n * Note: since v13, dynamic component creation via\n * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)\n * does **not** require resolving component factory: component class can be used directly.\n *\n * @deprecated Angular no longer requires Component factories. Please use other APIs where\n * Component class can be used directly.\n */\n abstract get componentFactoryResolver(): ComponentFactoryResolver;\n\n /**\n * The `NgModule` instance.\n */\n abstract get instance(): T;\n\n /**\n * Destroys the module instance and all of the data structures associated with it.\n */\n abstract destroy(): void;\n\n /**\n * Registers a callback to be executed when the module is destroyed.\n */\n abstract onDestroy(callback: () => void): void;\n}\n\nexport interface InternalNgModuleRef<T> extends NgModuleRef<T> {\n // Note: we are using the prefix _ as NgModuleData is an NgModuleRef and therefore directly\n // exposed to the user.\n _bootstrapComponents: Type<any>[];\n}\n\n/**\n * @publicApi\n *\n * @deprecated\n * This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy\n * JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)\n * for additional context. Angular provides APIs that accept NgModule classes directly (such as\n * [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and\n * [createNgModule](api/core/createNgModule)), consider switching to those APIs instead of\n * using factory-based ones.\n */\nexport abstract class NgModuleFactory<T> {\n abstract get moduleType(): Type<T>;\n abstract create(parentInjector: Injector|null): NgModuleRef<T>;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {createInjectorWithoutInjectorInstances} from '../di/create_injector';\nimport {Injector} from '../di/injector';\nimport {EnvironmentProviders, Provider} from '../di/interface/provider';\nimport {EnvironmentInjector, getNullInjector, R3Injector} from '../di/r3_injector';\nimport {Type} from '../interface/type';\nimport {ComponentFactoryResolver as viewEngine_ComponentFactoryResolver} from '../linker/component_factory_resolver';\nimport {InternalNgModuleRef, NgModuleFactory as viewEngine_NgModuleFactory, NgModuleRef as viewEngine_NgModuleRef} from '../linker/ng_module_factory';\nimport {assertDefined} from '../util/assert';\nimport {stringify} from '../util/stringify';\n\nimport {ComponentFactoryResolver} from './component_ref';\nimport {getNgModuleDef} from './definition';\nimport {maybeUnwrapFn} from './util/misc_utils';\n\n/**\n * Returns a new NgModuleRef instance based on the NgModule class and parent injector provided.\n *\n * @param ngModule NgModule class.\n * @param parentInjector Optional injector instance to use as a parent for the module injector. If\n * not provided, `NullInjector` will be used instead.\n * @returns NgModuleRef that represents an NgModule instance.\n *\n * @publicApi\n */\nexport function createNgModule<T>(\n ngModule: Type<T>, parentInjector?: Injector): viewEngine_NgModuleRef<T> {\n return new NgModuleRef<T>(ngModule, parentInjector ?? null);\n}\n\n/**\n * The `createNgModule` function alias for backwards-compatibility.\n * Please avoid using it directly and use `createNgModule` instead.\n *\n * @deprecated Use `createNgModule` instead.\n */\nexport const createNgModuleRef = createNgModule;\nexport class NgModuleRef<T> extends viewEngine_NgModuleRef<T> implements InternalNgModuleRef<T> {\n // tslint:disable-next-line:require-internal-with-underscore\n _bootstrapComponents: Type<any>[] = [];\n // tslint:disable-next-line:require-internal-with-underscore\n _r3Injector: R3Injector;\n override instance: T;\n destroyCbs: (() => void)[]|null = [];\n\n // When bootstrapping a module we have a dependency graph that looks like this:\n // ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the\n // module being resolved tries to inject the ComponentFactoryResolver, it'll create a\n // circular dependency which will result in a runtime error, because the injector doesn't\n // exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves\n // and providing it, rather than letting the injector resolve it.\n override readonly componentFactoryResolver: ComponentFactoryResolver =\n new ComponentFactoryResolver(this);\n\n constructor(ngModuleType: Type<T>, public _parent: Injector|null) {\n super();\n const ngModuleDef = getNgModuleDef(ngModuleType);\n ngDevMode &&\n assertDefined(\n ngModuleDef,\n `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);\n\n this._bootstrapComponents = maybeUnwrapFn(ngModuleDef!.bootstrap);\n this._r3Injector = createInjectorWithoutInjectorInstances(\n ngModuleType, _parent,\n [\n {provide: viewEngine_NgModuleRef, useValue: this}, {\n provide: viewEngine_ComponentFactoryResolver,\n useValue: this.componentFactoryResolver\n }\n ],\n stringify(ngModuleType), new Set(['environment'])) as R3Injector;\n\n // We need to resolve the injector types separately from the injector creation, because\n // the module might be trying to use this ref in its constructor for DI which will cause a\n // circular error that will eventually error out, because the injector isn't created yet.\n this._r3Injector.resolveInjectorInitializers();\n this.instance = this._r3Injector.get(ngModuleType);\n }\n\n override get injector(): EnvironmentInjector {\n return this._r3Injector;\n }\n\n override destroy(): void {\n ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');\n const injector = this._r3Injector;\n !injector.destroyed && injector.destroy();\n this.destroyCbs!.forEach(fn => fn());\n this.destroyCbs = null;\n }\n override onDestroy(callback: () => void): void {\n ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');\n this.destroyCbs!.push(callback);\n }\n}\n\nexport class NgModuleFactory<T> extends viewEngine_NgModuleFactory<T> {\n constructor(public moduleType: Type<T>) {\n super();\n }\n\n override create(parentInjector: Injector|null): viewEngine_NgModuleRef<T> {\n return new NgModuleRef(this.moduleType, parentInjector);\n }\n}\n\nclass EnvironmentNgModuleRefAdapter extends viewEngine_NgModuleRef<null> {\n override readonly injector: EnvironmentInjector;\n override readonly componentFactoryResolver: ComponentFactoryResolver =\n new ComponentFactoryResolver(this);\n override readonly instance = null;\n\n constructor(\n providers: Array<Provider|EnvironmentProviders>, parent: EnvironmentInjector|null,\n source: string|null) {\n super();\n const injector = new R3Injector(\n [\n ...providers,\n {provide: viewEngine_NgModuleRef, useValue: this},\n {provide: viewEngine_ComponentFactoryResolver, useValue: this.componentFactoryResolver},\n ],\n parent || getNullInjector(), source, new Set(['environment']));\n this.injector = injector;\n injector.resolveInjectorInitializers();\n }\n\n override destroy(): void {\n this.injector.destroy();\n }\n\n override onDestroy(callback: () => void): void {\n this.injector.onDestroy(callback);\n }\n}\n\n/**\n * Create a new environment injector.\n *\n * Learn more about environment injectors in\n * [this guide](guide/standalone-components#environment-injectors).\n *\n * @param providers An array of providers.\n * @param parent A parent environment injector.\n * @param debugName An optional name for this injector instance, which will be used in error\n * messages.\n *\n * @publicApi\n */\nexport function createEnvironmentInjector(\n providers: Array<Provider|EnvironmentProviders>, parent: EnvironmentInjector,\n debugName: string|null = null): EnvironmentInjector {\n const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);\n return adapter.injector;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ɵɵinject as inject} from '../../di/injector_compatibility';\nimport {ɵɵdefineInjectable as defineInjectable} from '../../di/interface/defs';\nimport {internalImportProvidersFrom} from '../../di/provider_collection';\nimport {EnvironmentInjector} from '../../di/r3_injector';\nimport {OnDestroy} from '../../interface/lifecycle_hooks';\nimport {ComponentDef} from '../interfaces/definition';\nimport {createEnvironmentInjector} from '../ng_module_ref';\n\n/**\n * A service used by the framework to create instances of standalone injectors. Those injectors are\n * created on demand in case of dynamic component instantiation and contain ambient providers\n * collected from the imports graph rooted at a given standalone component.\n */\nclass StandaloneService implements OnDestroy {\n cachedInjectors = new Map<string, EnvironmentInjector|null>();\n\n constructor(private _injector: EnvironmentInjector) {}\n\n getOrCreateStandaloneInjector(componentDef: ComponentDef<unknown>): EnvironmentInjector|null {\n if (!componentDef.standalone) {\n return null;\n }\n\n if (!this.cachedInjectors.has(componentDef.id)) {\n const providers = internalImportProvidersFrom(false, componentDef.type);\n const standaloneInjector = providers.length > 0 ?\n createEnvironmentInjector(\n [providers], this._injector, `Standalone[${componentDef.type.name}]`) :\n null;\n this.cachedInjectors.set(componentDef.id, standaloneInjector);\n }\n\n return this.cachedInjectors.get(componentDef.id)!;\n }\n\n ngOnDestroy() {\n try {\n for (const injector of this.cachedInjectors.values()) {\n if (injector !== null) {\n injector.destroy();\n }\n }\n } finally {\n this.cachedInjectors.clear();\n }\n }\n\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ defineInjectable({\n token: StandaloneService,\n providedIn: 'environment',\n factory: () => new StandaloneService(inject(EnvironmentInjector)),\n });\n}\n\n/**\n * A feature that acts as a setup code for the {@link StandaloneService}.\n *\n * The most important responsibility of this feature is to expose the \"getStandaloneInjector\"\n * function (an entry points to a standalone injector creation) on a component definition object. We\n * go through the features infrastructure to make sure that the standalone injector creation logic\n * is tree-shakable and not included in applications that don't use standalone components.\n *\n * @codeGenApi\n */\nexport function ɵɵStandaloneFeature(definition: ComponentDef<unknown>) {\n definition.getStandaloneInjector = (parentInjector: EnvironmentInjector) => {\n return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(definition);\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {assertIndexInRange} from '../util/assert';\nimport {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, getBinding, updateBinding} from './bindings';\nimport {LView} from './interfaces/view';\nimport {getBindingRoot, getLView} from './state';\nimport {NO_CHANGE} from './tokens';\n\n\n/**\n * Bindings for pure functions are stored after regular bindings.\n *\n * |-------decls------|---------vars---------| |----- hostVars (dir1) ------|\n * ------------------------------------------------------------------------------------------\n * | nodes/refs/pipes | bindings | fn slots | injector | dir1 | host bindings | host slots |\n * ------------------------------------------------------------------------------------------\n * ^ ^\n * TView.bindingStartIndex TView.expandoStartIndex\n *\n * Pure function instructions are given an offset from the binding root. Adding the offset to the\n * binding root gives the first index where the bindings are stored. In component views, the binding\n * root is the bindingStartIndex. In host bindings, the binding root is the expandoStartIndex +\n * any directive instances + any hostVars in directives evaluated before it.\n *\n * See VIEW_DATA.md for more information about host binding resolution.\n */\n\n/**\n * If the value hasn't been saved, calls the pure function to store and return the\n * value. If it has been saved, returns the saved value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn Function that returns a value\n * @param thisArg Optional calling context of pureFn\n * @returns value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction0<T>(slotOffset: number, pureFn: () => T, thisArg?: any): T {\n const bindingIndex = getBindingRoot() + slotOffset;\n const lView = getLView();\n return lView[bindingIndex] === NO_CHANGE ?\n updateBinding(lView, bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) :\n getBinding(lView, bindingIndex);\n}\n\n/**\n * If the value of the provided exp has changed, calls the pure function to return\n * an updated value. Or if the value has not changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn Function that returns an updated value\n * @param exp Updated expression value\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction1(\n slotOffset: number, pureFn: (v: any) => any, exp: any, thisArg?: any): any {\n return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction2(\n slotOffset: number, pureFn: (v1: any, v2: any) => any, exp1: any, exp2: any,\n thisArg?: any): any {\n return pureFunction2Internal(\n getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction3(\n slotOffset: number, pureFn: (v1: any, v2: any, v3: any) => any, exp1: any, exp2: any, exp3: any,\n thisArg?: any): any {\n return pureFunction3Internal(\n getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction4(\n slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any) => any, exp1: any, exp2: any,\n exp3: any, exp4: any, thisArg?: any): any {\n return pureFunction4Internal(\n getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param exp5\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction5(\n slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any) => any, exp1: any,\n exp2: any, exp3: any, exp4: any, exp5: any, thisArg?: any): any {\n const bindingIndex = getBindingRoot() + slotOffset;\n const lView = getLView();\n const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);\n return bindingUpdated(lView, bindingIndex + 4, exp5) || different ?\n updateBinding(\n lView, bindingIndex + 5,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) :\n pureFn(exp1, exp2, exp3, exp4, exp5)) :\n getBinding(lView, bindingIndex + 5);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param exp5\n * @param exp6\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction6(\n slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any) => any,\n exp1: any, exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, thisArg?: any): any {\n const bindingIndex = getBindingRoot() + slotOffset;\n const lView = getLView();\n const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);\n return bindingUpdated2(lView, bindingIndex + 4, exp5, exp6) || different ?\n updateBinding(\n lView, bindingIndex + 6,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) :\n pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) :\n getBinding(lView, bindingIndex + 6);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param exp5\n * @param exp6\n * @param exp7\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction7(\n slotOffset: number,\n pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any) => any, exp1: any,\n exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, exp7: any, thisArg?: any): any {\n const bindingIndex = getBindingRoot() + slotOffset;\n const lView = getLView();\n let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);\n return bindingUpdated3(lView, bindingIndex + 4, exp5, exp6, exp7) || different ?\n updateBinding(\n lView, bindingIndex + 7,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) :\n pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) :\n getBinding(lView, bindingIndex + 7);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param exp5\n * @param exp6\n * @param exp7\n * @param exp8\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunction8(\n slotOffset: number,\n pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any) => any,\n exp1: any, exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, exp7: any, exp8: any,\n thisArg?: any): any {\n const bindingIndex = getBindingRoot() + slotOffset;\n const lView = getLView();\n const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);\n return bindingUpdated4(lView, bindingIndex + 4, exp5, exp6, exp7, exp8) || different ?\n updateBinding(\n lView, bindingIndex + 8,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) :\n pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) :\n getBinding(lView, bindingIndex + 8);\n}\n\n/**\n * pureFunction instruction that can support any number of bindings.\n *\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn A pure function that takes binding values and builds an object or array\n * containing those values.\n * @param exps An array of binding values\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n * @codeGenApi\n */\nexport function ɵɵpureFunctionV(\n slotOffset: number, pureFn: (...v: any[]) => any, exps: any[], thisArg?: any): any {\n return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg);\n}\n\n/**\n * Results of a pure function invocation are stored in LView in a dedicated slot that is initialized\n * to NO_CHANGE. In rare situations a pure pipe might throw an exception on the very first\n * invocation and not produce any valid results. In this case LView would keep holding the NO_CHANGE\n * value. The NO_CHANGE is not something that we can use in expressions / bindings thus we convert\n * it to `undefined`.\n */\nfunction getPureFunctionReturnValue(lView: LView, returnValueIndex: number) {\n ngDevMode && assertIndexInRange(lView, returnValueIndex);\n const lastReturnValue = lView[returnValueIndex];\n return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue;\n}\n\n/**\n * If the value of the provided exp has changed, calls the pure function to return\n * an updated value. Or if the value has not changed, returns cached value.\n *\n * @param lView LView in which the function is being executed.\n * @param bindingRoot Binding root index.\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn Function that returns an updated value\n * @param exp Updated expression value\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n */\nexport function pureFunction1Internal(\n lView: LView, bindingRoot: number, slotOffset: number, pureFn: (v: any) => any, exp: any,\n thisArg?: any): any {\n const bindingIndex = bindingRoot + slotOffset;\n return bindingUpdated(lView, bindingIndex, exp) ?\n updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) :\n getPureFunctionReturnValue(lView, bindingIndex + 1);\n}\n\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param lView LView in which the function is being executed.\n * @param bindingRoot Binding root index.\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n */\nexport function pureFunction2Internal(\n lView: LView, bindingRoot: number, slotOffset: number, pureFn: (v1: any, v2: any) => any,\n exp1: any, exp2: any, thisArg?: any): any {\n const bindingIndex = bindingRoot + slotOffset;\n return bindingUpdated2(lView, bindingIndex, exp1, exp2) ?\n updateBinding(\n lView, bindingIndex + 2,\n thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) :\n getPureFunctionReturnValue(lView, bindingIndex + 2);\n}\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param lView LView in which the function is being executed.\n * @param bindingRoot Binding root index.\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n */\nexport function pureFunction3Internal(\n lView: LView, bindingRoot: number, slotOffset: number,\n pureFn: (v1: any, v2: any, v3: any) => any, exp1: any, exp2: any, exp3: any,\n thisArg?: any): any {\n const bindingIndex = bindingRoot + slotOffset;\n return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ?\n updateBinding(\n lView, bindingIndex + 3,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) :\n getPureFunctionReturnValue(lView, bindingIndex + 3);\n}\n\n\n/**\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param lView LView in which the function is being executed.\n * @param bindingRoot Binding root index.\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn\n * @param exp1\n * @param exp2\n * @param exp3\n * @param exp4\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n *\n */\nexport function pureFunction4Internal(\n lView: LView, bindingRoot: number, slotOffset: number,\n pureFn: (v1: any, v2: any, v3: any, v4: any) => any, exp1: any, exp2: any, exp3: any, exp4: any,\n thisArg?: any): any {\n const bindingIndex = bindingRoot + slotOffset;\n return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ?\n updateBinding(\n lView, bindingIndex + 4,\n thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) :\n getPureFunctionReturnValue(lView, bindingIndex + 4);\n}\n\n/**\n * pureFunction instruction that can support any number of bindings.\n *\n * If the value of any provided exp has changed, calls the pure function to return\n * an updated value. Or if no values have changed, returns cached value.\n *\n * @param lView LView in which the function is being executed.\n * @param bindingRoot Binding root index.\n * @param slotOffset the offset from binding root to the reserved slot\n * @param pureFn A pure function that takes binding values and builds an object or array\n * containing those values.\n * @param exps An array of binding values\n * @param thisArg Optional calling context of pureFn\n * @returns Updated or cached value\n */\nexport function pureFunctionVInternal(\n lView: LView, bindingRoot: number, slotOffset: number, pureFn: (...v: any[]) => any,\n exps: any[], thisArg?: any): any {\n let bindingIndex = bindingRoot + slotOffset;\n let different = false;\n for (let i = 0; i < exps.length; i++) {\n bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true);\n }\n return different ? updateBinding(lView, bindingIndex, pureFn.apply(thisArg, exps)) :\n getPureFunctionReturnValue(lView, bindingIndex);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {PipeTransform} from '../change_detection/pipe_transform';\nimport {setInjectImplementation} from '../di/inject_switch';\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {Type} from '../interface/type';\n\nimport {getFactoryDef} from './definition_factory';\nimport {setIncludeViewProviders} from './di';\nimport {store, ɵɵdirectiveInject} from './instructions/all';\nimport {isHostComponentStandalone} from './instructions/element_validation';\nimport {PipeDef, PipeDefList} from './interfaces/definition';\nimport {CONTEXT, DECLARATION_COMPONENT_VIEW, HEADER_OFFSET, LView, TVIEW} from './interfaces/view';\nimport {pureFunction1Internal, pureFunction2Internal, pureFunction3Internal, pureFunction4Internal, pureFunctionVInternal} from './pure_function';\nimport {getBindingRoot, getLView, getTView} from './state';\nimport {load} from './util/view_utils';\n\n\n\n/**\n * Create a pipe.\n *\n * @param index Pipe index where the pipe will be stored.\n * @param pipeName The name of the pipe\n * @returns T the instance of the pipe.\n *\n * @codeGenApi\n */\nexport function ɵɵpipe(index: number, pipeName: string): any {\n const tView = getTView();\n let pipeDef: PipeDef<any>;\n const adjustedIndex = index + HEADER_OFFSET;\n\n if (tView.firstCreatePass) {\n // The `getPipeDef` throws if a pipe with a given name is not found\n // (so we use non-null assertion below).\n pipeDef = getPipeDef(pipeName, tView.pipeRegistry)!;\n tView.data[adjustedIndex] = pipeDef;\n if (pipeDef.onDestroy) {\n (tView.destroyHooks ??= []).push(adjustedIndex, pipeDef.onDestroy);\n }\n } else {\n pipeDef = tView.data[adjustedIndex] as PipeDef<any>;\n }\n\n const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));\n const previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject);\n try {\n // DI for pipes is supposed to behave like directives when placed on a component\n // host node, which means that we have to disable access to `viewProviders`.\n const previousIncludeViewProviders = setIncludeViewProviders(false);\n const pipeInstance = pipeFactory();\n setIncludeViewProviders(previousIncludeViewProviders);\n store(tView, getLView(), adjustedIndex, pipeInstance);\n return pipeInstance;\n } finally {\n // we have to restore the injector implementation in finally, just in case the creation of the\n // pipe throws an error.\n setInjectImplementation(previousInjectImplementation);\n }\n}\n\n/**\n * Searches the pipe registry for a pipe with the given name. If one is found,\n * returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved.\n *\n * @param name Name of pipe to resolve\n * @param registry Full list of available pipes\n * @returns Matching PipeDef\n */\nfunction getPipeDef(name: string, registry: PipeDefList|null): PipeDef<any>|undefined {\n if (registry) {\n for (let i = registry.length - 1; i >= 0; i--) {\n const pipeDef = registry[i];\n if (name === pipeDef.name) {\n return pipeDef;\n }\n }\n }\n if (ngDevMode) {\n throw new RuntimeError(RuntimeErrorCode.PIPE_NOT_FOUND, getPipeNotFoundErrorMessage(name));\n }\n}\n\n/**\n * Generates a helpful error message for the user when a pipe is not found.\n *\n * @param name Name of the missing pipe\n * @returns The error message\n */\nfunction getPipeNotFoundErrorMessage(name: string) {\n const lView = getLView();\n const declarationLView = lView[DECLARATION_COMPONENT_VIEW] as LView<Type<unknown>>;\n const context = declarationLView[CONTEXT];\n const hostIsStandalone = isHostComponentStandalone(lView);\n const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : '';\n const verifyMessage = `Verify that it is ${\n hostIsStandalone ? 'included in the \\'@Component.imports\\' of this component' :\n 'declared or imported in this module'}`;\n const errorMessage =\n `The pipe '${name}' could not be found${componentInfoMessage}. ${verifyMessage}`;\n return errorMessage;\n}\n\n/**\n * Invokes a pipe with 1 arguments.\n *\n * This instruction acts as a guard to {@link PipeTransform#transform} invoking\n * the pipe only when an input to the pipe changes.\n *\n * @param index Pipe index where the pipe was stored on creation.\n * @param slotOffset the offset in the reserved slot space\n * @param v1 1st argument to {@link PipeTransform#transform}.\n *\n * @codeGenApi\n */\nexport function ɵɵpipeBind1(index: number, slotOffset: number, v1: any): any {\n const adjustedIndex = index + HEADER_OFFSET;\n const lView = getLView();\n const pipeInstance = load<PipeTransform>(lView, adjustedIndex);\n return isPure(lView, adjustedIndex) ?\n pureFunction1Internal(\n lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) :\n pipeInstance.transform(v1);\n}\n\n/**\n * Invokes a pipe with 2 arguments.\n *\n * This instruction acts as a guard to {@link PipeTransform#transform} invoking\n * the pipe only when an input to the pipe changes.\n *\n * @param index Pipe index where the pipe was stored on creation.\n * @param slotOffset the offset in the reserved slot space\n * @param v1 1st argument to {@link PipeTransform#transform}.\n * @param v2 2nd argument to {@link PipeTransform#transform}.\n *\n * @codeGenApi\n */\nexport function ɵɵpipeBind2(index: number, slotOffset: number, v1: any, v2: any): any {\n const adjustedIndex = index + HEADER_OFFSET;\n const lView = getLView();\n const pipeInstance = load<PipeTransform>(lView, adjustedIndex);\n return isPure(lView, adjustedIndex) ?\n pureFunction2Internal(\n lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) :\n pipeInstance.transform(v1, v2);\n}\n\n/**\n * Invokes a pipe with 3 arguments.\n *\n * This instruction acts as a guard to {@link PipeTransform#transform} invoking\n * the pipe only when an input to the pipe changes.\n *\n * @param index Pipe index where the pipe was stored on creation.\n * @param slotOffset the offset in the reserved slot space\n * @param v1 1st argument to {@link PipeTransform#transform}.\n * @param v2 2nd argument to {@link PipeTransform#transform}.\n * @param v3 4rd argument to {@link PipeTransform#transform}.\n *\n * @codeGenApi\n */\nexport function ɵɵpipeBind3(index: number, slotOffset: number, v1: any, v2: any, v3: any): any {\n const adjustedIndex = index + HEADER_OFFSET;\n const lView = getLView();\n const pipeInstance = load<PipeTransform>(lView, adjustedIndex);\n return isPure(lView, adjustedIndex) ?\n pureFunction3Internal(\n lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) :\n pipeInstance.transform(v1, v2, v3);\n}\n\n/**\n * Invokes a pipe with 4 arguments.\n *\n * This instruction acts as a guard to {@link PipeTransform#transform} invoking\n * the pipe only when an input to the pipe changes.\n *\n * @param index Pipe index where the pipe was stored on creation.\n * @param slotOffset the offset in the reserved slot space\n * @param v1 1st argument to {@link PipeTransform#transform}.\n * @param v2 2nd argument to {@link PipeTransform#transform}.\n * @param v3 3rd argument to {@link PipeTransform#transform}.\n * @param v4 4th argument to {@link PipeTransform#transform}.\n *\n * @codeGenApi\n */\nexport function ɵɵpipeBind4(\n index: number, slotOffset: number, v1: any, v2: any, v3: any, v4: any): any {\n const adjustedIndex = index + HEADER_OFFSET;\n const lView = getLView();\n const pipeInstance = load<PipeTransform>(lView, adjustedIndex);\n return isPure(lView, adjustedIndex) ? pureFunction4Internal(\n lView, getBindingRoot(), slotOffset,\n pipeInstance.transform, v1, v2, v3, v4, pipeInstance) :\n pipeInstance.transform(v1, v2, v3, v4);\n}\n\n/**\n * Invokes a pipe with variable number of arguments.\n *\n * This instruction acts as a guard to {@link PipeTransform#transform} invoking\n * the pipe only when an input to the pipe changes.\n *\n * @param index Pipe index where the pipe was stored on creation.\n * @param slotOffset the offset in the reserved slot space\n * @param values Array of arguments to pass to {@link PipeTransform#transform} method.\n *\n * @codeGenApi\n */\nexport function ɵɵpipeBindV(index: number, slotOffset: number, values: [any, ...any[]]): any {\n const adjustedIndex = index + HEADER_OFFSET;\n const lView = getLView();\n const pipeInstance = load<PipeTransform>(lView, adjustedIndex);\n return isPure(lView, adjustedIndex) ?\n pureFunctionVInternal(\n lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) :\n pipeInstance.transform.apply(pipeInstance, values);\n}\n\nfunction isPure(lView: LView, index: number): boolean {\n return (<PipeDef<any>>lView[TVIEW].data[index]).pure;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/// <reference types=\"rxjs\" />\n\nimport {PartialObserver, Subject, Subscription} from 'rxjs';\n\n/**\n * Use in components with the `@Output` directive to emit custom events\n * synchronously or asynchronously, and register handlers for those events\n * by subscribing to an instance.\n *\n * @usageNotes\n *\n * Extends\n * [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject)\n * for Angular by adding the `emit()` method.\n *\n * In the following example, a component defines two output properties\n * that create event emitters. When the title is clicked, the emitter\n * emits an open or close event to toggle the current visibility state.\n *\n * ```html\n * @Component({\n * selector: 'zippy',\n * template: `\n * <div class=\"zippy\">\n * <div (click)=\"toggle()\">Toggle</div>\n * <div [hidden]=\"!visible\">\n * <ng-content></ng-content>\n * </div>\n * </div>`})\n * export class Zippy {\n * visible: boolean = true;\n * @Output() open: EventEmitter<any> = new EventEmitter();\n * @Output() close: EventEmitter<any> = new EventEmitter();\n *\n * toggle() {\n * this.visible = !this.visible;\n * if (this.visible) {\n * this.open.emit(null);\n * } else {\n * this.close.emit(null);\n * }\n * }\n * }\n * ```\n *\n * Access the event object with the `$event` argument passed to the output event\n * handler:\n *\n * ```html\n * <zippy (open)=\"onOpen($event)\" (close)=\"onClose($event)\"></zippy>\n * ```\n *\n * @see [Observables in Angular](guide/observables-in-angular)\n * @publicApi\n */\nexport interface EventEmitter<T> extends Subject<T> {\n /**\n * @internal\n */\n __isAsync: boolean;\n\n /**\n * Creates an instance of this class that can\n * deliver events synchronously or asynchronously.\n *\n * @param [isAsync=false] When true, deliver events asynchronously.\n *\n */\n new(isAsync?: boolean): EventEmitter<T>;\n\n /**\n * Emits an event containing a given value.\n * @param value The value to emit.\n */\n emit(value?: T): void;\n\n /**\n * Registers handlers for events emitted by this instance.\n * @param next When supplied, a custom handler for emitted events.\n * @param error When supplied, a custom handler for an error notification from this emitter.\n * @param complete When supplied, a custom handler for a completion notification from this\n * emitter.\n */\n subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void):\n Subscription;\n /**\n * Registers handlers for events emitted by this instance.\n * @param observerOrNext When supplied, a custom handler for emitted events, or an observer\n * object.\n * @param error When supplied, a custom handler for an error notification from this emitter.\n * @param complete When supplied, a custom handler for a completion notification from this\n * emitter.\n */\n subscribe(observerOrNext?: any, error?: any, complete?: any): Subscription;\n}\n\nclass EventEmitter_ extends Subject<any> {\n __isAsync: boolean; // tslint:disable-line\n\n constructor(isAsync: boolean = false) {\n super();\n this.__isAsync = isAsync;\n }\n\n emit(value?: any) {\n super.next(value);\n }\n\n override subscribe(observerOrNext?: any, error?: any, complete?: any): Subscription {\n let nextFn = observerOrNext;\n let errorFn = error || (() => null);\n let completeFn = complete;\n\n if (observerOrNext && typeof observerOrNext === 'object') {\n const observer = observerOrNext as PartialObserver<unknown>;\n nextFn = observer.next?.bind(observer);\n errorFn = observer.error?.bind(observer);\n completeFn = observer.complete?.bind(observer);\n }\n\n if (this.__isAsync) {\n errorFn = _wrapInTimeout(errorFn);\n\n if (nextFn) {\n nextFn = _wrapInTimeout(nextFn);\n }\n\n if (completeFn) {\n completeFn = _wrapInTimeout(completeFn);\n }\n }\n\n const sink = super.subscribe({next: nextFn, error: errorFn, complete: completeFn});\n\n if (observerOrNext instanceof Subscription) {\n observerOrNext.add(sink);\n }\n\n return sink;\n }\n}\n\nfunction _wrapInTimeout(fn: (value: unknown) => any) {\n return (value: unknown) => {\n setTimeout(fn, undefined, value);\n };\n}\n\n/**\n * @publicApi\n */\nexport const EventEmitter: {\n new (isAsync?: boolean): EventEmitter<any>; new<T>(isAsync?: boolean): EventEmitter<T>;\n readonly prototype: EventEmitter<any>;\n} = EventEmitter_ as any;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Observable} from 'rxjs';\n\nimport {EventEmitter} from '../event_emitter';\nimport {arrayEquals, flatten} from '../util/array_utils';\n\nfunction symbolIterator<T>(this: QueryList<T>): Iterator<T> {\n // @ts-expect-error accessing a private member\n return this._results[Symbol.iterator]();\n}\n\n/**\n * An unmodifiable list of items that Angular keeps up to date when the state\n * of the application changes.\n *\n * The type of object that {@link ViewChildren}, {@link ContentChildren}, and {@link QueryList}\n * provide.\n *\n * Implements an iterable interface, therefore it can be used in both ES6\n * javascript `for (var i of items)` loops as well as in Angular templates with\n * `*ngFor=\"let i of myList\"`.\n *\n * Changes can be observed by subscribing to the changes `Observable`.\n *\n * NOTE: In the future this class will implement an `Observable` interface.\n *\n * @usageNotes\n * ### Example\n * ```typescript\n * @Component({...})\n * class Container {\n * @ViewChildren(Item) items:QueryList<Item>;\n * }\n * ```\n *\n * @publicApi\n */\nexport class QueryList<T> implements Iterable<T> {\n public readonly dirty = true;\n private _results: Array<T> = [];\n private _changesDetected: boolean = false;\n private _changes: EventEmitter<QueryList<T>>|null = null;\n\n readonly length: number = 0;\n readonly first: T = undefined!;\n readonly last: T = undefined!;\n\n /**\n * Returns `Observable` of `QueryList` notifying the subscriber of changes.\n */\n get changes(): Observable<any> {\n return this._changes || (this._changes = new EventEmitter());\n }\n\n /**\n * @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change\n * has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in\n * the same result)\n */\n constructor(private _emitDistinctChangesOnly: boolean = false) {\n // This function should be declared on the prototype, but doing so there will cause the class\n // declaration to have side-effects and become not tree-shakable. For this reason we do it in\n // the constructor.\n // [Symbol.iterator](): Iterator<T> { ... }\n const proto = QueryList.prototype;\n if (!proto[Symbol.iterator]) proto[Symbol.iterator] = symbolIterator;\n }\n\n /**\n * Returns the QueryList entry at `index`.\n */\n get(index: number): T|undefined {\n return this._results[index];\n }\n\n /**\n * See\n * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\n */\n map<U>(fn: (item: T, index: number, array: T[]) => U): U[] {\n return this._results.map(fn);\n }\n\n /**\n * See\n * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)\n */\n filter(fn: (item: T, index: number, array: T[]) => boolean): T[] {\n return this._results.filter(fn);\n }\n\n /**\n * See\n * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)\n */\n find(fn: (item: T, index: number, array: T[]) => boolean): T|undefined {\n return this._results.find(fn);\n }\n\n /**\n * See\n * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)\n */\n reduce<U>(fn: (prevValue: U, curValue: T, curIndex: number, array: T[]) => U, init: U): U {\n return this._results.reduce(fn, init);\n }\n\n /**\n * See\n * [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)\n */\n forEach(fn: (item: T, index: number, array: T[]) => void): void {\n this._results.forEach(fn);\n }\n\n /**\n * See\n * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)\n */\n some(fn: (value: T, index: number, array: T[]) => boolean): boolean {\n return this._results.some(fn);\n }\n\n /**\n * Returns a copy of the internal results list as an Array.\n */\n toArray(): T[] {\n return this._results.slice();\n }\n\n toString(): string {\n return this._results.toString();\n }\n\n /**\n * Updates the stored data of the query list, and resets the `dirty` flag to `false`, so that\n * on change detection, it will not notify of changes to the queries, unless a new change\n * occurs.\n *\n * @param resultsTree The query results to store\n * @param identityAccessor Optional function for extracting stable object identity from a value\n * in the array. This function is executed for each element of the query result list while\n * comparing current query list with the new one (provided as a first argument of the `reset`\n * function) to detect if the lists are different. If the function is not provided, elements\n * are compared as is (without any pre-processing).\n */\n reset(resultsTree: Array<T|any[]>, identityAccessor?: (value: T) => unknown): void {\n // Cast to `QueryListInternal` so that we can mutate fields which are readonly for the usage of\n // QueryList (but not for QueryList itself.)\n const self = this as QueryListInternal<T>;\n (self as {dirty: boolean}).dirty = false;\n const newResultFlat = flatten(resultsTree);\n if (this._changesDetected = !arrayEquals(self._results, newResultFlat, identityAccessor)) {\n self._results = newResultFlat;\n self.length = newResultFlat.length;\n self.last = newResultFlat[this.length - 1];\n self.first = newResultFlat[0];\n }\n }\n\n /**\n * Triggers a change event by emitting on the `changes` {@link EventEmitter}.\n */\n notifyOnChanges(): void {\n if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly))\n this._changes.emit(this);\n }\n\n /** internal */\n setDirty() {\n (this as {dirty: boolean}).dirty = true;\n }\n\n /** internal */\n destroy(): void {\n (this.changes as EventEmitter<any>).complete();\n (this.changes as EventEmitter<any>).unsubscribe();\n }\n\n // The implementation of `Symbol.iterator` should be declared here, but this would cause\n // tree-shaking issues with `QueryList. So instead, it's added in the constructor (see comments\n // there) and this declaration is left here to ensure that TypeScript considers QueryList to\n // implement the Iterable interface. This is required for template type-checking of NgFor loops\n // over QueryLists to work correctly, since QueryList must be assignable to NgIterable.\n [Symbol.iterator]!: () => Iterator<T>;\n}\n\n/**\n * Internal set of APIs used by the framework. (not to be made public)\n */\ninterface QueryListInternal<T> extends QueryList<T> {\n reset(a: any[]): void;\n notifyOnChanges(): void;\n length: number;\n last: T;\n first: T;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../di/injector';\nimport {assertLContainer} from '../render3/assert';\nimport {createLView, renderView} from '../render3/instructions/shared';\nimport {TContainerNode, TNode, TNodeType} from '../render3/interfaces/node';\nimport {DECLARATION_LCONTAINER, LView, LViewFlags, QUERIES, TView} from '../render3/interfaces/view';\nimport {getCurrentTNode, getLView} from '../render3/state';\nimport {ViewRef as R3_ViewRef} from '../render3/view_ref';\nimport {assertDefined} from '../util/assert';\n\nimport {createElementRef, ElementRef} from './element_ref';\nimport {EmbeddedViewRef} from './view_ref';\n\n/**\n * Represents an embedded template that can be used to instantiate embedded views.\n * To instantiate embedded views based on a template, use the `ViewContainerRef`\n * method `createEmbeddedView()`.\n *\n * Access a `TemplateRef` instance by placing a directive on an `<ng-template>`\n * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view\n * is injected into the constructor of the directive,\n * using the `TemplateRef` token.\n *\n * You can also use a `Query` to find a `TemplateRef` associated with\n * a component or a directive.\n *\n * @see `ViewContainerRef`\n * @see [Navigate the Component Tree with DI](guide/dependency-injection-navtree)\n *\n * @publicApi\n */\nexport abstract class TemplateRef<C> {\n /**\n * The anchor element in the parent view for this embedded view.\n *\n * The data-binding and injection contexts of embedded views created from this `TemplateRef`\n * inherit from the contexts of this location.\n *\n * Typically new embedded views are attached to the view container of this location, but in\n * advanced use-cases, the view can be attached to a different container while keeping the\n * data-binding and injection context from the original location.\n *\n */\n // TODO(i): rename to anchor or location\n abstract readonly elementRef: ElementRef;\n\n /**\n * Instantiates an unattached embedded view based on this template.\n * @param context The data-binding context of the embedded view, as declared\n * in the `<ng-template>` usage.\n * @param injector Injector to be used within the embedded view.\n * @returns The new embedded view object.\n */\n abstract createEmbeddedView(context: C, injector?: Injector): EmbeddedViewRef<C>;\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__: () => TemplateRef<any>| null = injectTemplateRef;\n}\n\nconst ViewEngineTemplateRef = TemplateRef;\n\n// TODO(alxhub): combine interface and implementation. Currently this is challenging since something\n// in g3 depends on them being separate.\nconst R3TemplateRef = class TemplateRef<T> extends ViewEngineTemplateRef<T> {\n constructor(\n private _declarationLView: LView, private _declarationTContainer: TContainerNode,\n public override elementRef: ElementRef) {\n super();\n }\n\n override createEmbeddedView(context: T, injector?: Injector): EmbeddedViewRef<T> {\n const embeddedTView = this._declarationTContainer.tView as TView;\n const embeddedLView = createLView(\n this._declarationLView, embeddedTView, context, LViewFlags.CheckAlways, null,\n embeddedTView.declTNode, null, null, null, null, injector || null);\n\n const declarationLContainer = this._declarationLView[this._declarationTContainer.index];\n ngDevMode && assertLContainer(declarationLContainer);\n embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;\n\n const declarationViewLQueries = this._declarationLView[QUERIES];\n if (declarationViewLQueries !== null) {\n embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);\n }\n\n renderView(embeddedTView, embeddedLView, context);\n\n return new R3_ViewRef<T>(embeddedLView);\n }\n};\n\n/**\n * Creates a TemplateRef given a node.\n *\n * @returns The TemplateRef instance to use\n */\nexport function injectTemplateRef<T>(): TemplateRef<T>|null {\n return createTemplateRef<T>(getCurrentTNode()!, getLView());\n}\n\n/**\n * Creates a TemplateRef and stores it on the injector.\n *\n * @param hostTNode The node on which a TemplateRef is requested\n * @param hostLView The `LView` to which the node belongs\n * @returns The TemplateRef instance or null if we can't create a TemplateRef on a given node type\n */\nexport function createTemplateRef<T>(hostTNode: TNode, hostLView: LView): TemplateRef<T>|null {\n if (hostTNode.type & TNodeType.Container) {\n ngDevMode && assertDefined(hostTNode.tView, 'TView must be allocated');\n return new R3TemplateRef(\n hostLView, hostTNode as TContainerNode, createElementRef(hostTNode, hostLView));\n }\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../di/injector';\nimport {EnvironmentInjector} from '../di/r3_injector';\nimport {isType, Type} from '../interface/type';\nimport {assertNodeInjector} from '../render3/assert';\nimport {ComponentFactory as R3ComponentFactory} from '../render3/component_ref';\nimport {getComponentDef} from '../render3/definition';\nimport {getParentInjectorLocation, NodeInjector} from '../render3/di';\nimport {addToViewTree, createLContainer} from '../render3/instructions/shared';\nimport {CONTAINER_HEADER_OFFSET, LContainer, NATIVE, VIEW_REFS} from '../render3/interfaces/container';\nimport {NodeInjectorOffset} from '../render3/interfaces/injector';\nimport {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNodeType} from '../render3/interfaces/node';\nimport {RComment, RElement} from '../render3/interfaces/renderer_dom';\nimport {isLContainer} from '../render3/interfaces/type_checks';\nimport {LView, PARENT, RENDERER, T_HOST, TVIEW} from '../render3/interfaces/view';\nimport {assertTNodeType} from '../render3/node_assert';\nimport {addViewToContainer, destroyLView, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode} from '../render3/node_manipulation';\nimport {getCurrentTNode, getLView} from '../render3/state';\nimport {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from '../render3/util/injector_utils';\nimport {getNativeByTNode, unwrapRNode, viewAttachedToContainer} from '../render3/util/view_utils';\nimport {ViewRef as R3ViewRef} from '../render3/view_ref';\nimport {addToArray, removeFromArray} from '../util/array_utils';\nimport {assertDefined, assertEqual, assertGreaterThan, assertLessThan, throwError} from '../util/assert';\n\nimport {ComponentFactory, ComponentRef} from './component_factory';\nimport {createElementRef, ElementRef} from './element_ref';\nimport {NgModuleRef} from './ng_module_factory';\nimport {TemplateRef} from './template_ref';\nimport {EmbeddedViewRef, ViewRef} from './view_ref';\n/**\n * Represents a container where one or more views can be attached to a component.\n *\n * Can contain *host views* (created by instantiating a\n * component with the `createComponent()` method), and *embedded views*\n * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).\n *\n * A view container instance can contain other view containers,\n * creating a [view hierarchy](guide/glossary#view-hierarchy).\n *\n * @see `ComponentRef`\n * @see `EmbeddedViewRef`\n *\n * @publicApi\n */\nexport abstract class ViewContainerRef {\n /**\n * Anchor element that specifies the location of this container in the containing view.\n * Each view container can have only one anchor element, and each anchor element\n * can have only a single view container.\n *\n * Root elements of views attached to this container become siblings of the anchor element in\n * the rendered view.\n *\n * Access the `ViewContainerRef` of an element by placing a `Directive` injected\n * with `ViewContainerRef` on the element, or use a `ViewChild` query.\n *\n * <!-- TODO: rename to anchorElement -->\n */\n abstract get element(): ElementRef;\n\n /**\n * The [dependency injector](guide/glossary#injector) for this view container.\n */\n abstract get injector(): Injector;\n\n /** @deprecated No replacement */\n abstract get parentInjector(): Injector;\n\n /**\n * Destroys all views in this container.\n */\n abstract clear(): void;\n\n /**\n * Retrieves a view from this container.\n * @param index The 0-based index of the view to retrieve.\n * @returns The `ViewRef` instance, or null if the index is out of range.\n */\n abstract get(index: number): ViewRef|null;\n\n /**\n * Reports how many views are currently attached to this container.\n * @returns The number of views.\n */\n abstract get length(): number;\n\n /**\n * Instantiates an embedded view and inserts it\n * into this container.\n * @param templateRef The HTML template that defines the view.\n * @param context The data-binding context of the embedded view, as declared\n * in the `<ng-template>` usage.\n * @param options Extra configuration for the created view. Includes:\n * * index: The 0-based index at which to insert the new view into this container.\n * If not specified, appends the new view as the last entry.\n * * injector: Injector to be used within the embedded view.\n *\n * @returns The `ViewRef` instance for the newly created view.\n */\n abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, options?: {\n index?: number,\n injector?: Injector\n }): EmbeddedViewRef<C>;\n\n /**\n * Instantiates an embedded view and inserts it\n * into this container.\n * @param templateRef The HTML template that defines the view.\n * @param context The data-binding context of the embedded view, as declared\n * in the `<ng-template>` usage.\n * @param index The 0-based index at which to insert the new view into this container.\n * If not specified, appends the new view as the last entry.\n *\n * @returns The `ViewRef` instance for the newly created view.\n */\n abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number):\n EmbeddedViewRef<C>;\n\n /**\n * Instantiates a single component and inserts its host view into this container.\n *\n * @param componentType Component Type to use.\n * @param options An object that contains extra parameters:\n * * index: the index at which to insert the new component's host view into this container.\n * If not specified, appends the new view as the last entry.\n * * injector: the injector to use as the parent for the new component.\n * * ngModuleRef: an NgModuleRef of the component's NgModule, you should almost always provide\n * this to ensure that all expected providers are available for the component\n * instantiation.\n * * environmentInjector: an EnvironmentInjector which will provide the component's environment.\n * you should almost always provide this to ensure that all expected providers\n * are available for the component instantiation. This option is intended to\n * replace the `ngModuleRef` parameter.\n * * projectableNodes: list of DOM nodes that should be projected through\n * [`<ng-content>`](api/core/ng-content) of the new component instance.\n *\n * @returns The new `ComponentRef` which contains the component instance and the host view.\n */\n abstract createComponent<C>(componentType: Type<C>, options?: {\n index?: number,\n injector?: Injector,\n ngModuleRef?: NgModuleRef<unknown>,\n environmentInjector?: EnvironmentInjector|NgModuleRef<unknown>,\n projectableNodes?: Node[][],\n }): ComponentRef<C>;\n\n /**\n * Instantiates a single component and inserts its host view into this container.\n *\n * @param componentFactory Component factory to use.\n * @param index The index at which to insert the new component's host view into this container.\n * If not specified, appends the new view as the last entry.\n * @param injector The injector to use as the parent for the new component.\n * @param projectableNodes List of DOM nodes that should be projected through\n * [`<ng-content>`](api/core/ng-content) of the new component instance.\n * @param ngModuleRef An instance of the NgModuleRef that represent an NgModule.\n * This information is used to retrieve corresponding NgModule injector.\n *\n * @returns The new `ComponentRef` which contains the component instance and the host view.\n *\n * @deprecated Angular no longer requires component factories to dynamically create components.\n * Use different signature of the `createComponent` method, which allows passing\n * Component class directly.\n */\n abstract createComponent<C>(\n componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,\n projectableNodes?: any[][],\n environmentInjector?: EnvironmentInjector|NgModuleRef<any>): ComponentRef<C>;\n\n /**\n * Inserts a view into this container.\n * @param viewRef The view to insert.\n * @param index The 0-based index at which to insert the view.\n * If not specified, appends the new view as the last entry.\n * @returns The inserted `ViewRef` instance.\n *\n */\n abstract insert(viewRef: ViewRef, index?: number): ViewRef;\n\n /**\n * Moves a view to a new location in this container.\n * @param viewRef The view to move.\n * @param index The 0-based index of the new location.\n * @returns The moved `ViewRef` instance.\n */\n abstract move(viewRef: ViewRef, currentIndex: number): ViewRef;\n\n /**\n * Returns the index of a view within the current container.\n * @param viewRef The view to query.\n * @returns The 0-based index of the view's position in this container,\n * or `-1` if this container doesn't contain the view.\n */\n abstract indexOf(viewRef: ViewRef): number;\n\n /**\n * Destroys a view attached to this container\n * @param index The 0-based index of the view to destroy.\n * If not specified, the last view in the container is removed.\n */\n abstract remove(index?: number): void;\n\n /**\n * Detaches a view from this container without destroying it.\n * Use along with `insert()` to move a view within the current container.\n * @param index The 0-based index of the view to detach.\n * If not specified, the last view in the container is detached.\n */\n abstract detach(index?: number): ViewRef|null;\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__: () => ViewContainerRef = injectViewContainerRef;\n}\n\n/**\n * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef\n * already exists, retrieves the existing ViewContainerRef.\n *\n * @returns The ViewContainerRef instance to use\n */\nexport function injectViewContainerRef(): ViewContainerRef {\n const previousTNode = getCurrentTNode() as TElementNode | TElementContainerNode | TContainerNode;\n return createContainerRef(previousTNode, getLView());\n}\n\nconst VE_ViewContainerRef = ViewContainerRef;\n\n// TODO(alxhub): cleaning up this indirection triggers a subtle bug in Closure in g3. Once the fix\n// for that lands, this can be cleaned up.\nconst R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {\n constructor(\n private _lContainer: LContainer,\n private _hostTNode: TElementNode|TContainerNode|TElementContainerNode,\n private _hostLView: LView) {\n super();\n }\n\n override get element(): ElementRef {\n return createElementRef(this._hostTNode, this._hostLView);\n }\n\n override get injector(): Injector {\n return new NodeInjector(this._hostTNode, this._hostLView);\n }\n\n /** @deprecated No replacement */\n override get parentInjector(): Injector {\n const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostLView);\n if (hasParentInjector(parentLocation)) {\n const parentView = getParentInjectorView(parentLocation, this._hostLView);\n const injectorIndex = getParentInjectorIndex(parentLocation);\n ngDevMode && assertNodeInjector(parentView, injectorIndex);\n const parentTNode =\n parentView[TVIEW].data[injectorIndex + NodeInjectorOffset.TNODE] as TElementNode;\n return new NodeInjector(parentTNode, parentView);\n } else {\n return new NodeInjector(null, this._hostLView);\n }\n }\n\n override clear(): void {\n while (this.length > 0) {\n this.remove(this.length - 1);\n }\n }\n\n override get(index: number): ViewRef|null {\n const viewRefs = getViewRefs(this._lContainer);\n return viewRefs !== null && viewRefs[index] || null;\n }\n\n override get length(): number {\n return this._lContainer.length - CONTAINER_HEADER_OFFSET;\n }\n\n override createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, options?: {\n index?: number,\n injector?: Injector\n }): EmbeddedViewRef<C>;\n override createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number):\n EmbeddedViewRef<C>;\n override createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, indexOrOptions?: number|{\n index?: number,\n injector?: Injector\n }): EmbeddedViewRef<C> {\n let index: number|undefined;\n let injector: Injector|undefined;\n\n if (typeof indexOrOptions === 'number') {\n index = indexOrOptions;\n } else if (indexOrOptions != null) {\n index = indexOrOptions.index;\n injector = indexOrOptions.injector;\n }\n\n const viewRef = templateRef.createEmbeddedView(context || <any>{}, injector);\n this.insert(viewRef, index);\n return viewRef;\n }\n\n override createComponent<C>(componentType: Type<C>, options?: {\n index?: number,\n injector?: Injector,\n projectableNodes?: Node[][],\n ngModuleRef?: NgModuleRef<unknown>,\n }): ComponentRef<C>;\n /**\n * @deprecated Angular no longer requires component factories to dynamically create components.\n * Use different signature of the `createComponent` method, which allows passing\n * Component class directly.\n */\n override createComponent<C>(\n componentFactory: ComponentFactory<C>, index?: number|undefined,\n injector?: Injector|undefined, projectableNodes?: any[][]|undefined,\n environmentInjector?: EnvironmentInjector|NgModuleRef<any>|undefined): ComponentRef<C>;\n override createComponent<C>(\n componentFactoryOrType: ComponentFactory<C>|Type<C>, indexOrOptions?: number|undefined|{\n index?: number,\n injector?: Injector,\n ngModuleRef?: NgModuleRef<unknown>,\n environmentInjector?: EnvironmentInjector|NgModuleRef<unknown>,\n projectableNodes?: Node[][],\n },\n injector?: Injector|undefined, projectableNodes?: any[][]|undefined,\n environmentInjector?: EnvironmentInjector|NgModuleRef<any>|undefined): ComponentRef<C> {\n const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType);\n let index: number|undefined;\n\n // This function supports 2 signatures and we need to handle options correctly for both:\n // 1. When first argument is a Component type. This signature also requires extra\n // options to be provided as as object (more ergonomic option).\n // 2. First argument is a Component factory. In this case extra options are represented as\n // positional arguments. This signature is less ergonomic and will be deprecated.\n if (isComponentFactory) {\n if (ngDevMode) {\n assertEqual(\n typeof indexOrOptions !== 'object', true,\n 'It looks like Component factory was provided as the first argument ' +\n 'and an options object as the second argument. This combination of arguments ' +\n 'is incompatible. You can either change the first argument to provide Component ' +\n 'type or change the second argument to be a number (representing an index at ' +\n 'which to insert the new component\\'s host view into this container)');\n }\n index = indexOrOptions as number | undefined;\n } else {\n if (ngDevMode) {\n assertDefined(\n getComponentDef(componentFactoryOrType),\n `Provided Component class doesn't contain Component definition. ` +\n `Please check whether provided class has @Component decorator.`);\n assertEqual(\n typeof indexOrOptions !== 'number', true,\n 'It looks like Component type was provided as the first argument ' +\n 'and a number (representing an index at which to insert the new component\\'s ' +\n 'host view into this container as the second argument. This combination of arguments ' +\n 'is incompatible. Please use an object as the second argument instead.');\n }\n const options = (indexOrOptions || {}) as {\n index?: number,\n injector?: Injector,\n ngModuleRef?: NgModuleRef<unknown>,\n environmentInjector?: EnvironmentInjector | NgModuleRef<unknown>,\n projectableNodes?: Node[][],\n };\n if (ngDevMode && options.environmentInjector && options.ngModuleRef) {\n throwError(\n `Cannot pass both environmentInjector and ngModuleRef options to createComponent().`);\n }\n index = options.index;\n injector = options.injector;\n projectableNodes = options.projectableNodes;\n environmentInjector = options.environmentInjector || options.ngModuleRef;\n }\n\n const componentFactory: ComponentFactory<C> = isComponentFactory ?\n componentFactoryOrType as ComponentFactory<C>:\n new R3ComponentFactory(getComponentDef(componentFactoryOrType)!);\n const contextInjector = injector || this.parentInjector;\n\n // If an `NgModuleRef` is not provided explicitly, try retrieving it from the DI tree.\n if (!environmentInjector && (componentFactory as any).ngModule == null) {\n // For the `ComponentFactory` case, entering this logic is very unlikely, since we expect that\n // an instance of a `ComponentFactory`, resolved via `ComponentFactoryResolver` would have an\n // `ngModule` field. This is possible in some test scenarios and potentially in some JIT-based\n // use-cases. For the `ComponentFactory` case we preserve backwards-compatibility and try\n // using a provided injector first, then fall back to the parent injector of this\n // `ViewContainerRef` instance.\n //\n // For the factory-less case, it's critical to establish a connection with the module\n // injector tree (by retrieving an instance of an `NgModuleRef` and accessing its injector),\n // so that a component can use DI tokens provided in MgModules. For this reason, we can not\n // rely on the provided injector, since it might be detached from the DI tree (for example, if\n // it was created via `Injector.create` without specifying a parent injector, or if an\n // injector is retrieved from an `NgModuleRef` created via `createNgModule` using an\n // NgModule outside of a module tree). Instead, we always use `ViewContainerRef`'s parent\n // injector, which is normally connected to the DI tree, which includes module injector\n // subtree.\n const _injector = isComponentFactory ? contextInjector : this.parentInjector;\n\n // DO NOT REFACTOR. The code here used to have a `injector.get(NgModuleRef, null) ||\n // undefined` expression which seems to cause internal google apps to fail. This is documented\n // in the following internal bug issue: go/b/142967802\n const result = _injector.get(EnvironmentInjector, null);\n if (result) {\n environmentInjector = result;\n }\n }\n\n const componentRef =\n componentFactory.create(contextInjector, projectableNodes, undefined, environmentInjector);\n this.insert(componentRef.hostView, index);\n return componentRef;\n }\n\n override insert(viewRef: ViewRef, index?: number): ViewRef {\n const lView = (viewRef as R3ViewRef<any>)._lView!;\n const tView = lView[TVIEW];\n\n if (ngDevMode && viewRef.destroyed) {\n throw new Error('Cannot insert a destroyed View in a ViewContainer!');\n }\n\n if (viewAttachedToContainer(lView)) {\n // If view is already attached, detach it first so we clean up references appropriately.\n\n const prevIdx = this.indexOf(viewRef);\n\n // A view might be attached either to this or a different container. The `prevIdx` for\n // those cases will be:\n // equal to -1 for views attached to this ViewContainerRef\n // >= 0 for views attached to a different ViewContainerRef\n if (prevIdx !== -1) {\n this.detach(prevIdx);\n } else {\n const prevLContainer = lView[PARENT] as LContainer;\n ngDevMode &&\n assertEqual(\n isLContainer(prevLContainer), true,\n 'An attached view should have its PARENT point to a container.');\n\n\n // We need to re-create a R3ViewContainerRef instance since those are not stored on\n // LView (nor anywhere else).\n const prevVCRef = new R3ViewContainerRef(\n prevLContainer, prevLContainer[T_HOST] as TDirectiveHostNode, prevLContainer[PARENT]);\n\n prevVCRef.detach(prevVCRef.indexOf(viewRef));\n }\n }\n\n // Logical operation of adding `LView` to `LContainer`\n const adjustedIdx = this._adjustIndex(index);\n const lContainer = this._lContainer;\n insertView(tView, lView, lContainer, adjustedIdx);\n\n // Physical operation of adding the DOM nodes.\n const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);\n const renderer = lView[RENDERER];\n const parentRNode = nativeParentNode(renderer, lContainer[NATIVE] as RElement | RComment);\n if (parentRNode !== null) {\n addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);\n }\n\n (viewRef as R3ViewRef<any>).attachToViewContainerRef();\n addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);\n\n return viewRef;\n }\n\n override move(viewRef: ViewRef, newIndex: number): ViewRef {\n if (ngDevMode && viewRef.destroyed) {\n throw new Error('Cannot move a destroyed View in a ViewContainer!');\n }\n return this.insert(viewRef, newIndex);\n }\n\n override indexOf(viewRef: ViewRef): number {\n const viewRefsArr = getViewRefs(this._lContainer);\n return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1;\n }\n\n override remove(index?: number): void {\n const adjustedIdx = this._adjustIndex(index, -1);\n const detachedView = detachView(this._lContainer, adjustedIdx);\n\n if (detachedView) {\n // Before destroying the view, remove it from the container's array of `ViewRef`s.\n // This ensures the view container length is updated before calling\n // `destroyLView`, which could recursively call view container methods that\n // rely on an accurate container length.\n // (e.g. a method on this view container being called by a child directive's OnDestroy\n // lifecycle hook)\n removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx);\n destroyLView(detachedView[TVIEW], detachedView);\n }\n }\n\n override detach(index?: number): ViewRef|null {\n const adjustedIdx = this._adjustIndex(index, -1);\n const view = detachView(this._lContainer, adjustedIdx);\n\n const wasDetached =\n view && removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx) != null;\n return wasDetached ? new R3ViewRef(view!) : null;\n }\n\n private _adjustIndex(index?: number, shift: number = 0) {\n if (index == null) {\n return this.length + shift;\n }\n if (ngDevMode) {\n assertGreaterThan(index, -1, `ViewRef index must be positive, got ${index}`);\n // +1 because it's legal to insert at the end.\n assertLessThan(index, this.length + 1 + shift, 'index');\n }\n return index;\n }\n};\n\nfunction getViewRefs(lContainer: LContainer): ViewRef[]|null {\n return lContainer[VIEW_REFS] as ViewRef[];\n}\n\nfunction getOrCreateViewRefs(lContainer: LContainer): ViewRef[] {\n return (lContainer[VIEW_REFS] || (lContainer[VIEW_REFS] = [])) as ViewRef[];\n}\n\n/**\n * Creates a ViewContainerRef and stores it on the injector.\n *\n * @param ViewContainerRefToken The ViewContainerRef type\n * @param ElementRefToken The ElementRef type\n * @param hostTNode The node that is requesting a ViewContainerRef\n * @param hostLView The view to which the node belongs\n * @returns The ViewContainerRef instance to use\n */\nexport function createContainerRef(\n hostTNode: TElementNode|TContainerNode|TElementContainerNode,\n hostLView: LView): ViewContainerRef {\n ngDevMode && assertTNodeType(hostTNode, TNodeType.AnyContainer | TNodeType.AnyRNode);\n\n let lContainer: LContainer;\n const slotValue = hostLView[hostTNode.index];\n if (isLContainer(slotValue)) {\n // If the host is a container, we don't need to create a new LContainer\n lContainer = slotValue;\n } else {\n let commentNode: RComment;\n // If the host is an element container, the native host element is guaranteed to be a\n // comment and we can reuse that comment as anchor element for the new LContainer.\n // The comment node in question is already part of the DOM structure so we don't need to append\n // it again.\n if (hostTNode.type & TNodeType.ElementContainer) {\n commentNode = unwrapRNode(slotValue) as RComment;\n } else {\n // If the host is a regular element, we have to insert a comment node manually which will\n // be used as an anchor when inserting elements. In this specific case we use low-level DOM\n // manipulation to insert it.\n const renderer = hostLView[RENDERER];\n ngDevMode && ngDevMode.rendererCreateComment++;\n commentNode = renderer.createComment(ngDevMode ? 'container' : '');\n\n const hostNative = getNativeByTNode(hostTNode, hostLView)!;\n const parentOfHostNative = nativeParentNode(renderer, hostNative);\n nativeInsertBefore(\n renderer, parentOfHostNative!, commentNode, nativeNextSibling(renderer, hostNative),\n false);\n }\n\n hostLView[hostTNode.index] = lContainer =\n createLContainer(slotValue, hostLView, commentNode, hostTNode);\n\n addToViewTree(hostLView, lContainer);\n }\n\n return new R3ViewContainerRef(lContainer, hostTNode, hostLView);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @description\n *\n * Represents a type that a Component or other object is instances of.\n *\n * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by\n * the `MyCustomComponent` constructor function.\n *\n * @publicApi\n */\nexport const Type = Function;\n\nexport function isType(v: any): v is Type<any> {\n return typeof v === 'function';\n}\n\n/**\n * @description\n *\n * Represents an abstract class `T`, if applied to a concrete class it would stop being\n * instantiable.\n *\n * @publicApi\n */\nexport interface AbstractType<T> extends Function {\n prototype: T;\n}\n\nexport interface Type<T> extends Function {\n new(...args: any[]): T;\n}\n\nexport type Mutable<T extends {[x: string]: any}, K extends string> = {\n [P in K]: T[P];\n};\n\n/**\n * Returns a writable type version of type.\n *\n * USAGE:\n * Given:\n * ```\n * interface Person {readonly name: string}\n * ```\n *\n * We would like to get a read/write version of `Person`.\n * ```\n * const WritablePerson = Writable<Person>;\n * ```\n *\n * The result is that you can do:\n *\n * ```\n * const readonlyPerson: Person = {name: 'Marry'};\n * readonlyPerson.name = 'John'; // TypeError\n * (readonlyPerson as WritablePerson).name = 'John'; // OK\n *\n * // Error: Correctly detects that `Person` did not have `age` property.\n * (readonlyPerson as WritablePerson).age = 30;\n * ```\n */\nexport type Writable<T> = {\n -readonly[K in keyof T]: T[K];\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n// We are temporarily importing the existing viewEngine_from core so we can be sure we are\n// correctly implementing its interfaces for backwards compatibility.\n\nimport {ProviderToken} from '../di/provider_token';\nimport {createElementRef, ElementRef as ViewEngine_ElementRef, unwrapElementRef} from '../linker/element_ref';\nimport {QueryList} from '../linker/query_list';\nimport {createTemplateRef, TemplateRef as ViewEngine_TemplateRef} from '../linker/template_ref';\nimport {createContainerRef, ViewContainerRef} from '../linker/view_container_ref';\nimport {assertDefined, assertIndexInRange, assertNumber, throwError} from '../util/assert';\nimport {stringify} from '../util/stringify';\n\nimport {assertFirstCreatePass, assertLContainer} from './assert';\nimport {getNodeInjectable, locateDirectiveOrProvider} from './di';\nimport {storeCleanupWithContext} from './instructions/shared';\nimport {CONTAINER_HEADER_OFFSET, LContainer, MOVED_VIEWS} from './interfaces/container';\nimport {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType} from './interfaces/node';\nimport {LQueries, LQuery, QueryFlags, TQueries, TQuery, TQueryMetadata} from './interfaces/query';\nimport {DECLARATION_LCONTAINER, LView, PARENT, QUERIES, TVIEW, TView} from './interfaces/view';\nimport {assertTNodeType} from './node_assert';\nimport {getCurrentQueryIndex, getCurrentTNode, getLView, getTView, setCurrentQueryIndex} from './state';\nimport {isCreationMode} from './util/view_utils';\n\nclass LQuery_<T> implements LQuery<T> {\n matches: (T|null)[]|null = null;\n constructor(public queryList: QueryList<T>) {}\n clone(): LQuery<T> {\n return new LQuery_(this.queryList);\n }\n setDirty(): void {\n this.queryList.setDirty();\n }\n}\n\nclass LQueries_ implements LQueries {\n constructor(public queries: LQuery<any>[] = []) {}\n\n createEmbeddedView(tView: TView): LQueries|null {\n const tQueries = tView.queries;\n if (tQueries !== null) {\n const noOfInheritedQueries =\n tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length;\n const viewLQueries: LQuery<any>[] = [];\n\n // An embedded view has queries propagated from a declaration view at the beginning of the\n // TQueries collection and up until a first content query declared in the embedded view. Only\n // propagated LQueries are created at this point (LQuery corresponding to declared content\n // queries will be instantiated from the content query instructions for each directive).\n for (let i = 0; i < noOfInheritedQueries; i++) {\n const tQuery = tQueries.getByIndex(i);\n const parentLQuery = this.queries[tQuery.indexInDeclarationView];\n viewLQueries.push(parentLQuery.clone());\n }\n\n return new LQueries_(viewLQueries);\n }\n\n return null;\n }\n\n insertView(tView: TView): void {\n this.dirtyQueriesWithMatches(tView);\n }\n\n detachView(tView: TView): void {\n this.dirtyQueriesWithMatches(tView);\n }\n\n private dirtyQueriesWithMatches(tView: TView) {\n for (let i = 0; i < this.queries.length; i++) {\n if (getTQuery(tView, i).matches !== null) {\n this.queries[i].setDirty();\n }\n }\n }\n}\n\nclass TQueryMetadata_ implements TQueryMetadata {\n constructor(\n public predicate: ProviderToken<unknown>|string[], public flags: QueryFlags,\n public read: any = null) {}\n}\n\nclass TQueries_ implements TQueries {\n constructor(private queries: TQuery[] = []) {}\n\n elementStart(tView: TView, tNode: TNode): void {\n ngDevMode &&\n assertFirstCreatePass(\n tView, 'Queries should collect results on the first template pass only');\n for (let i = 0; i < this.queries.length; i++) {\n this.queries[i].elementStart(tView, tNode);\n }\n }\n elementEnd(tNode: TNode): void {\n for (let i = 0; i < this.queries.length; i++) {\n this.queries[i].elementEnd(tNode);\n }\n }\n embeddedTView(tNode: TNode): TQueries|null {\n let queriesForTemplateRef: TQuery[]|null = null;\n\n for (let i = 0; i < this.length; i++) {\n const childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0;\n const tqueryClone = this.getByIndex(i).embeddedTView(tNode, childQueryIndex);\n\n if (tqueryClone) {\n tqueryClone.indexInDeclarationView = i;\n if (queriesForTemplateRef !== null) {\n queriesForTemplateRef.push(tqueryClone);\n } else {\n queriesForTemplateRef = [tqueryClone];\n }\n }\n }\n\n return queriesForTemplateRef !== null ? new TQueries_(queriesForTemplateRef) : null;\n }\n\n template(tView: TView, tNode: TNode): void {\n ngDevMode &&\n assertFirstCreatePass(\n tView, 'Queries should collect results on the first template pass only');\n for (let i = 0; i < this.queries.length; i++) {\n this.queries[i].template(tView, tNode);\n }\n }\n\n getByIndex(index: number): TQuery {\n ngDevMode && assertIndexInRange(this.queries, index);\n return this.queries[index];\n }\n\n get length(): number {\n return this.queries.length;\n }\n\n track(tquery: TQuery): void {\n this.queries.push(tquery);\n }\n}\n\nclass TQuery_ implements TQuery {\n matches: number[]|null = null;\n indexInDeclarationView = -1;\n crossesNgTemplate = false;\n\n /**\n * A node index on which a query was declared (-1 for view queries and ones inherited from the\n * declaration template). We use this index (alongside with _appliesToNextNode flag) to know\n * when to apply content queries to elements in a template.\n */\n private _declarationNodeIndex: number;\n\n /**\n * A flag indicating if a given query still applies to nodes it is crossing. We use this flag\n * (alongside with _declarationNodeIndex) to know when to stop applying content queries to\n * elements in a template.\n */\n private _appliesToNextNode = true;\n\n constructor(public metadata: TQueryMetadata, nodeIndex: number = -1) {\n this._declarationNodeIndex = nodeIndex;\n }\n\n elementStart(tView: TView, tNode: TNode): void {\n if (this.isApplyingToNode(tNode)) {\n this.matchTNode(tView, tNode);\n }\n }\n\n elementEnd(tNode: TNode): void {\n if (this._declarationNodeIndex === tNode.index) {\n this._appliesToNextNode = false;\n }\n }\n\n template(tView: TView, tNode: TNode): void {\n this.elementStart(tView, tNode);\n }\n\n embeddedTView(tNode: TNode, childQueryIndex: number): TQuery|null {\n if (this.isApplyingToNode(tNode)) {\n this.crossesNgTemplate = true;\n // A marker indicating a `<ng-template>` element (a placeholder for query results from\n // embedded views created based on this `<ng-template>`).\n this.addMatch(-tNode.index, childQueryIndex);\n return new TQuery_(this.metadata);\n }\n return null;\n }\n\n private isApplyingToNode(tNode: TNode): boolean {\n if (this._appliesToNextNode &&\n (this.metadata.flags & QueryFlags.descendants) !== QueryFlags.descendants) {\n const declarationNodeIdx = this._declarationNodeIndex;\n let parent = tNode.parent;\n // Determine if a given TNode is a \"direct\" child of a node on which a content query was\n // declared (only direct children of query's host node can match with the descendants: false\n // option). There are 3 main use-case / conditions to consider here:\n // - <needs-target><i #target></i></needs-target>: here <i #target> parent node is a query\n // host node;\n // - <needs-target><ng-template [ngIf]=\"true\"><i #target></i></ng-template></needs-target>:\n // here <i #target> parent node is null;\n // - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need\n // to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse\n // up past the query's host node!).\n while (parent !== null && (parent.type & TNodeType.ElementContainer) &&\n parent.index !== declarationNodeIdx) {\n parent = parent.parent;\n }\n return declarationNodeIdx === (parent !== null ? parent.index : -1);\n }\n return this._appliesToNextNode;\n }\n\n private matchTNode(tView: TView, tNode: TNode): void {\n const predicate = this.metadata.predicate;\n if (Array.isArray(predicate)) {\n for (let i = 0; i < predicate.length; i++) {\n const name = predicate[i];\n this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, name));\n // Also try matching the name to a provider since strings can be used as DI tokens too.\n this.matchTNodeWithReadOption(\n tView, tNode, locateDirectiveOrProvider(tNode, tView, name, false, false));\n }\n } else {\n if ((predicate as any) === ViewEngine_TemplateRef) {\n if (tNode.type & TNodeType.Container) {\n this.matchTNodeWithReadOption(tView, tNode, -1);\n }\n } else {\n this.matchTNodeWithReadOption(\n tView, tNode, locateDirectiveOrProvider(tNode, tView, predicate, false, false));\n }\n }\n }\n\n private matchTNodeWithReadOption(tView: TView, tNode: TNode, nodeMatchIdx: number|null): void {\n if (nodeMatchIdx !== null) {\n const read = this.metadata.read;\n if (read !== null) {\n if (read === ViewEngine_ElementRef || read === ViewContainerRef ||\n read === ViewEngine_TemplateRef && (tNode.type & TNodeType.Container)) {\n this.addMatch(tNode.index, -2);\n } else {\n const directiveOrProviderIdx =\n locateDirectiveOrProvider(tNode, tView, read, false, false);\n if (directiveOrProviderIdx !== null) {\n this.addMatch(tNode.index, directiveOrProviderIdx);\n }\n }\n } else {\n this.addMatch(tNode.index, nodeMatchIdx);\n }\n }\n }\n\n private addMatch(tNodeIdx: number, matchIdx: number) {\n if (this.matches === null) {\n this.matches = [tNodeIdx, matchIdx];\n } else {\n this.matches.push(tNodeIdx, matchIdx);\n }\n }\n}\n\n/**\n * Iterates over local names for a given node and returns directive index\n * (or -1 if a local name points to an element).\n *\n * @param tNode static data of a node to check\n * @param selector selector to match\n * @returns directive index, -1 or null if a selector didn't match any of the local names\n */\nfunction getIdxOfMatchingSelector(tNode: TNode, selector: string): number|null {\n const localNames = tNode.localNames;\n if (localNames !== null) {\n for (let i = 0; i < localNames.length; i += 2) {\n if (localNames[i] === selector) {\n return localNames[i + 1] as number;\n }\n }\n }\n return null;\n}\n\n\nfunction createResultByTNodeType(tNode: TNode, currentView: LView): any {\n if (tNode.type & (TNodeType.AnyRNode | TNodeType.ElementContainer)) {\n return createElementRef(tNode, currentView);\n } else if (tNode.type & TNodeType.Container) {\n return createTemplateRef(tNode, currentView);\n }\n return null;\n}\n\n\nfunction createResultForNode(lView: LView, tNode: TNode, matchingIdx: number, read: any): any {\n if (matchingIdx === -1) {\n // if read token and / or strategy is not specified, detect it using appropriate tNode type\n return createResultByTNodeType(tNode, lView);\n } else if (matchingIdx === -2) {\n // read a special token from a node injector\n return createSpecialToken(lView, tNode, read);\n } else {\n // read a token\n return getNodeInjectable(lView, lView[TVIEW], matchingIdx, tNode as TElementNode);\n }\n}\n\nfunction createSpecialToken(lView: LView, tNode: TNode, read: any): any {\n if (read === ViewEngine_ElementRef) {\n return createElementRef(tNode, lView);\n } else if (read === ViewEngine_TemplateRef) {\n return createTemplateRef(tNode, lView);\n } else if (read === ViewContainerRef) {\n ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);\n return createContainerRef(\n tNode as TElementNode | TContainerNode | TElementContainerNode, lView);\n } else {\n ngDevMode &&\n throwError(\n `Special token to read should be one of ElementRef, TemplateRef or ViewContainerRef but got ${\n stringify(read)}.`);\n }\n}\n\n/**\n * A helper function that creates query results for a given view. This function is meant to do the\n * processing once and only once for a given view instance (a set of results for a given view\n * doesn't change).\n */\nfunction materializeViewResults<T>(\n tView: TView, lView: LView, tQuery: TQuery, queryIndex: number): (T|null)[] {\n const lQuery = lView[QUERIES]!.queries![queryIndex];\n if (lQuery.matches === null) {\n const tViewData = tView.data;\n const tQueryMatches = tQuery.matches!;\n const result: T|null[] = [];\n for (let i = 0; i < tQueryMatches.length; i += 2) {\n const matchedNodeIdx = tQueryMatches[i];\n if (matchedNodeIdx < 0) {\n // we at the <ng-template> marker which might have results in views created based on this\n // <ng-template> - those results will be in separate views though, so here we just leave\n // null as a placeholder\n result.push(null);\n } else {\n ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx);\n const tNode = tViewData[matchedNodeIdx] as TNode;\n result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read));\n }\n }\n lQuery.matches = result;\n }\n\n return lQuery.matches;\n}\n\n/**\n * A helper function that collects (already materialized) query results from a tree of views,\n * starting with a provided LView.\n */\nfunction collectQueryResults<T>(tView: TView, lView: LView, queryIndex: number, result: T[]): T[] {\n const tQuery = tView.queries!.getByIndex(queryIndex);\n const tQueryMatches = tQuery.matches;\n if (tQueryMatches !== null) {\n const lViewResults = materializeViewResults<T>(tView, lView, tQuery, queryIndex);\n\n for (let i = 0; i < tQueryMatches.length; i += 2) {\n const tNodeIdx = tQueryMatches[i];\n if (tNodeIdx > 0) {\n result.push(lViewResults[i / 2] as T);\n } else {\n const childQueryIndex = tQueryMatches[i + 1];\n\n const declarationLContainer = lView[-tNodeIdx] as LContainer;\n ngDevMode && assertLContainer(declarationLContainer);\n\n // collect matches for views inserted in this container\n for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) {\n const embeddedLView = declarationLContainer[i];\n if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) {\n collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);\n }\n }\n\n // collect matches for views created from this declaration container and inserted into\n // different containers\n if (declarationLContainer[MOVED_VIEWS] !== null) {\n const embeddedLViews = declarationLContainer[MOVED_VIEWS]!;\n for (let i = 0; i < embeddedLViews.length; i++) {\n const embeddedLView = embeddedLViews[i];\n collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);\n }\n }\n }\n }\n }\n return result;\n}\n\n/**\n * Refreshes a query by combining matches from all active views and removing matches from deleted\n * views.\n *\n * @returns `true` if a query got dirty during change detection or if this is a static query\n * resolving in creation mode, `false` otherwise.\n *\n * @codeGenApi\n */\nexport function ɵɵqueryRefresh(queryList: QueryList<any>): boolean {\n const lView = getLView();\n const tView = getTView();\n const queryIndex = getCurrentQueryIndex();\n\n setCurrentQueryIndex(queryIndex + 1);\n\n const tQuery = getTQuery(tView, queryIndex);\n if (queryList.dirty &&\n (isCreationMode(lView) ===\n ((tQuery.metadata.flags & QueryFlags.isStatic) === QueryFlags.isStatic))) {\n if (tQuery.matches === null) {\n queryList.reset([]);\n } else {\n const result = tQuery.crossesNgTemplate ?\n collectQueryResults(tView, lView, queryIndex, []) :\n materializeViewResults(tView, lView, tQuery, queryIndex);\n queryList.reset(result, unwrapElementRef);\n queryList.notifyOnChanges();\n }\n return true;\n }\n\n return false;\n}\n\n/**\n * Creates new QueryList, stores the reference in LView and returns QueryList.\n *\n * @param predicate The type for which the query will search\n * @param flags Flags associated with the query\n * @param read What to save in the query\n *\n * @codeGenApi\n */\nexport function ɵɵviewQuery<T>(\n predicate: ProviderToken<unknown>|string[], flags: QueryFlags, read?: any): void {\n ngDevMode && assertNumber(flags, 'Expecting flags');\n const tView = getTView();\n if (tView.firstCreatePass) {\n createTQuery(tView, new TQueryMetadata_(predicate, flags, read), -1);\n if ((flags & QueryFlags.isStatic) === QueryFlags.isStatic) {\n tView.staticViewQueries = true;\n }\n }\n createLQuery<T>(tView, getLView(), flags);\n}\n\n/**\n * Registers a QueryList, associated with a content query, for later refresh (part of a view\n * refresh).\n *\n * @param directiveIndex Current directive index\n * @param predicate The type for which the query will search\n * @param flags Flags associated with the query\n * @param read What to save in the query\n * @returns QueryList<T>\n *\n * @codeGenApi\n */\nexport function ɵɵcontentQuery<T>(\n directiveIndex: number, predicate: ProviderToken<unknown>|string[], flags: QueryFlags,\n read?: any): void {\n ngDevMode && assertNumber(flags, 'Expecting flags');\n const tView = getTView();\n if (tView.firstCreatePass) {\n const tNode = getCurrentTNode()!;\n createTQuery(tView, new TQueryMetadata_(predicate, flags, read), tNode.index);\n saveContentQueryAndDirectiveIndex(tView, directiveIndex);\n if ((flags & QueryFlags.isStatic) === QueryFlags.isStatic) {\n tView.staticContentQueries = true;\n }\n }\n\n createLQuery<T>(tView, getLView(), flags);\n}\n\n/**\n * Loads a QueryList corresponding to the current view or content query.\n *\n * @codeGenApi\n */\nexport function ɵɵloadQuery<T>(): QueryList<T> {\n return loadQueryInternal<T>(getLView(), getCurrentQueryIndex());\n}\n\nfunction loadQueryInternal<T>(lView: LView, queryIndex: number): QueryList<T> {\n ngDevMode &&\n assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query');\n ngDevMode && assertIndexInRange(lView[QUERIES]!.queries, queryIndex);\n return lView[QUERIES]!.queries[queryIndex].queryList;\n}\n\nfunction createLQuery<T>(tView: TView, lView: LView, flags: QueryFlags) {\n const queryList = new QueryList<T>(\n (flags & QueryFlags.emitDistinctChangesOnly) === QueryFlags.emitDistinctChangesOnly);\n storeCleanupWithContext(tView, lView, queryList, queryList.destroy);\n\n if (lView[QUERIES] === null) lView[QUERIES] = new LQueries_();\n lView[QUERIES]!.queries.push(new LQuery_(queryList));\n}\n\nfunction createTQuery(tView: TView, metadata: TQueryMetadata, nodeIndex: number): void {\n if (tView.queries === null) tView.queries = new TQueries_();\n tView.queries.track(new TQuery_(metadata, nodeIndex));\n}\n\nfunction saveContentQueryAndDirectiveIndex(tView: TView, directiveIndex: number) {\n const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []);\n const lastSavedDirectiveIndex =\n tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1;\n if (directiveIndex !== lastSavedDirectiveIndex) {\n tViewContentQueries.push(tView.queries!.length - 1, directiveIndex);\n }\n}\n\nfunction getTQuery(tView: TView, index: number): TQuery {\n ngDevMode && assertDefined(tView.queries, 'TQueries must be defined to retrieve a TQuery');\n return tView.queries!.getByIndex(index);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {createTemplateRef, TemplateRef} from '../linker/template_ref';\nimport {TNode} from './interfaces/node';\nimport {LView} from './interfaces/view';\n\n\n/**\n * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the\n * `<ng-template>` element.\n *\n * @codeGenApi\n */\nexport function ɵɵtemplateRefExtractor(tNode: TNode, lView: LView): TemplateRef<any>|null {\n return createTemplateRef(tNode, lView);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ModuleWithProviders} from '../../di/interface/provider';\nimport {Type} from '../../interface/type';\nimport {NgModuleDef} from '../../metadata/ng_module_def';\nimport {getNgModuleDef} from '../definition';\n\nexport function isModuleWithProviders(value: any): value is ModuleWithProviders<{}> {\n return (value as {ngModule?: any}).ngModule !== undefined;\n}\n\nexport function isNgModule<T>(value: Type<T>): value is Type<T>&{ɵmod: NgModuleDef<T>} {\n return !!getNgModuleDef(value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function noop(...args: any[]): any {\n // Do nothing.\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/*\n * This file exists to support compilation of @angular/core in Ivy mode.\n *\n * When the Angular compiler processes a compilation unit, it normally writes imports to\n * @angular/core. When compiling the core package itself this strategy isn't usable. Instead, the\n * compiler writes imports to this file.\n *\n * Only a subset of such imports are supported - core is not allowed to declare components or pipes.\n * A check in ngtsc's `R3SymbolsImportRewriter` validates this condition. The rewriter is only used\n * when compiling @angular/core and is responsible for translating an external name (prefixed with\n * ɵ) to the internal symbol name as exported below.\n *\n * The below symbols are used for @Injectable and @NgModule compilation.\n */\n\nexport {ɵɵinject} from './di/injector_compatibility';\nexport {ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵInjectableDeclaration} from './di/interface/defs';\nexport {NgModuleDef} from './metadata/ng_module_def';\nexport {ɵɵdefineNgModule} from './render3/definition';\nexport {ɵɵFactoryDeclaration, ɵɵInjectorDeclaration, ɵɵNgModuleDeclaration} from './render3/interfaces/public_definitions';\nexport {setClassMetadata} from './render3/metadata';\nexport {NgModuleFactory} from './render3/ng_module_ref';\nexport {noSideEffects as ɵnoSideEffects} from './util/closure';\n\n\n\n/**\n * The existence of this constant (in this particular file) informs the Angular compiler that the\n * current program is actually @angular/core, which needs to be compiled specially.\n */\nexport const ITS_JUST_ANGULAR = true;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Observable} from 'rxjs';\n\nimport {Inject, Injectable, InjectionToken, Optional} from './di';\nimport {isObservable, isPromise} from './util/lang';\nimport {noop} from './util/noop';\n\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") that you can use to provide\n * one or more initialization functions.\n *\n * The provided functions are injected at application startup and executed during\n * app initialization. If any of these functions returns a Promise or an Observable, initialization\n * does not complete until the Promise is resolved or the Observable is completed.\n *\n * You can, for example, create a factory function that loads language data\n * or an external configuration, and provide that function to the `APP_INITIALIZER` token.\n * The function is executed during the application bootstrap process,\n * and the needed data is available on startup.\n *\n * @see `ApplicationInitStatus`\n *\n * @usageNotes\n *\n * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token\n * and a function returning a promise.\n *\n * ```\n * function initializeApp(): Promise<any> {\n * return new Promise((resolve, reject) => {\n * // Do some asynchronous stuff\n * resolve();\n * });\n * }\n *\n * @NgModule({\n * imports: [BrowserModule],\n * declarations: [AppComponent],\n * bootstrap: [AppComponent],\n * providers: [{\n * provide: APP_INITIALIZER,\n * useFactory: () => initializeApp,\n * multi: true\n * }]\n * })\n * export class AppModule {}\n * ```\n *\n * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function\n * returning an observable, see an example below. Note: the `HttpClient` in this example is used for\n * demo purposes to illustrate how the factory function can work with other providers available\n * through DI.\n *\n * ```\n * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {\n * return () => httpClient.get(\"https://someUrl.com/api/user\")\n * .pipe(\n * tap(user => { ... })\n * );\n * }\n *\n * @NgModule({\n * imports: [BrowserModule, HttpClientModule],\n * declarations: [AppComponent],\n * bootstrap: [AppComponent],\n * providers: [{\n * provide: APP_INITIALIZER,\n * useFactory: initializeAppFactory,\n * deps: [HttpClient],\n * multi: true\n * }]\n * })\n * export class AppModule {}\n * ```\n *\n * @publicApi\n */\nexport const APP_INITIALIZER =\n new InjectionToken<ReadonlyArray<() => Observable<unknown>| Promise<unknown>| void>>(\n 'Application Initializer');\n\n/**\n * A class that reflects the state of running {@link APP_INITIALIZER} functions.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class ApplicationInitStatus {\n private resolve = noop;\n private reject = noop;\n private initialized = false;\n public readonly donePromise: Promise<any>;\n public readonly done = false;\n\n constructor(@Inject(APP_INITIALIZER) @Optional() private readonly appInits:\n ReadonlyArray<() => Observable<unknown>| Promise<unknown>| void>) {\n // TODO: Throw RuntimeErrorCode.INVALID_MULTI_PROVIDER if appInits is not an array\n this.donePromise = new Promise((res, rej) => {\n this.resolve = res;\n this.reject = rej;\n });\n }\n\n /** @internal */\n runInitializers() {\n if (this.initialized) {\n return;\n }\n\n const asyncInitPromises: Promise<any>[] = [];\n\n const complete = () => {\n (this as {done: boolean}).done = true;\n this.resolve();\n };\n\n if (this.appInits) {\n for (let i = 0; i < this.appInits.length; i++) {\n const initResult = this.appInits[i]();\n if (isPromise(initResult)) {\n asyncInitPromises.push(initResult);\n } else if (isObservable(initResult)) {\n const observableAsPromise = new Promise<void>((resolve, reject) => {\n initResult.subscribe({complete: resolve, error: reject});\n });\n asyncInitPromises.push(observableAsPromise);\n }\n }\n }\n\n Promise.all(asyncInitPromises)\n .then(() => {\n complete();\n })\n .catch(e => {\n this.reject(e);\n });\n\n if (asyncInitPromises.length === 0) {\n complete();\n }\n this.initialized = true;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from './di';\n\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") representing a unique string ID, used\n * primarily for prefixing application attributes and CSS styles when\n * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.\n *\n * BY default, the value is randomly generated and assigned to the application by Angular.\n * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure\n * the root {@link Injector} that uses this token.\n *\n * @publicApi\n */\nexport const APP_ID = new InjectionToken<string>('AppId', {\n providedIn: 'root',\n factory: _appIdRandomProviderFactory,\n});\n\nexport function _appIdRandomProviderFactory() {\n return `${_randomChar()}${_randomChar()}${_randomChar()}`;\n}\n\n/**\n * Providers that generate a random `APP_ID_TOKEN`.\n * @publicApi\n */\nexport const APP_ID_RANDOM_PROVIDER = {\n provide: APP_ID,\n useFactory: _appIdRandomProviderFactory,\n deps: <any[]>[],\n};\n\nfunction _randomChar(): string {\n return String.fromCharCode(97 + Math.floor(Math.random() * 25));\n}\n\n/**\n * A function that is executed when a platform is initialized.\n * @publicApi\n */\nexport const PLATFORM_INITIALIZER = new InjectionToken<Array<() => void>>('Platform Initializer');\n\n/**\n * A token that indicates an opaque platform ID.\n * @publicApi\n */\nexport const PLATFORM_ID = new InjectionToken<Object>('Platform ID', {\n providedIn: 'platform',\n factory: () => 'unknown', // set a default platform name, when none set explicitly\n});\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") that indicates the root directory of\n * the application\n * @publicApi\n */\nexport const PACKAGE_ROOT_URL = new InjectionToken<string>('Application Packages Root URL');\n\n// We keep this token here, rather than the animations package, so that modules that only care\n// about which animations module is loaded (e.g. the CDK) can retrieve it without having to\n// include extra dependencies. See #44970 for more context.\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") that indicates which animations\n * module has been loaded.\n * @publicApi\n */\nexport const ANIMATION_MODULE_TYPE =\n new InjectionToken<'NoopAnimations'|'BrowserAnimations'>('AnimationModuleType');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable} from './di';\n\n@Injectable({providedIn: 'platform'})\nexport class Console {\n log(message: string): void {\n // tslint:disable-next-line:no-console\n console.log(message);\n }\n // Note: for reporting errors use `DOM.logError()` as it is platform specific\n warn(message: string): void {\n // tslint:disable-next-line:no-console\n console.warn(message);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '../di/injection_token';\nimport {inject} from '../di/injector_compatibility';\nimport {InjectFlags} from '../di/interface/injector';\n\nimport {DEFAULT_LOCALE_ID, USD_CURRENCY_CODE} from './localization';\n\ndeclare const $localize: {locale?: string};\n\n/**\n * Work out the locale from the potential global properties.\n *\n * * Closure Compiler: use `goog.LOCALE`.\n * * Ivy enabled: use `$localize.locale`\n */\nexport function getGlobalLocale(): string {\n if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode &&\n typeof goog !== 'undefined' && goog.LOCALE !== 'en') {\n // * The default `goog.LOCALE` value is `en`, while Angular used `en-US`.\n // * In order to preserve backwards compatibility, we use Angular default value over\n // Closure Compiler's one.\n return goog.LOCALE;\n } else {\n // KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE\n // COMPILE-TIME INLINER.\n //\n // * During compile time inlining of translations the expression will be replaced\n // with a string literal that is the current locale. Other forms of this expression are not\n // guaranteed to be replaced.\n //\n // * During runtime translation evaluation, the developer is required to set `$localize.locale`\n // if required, or just to provide their own `LOCALE_ID` provider.\n return (typeof $localize !== 'undefined' && $localize.locale) || DEFAULT_LOCALE_ID;\n }\n}\n\n/**\n * Provide this token to set the locale of your application.\n * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,\n * DecimalPipe and PercentPipe) and by ICU expressions.\n *\n * See the [i18n guide](guide/i18n-common-locale-id) for more information.\n *\n * @usageNotes\n * ### Example\n *\n * ```typescript\n * import { LOCALE_ID } from '@angular/core';\n * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n * import { AppModule } from './app/app.module';\n *\n * platformBrowserDynamic().bootstrapModule(AppModule, {\n * providers: [{provide: LOCALE_ID, useValue: 'en-US' }]\n * });\n * ```\n *\n * @publicApi\n */\nexport const LOCALE_ID: InjectionToken<string> = new InjectionToken('LocaleId', {\n providedIn: 'root',\n factory: () =>\n inject(LOCALE_ID, InjectFlags.Optional | InjectFlags.SkipSelf) || getGlobalLocale(),\n});\n\n/**\n * Provide this token to set the default currency code your application uses for\n * CurrencyPipe when there is no currency code passed into it. This is only used by\n * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.\n *\n * See the [i18n guide](guide/i18n-common-locale-id) for more information.\n *\n * <div class=\"alert is-helpful\">\n *\n * **Deprecation notice:**\n *\n * The default currency code is currently always `USD` but this is deprecated from v9.\n *\n * **In v10 the default currency code will be taken from the current locale.**\n *\n * If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in\n * your application `NgModule`:\n *\n * ```ts\n * {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}\n * ```\n *\n * </div>\n *\n * @usageNotes\n * ### Example\n *\n * ```typescript\n * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n * import { AppModule } from './app/app.module';\n *\n * platformBrowserDynamic().bootstrapModule(AppModule, {\n * providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }]\n * });\n * ```\n *\n * @publicApi\n */\nexport const DEFAULT_CURRENCY_CODE = new InjectionToken<string>('DefaultCurrencyCode', {\n providedIn: 'root',\n factory: () => USD_CURRENCY_CODE,\n});\n\n/**\n * Use this token at bootstrap to provide the content of your translation file (`xtb`,\n * `xlf` or `xlf2`) when you want to translate your application in another language.\n *\n * See the [i18n guide](guide/i18n-common-merge) for more information.\n *\n * @usageNotes\n * ### Example\n *\n * ```typescript\n * import { TRANSLATIONS } from '@angular/core';\n * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n * import { AppModule } from './app/app.module';\n *\n * // content of your translation file\n * const translations = '....';\n *\n * platformBrowserDynamic().bootstrapModule(AppModule, {\n * providers: [{provide: TRANSLATIONS, useValue: translations }]\n * });\n * ```\n *\n * @publicApi\n */\nexport const TRANSLATIONS = new InjectionToken<string>('Translations');\n\n/**\n * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,\n * `xlf` or `xlf2`.\n *\n * See the [i18n guide](guide/i18n-common-merge) for more information.\n *\n * @usageNotes\n * ### Example\n *\n * ```typescript\n * import { TRANSLATIONS_FORMAT } from '@angular/core';\n * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n * import { AppModule } from './app/app.module';\n *\n * platformBrowserDynamic().bootstrapModule(AppModule, {\n * providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]\n * });\n * ```\n *\n * @publicApi\n */\nexport const TRANSLATIONS_FORMAT = new InjectionToken<string>('TranslationsFormat');\n\n/**\n * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy\n * that the compiler should use in case of missing translations:\n * - Error: throw if you have missing translations.\n * - Warning (default): show a warning in the console and/or shell.\n * - Ignore: do nothing.\n *\n * See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.\n *\n * @usageNotes\n * ### Example\n * ```typescript\n * import { MissingTranslationStrategy } from '@angular/core';\n * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n * import { AppModule } from './app/app.module';\n *\n * platformBrowserDynamic().bootstrapModule(AppModule, {\n * missingTranslation: MissingTranslationStrategy.Error\n * });\n * ```\n *\n * @publicApi\n */\nexport enum MissingTranslationStrategy {\n Error = 0,\n Warning = 1,\n Ignore = 2,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable} from '../di/injectable';\nimport {InjectionToken} from '../di/injection_token';\nimport {StaticProvider} from '../di/interface/provider';\nimport {MissingTranslationStrategy} from '../i18n/tokens';\nimport {Type} from '../interface/type';\nimport {ViewEncapsulation} from '../metadata/view';\nimport {ComponentFactory as ComponentFactoryR3} from '../render3/component_ref';\nimport {getComponentDef, getNgModuleDef} from '../render3/definition';\nimport {NgModuleFactory as NgModuleFactoryR3} from '../render3/ng_module_ref';\nimport {maybeUnwrapFn} from '../render3/util/misc_utils';\n\nimport {ComponentFactory} from './component_factory';\nimport {NgModuleFactory} from './ng_module_factory';\n\n/**\n * Combination of NgModuleFactory and ComponentFactories.\n *\n * @publicApi\n *\n * @deprecated\n * Ivy JIT mode doesn't require accessing this symbol.\n * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for\n * additional context.\n */\nexport class ModuleWithComponentFactories<T> {\n constructor(\n public ngModuleFactory: NgModuleFactory<T>,\n public componentFactories: ComponentFactory<any>[]) {}\n}\n\n/**\n * Low-level service for running the angular compiler during runtime\n * to create {@link ComponentFactory}s, which\n * can later be used to create and render a Component instance.\n *\n * Each `@NgModule` provides an own `Compiler` to its injector,\n * that will use the directives/pipes of the ng module for compilation\n * of components.\n *\n * @publicApi\n *\n * @deprecated\n * Ivy JIT mode doesn't require accessing this symbol.\n * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for\n * additional context.\n */\n@Injectable({providedIn: 'root'})\nexport class Compiler {\n /**\n * Compiles the given NgModule and all of its components. All templates of the components listed\n * in `entryComponents` have to be inlined.\n */\n compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> {\n return new NgModuleFactoryR3(moduleType);\n }\n\n /**\n * Compiles the given NgModule and all of its components\n */\n compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> {\n return Promise.resolve(this.compileModuleSync(moduleType));\n }\n\n /**\n * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.\n */\n compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T> {\n const ngModuleFactory = this.compileModuleSync(moduleType);\n const moduleDef = getNgModuleDef(moduleType)!;\n const componentFactories =\n maybeUnwrapFn(moduleDef.declarations)\n .reduce((factories: ComponentFactory<any>[], declaration: Type<any>) => {\n const componentDef = getComponentDef(declaration);\n componentDef && factories.push(new ComponentFactoryR3(componentDef));\n return factories;\n }, [] as ComponentFactory<any>[]);\n return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);\n }\n\n /**\n * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.\n */\n compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>):\n Promise<ModuleWithComponentFactories<T>> {\n return Promise.resolve(this.compileModuleAndAllComponentsSync(moduleType));\n }\n\n /**\n * Clears all caches.\n */\n clearCache(): void {}\n\n /**\n * Clears the cache for the given component/ngModule.\n */\n clearCacheFor(type: Type<any>) {}\n\n /**\n * Returns the id for a given NgModule, if one is defined and known to the compiler.\n */\n getModuleId(moduleType: Type<any>): string|undefined {\n return undefined;\n }\n}\n\n/**\n * Options for creating a compiler.\n *\n * Note: the `useJit` and `missingTranslation` config options are not used in Ivy, passing them has\n * no effect. Those config options are deprecated since v13.\n *\n * @publicApi\n */\nexport type CompilerOptions = {\n /**\n * @deprecated not used at all in Ivy, providing this config option has no effect.\n */\n useJit?: boolean,\n defaultEncapsulation?: ViewEncapsulation,\n providers?: StaticProvider[],\n /**\n * @deprecated not used at all in Ivy, providing this config option has no effect.\n */\n missingTranslation?: MissingTranslationStrategy,\n preserveWhitespaces?: boolean,\n};\n\n/**\n * Token to provide CompilerOptions in the platform injector.\n *\n * @publicApi\n */\nexport const COMPILER_OPTIONS = new InjectionToken<CompilerOptions[]>('compilerOptions');\n\n/**\n * A factory for creating a Compiler\n *\n * @publicApi\n *\n * @deprecated\n * Ivy JIT mode doesn't require accessing this symbol.\n * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for\n * additional context.\n */\nexport abstract class CompilerFactory {\n abstract createCompiler(options?: CompilerOptions[]): Compiler;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst promise: Promise<any> = (() => Promise.resolve(0))();\n\ndeclare const Zone: any;\n\nexport function scheduleMicroTask(fn: Function) {\n if (typeof Zone === 'undefined') {\n // use promise to schedule microTask instead of use Zone\n promise.then(() => {\n fn && fn.apply(null, null);\n });\n } else {\n Zone.current.scheduleMicroTask('scheduleMicrotask', fn);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../errors';\nimport {EventEmitter} from '../event_emitter';\nimport {global} from '../util/global';\nimport {noop} from '../util/noop';\nimport {getNativeRequestAnimationFrame} from '../util/raf';\n\nimport {AsyncStackTaggingZoneSpec} from './async-stack-tagging';\n\n/**\n * An injectable service for executing work inside or outside of the Angular zone.\n *\n * The most common use of this service is to optimize performance when starting a work consisting of\n * one or more asynchronous tasks that don't require UI updates or error handling to be handled by\n * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks\n * can reenter the Angular zone via {@link #run}.\n *\n * <!-- TODO: add/fix links to:\n * - docs explaining zones and the use of zones in Angular and change-detection\n * - link to runOutsideAngular/run (throughout this file!)\n * -->\n *\n * @usageNotes\n * ### Example\n *\n * ```\n * import {Component, NgZone} from '@angular/core';\n * import {NgIf} from '@angular/common';\n *\n * @Component({\n * selector: 'ng-zone-demo',\n * template: `\n * <h2>Demo: NgZone</h2>\n *\n * <p>Progress: {{progress}}%</p>\n * <p *ngIf=\"progress >= 100\">Done processing {{label}} of Angular zone!</p>\n *\n * <button (click)=\"processWithinAngularZone()\">Process within Angular zone</button>\n * <button (click)=\"processOutsideOfAngularZone()\">Process outside of Angular zone</button>\n * `,\n * })\n * export class NgZoneDemo {\n * progress: number = 0;\n * label: string;\n *\n * constructor(private _ngZone: NgZone) {}\n *\n * // Loop inside the Angular zone\n * // so the UI DOES refresh after each setTimeout cycle\n * processWithinAngularZone() {\n * this.label = 'inside';\n * this.progress = 0;\n * this._increaseProgress(() => console.log('Inside Done!'));\n * }\n *\n * // Loop outside of the Angular zone\n * // so the UI DOES NOT refresh after each setTimeout cycle\n * processOutsideOfAngularZone() {\n * this.label = 'outside';\n * this.progress = 0;\n * this._ngZone.runOutsideAngular(() => {\n * this._increaseProgress(() => {\n * // reenter the Angular zone and display done\n * this._ngZone.run(() => { console.log('Outside Done!'); });\n * });\n * });\n * }\n *\n * _increaseProgress(doneCallback: () => void) {\n * this.progress += 1;\n * console.log(`Current progress: ${this.progress}%`);\n *\n * if (this.progress < 100) {\n * window.setTimeout(() => this._increaseProgress(doneCallback), 10);\n * } else {\n * doneCallback();\n * }\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport class NgZone {\n readonly hasPendingMacrotasks: boolean = false;\n readonly hasPendingMicrotasks: boolean = false;\n\n /**\n * Whether there are no outstanding microtasks or macrotasks.\n */\n readonly isStable: boolean = true;\n\n /**\n * Notifies when code enters Angular Zone. This gets fired first on VM Turn.\n */\n readonly onUnstable: EventEmitter<any> = new EventEmitter(false);\n\n /**\n * Notifies when there is no more microtasks enqueued in the current VM Turn.\n * This is a hint for Angular to do change detection, which may enqueue more microtasks.\n * For this reason this event can fire multiple times per VM Turn.\n */\n readonly onMicrotaskEmpty: EventEmitter<any> = new EventEmitter(false);\n\n /**\n * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which\n * implies we are about to relinquish VM turn.\n * This event gets called just once.\n */\n readonly onStable: EventEmitter<any> = new EventEmitter(false);\n\n /**\n * Notifies that an error has been delivered.\n */\n readonly onError: EventEmitter<any> = new EventEmitter(false);\n\n\n constructor({\n enableLongStackTrace = false,\n shouldCoalesceEventChangeDetection = false,\n shouldCoalesceRunChangeDetection = false\n }) {\n if (typeof Zone == 'undefined') {\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_ZONEJS,\n ngDevMode && `In this configuration Angular requires Zone.js`);\n }\n\n Zone.assertZonePatched();\n const self = this as any as NgZonePrivate;\n self._nesting = 0;\n\n self._outer = self._inner = Zone.current;\n\n // AsyncStackTaggingZoneSpec provides `linked stack traces` to show\n // where the async operation is scheduled. For more details, refer\n // to this article, https://developer.chrome.com/blog/devtools-better-angular-debugging/\n // And we only import this AsyncStackTaggingZoneSpec in development mode,\n // in the production mode, the AsyncStackTaggingZoneSpec will be tree shaken away.\n if (ngDevMode) {\n self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular'));\n }\n\n if ((Zone as any)['TaskTrackingZoneSpec']) {\n self._inner = self._inner.fork(new ((Zone as any)['TaskTrackingZoneSpec'] as any));\n }\n\n if (enableLongStackTrace && (Zone as any)['longStackTraceZoneSpec']) {\n self._inner = self._inner.fork((Zone as any)['longStackTraceZoneSpec']);\n }\n // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be\n // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.\n self.shouldCoalesceEventChangeDetection =\n !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;\n self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;\n self.lastRequestAnimationFrameId = -1;\n self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;\n forkInnerZoneWithAngularBehavior(self);\n }\n\n static isInAngularZone(): boolean {\n // Zone needs to be checked, because this method might be called even when NoopNgZone is used.\n return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true;\n }\n\n static assertInAngularZone(): void {\n if (!NgZone.isInAngularZone()) {\n throw new RuntimeError(\n RuntimeErrorCode.UNEXPECTED_ZONE_STATE,\n ngDevMode && 'Expected to be in Angular Zone, but it is not!');\n }\n }\n\n static assertNotInAngularZone(): void {\n if (NgZone.isInAngularZone()) {\n throw new RuntimeError(\n RuntimeErrorCode.UNEXPECTED_ZONE_STATE,\n ngDevMode && 'Expected to not be in Angular Zone, but it is!');\n }\n }\n\n /**\n * Executes the `fn` function synchronously within the Angular zone and returns value returned by\n * the function.\n *\n * Running functions via `run` allows you to reenter Angular zone from a task that was executed\n * outside of the Angular zone (typically started via {@link #runOutsideAngular}).\n *\n * Any future tasks or microtasks scheduled from within this function will continue executing from\n * within the Angular zone.\n *\n * If a synchronous error happens it will be rethrown and not reported via `onError`.\n */\n run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T {\n return (this as any as NgZonePrivate)._inner.run(fn, applyThis, applyArgs);\n }\n\n /**\n * Executes the `fn` function synchronously within the Angular zone as a task and returns value\n * returned by the function.\n *\n * Running functions via `run` allows you to reenter Angular zone from a task that was executed\n * outside of the Angular zone (typically started via {@link #runOutsideAngular}).\n *\n * Any future tasks or microtasks scheduled from within this function will continue executing from\n * within the Angular zone.\n *\n * If a synchronous error happens it will be rethrown and not reported via `onError`.\n */\n runTask<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[], name?: string): T {\n const zone = (this as any as NgZonePrivate)._inner;\n const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);\n try {\n return zone.runTask(task, applyThis, applyArgs);\n } finally {\n zone.cancelTask(task);\n }\n }\n\n /**\n * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not\n * rethrown.\n */\n runGuarded<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T {\n return (this as any as NgZonePrivate)._inner.runGuarded(fn, applyThis, applyArgs);\n }\n\n /**\n * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by\n * the function.\n *\n * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do\n * work that\n * doesn't trigger Angular change-detection or is subject to Angular's error handling.\n *\n * Any future tasks or microtasks scheduled from within this function will continue executing from\n * outside of the Angular zone.\n *\n * Use {@link #run} to reenter the Angular zone and do work that updates the application model.\n */\n runOutsideAngular<T>(fn: (...args: any[]) => T): T {\n return (this as any as NgZonePrivate)._outer.run(fn);\n }\n}\n\nconst EMPTY_PAYLOAD = {};\n\ninterface NgZonePrivate extends NgZone {\n _outer: Zone;\n _inner: Zone;\n _nesting: number;\n _hasPendingMicrotasks: boolean;\n\n hasPendingMacrotasks: boolean;\n hasPendingMicrotasks: boolean;\n lastRequestAnimationFrameId: number;\n /**\n * A flag to indicate if NgZone is currently inside\n * checkStable and to prevent re-entry. The flag is\n * needed because it is possible to invoke the change\n * detection from within change detection leading to\n * incorrect behavior.\n *\n * For detail, please refer here,\n * https://github.com/angular/angular/pull/40540\n */\n isCheckStableRunning: boolean;\n isStable: boolean;\n /**\n * Optionally specify coalescing event change detections or not.\n * Consider the following case.\n *\n * <div (click)=\"doSomething()\">\n * <button (click)=\"doSomethingElse()\"></button>\n * </div>\n *\n * When button is clicked, because of the event bubbling, both\n * event handlers will be called and 2 change detections will be\n * triggered. We can coalesce such kind of events to trigger\n * change detection only once.\n *\n * By default, this option will be false. So the events will not be\n * coalesced and the change detection will be triggered multiple times.\n * And if this option be set to true, the change detection will be\n * triggered async by scheduling it in an animation frame. So in the case above,\n * the change detection will only be trigged once.\n */\n shouldCoalesceEventChangeDetection: boolean;\n /**\n * Optionally specify if `NgZone#run()` method invocations should be coalesced\n * into a single change detection.\n *\n * Consider the following case.\n *\n * for (let i = 0; i < 10; i ++) {\n * ngZone.run(() => {\n * // do something\n * });\n * }\n *\n * This case triggers the change detection multiple times.\n * With ngZoneRunCoalescing options, all change detections in an event loops trigger only once.\n * In addition, the change detection executes in requestAnimation.\n *\n */\n shouldCoalesceRunChangeDetection: boolean;\n\n nativeRequestAnimationFrame: (callback: FrameRequestCallback) => number;\n\n // Cache a \"fake\" top eventTask so you don't need to schedule a new task every\n // time you run a `checkStable`.\n fakeTopEventTask: Task;\n}\n\nfunction checkStable(zone: NgZonePrivate) {\n // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent\n // re-entry. The case is:\n //\n // @Component({...})\n // export class AppComponent {\n // constructor(private ngZone: NgZone) {\n // this.ngZone.onStable.subscribe(() => {\n // this.ngZone.run(() => console.log('stable'););\n // });\n // }\n //\n // The onStable subscriber run another function inside ngZone\n // which causes `checkStable()` re-entry.\n // But this fix causes some issues in g3, so this fix will be\n // launched in another PR.\n if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {\n try {\n zone._nesting++;\n zone.onMicrotaskEmpty.emit(null);\n } finally {\n zone._nesting--;\n if (!zone.hasPendingMicrotasks) {\n try {\n zone.runOutsideAngular(() => zone.onStable.emit(null));\n } finally {\n zone.isStable = true;\n }\n }\n }\n }\n}\n\nfunction delayChangeDetectionForEvents(zone: NgZonePrivate) {\n /**\n * We also need to check _nesting here\n * Consider the following case with shouldCoalesceRunChangeDetection = true\n *\n * ngZone.run(() => {});\n * ngZone.run(() => {});\n *\n * We want the two `ngZone.run()` only trigger one change detection\n * when shouldCoalesceRunChangeDetection is true.\n * And because in this case, change detection run in async way(requestAnimationFrame),\n * so we also need to check the _nesting here to prevent multiple\n * change detections.\n */\n if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {\n return;\n }\n zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(global, () => {\n // This is a work around for https://github.com/angular/angular/issues/36839.\n // The core issue is that when event coalescing is enabled it is possible for microtasks\n // to get flushed too early (As is the case with `Promise.then`) between the\n // coalescing eventTasks.\n //\n // To workaround this we schedule a \"fake\" eventTask before we process the\n // coalescing eventTasks. The benefit of this is that the \"fake\" container eventTask\n // will prevent the microtasks queue from getting drained in between the coalescing\n // eventTask execution.\n if (!zone.fakeTopEventTask) {\n zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {\n zone.lastRequestAnimationFrameId = -1;\n updateMicroTaskStatus(zone);\n zone.isCheckStableRunning = true;\n checkStable(zone);\n zone.isCheckStableRunning = false;\n }, undefined, () => {}, () => {});\n }\n zone.fakeTopEventTask.invoke();\n });\n updateMicroTaskStatus(zone);\n}\n\nfunction forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) {\n const delayChangeDetectionForEventsDelegate = () => {\n delayChangeDetectionForEvents(zone);\n };\n zone._inner = zone._inner.fork({\n name: 'angular',\n properties: <any>{'isAngularZone': true},\n onInvokeTask:\n (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any,\n applyArgs: any): any => {\n try {\n onEnter(zone);\n return delegate.invokeTask(target, task, applyThis, applyArgs);\n } finally {\n if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||\n zone.shouldCoalesceRunChangeDetection) {\n delayChangeDetectionForEventsDelegate();\n }\n onLeave(zone);\n }\n },\n\n onInvoke:\n (delegate: ZoneDelegate, current: Zone, target: Zone, callback: Function, applyThis: any,\n applyArgs?: any[], source?: string): any => {\n try {\n onEnter(zone);\n return delegate.invoke(target, callback, applyThis, applyArgs, source);\n } finally {\n if (zone.shouldCoalesceRunChangeDetection) {\n delayChangeDetectionForEventsDelegate();\n }\n onLeave(zone);\n }\n },\n\n onHasTask:\n (delegate: ZoneDelegate, current: Zone, target: Zone, hasTaskState: HasTaskState) => {\n delegate.hasTask(target, hasTaskState);\n if (current === target) {\n // We are only interested in hasTask events which originate from our zone\n // (A child hasTask event is not interesting to us)\n if (hasTaskState.change == 'microTask') {\n zone._hasPendingMicrotasks = hasTaskState.microTask;\n updateMicroTaskStatus(zone);\n checkStable(zone);\n } else if (hasTaskState.change == 'macroTask') {\n zone.hasPendingMacrotasks = hasTaskState.macroTask;\n }\n }\n },\n\n onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): boolean => {\n delegate.handleError(target, error);\n zone.runOutsideAngular(() => zone.onError.emit(error));\n return false;\n }\n });\n}\n\nfunction updateMicroTaskStatus(zone: NgZonePrivate) {\n if (zone._hasPendingMicrotasks ||\n ((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&\n zone.lastRequestAnimationFrameId !== -1)) {\n zone.hasPendingMicrotasks = true;\n } else {\n zone.hasPendingMicrotasks = false;\n }\n}\n\nfunction onEnter(zone: NgZonePrivate) {\n zone._nesting++;\n if (zone.isStable) {\n zone.isStable = false;\n zone.onUnstable.emit(null);\n }\n}\n\nfunction onLeave(zone: NgZonePrivate) {\n zone._nesting--;\n checkStable(zone);\n}\n\n/**\n * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls\n * to framework to perform rendering.\n */\nexport class NoopNgZone implements NgZone {\n readonly hasPendingMicrotasks: boolean = false;\n readonly hasPendingMacrotasks: boolean = false;\n readonly isStable: boolean = true;\n readonly onUnstable: EventEmitter<any> = new EventEmitter();\n readonly onMicrotaskEmpty: EventEmitter<any> = new EventEmitter();\n readonly onStable: EventEmitter<any> = new EventEmitter();\n readonly onError: EventEmitter<any> = new EventEmitter();\n\n run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any): T {\n return fn.apply(applyThis, applyArgs);\n }\n\n runGuarded<T>(fn: (...args: any[]) => any, applyThis?: any, applyArgs?: any): T {\n return fn.apply(applyThis, applyArgs);\n }\n\n runOutsideAngular<T>(fn: (...args: any[]) => T): T {\n return fn();\n }\n\n runTask<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any, name?: string): T {\n return fn.apply(applyThis, applyArgs);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {global} from './global';\n\nexport function getNativeRequestAnimationFrame() {\n let nativeRequestAnimationFrame: (callback: FrameRequestCallback) => number =\n global['requestAnimationFrame'];\n let nativeCancelAnimationFrame: (handle: number) => void = global['cancelAnimationFrame'];\n if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame! && nativeCancelAnimationFrame!) {\n // use unpatched version of requestAnimationFrame(native delegate) if possible\n // to avoid another Change detection\n const unpatchedRequestAnimationFrame =\n (nativeRequestAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];\n if (unpatchedRequestAnimationFrame) {\n nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;\n }\n const unpatchedCancelAnimationFrame =\n (nativeCancelAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];\n if (unpatchedCancelAnimationFrame) {\n nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;\n }\n }\n return {nativeRequestAnimationFrame, nativeCancelAnimationFrame};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, Injectable, InjectionToken} from '../di';\nimport {scheduleMicroTask} from '../util/microtask';\nimport {NgZone} from '../zone/ng_zone';\n\n/**\n * Testability API.\n * `declare` keyword causes tsickle to generate externs, so these methods are\n * not renamed by Closure Compiler.\n * @publicApi\n */\nexport declare interface PublicTestability {\n isStable(): boolean;\n whenStable(callback: Function, timeout?: number, updateCallback?: Function): void;\n findProviders(using: any, provider: string, exactMatch: boolean): any[];\n}\n\n// Angular internal, not intended for public API.\nexport interface PendingMacrotask {\n source: string;\n creationLocation: Error;\n runCount?: number;\n data?: TaskData;\n}\n\nexport interface TaskData {\n target?: XMLHttpRequest;\n delay?: number;\n isPeriodic?: boolean;\n}\n\n// Angular internal, not intended for public API.\nexport type DoneCallback = (didWork: boolean, tasks?: PendingMacrotask[]) => void;\nexport type UpdateCallback = (tasks: PendingMacrotask[]) => boolean;\n\ninterface WaitCallback {\n // Needs to be 'any' - setTimeout returns a number according to ES6, but\n // on NodeJS it returns a Timer.\n timeoutId: any;\n doneCb: DoneCallback;\n updateCb?: UpdateCallback;\n}\n\n/**\n * Internal injection token that can used to access an instance of a Testability class.\n *\n * This token acts as a bridge between the core bootstrap code and the `Testability` class. This is\n * needed to ensure that there are no direct references to the `Testability` class, so it can be\n * tree-shaken away (if not referenced). For the environments/setups when the `Testability` class\n * should be available, this token is used to add a provider that references the `Testability`\n * class. Otherwise, only this token is retained in a bundle, but the `Testability` class is not.\n */\nexport const TESTABILITY = new InjectionToken<Testability>('');\n\n/**\n * Internal injection token to retrieve Testability getter class instance.\n */\nexport const TESTABILITY_GETTER = new InjectionToken<GetTestability>('');\n\n/**\n * The Testability service provides testing hooks that can be accessed from\n * the browser.\n *\n * Angular applications bootstrapped using an NgModule (via `@NgModule.bootstrap` field) will also\n * instantiate Testability by default (in both development and production modes).\n *\n * For applications bootstrapped using the `bootstrapApplication` function, Testability is not\n * included by default. You can include it into your applications by getting the list of necessary\n * providers using the `provideProtractorTestingSupport()` function and adding them into the\n * `options.providers` array. Example:\n *\n * ```typescript\n * import {provideProtractorTestingSupport} from '@angular/platform-browser';\n *\n * await bootstrapApplication(RootComponent, providers: [provideProtractorTestingSupport()]);\n * ```\n *\n * @publicApi\n */\n@Injectable()\nexport class Testability implements PublicTestability {\n private _pendingCount: number = 0;\n private _isZoneStable: boolean = true;\n /**\n * Whether any work was done since the last 'whenStable' callback. This is\n * useful to detect if this could have potentially destabilized another\n * component while it is stabilizing.\n * @internal\n */\n private _didWork: boolean = false;\n private _callbacks: WaitCallback[] = [];\n\n private taskTrackingZone: {macroTasks: Task[]}|null = null;\n\n constructor(\n private _ngZone: NgZone, private registry: TestabilityRegistry,\n @Inject(TESTABILITY_GETTER) testabilityGetter: GetTestability) {\n // If there was no Testability logic registered in the global scope\n // before, register the current testability getter as a global one.\n if (!_testabilityGetter) {\n setTestabilityGetter(testabilityGetter);\n testabilityGetter.addToWindow(registry);\n }\n this._watchAngularEvents();\n _ngZone.run(() => {\n this.taskTrackingZone =\n typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone');\n });\n }\n\n private _watchAngularEvents(): void {\n this._ngZone.onUnstable.subscribe({\n next: () => {\n this._didWork = true;\n this._isZoneStable = false;\n }\n });\n\n this._ngZone.runOutsideAngular(() => {\n this._ngZone.onStable.subscribe({\n next: () => {\n NgZone.assertNotInAngularZone();\n scheduleMicroTask(() => {\n this._isZoneStable = true;\n this._runCallbacksIfReady();\n });\n }\n });\n });\n }\n\n /**\n * Increases the number of pending request\n * @deprecated pending requests are now tracked with zones.\n */\n increasePendingRequestCount(): number {\n this._pendingCount += 1;\n this._didWork = true;\n return this._pendingCount;\n }\n\n /**\n * Decreases the number of pending request\n * @deprecated pending requests are now tracked with zones\n */\n decreasePendingRequestCount(): number {\n this._pendingCount -= 1;\n if (this._pendingCount < 0) {\n throw new Error('pending async requests below zero');\n }\n this._runCallbacksIfReady();\n return this._pendingCount;\n }\n\n /**\n * Whether an associated application is stable\n */\n isStable(): boolean {\n return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;\n }\n\n private _runCallbacksIfReady(): void {\n if (this.isStable()) {\n // Schedules the call backs in a new frame so that it is always async.\n scheduleMicroTask(() => {\n while (this._callbacks.length !== 0) {\n let cb = this._callbacks.pop()!;\n clearTimeout(cb.timeoutId);\n cb.doneCb(this._didWork);\n }\n this._didWork = false;\n });\n } else {\n // Still not stable, send updates.\n let pending = this.getPendingTasks();\n this._callbacks = this._callbacks.filter((cb) => {\n if (cb.updateCb && cb.updateCb(pending)) {\n clearTimeout(cb.timeoutId);\n return false;\n }\n\n return true;\n });\n\n this._didWork = true;\n }\n }\n\n private getPendingTasks(): PendingMacrotask[] {\n if (!this.taskTrackingZone) {\n return [];\n }\n\n // Copy the tasks data so that we don't leak tasks.\n return this.taskTrackingZone.macroTasks.map((t: Task) => {\n return {\n source: t.source,\n // From TaskTrackingZone:\n // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40\n creationLocation: (t as any).creationLocation as Error,\n data: t.data\n };\n });\n }\n\n private addCallback(cb: DoneCallback, timeout?: number, updateCb?: UpdateCallback) {\n let timeoutId: any = -1;\n if (timeout && timeout > 0) {\n timeoutId = setTimeout(() => {\n this._callbacks = this._callbacks.filter((cb) => cb.timeoutId !== timeoutId);\n cb(this._didWork, this.getPendingTasks());\n }, timeout);\n }\n this._callbacks.push(<WaitCallback>{doneCb: cb, timeoutId: timeoutId, updateCb: updateCb});\n }\n\n /**\n * Wait for the application to be stable with a timeout. If the timeout is reached before that\n * happens, the callback receives a list of the macro tasks that were pending, otherwise null.\n *\n * @param doneCb The callback to invoke when Angular is stable or the timeout expires\n * whichever comes first.\n * @param timeout Optional. The maximum time to wait for Angular to become stable. If not\n * specified, whenStable() will wait forever.\n * @param updateCb Optional. If specified, this callback will be invoked whenever the set of\n * pending macrotasks changes. If this callback returns true doneCb will not be invoked\n * and no further updates will be issued.\n */\n whenStable(doneCb: Function, timeout?: number, updateCb?: Function): void {\n if (updateCb && !this.taskTrackingZone) {\n throw new Error(\n 'Task tracking zone is required when passing an update callback to ' +\n 'whenStable(). Is \"zone.js/plugins/task-tracking\" loaded?');\n }\n // These arguments are 'Function' above to keep the public API simple.\n this.addCallback(doneCb as DoneCallback, timeout, updateCb as UpdateCallback);\n this._runCallbacksIfReady();\n }\n\n /**\n * Get the number of pending requests\n * @deprecated pending requests are now tracked with zones\n */\n getPendingRequestCount(): number {\n return this._pendingCount;\n }\n /**\n * Registers an application with a testability hook so that it can be tracked.\n * @param token token of application, root element\n *\n * @internal\n */\n registerApplication(token: any) {\n this.registry.registerApplication(token, this);\n }\n\n /**\n * Unregisters an application.\n * @param token token of application, root element\n *\n * @internal\n */\n unregisterApplication(token: any) {\n this.registry.unregisterApplication(token);\n }\n\n /**\n * Find providers by name\n * @param using The root element to search from\n * @param provider The name of binding variable\n * @param exactMatch Whether using exactMatch\n */\n findProviders(using: any, provider: string, exactMatch: boolean): any[] {\n // TODO(juliemr): implement.\n return [];\n }\n}\n\n/**\n * A global registry of {@link Testability} instances for specific elements.\n * @publicApi\n */\n@Injectable({providedIn: 'platform'})\nexport class TestabilityRegistry {\n /** @internal */\n _applications = new Map<any, Testability>();\n\n /**\n * Registers an application with a testability hook so that it can be tracked\n * @param token token of application, root element\n * @param testability Testability hook\n */\n registerApplication(token: any, testability: Testability) {\n this._applications.set(token, testability);\n }\n\n /**\n * Unregisters an application.\n * @param token token of application, root element\n */\n unregisterApplication(token: any) {\n this._applications.delete(token);\n }\n\n /**\n * Unregisters all applications\n */\n unregisterAllApplications() {\n this._applications.clear();\n }\n\n /**\n * Get a testability hook associated with the application\n * @param elem root element\n */\n getTestability(elem: any): Testability|null {\n return this._applications.get(elem) || null;\n }\n\n /**\n * Get all registered testabilities\n */\n getAllTestabilities(): Testability[] {\n return Array.from(this._applications.values());\n }\n\n /**\n * Get all registered applications(root elements)\n */\n getAllRootElements(): any[] {\n return Array.from(this._applications.keys());\n }\n\n /**\n * Find testability of a node in the Tree\n * @param elem node\n * @param findInAncestors whether finding testability in ancestors if testability was not found in\n * current node\n */\n findTestabilityInTree(elem: Node, findInAncestors: boolean = true): Testability|null {\n return _testabilityGetter?.findTestabilityInTree(this, elem, findInAncestors) ?? null;\n }\n}\n\n/**\n * Adapter interface for retrieving the `Testability` service associated for a\n * particular context.\n *\n * @publicApi\n */\nexport interface GetTestability {\n addToWindow(registry: TestabilityRegistry): void;\n findTestabilityInTree(registry: TestabilityRegistry, elem: any, findInAncestors: boolean):\n Testability|null;\n}\n\n/**\n * Set the {@link GetTestability} implementation used by the Angular testing framework.\n * @publicApi\n */\nexport function setTestabilityGetter(getter: GetTestability): void {\n _testabilityGetter = getter;\n}\n\nlet _testabilityGetter: GetTestability|undefined;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport './util/ng_jit_mode';\n\nimport {merge, Observable, Observer, Subscription} from 'rxjs';\nimport {share} from 'rxjs/operators';\n\nimport {ApplicationInitStatus} from './application_init';\nimport {PLATFORM_INITIALIZER} from './application_tokens';\nimport {getCompilerFacade, JitCompilerUsage} from './compiler/compiler_facade';\nimport {Console} from './console';\nimport {Injectable} from './di/injectable';\nimport {InjectionToken} from './di/injection_token';\nimport {Injector} from './di/injector';\nimport {EnvironmentProviders, Provider, StaticProvider} from './di/interface/provider';\nimport {EnvironmentInjector} from './di/r3_injector';\nimport {INJECTOR_SCOPE} from './di/scope';\nimport {ErrorHandler} from './error_handler';\nimport {formatRuntimeError, RuntimeError, RuntimeErrorCode} from './errors';\nimport {DEFAULT_LOCALE_ID} from './i18n/localization';\nimport {LOCALE_ID} from './i18n/tokens';\nimport {Type} from './interface/type';\nimport {COMPILER_OPTIONS, CompilerOptions} from './linker/compiler';\nimport {ComponentFactory, ComponentRef} from './linker/component_factory';\nimport {ComponentFactoryResolver} from './linker/component_factory_resolver';\nimport {InternalNgModuleRef, NgModuleFactory, NgModuleRef} from './linker/ng_module_factory';\nimport {InternalViewRef, ViewRef} from './linker/view_ref';\nimport {isComponentResourceResolutionQueueEmpty, resolveComponentResources} from './metadata/resource_loading';\nimport {assertNgModuleType} from './render3/assert';\nimport {ComponentFactory as R3ComponentFactory} from './render3/component_ref';\nimport {isStandalone} from './render3/definition';\nimport {assertStandaloneComponentType} from './render3/errors';\nimport {setLocaleId} from './render3/i18n/i18n_locale_id';\nimport {setJitOptions} from './render3/jit/jit_options';\nimport {createEnvironmentInjector, NgModuleFactory as R3NgModuleFactory} from './render3/ng_module_ref';\nimport {publishDefaultGlobalUtils as _publishDefaultGlobalUtils} from './render3/util/global_utils';\nimport {TESTABILITY} from './testability/testability';\nimport {isPromise} from './util/lang';\nimport {scheduleMicroTask} from './util/microtask';\nimport {stringify} from './util/stringify';\nimport {NgZone, NoopNgZone} from './zone/ng_zone';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\nlet _platformInjector: Injector|null = null;\n\n/**\n * Internal token to indicate whether having multiple bootstrapped platform should be allowed (only\n * one bootstrapped platform is allowed by default). This token helps to support SSR scenarios.\n */\nexport const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken<boolean>('AllowMultipleToken');\n\n/**\n * Internal token that allows to register extra callbacks that should be invoked during the\n * `PlatformRef.destroy` operation. This token is needed to avoid a direct reference to the\n * `PlatformRef` class (i.e. register the callback via `PlatformRef.onDestroy`), thus making the\n * entire class tree-shakeable.\n */\nconst PLATFORM_DESTROY_LISTENERS =\n new InjectionToken<Set<VoidFunction>>('PlatformDestroyListeners');\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") that provides a set of callbacks to\n * be called for every component that is bootstrapped.\n *\n * Each callback must take a `ComponentRef` instance and return nothing.\n *\n * `(componentRef: ComponentRef) => void`\n *\n * @publicApi\n */\nexport const APP_BOOTSTRAP_LISTENER =\n new InjectionToken<Array<(compRef: ComponentRef<any>) => void>>('appBootstrapListener');\n\nexport function compileNgModuleFactory<M>(\n injector: Injector, options: CompilerOptions,\n moduleType: Type<M>): Promise<NgModuleFactory<M>> {\n ngDevMode && assertNgModuleType(moduleType);\n\n const moduleFactory = new R3NgModuleFactory(moduleType);\n\n // All of the logic below is irrelevant for AOT-compiled code.\n if (typeof ngJitMode !== 'undefined' && !ngJitMode) {\n return Promise.resolve(moduleFactory);\n }\n\n const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options);\n\n // Configure the compiler to use the provided options. This call may fail when multiple modules\n // are bootstrapped with incompatible options, as a component can only be compiled according to\n // a single set of options.\n setJitOptions({\n defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),\n preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces)),\n });\n\n if (isComponentResourceResolutionQueueEmpty()) {\n return Promise.resolve(moduleFactory);\n }\n\n const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers!));\n\n // In case there are no compiler providers, we just return the module factory as\n // there won't be any resource loader. This can happen with Ivy, because AOT compiled\n // modules can be still passed through \"bootstrapModule\". In that case we shouldn't\n // unnecessarily require the JIT compiler.\n if (compilerProviders.length === 0) {\n return Promise.resolve(moduleFactory);\n }\n\n const compiler = getCompilerFacade({\n usage: JitCompilerUsage.Decorator,\n kind: 'NgModule',\n type: moduleType,\n });\n const compilerInjector = Injector.create({providers: compilerProviders});\n const resourceLoader = compilerInjector.get(compiler.ResourceLoader);\n // The resource loader can also return a string while the \"resolveComponentResources\"\n // always expects a promise. Therefore we need to wrap the returned value in a promise.\n return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url)))\n .then(() => moduleFactory);\n}\n\nexport function publishDefaultGlobalUtils() {\n ngDevMode && _publishDefaultGlobalUtils();\n}\n\nexport function isBoundToModule<C>(cf: ComponentFactory<C>): boolean {\n return (cf as R3ComponentFactory<C>).isBoundToModule;\n}\n\n/**\n * A token for third-party components that can register themselves with NgProbe.\n *\n * @publicApi\n */\nexport class NgProbeToken {\n constructor(public name: string, public token: any) {}\n}\n\n/**\n * Creates a platform.\n * Platforms must be created on launch using this function.\n *\n * @publicApi\n */\nexport function createPlatform(injector: Injector): PlatformRef {\n if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {\n throw new RuntimeError(\n RuntimeErrorCode.MULTIPLE_PLATFORMS,\n ngDevMode &&\n 'There can be only one platform. Destroy the previous one to create a new one.');\n }\n publishDefaultGlobalUtils();\n _platformInjector = injector;\n const platform = injector.get(PlatformRef);\n runPlatformInitializers(injector);\n return platform;\n}\n\n/**\n * The goal of this function is to bootstrap a platform injector,\n * but avoid referencing `PlatformRef` class.\n * This function is needed for bootstrapping a Standalone Component.\n */\nexport function createOrReusePlatformInjector(providers: StaticProvider[] = []): Injector {\n // If a platform injector already exists, it means that the platform\n // is already bootstrapped and no additional actions are required.\n if (_platformInjector) return _platformInjector;\n\n // Otherwise, setup a new platform injector and run platform initializers.\n const injector = createPlatformInjector(providers);\n _platformInjector = injector;\n publishDefaultGlobalUtils();\n runPlatformInitializers(injector);\n return injector;\n}\n\nexport function runPlatformInitializers(injector: Injector): void {\n const inits = injector.get(PLATFORM_INITIALIZER, null);\n if (inits) {\n inits.forEach((init: any) => init());\n }\n}\n\n/**\n * Internal create application API that implements the core application creation logic and optional\n * bootstrap logic.\n *\n * Platforms (such as `platform-browser`) may require different set of application and platform\n * providers for an application to function correctly. As a result, platforms may use this function\n * internally and supply the necessary providers during the bootstrap, while exposing\n * platform-specific APIs as a part of their public API.\n *\n * @returns A promise that returns an `ApplicationRef` instance once resolved.\n */\nexport function internalCreateApplication(config: {\n rootComponent?: Type<unknown>,\n appProviders?: Array<Provider|EnvironmentProviders>,\n platformProviders?: Provider[],\n}): Promise<ApplicationRef> {\n const {rootComponent, appProviders, platformProviders} = config;\n\n if (NG_DEV_MODE && rootComponent !== undefined) {\n assertStandaloneComponentType(rootComponent);\n }\n\n const platformInjector = createOrReusePlatformInjector(platformProviders as StaticProvider[]);\n\n const ngZone = getNgZone('zone.js', getNgZoneOptions());\n\n return ngZone.run(() => {\n // Create root application injector based on a set of providers configured at the platform\n // bootstrap level as well as providers passed to the bootstrap call by a user.\n const allAppProviders = [\n {provide: NgZone, useValue: ngZone}, //\n ...(appProviders || []), //\n ];\n\n const envInjector = createEnvironmentInjector(\n allAppProviders, platformInjector as EnvironmentInjector, 'Environment Injector');\n\n const exceptionHandler: ErrorHandler|null = envInjector.get(ErrorHandler, null);\n if (NG_DEV_MODE && !exceptionHandler) {\n throw new RuntimeError(\n RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND,\n 'No `ErrorHandler` found in the Dependency Injection tree.');\n }\n\n let onErrorSubscription: Subscription;\n ngZone.runOutsideAngular(() => {\n onErrorSubscription = ngZone.onError.subscribe({\n next: (error: any) => {\n exceptionHandler!.handleError(error);\n }\n });\n });\n\n // If the whole platform is destroyed, invoke the `destroy` method\n // for all bootstrapped applications as well.\n const destroyListener = () => envInjector.destroy();\n const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS);\n onPlatformDestroyListeners.add(destroyListener);\n\n envInjector.onDestroy(() => {\n onErrorSubscription.unsubscribe();\n onPlatformDestroyListeners.delete(destroyListener);\n });\n\n return _callAndReportToErrorHandler(exceptionHandler!, ngZone, () => {\n const initStatus = envInjector.get(ApplicationInitStatus);\n initStatus.runInitializers();\n\n return initStatus.donePromise.then(() => {\n const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);\n setLocaleId(localeId || DEFAULT_LOCALE_ID);\n\n const appRef = envInjector.get(ApplicationRef);\n if (rootComponent !== undefined) {\n appRef.bootstrap(rootComponent);\n }\n return appRef;\n });\n });\n });\n}\n\n/**\n * Creates a factory for a platform. Can be used to provide or override `Providers` specific to\n * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.\n * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories\n * to build up configurations that might be required by different libraries or parts of the\n * application.\n * @param name Identifies the new platform factory.\n * @param providers A set of dependency providers for platforms created with the new factory.\n *\n * @publicApi\n */\nexport function createPlatformFactory(\n parentPlatformFactory: ((extraProviders?: StaticProvider[]) => PlatformRef)|null, name: string,\n providers: StaticProvider[] = []): (extraProviders?: StaticProvider[]) => PlatformRef {\n const desc = `Platform: ${name}`;\n const marker = new InjectionToken(desc);\n return (extraProviders: StaticProvider[] = []) => {\n let platform = getPlatform();\n if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {\n const platformProviders: StaticProvider[] = [\n ...providers, //\n ...extraProviders, //\n {provide: marker, useValue: true}\n ];\n if (parentPlatformFactory) {\n parentPlatformFactory(platformProviders);\n } else {\n createPlatform(createPlatformInjector(platformProviders, desc));\n }\n }\n return assertPlatform(marker);\n };\n}\n\n/**\n * Checks that there is currently a platform that contains the given token as a provider.\n *\n * @publicApi\n */\nexport function assertPlatform(requiredToken: any): PlatformRef {\n const platform = getPlatform();\n\n if (!platform) {\n throw new RuntimeError(RuntimeErrorCode.PLATFORM_NOT_FOUND, ngDevMode && 'No platform exists!');\n }\n\n if ((typeof ngDevMode === 'undefined' || ngDevMode) &&\n !platform.injector.get(requiredToken, null)) {\n throw new RuntimeError(\n RuntimeErrorCode.MULTIPLE_PLATFORMS,\n 'A platform with a different configuration has been created. Please destroy it first.');\n }\n\n return platform;\n}\n\n/**\n * Helper function to create an instance of a platform injector (that maintains the 'platform'\n * scope).\n */\nexport function createPlatformInjector(providers: StaticProvider[] = [], name?: string): Injector {\n return Injector.create({\n name,\n providers: [\n {provide: INJECTOR_SCOPE, useValue: 'platform'},\n {provide: PLATFORM_DESTROY_LISTENERS, useValue: new Set([() => _platformInjector = null])},\n ...providers\n ],\n });\n}\n\n/**\n * Destroys the current Angular platform and all Angular applications on the page.\n * Destroys all modules and listeners registered with the platform.\n *\n * @publicApi\n */\nexport function destroyPlatform(): void {\n getPlatform()?.destroy();\n}\n\n/**\n * Returns the current platform.\n *\n * @publicApi\n */\nexport function getPlatform(): PlatformRef|null {\n return _platformInjector?.get(PlatformRef) ?? null;\n}\n\n/**\n * Provides additional options to the bootstrapping process.\n *\n * @publicApi\n */\nexport interface BootstrapOptions {\n /**\n * Optionally specify which `NgZone` should be used.\n *\n * - Provide your own `NgZone` instance.\n * - `zone.js` - Use default `NgZone` which requires `Zone.js`.\n * - `noop` - Use `NoopNgZone` which does nothing.\n */\n ngZone?: NgZone|'zone.js'|'noop';\n\n /**\n * Optionally specify coalescing event change detections or not.\n * Consider the following case.\n *\n * ```\n * <div (click)=\"doSomething()\">\n * <button (click)=\"doSomethingElse()\"></button>\n * </div>\n * ```\n *\n * When button is clicked, because of the event bubbling, both\n * event handlers will be called and 2 change detections will be\n * triggered. We can coalesce such kind of events to only trigger\n * change detection only once.\n *\n * By default, this option will be false. So the events will not be\n * coalesced and the change detection will be triggered multiple times.\n * And if this option be set to true, the change detection will be\n * triggered async by scheduling a animation frame. So in the case above,\n * the change detection will only be triggered once.\n */\n ngZoneEventCoalescing?: boolean;\n\n /**\n * Optionally specify if `NgZone#run()` method invocations should be coalesced\n * into a single change detection.\n *\n * Consider the following case.\n * ```\n * for (let i = 0; i < 10; i ++) {\n * ngZone.run(() => {\n * // do something\n * });\n * }\n * ```\n *\n * This case triggers the change detection multiple times.\n * With ngZoneRunCoalescing options, all change detections in an event loop trigger only once.\n * In addition, the change detection executes in requestAnimation.\n *\n */\n ngZoneRunCoalescing?: boolean;\n}\n\n/**\n * The Angular platform is the entry point for Angular on a web page.\n * Each page has exactly one platform. Services (such as reflection) which are common\n * to every Angular application running on the page are bound in its scope.\n * A page's platform is initialized implicitly when a platform is created using a platform\n * factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'platform'})\nexport class PlatformRef {\n private _modules: NgModuleRef<any>[] = [];\n private _destroyListeners: Array<() => void> = [];\n private _destroyed: boolean = false;\n\n /** @internal */\n constructor(private _injector: Injector) {}\n\n /**\n * Creates an instance of an `@NgModule` for the given platform.\n *\n * @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function\n * argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.\n */\n bootstrapModuleFactory<M>(moduleFactory: NgModuleFactory<M>, options?: BootstrapOptions):\n Promise<NgModuleRef<M>> {\n // Note: We need to create the NgZone _before_ we instantiate the module,\n // as instantiating the module creates some providers eagerly.\n // So we create a mini parent injector that just contains the new NgZone and\n // pass that as parent to the NgModuleFactory.\n const ngZone = getNgZone(options?.ngZone, getNgZoneOptions(options));\n const providers: StaticProvider[] = [{provide: NgZone, useValue: ngZone}];\n // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are\n // created within the Angular zone\n // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be\n // created outside of the Angular zone.\n return ngZone.run(() => {\n const ngZoneInjector = Injector.create(\n {providers: providers, parent: this.injector, name: moduleFactory.moduleType.name});\n const moduleRef = <InternalNgModuleRef<M>>moduleFactory.create(ngZoneInjector);\n const exceptionHandler: ErrorHandler|null = moduleRef.injector.get(ErrorHandler, null);\n if (!exceptionHandler) {\n throw new RuntimeError(\n RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND,\n ngDevMode && 'No ErrorHandler. Is platform module (BrowserModule) included?');\n }\n ngZone!.runOutsideAngular(() => {\n const subscription = ngZone!.onError.subscribe({\n next: (error: any) => {\n exceptionHandler.handleError(error);\n }\n });\n moduleRef.onDestroy(() => {\n remove(this._modules, moduleRef);\n subscription.unsubscribe();\n });\n });\n return _callAndReportToErrorHandler(exceptionHandler, ngZone!, () => {\n const initStatus: ApplicationInitStatus = moduleRef.injector.get(ApplicationInitStatus);\n initStatus.runInitializers();\n return initStatus.donePromise.then(() => {\n // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy\n const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);\n setLocaleId(localeId || DEFAULT_LOCALE_ID);\n this._moduleDoBootstrap(moduleRef);\n return moduleRef;\n });\n });\n });\n }\n\n /**\n * Creates an instance of an `@NgModule` for a given platform.\n *\n * @usageNotes\n * ### Simple Example\n *\n * ```typescript\n * @NgModule({\n * imports: [BrowserModule]\n * })\n * class MyModule {}\n *\n * let moduleRef = platformBrowser().bootstrapModule(MyModule);\n * ```\n *\n */\n bootstrapModule<M>(\n moduleType: Type<M>,\n compilerOptions: (CompilerOptions&BootstrapOptions)|\n Array<CompilerOptions&BootstrapOptions> = []): Promise<NgModuleRef<M>> {\n const options = optionsReducer({}, compilerOptions);\n return compileNgModuleFactory(this.injector, options, moduleType)\n .then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));\n }\n\n private _moduleDoBootstrap(moduleRef: InternalNgModuleRef<any>): void {\n const appRef = moduleRef.injector.get(ApplicationRef);\n if (moduleRef._bootstrapComponents.length > 0) {\n moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));\n } else if (moduleRef.instance.ngDoBootstrap) {\n moduleRef.instance.ngDoBootstrap(appRef);\n } else {\n throw new RuntimeError(\n RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND,\n ngDevMode &&\n `The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` +\n `but it does not declare \"@NgModule.bootstrap\" components nor a \"ngDoBootstrap\" method. ` +\n `Please define one of these.`);\n }\n this._modules.push(moduleRef);\n }\n\n /**\n * Registers a listener to be called when the platform is destroyed.\n */\n onDestroy(callback: () => void): void {\n this._destroyListeners.push(callback);\n }\n\n /**\n * Retrieves the platform {@link Injector}, which is the parent injector for\n * every Angular application on the page and provides singleton providers.\n */\n get injector(): Injector {\n return this._injector;\n }\n\n /**\n * Destroys the current Angular platform and all Angular applications on the page.\n * Destroys all modules and listeners registered with the platform.\n */\n destroy() {\n if (this._destroyed) {\n throw new RuntimeError(\n RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED,\n ngDevMode && 'The platform has already been destroyed!');\n }\n this._modules.slice().forEach(module => module.destroy());\n this._destroyListeners.forEach(listener => listener());\n\n const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null);\n if (destroyListeners) {\n destroyListeners.forEach(listener => listener());\n destroyListeners.clear();\n }\n\n this._destroyed = true;\n }\n\n /**\n * Indicates whether this instance was destroyed.\n */\n get destroyed() {\n return this._destroyed;\n }\n}\n\n// Set of options recognized by the NgZone.\ninterface NgZoneOptions {\n enableLongStackTrace: boolean;\n shouldCoalesceEventChangeDetection: boolean;\n shouldCoalesceRunChangeDetection: boolean;\n}\n\n// Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) ->\n// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in\n// a set of default options returned.\nfunction getNgZoneOptions(options?: BootstrapOptions): NgZoneOptions {\n return {\n enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode,\n shouldCoalesceEventChangeDetection: !!(options && options.ngZoneEventCoalescing) || false,\n shouldCoalesceRunChangeDetection: !!(options && options.ngZoneRunCoalescing) || false,\n };\n}\n\nfunction getNgZone(ngZoneToUse: NgZone|'zone.js'|'noop'|undefined, options: NgZoneOptions): NgZone {\n let ngZone: NgZone;\n\n if (ngZoneToUse === 'noop') {\n ngZone = new NoopNgZone();\n } else {\n ngZone = (ngZoneToUse === 'zone.js' ? undefined : ngZoneToUse) || new NgZone(options);\n }\n return ngZone;\n}\n\nfunction _callAndReportToErrorHandler(\n errorHandler: ErrorHandler, ngZone: NgZone, callback: () => any): any {\n try {\n const result = callback();\n if (isPromise(result)) {\n return result.catch((e: any) => {\n ngZone.runOutsideAngular(() => errorHandler.handleError(e));\n // rethrow as the exception handler might not do it\n throw e;\n });\n }\n\n return result;\n } catch (e) {\n ngZone.runOutsideAngular(() => errorHandler.handleError(e));\n // rethrow as the exception handler might not do it\n throw e;\n }\n}\n\nfunction optionsReducer<T extends Object>(dst: any, objs: T|T[]): T {\n if (Array.isArray(objs)) {\n dst = objs.reduce(optionsReducer, dst);\n } else {\n dst = {...dst, ...(objs as any)};\n }\n return dst;\n}\n\n/**\n * A reference to an Angular application running on a page.\n *\n * @usageNotes\n *\n * {@a is-stable-examples}\n * ### isStable examples and caveats\n *\n * Note two important points about `isStable`, demonstrated in the examples below:\n * - the application will never be stable if you start any kind\n * of recurrent asynchronous task when the application starts\n * (for example for a polling process, started with a `setInterval`, a `setTimeout`\n * or using RxJS operators like `interval`);\n * - the `isStable` Observable runs outside of the Angular zone.\n *\n * Let's imagine that you start a recurrent task\n * (here incrementing a counter, using RxJS `interval`),\n * and at the same time subscribe to `isStable`.\n *\n * ```\n * constructor(appRef: ApplicationRef) {\n * appRef.isStable.pipe(\n * filter(stable => stable)\n * ).subscribe(() => console.log('App is stable now');\n * interval(1000).subscribe(counter => console.log(counter));\n * }\n * ```\n * In this example, `isStable` will never emit `true`,\n * and the trace \"App is stable now\" will never get logged.\n *\n * If you want to execute something when the app is stable,\n * you have to wait for the application to be stable\n * before starting your polling process.\n *\n * ```\n * constructor(appRef: ApplicationRef) {\n * appRef.isStable.pipe(\n * first(stable => stable),\n * tap(stable => console.log('App is stable now')),\n * switchMap(() => interval(1000))\n * ).subscribe(counter => console.log(counter));\n * }\n * ```\n * In this example, the trace \"App is stable now\" will be logged\n * and then the counter starts incrementing every second.\n *\n * Note also that this Observable runs outside of the Angular zone,\n * which means that the code in the subscription\n * to this Observable will not trigger the change detection.\n *\n * Let's imagine that instead of logging the counter value,\n * you update a field of your component\n * and display it in its template.\n *\n * ```\n * constructor(appRef: ApplicationRef) {\n * appRef.isStable.pipe(\n * first(stable => stable),\n * switchMap(() => interval(1000))\n * ).subscribe(counter => this.value = counter);\n * }\n * ```\n * As the `isStable` Observable runs outside the zone,\n * the `value` field will be updated properly,\n * but the template will not be refreshed!\n *\n * You'll have to manually trigger the change detection to update the template.\n *\n * ```\n * constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) {\n * appRef.isStable.pipe(\n * first(stable => stable),\n * switchMap(() => interval(1000))\n * ).subscribe(counter => {\n * this.value = counter;\n * cd.detectChanges();\n * });\n * }\n * ```\n *\n * Or make the subscription callback run inside the zone.\n *\n * ```\n * constructor(appRef: ApplicationRef, zone: NgZone) {\n * appRef.isStable.pipe(\n * first(stable => stable),\n * switchMap(() => interval(1000))\n * ).subscribe(counter => zone.run(() => this.value = counter));\n * }\n * ```\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class ApplicationRef {\n /** @internal */\n private _bootstrapListeners: ((compRef: ComponentRef<any>) => void)[] = [];\n private _views: InternalViewRef[] = [];\n private _runningTick: boolean = false;\n private _stable = true;\n private _onMicrotaskEmptySubscription: Subscription;\n private _destroyed = false;\n private _destroyListeners: Array<() => void> = [];\n\n /**\n * Indicates whether this instance was destroyed.\n */\n get destroyed() {\n return this._destroyed;\n }\n\n /**\n * Get a list of component types registered to this application.\n * This list is populated even before the component is created.\n */\n public readonly componentTypes: Type<any>[] = [];\n\n /**\n * Get a list of components registered to this application.\n */\n public readonly components: ComponentRef<any>[] = [];\n\n /**\n * Returns an Observable that indicates when the application is stable or unstable.\n *\n * @see [Usage notes](#is-stable-examples) for examples and caveats when using this API.\n */\n // TODO(issue/24571): remove '!'.\n public readonly isStable!: Observable<boolean>;\n\n /**\n * The `EnvironmentInjector` used to create this application.\n */\n get injector(): EnvironmentInjector {\n return this._injector;\n }\n\n /** @internal */\n constructor(\n private _zone: NgZone,\n private _injector: EnvironmentInjector,\n private _exceptionHandler: ErrorHandler,\n ) {\n this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({\n next: () => {\n this._zone.run(() => {\n this.tick();\n });\n }\n });\n\n const isCurrentlyStable = new Observable<boolean>((observer: Observer<boolean>) => {\n this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks &&\n !this._zone.hasPendingMicrotasks;\n this._zone.runOutsideAngular(() => {\n observer.next(this._stable);\n observer.complete();\n });\n });\n\n const isStable = new Observable<boolean>((observer: Observer<boolean>) => {\n // Create the subscription to onStable outside the Angular Zone so that\n // the callback is run outside the Angular Zone.\n let stableSub: Subscription;\n this._zone.runOutsideAngular(() => {\n stableSub = this._zone.onStable.subscribe(() => {\n NgZone.assertNotInAngularZone();\n\n // Check whether there are no pending macro/micro tasks in the next tick\n // to allow for NgZone to update the state.\n scheduleMicroTask(() => {\n if (!this._stable && !this._zone.hasPendingMacrotasks &&\n !this._zone.hasPendingMicrotasks) {\n this._stable = true;\n observer.next(true);\n }\n });\n });\n });\n\n const unstableSub: Subscription = this._zone.onUnstable.subscribe(() => {\n NgZone.assertInAngularZone();\n if (this._stable) {\n this._stable = false;\n this._zone.runOutsideAngular(() => {\n observer.next(false);\n });\n }\n });\n\n return () => {\n stableSub.unsubscribe();\n unstableSub.unsubscribe();\n };\n });\n\n (this as {isStable: Observable<boolean>}).isStable =\n merge(isCurrentlyStable, isStable.pipe(share()));\n }\n\n /**\n * Bootstrap a component onto the element identified by its selector or, optionally, to a\n * specified element.\n *\n * @usageNotes\n * ### Bootstrap process\n *\n * When bootstrapping a component, Angular mounts it onto a target DOM element\n * and kicks off automatic change detection. The target DOM element can be\n * provided using the `rootSelectorOrNode` argument.\n *\n * If the target DOM element is not provided, Angular tries to find one on a page\n * using the `selector` of the component that is being bootstrapped\n * (first matched element is used).\n *\n * ### Example\n *\n * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,\n * but it requires us to know the component while writing the application code.\n *\n * Imagine a situation where we have to wait for an API call to decide about the component to\n * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to\n * dynamically bootstrap a component.\n *\n * {@example core/ts/platform/platform.ts region='componentSelector'}\n *\n * Optionally, a component can be mounted onto a DOM element that does not match the\n * selector of the bootstrapped component.\n *\n * In the following example, we are providing a CSS selector to match the target element.\n *\n * {@example core/ts/platform/platform.ts region='cssSelector'}\n *\n * While in this example, we are providing reference to a DOM node.\n *\n * {@example core/ts/platform/platform.ts region='domNode'}\n */\n bootstrap<C>(component: Type<C>, rootSelectorOrNode?: string|any): ComponentRef<C>;\n\n /**\n * Bootstrap a component onto the element identified by its selector or, optionally, to a\n * specified element.\n *\n * @usageNotes\n * ### Bootstrap process\n *\n * When bootstrapping a component, Angular mounts it onto a target DOM element\n * and kicks off automatic change detection. The target DOM element can be\n * provided using the `rootSelectorOrNode` argument.\n *\n * If the target DOM element is not provided, Angular tries to find one on a page\n * using the `selector` of the component that is being bootstrapped\n * (first matched element is used).\n *\n * ### Example\n *\n * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,\n * but it requires us to know the component while writing the application code.\n *\n * Imagine a situation where we have to wait for an API call to decide about the component to\n * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to\n * dynamically bootstrap a component.\n *\n * {@example core/ts/platform/platform.ts region='componentSelector'}\n *\n * Optionally, a component can be mounted onto a DOM element that does not match the\n * selector of the bootstrapped component.\n *\n * In the following example, we are providing a CSS selector to match the target element.\n *\n * {@example core/ts/platform/platform.ts region='cssSelector'}\n *\n * While in this example, we are providing reference to a DOM node.\n *\n * {@example core/ts/platform/platform.ts region='domNode'}\n *\n * @deprecated Passing Component factories as the `Application.bootstrap` function argument is\n * deprecated. Pass Component Types instead.\n */\n bootstrap<C>(componentFactory: ComponentFactory<C>, rootSelectorOrNode?: string|any):\n ComponentRef<C>;\n\n /**\n * Bootstrap a component onto the element identified by its selector or, optionally, to a\n * specified element.\n *\n * @usageNotes\n * ### Bootstrap process\n *\n * When bootstrapping a component, Angular mounts it onto a target DOM element\n * and kicks off automatic change detection. The target DOM element can be\n * provided using the `rootSelectorOrNode` argument.\n *\n * If the target DOM element is not provided, Angular tries to find one on a page\n * using the `selector` of the component that is being bootstrapped\n * (first matched element is used).\n *\n * ### Example\n *\n * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,\n * but it requires us to know the component while writing the application code.\n *\n * Imagine a situation where we have to wait for an API call to decide about the component to\n * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to\n * dynamically bootstrap a component.\n *\n * {@example core/ts/platform/platform.ts region='componentSelector'}\n *\n * Optionally, a component can be mounted onto a DOM element that does not match the\n * selector of the bootstrapped component.\n *\n * In the following example, we are providing a CSS selector to match the target element.\n *\n * {@example core/ts/platform/platform.ts region='cssSelector'}\n *\n * While in this example, we are providing reference to a DOM node.\n *\n * {@example core/ts/platform/platform.ts region='domNode'}\n */\n bootstrap<C>(componentOrFactory: ComponentFactory<C>|Type<C>, rootSelectorOrNode?: string|any):\n ComponentRef<C> {\n NG_DEV_MODE && this.warnIfDestroyed();\n const isComponentFactory = componentOrFactory instanceof ComponentFactory;\n const initStatus = this._injector.get(ApplicationInitStatus);\n\n if (!initStatus.done) {\n const standalone = !isComponentFactory && isStandalone(componentOrFactory);\n const errorMessage =\n 'Cannot bootstrap as there are still asynchronous initializers running.' +\n (standalone ? '' :\n ' Bootstrap components in the `ngDoBootstrap` method of the root module.');\n throw new RuntimeError(\n RuntimeErrorCode.ASYNC_INITIALIZERS_STILL_RUNNING, NG_DEV_MODE && errorMessage);\n }\n\n let componentFactory: ComponentFactory<C>;\n if (isComponentFactory) {\n componentFactory = componentOrFactory;\n } else {\n const resolver = this._injector.get(ComponentFactoryResolver);\n componentFactory = resolver.resolveComponentFactory(componentOrFactory)!;\n }\n this.componentTypes.push(componentFactory.componentType);\n\n // Create a factory associated with the current module if it's not bound to some other\n const ngModule =\n isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef);\n const selectorOrNode = rootSelectorOrNode || componentFactory.selector;\n const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);\n const nativeElement = compRef.location.nativeElement;\n const testability = compRef.injector.get(TESTABILITY, null);\n testability?.registerApplication(nativeElement);\n\n compRef.onDestroy(() => {\n this.detachView(compRef.hostView);\n remove(this.components, compRef);\n testability?.unregisterApplication(nativeElement);\n });\n\n this._loadComponent(compRef);\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n const _console = this._injector.get(Console);\n _console.log(\n `Angular is running in development mode. Call enableProdMode() to enable production mode.`);\n }\n return compRef;\n }\n\n /**\n * Invoke this method to explicitly process change detection and its side-effects.\n *\n * In development mode, `tick()` also performs a second change detection cycle to ensure that no\n * further changes are detected. If additional changes are picked up during this second cycle,\n * bindings in the app have side-effects that cannot be resolved in a single change detection\n * pass.\n * In this case, Angular throws an error, since an Angular application can only have one change\n * detection pass during which all change detection must complete.\n */\n tick(): void {\n NG_DEV_MODE && this.warnIfDestroyed();\n if (this._runningTick) {\n throw new RuntimeError(\n RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK,\n ngDevMode && 'ApplicationRef.tick is called recursively');\n }\n\n try {\n this._runningTick = true;\n for (let view of this._views) {\n view.detectChanges();\n }\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n for (let view of this._views) {\n view.checkNoChanges();\n }\n }\n } catch (e) {\n // Attention: Don't rethrow as it could cancel subscriptions to Observables!\n this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));\n } finally {\n this._runningTick = false;\n }\n }\n\n /**\n * Attaches a view so that it will be dirty checked.\n * The view will be automatically detached when it is destroyed.\n * This will throw if the view is already attached to a ViewContainer.\n */\n attachView(viewRef: ViewRef): void {\n NG_DEV_MODE && this.warnIfDestroyed();\n const view = (viewRef as InternalViewRef);\n this._views.push(view);\n view.attachToAppRef(this);\n }\n\n /**\n * Detaches a view from dirty checking again.\n */\n detachView(viewRef: ViewRef): void {\n NG_DEV_MODE && this.warnIfDestroyed();\n const view = (viewRef as InternalViewRef);\n remove(this._views, view);\n view.detachFromAppRef();\n }\n\n private _loadComponent(componentRef: ComponentRef<any>): void {\n this.attachView(componentRef.hostView);\n this.tick();\n this.components.push(componentRef);\n // Get the listeners lazily to prevent DI cycles.\n const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []);\n if (ngDevMode && !Array.isArray(listeners)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_MULTI_PROVIDER,\n 'Unexpected type of the `APP_BOOTSTRAP_LISTENER` token value ' +\n `(expected an array, but got ${typeof listeners}). ` +\n 'Please check that the `APP_BOOTSTRAP_LISTENER` token is configured as a ' +\n '`multi: true` provider.');\n }\n listeners.push(...this._bootstrapListeners);\n listeners.forEach((listener) => listener(componentRef));\n }\n\n /** @internal */\n ngOnDestroy() {\n if (this._destroyed) return;\n\n try {\n // Call all the lifecycle hooks.\n this._destroyListeners.forEach(listener => listener());\n\n // Destroy all registered views.\n this._views.slice().forEach((view) => view.destroy());\n this._onMicrotaskEmptySubscription.unsubscribe();\n } finally {\n // Indicate that this instance is destroyed.\n this._destroyed = true;\n\n // Release all references.\n this._views = [];\n this._bootstrapListeners = [];\n this._destroyListeners = [];\n }\n }\n\n /**\n * Registers a listener to be called when an instance is destroyed.\n *\n * @param callback A callback function to add as a listener.\n * @returns A function which unregisters a listener.\n *\n * @internal\n */\n onDestroy(callback: () => void): VoidFunction {\n NG_DEV_MODE && this.warnIfDestroyed();\n this._destroyListeners.push(callback);\n return () => remove(this._destroyListeners, callback);\n }\n\n /**\n * Destroys an Angular application represented by this `ApplicationRef`. Calling this function\n * will destroy the associated environment injectors as well as all the bootstrapped components\n * with their views.\n */\n destroy(): void {\n if (this._destroyed) {\n throw new RuntimeError(\n RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED,\n ngDevMode && 'This instance of the `ApplicationRef` has already been destroyed.');\n }\n\n // This is a temporary type to represent an instance of an R3Injector, which can be destroyed.\n // The type will be replaced with a different one once destroyable injector type is available.\n type DestroyableInjector = Injector&{destroy?: Function, destroyed?: boolean};\n\n const injector = this._injector as DestroyableInjector;\n\n // Check that this injector instance supports destroy operation.\n if (injector.destroy && !injector.destroyed) {\n // Destroying an underlying injector will trigger the `ngOnDestroy` lifecycle\n // hook, which invokes the remaining cleanup actions.\n injector.destroy();\n }\n }\n\n /**\n * Returns the number of attached views.\n */\n get viewCount() {\n return this._views.length;\n }\n\n private warnIfDestroyed() {\n if (NG_DEV_MODE && this._destroyed) {\n console.warn(formatRuntimeError(\n RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED,\n 'This instance of the `ApplicationRef` has already been destroyed.'));\n }\n }\n}\n\nfunction remove<T>(list: T[], el: T): void {\n const index = list.indexOf(el);\n if (index > -1) {\n list.splice(index, 1);\n }\n}\n\nfunction _lastDefined<T>(args: T[]): T|undefined {\n for (let i = args.length - 1; i >= 0; i--) {\n if (args[i] !== undefined) {\n return args[i];\n }\n }\n return undefined;\n}\n\nfunction _mergeArrays(parts: any[][]): any[] {\n const result: any[] = [];\n parts.forEach((part) => part && result.push(...part));\n return result;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {global} from './global';\n\n/**\n * Returns whether Angular is in development mode.\n *\n * By default, this is true, unless `enableProdMode` is invoked prior to calling this method or the\n * application is built using the Angular CLI with the `optimization` option.\n * @see {@link cli/build ng build}\n *\n * @publicApi\n */\nexport function isDevMode(): boolean {\n return typeof ngDevMode === 'undefined' || !!ngDevMode;\n}\n\n/**\n * Disable Angular's development mode, which turns off assertions and other\n * checks within the framework.\n *\n * One important assertion this disables verifies that a change detection pass\n * does not result in additional changes to any bindings (also known as\n * unidirectional data flow).\n *\n * Using this method is discouraged as the Angular CLI will set production mode when using the\n * `optimization` option.\n * @see {@link cli/build ng build}\n *\n * @publicApi\n */\nexport function enableProdMode(): void {\n // The below check is there so when ngDevMode is set via terser\n // `global['ngDevMode'] = false;` is also dropped.\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n global['ngDevMode'] = false;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectFlags} from '../di';\nimport {InternalInjectFlags} from '../di/interface/injector';\nimport {TNode, TNodeType} from '../render3/interfaces/node';\nimport {isComponentHost} from '../render3/interfaces/type_checks';\nimport {DECLARATION_COMPONENT_VIEW, LView} from '../render3/interfaces/view';\nimport {getCurrentTNode, getLView} from '../render3/state';\nimport {getComponentLViewByIndex} from '../render3/util/view_utils';\nimport {ViewRef} from '../render3/view_ref';\n\n/**\n * Base class that provides change detection functionality.\n * A change-detection tree collects all views that are to be checked for changes.\n * Use the methods to add and remove views from the tree, initiate change-detection,\n * and explicitly mark views as _dirty_, meaning that they have changed and need to be re-rendered.\n *\n * @see [Using change detection hooks](guide/lifecycle-hooks#using-change-detection-hooks)\n * @see [Defining custom change detection](guide/lifecycle-hooks#defining-custom-change-detection)\n *\n * @usageNotes\n *\n * The following examples demonstrate how to modify default change-detection behavior\n * to perform explicit detection when needed.\n *\n * ### Use `markForCheck()` with `CheckOnce` strategy\n *\n * The following example sets the `OnPush` change-detection strategy for a component\n * (`CheckOnce`, rather than the default `CheckAlways`), then forces a second check\n * after an interval. See [live demo](https://plnkr.co/edit/GC512b?p=preview).\n *\n * <code-example path=\"core/ts/change_detect/change-detection.ts\"\n * region=\"mark-for-check\"></code-example>\n *\n * ### Detach change detector to limit how often check occurs\n *\n * The following example defines a component with a large list of read-only data\n * that is expected to change constantly, many times per second.\n * To improve performance, we want to check and update the list\n * less often than the changes actually occur. To do that, we detach\n * the component's change detector and perform an explicit local check every five seconds.\n *\n * <code-example path=\"core/ts/change_detect/change-detection.ts\" region=\"detach\"></code-example>\n *\n *\n * ### Reattaching a detached component\n *\n * The following example creates a component displaying live data.\n * The component detaches its change detector from the main change detector tree\n * when the `live` property is set to false, and reattaches it when the property\n * becomes true.\n *\n * <code-example path=\"core/ts/change_detect/change-detection.ts\" region=\"reattach\"></code-example>\n *\n * @publicApi\n */\nexport abstract class ChangeDetectorRef {\n /**\n * When a view uses the {@link ChangeDetectionStrategy#OnPush OnPush} (checkOnce)\n * change detection strategy, explicitly marks the view as changed so that\n * it can be checked again.\n *\n * Components are normally marked as dirty (in need of rerendering) when inputs\n * have changed or events have fired in the view. Call this method to ensure that\n * a component is checked even if these triggers have not occurred.\n *\n * <!-- TODO: Add a link to a chapter on OnPush components -->\n *\n */\n abstract markForCheck(): void;\n\n /**\n * Detaches this view from the change-detection tree.\n * A detached view is not checked until it is reattached.\n * Use in combination with `detectChanges()` to implement local change detection checks.\n *\n * Detached views are not checked during change detection runs until they are\n * re-attached, even if they are marked as dirty.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->\n *\n */\n abstract detach(): void;\n\n /**\n * Checks this view and its children. Use in combination with {@link ChangeDetectorRef#detach\n * detach}\n * to implement local change detection checks.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->\n *\n */\n abstract detectChanges(): void;\n\n /**\n * Checks the change detector and its children, and throws if any changes are detected.\n *\n * Use in development mode to verify that running change detection doesn't introduce\n * other changes. Calling it in production mode is a noop.\n */\n abstract checkNoChanges(): void;\n\n /**\n * Re-attaches the previously detached view to the change detection tree.\n * Views are attached to the tree by default.\n *\n * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->\n *\n */\n abstract reattach(): void;\n\n /**\n * @internal\n * @nocollapse\n */\n static __NG_ELEMENT_ID__: (flags: InjectFlags) => ChangeDetectorRef = injectChangeDetectorRef;\n}\n\n\n\n/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */\nexport function injectChangeDetectorRef(flags: InjectFlags): ChangeDetectorRef {\n return createViewRef(\n getCurrentTNode()!, getLView(),\n (flags & InternalInjectFlags.ForPipe) === InternalInjectFlags.ForPipe);\n}\n\n/**\n * Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).\n *\n * @param tNode The node that is requesting a ChangeDetectorRef\n * @param lView The view to which the node belongs\n * @param isPipe Whether the view is being injected into a pipe.\n * @returns The ChangeDetectorRef to use\n */\nfunction createViewRef(tNode: TNode, lView: LView, isPipe: boolean): ChangeDetectorRef {\n if (isComponentHost(tNode) && !isPipe) {\n // The LView represents the location where the component is declared.\n // Instead we want the LView for the component View and so we need to look it up.\n const componentView = getComponentLViewByIndex(tNode.index, lView); // look down\n return new ViewRef(componentView, componentView);\n } else if (tNode.type & (TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Icu)) {\n // The LView represents the location where the injection is requested from.\n // We need to locate the containing LView (in case where the `lView` is an embedded view)\n const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up\n return new ViewRef(hostComponentView, lView);\n }\n return null!;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {isListLikeIterable, iterateListLike} from '../../util/iterable';\nimport {stringify} from '../../util/stringify';\n\nimport {IterableChangeRecord, IterableChanges, IterableDiffer, IterableDifferFactory, NgIterable, TrackByFunction} from './iterable_differs';\n\n\nexport class DefaultIterableDifferFactory implements IterableDifferFactory {\n constructor() {}\n supports(obj: Object|null|undefined): boolean {\n return isListLikeIterable(obj);\n }\n\n create<V>(trackByFn?: TrackByFunction<V>): DefaultIterableDiffer<V> {\n return new DefaultIterableDiffer<V>(trackByFn);\n }\n}\n\nconst trackByIdentity = (index: number, item: any) => item;\n\n/**\n * @deprecated v4.0.0 - Should not be part of public API.\n * @publicApi\n */\nexport class DefaultIterableDiffer<V> implements IterableDiffer<V>, IterableChanges<V> {\n public readonly length: number = 0;\n // TODO(issue/24571): remove '!'.\n public readonly collection!: V[]|Iterable<V>|null;\n // Keeps track of the used records at any point in time (during & across `_check()` calls)\n private _linkedRecords: _DuplicateMap<V>|null = null;\n // Keeps track of the removed records at any point in time during `_check()` calls.\n private _unlinkedRecords: _DuplicateMap<V>|null = null;\n private _previousItHead: IterableChangeRecord_<V>|null = null;\n private _itHead: IterableChangeRecord_<V>|null = null;\n private _itTail: IterableChangeRecord_<V>|null = null;\n private _additionsHead: IterableChangeRecord_<V>|null = null;\n private _additionsTail: IterableChangeRecord_<V>|null = null;\n private _movesHead: IterableChangeRecord_<V>|null = null;\n private _movesTail: IterableChangeRecord_<V>|null = null;\n private _removalsHead: IterableChangeRecord_<V>|null = null;\n private _removalsTail: IterableChangeRecord_<V>|null = null;\n // Keeps track of records where custom track by is the same, but item identity has changed\n private _identityChangesHead: IterableChangeRecord_<V>|null = null;\n private _identityChangesTail: IterableChangeRecord_<V>|null = null;\n private _trackByFn: TrackByFunction<V>;\n\n constructor(trackByFn?: TrackByFunction<V>) {\n this._trackByFn = trackByFn || trackByIdentity;\n }\n\n forEachItem(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._itHead; record !== null; record = record._next) {\n fn(record);\n }\n }\n\n forEachOperation(\n fn: (item: IterableChangeRecord<V>, previousIndex: number|null, currentIndex: number|null) =>\n void) {\n let nextIt = this._itHead;\n let nextRemove = this._removalsHead;\n let addRemoveOffset = 0;\n let moveOffsets: number[]|null = null;\n while (nextIt || nextRemove) {\n // Figure out which is the next record to process\n // Order: remove, add, move\n const record: IterableChangeRecord<V> = !nextRemove ||\n nextIt &&\n nextIt.currentIndex! <\n getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ?\n nextIt! :\n nextRemove;\n const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets);\n const currentIndex = record.currentIndex;\n\n // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary\n if (record === nextRemove) {\n addRemoveOffset--;\n nextRemove = nextRemove._nextRemoved;\n } else {\n nextIt = nextIt!._next;\n if (record.previousIndex == null) {\n addRemoveOffset++;\n } else {\n // INVARIANT: currentIndex < previousIndex\n if (!moveOffsets) moveOffsets = [];\n const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset;\n const localCurrentIndex = currentIndex! - addRemoveOffset;\n if (localMovePreviousIndex != localCurrentIndex) {\n for (let i = 0; i < localMovePreviousIndex; i++) {\n const offset = i < moveOffsets.length ? moveOffsets[i] : (moveOffsets[i] = 0);\n const index = offset + i;\n if (localCurrentIndex <= index && index < localMovePreviousIndex) {\n moveOffsets[i] = offset + 1;\n }\n }\n const previousIndex = record.previousIndex;\n moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex;\n }\n }\n }\n\n if (adjPreviousIndex !== currentIndex) {\n fn(record, adjPreviousIndex, currentIndex);\n }\n }\n }\n\n forEachPreviousItem(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._previousItHead; record !== null; record = record._nextPrevious) {\n fn(record);\n }\n }\n\n forEachAddedItem(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._additionsHead; record !== null; record = record._nextAdded) {\n fn(record);\n }\n }\n\n forEachMovedItem(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._movesHead; record !== null; record = record._nextMoved) {\n fn(record);\n }\n }\n\n forEachRemovedItem(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._removalsHead; record !== null; record = record._nextRemoved) {\n fn(record);\n }\n }\n\n forEachIdentityChange(fn: (record: IterableChangeRecord_<V>) => void) {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {\n fn(record);\n }\n }\n\n diff(collection: NgIterable<V>|null|undefined): DefaultIterableDiffer<V>|null {\n if (collection == null) collection = [];\n if (!isListLikeIterable(collection)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_DIFFER_INPUT,\n ngDevMode &&\n `Error trying to diff '${\n stringify(collection)}'. Only arrays and iterables are allowed`);\n }\n\n if (this.check(collection)) {\n return this;\n } else {\n return null;\n }\n }\n\n onDestroy() {}\n\n check(collection: NgIterable<V>): boolean {\n this._reset();\n\n let record: IterableChangeRecord_<V>|null = this._itHead;\n let mayBeDirty: boolean = false;\n let index: number;\n let item: V;\n let itemTrackBy: any;\n if (Array.isArray(collection)) {\n (this as {length: number}).length = collection.length;\n\n for (let index = 0; index < this.length; index++) {\n item = collection[index];\n itemTrackBy = this._trackByFn(index, item);\n if (record === null || !Object.is(record.trackById, itemTrackBy)) {\n record = this._mismatch(record, item, itemTrackBy, index);\n mayBeDirty = true;\n } else {\n if (mayBeDirty) {\n // TODO(misko): can we limit this to duplicates only?\n record = this._verifyReinsertion(record, item, itemTrackBy, index);\n }\n if (!Object.is(record.item, item)) this._addIdentityChange(record, item);\n }\n\n record = record._next;\n }\n } else {\n index = 0;\n iterateListLike(collection, (item: V) => {\n itemTrackBy = this._trackByFn(index, item);\n if (record === null || !Object.is(record.trackById, itemTrackBy)) {\n record = this._mismatch(record, item, itemTrackBy, index);\n mayBeDirty = true;\n } else {\n if (mayBeDirty) {\n // TODO(misko): can we limit this to duplicates only?\n record = this._verifyReinsertion(record, item, itemTrackBy, index);\n }\n if (!Object.is(record.item, item)) this._addIdentityChange(record, item);\n }\n record = record._next;\n index++;\n });\n (this as {length: number}).length = index;\n }\n\n this._truncate(record);\n (this as {collection: V[] | Iterable<V>}).collection = collection;\n return this.isDirty;\n }\n\n /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity\n * changes.\n */\n get isDirty(): boolean {\n return this._additionsHead !== null || this._movesHead !== null ||\n this._removalsHead !== null || this._identityChangesHead !== null;\n }\n\n /**\n * Reset the state of the change objects to show no changes. This means set previousKey to\n * currentKey, and clear all of the queues (additions, moves, removals).\n * Set the previousIndexes of moved and added items to their currentIndexes\n * Reset the list of additions, moves and removals\n *\n * @internal\n */\n _reset() {\n if (this.isDirty) {\n let record: IterableChangeRecord_<V>|null;\n\n for (record = this._previousItHead = this._itHead; record !== null; record = record._next) {\n record._nextPrevious = record._next;\n }\n\n for (record = this._additionsHead; record !== null; record = record._nextAdded) {\n record.previousIndex = record.currentIndex;\n }\n this._additionsHead = this._additionsTail = null;\n\n for (record = this._movesHead; record !== null; record = record._nextMoved) {\n record.previousIndex = record.currentIndex;\n }\n this._movesHead = this._movesTail = null;\n this._removalsHead = this._removalsTail = null;\n this._identityChangesHead = this._identityChangesTail = null;\n\n // TODO(vicb): when assert gets supported\n // assert(!this.isDirty);\n }\n }\n\n /**\n * This is the core function which handles differences between collections.\n *\n * - `record` is the record which we saw at this position last time. If null then it is a new\n * item.\n * - `item` is the current item in the collection\n * - `index` is the position of the item in the collection\n *\n * @internal\n */\n _mismatch(record: IterableChangeRecord_<V>|null, item: V, itemTrackBy: any, index: number):\n IterableChangeRecord_<V> {\n // The previous record after which we will append the current one.\n let previousRecord: IterableChangeRecord_<V>|null;\n\n if (record === null) {\n previousRecord = this._itTail;\n } else {\n previousRecord = record._prev;\n // Remove the record from the collection since we know it does not match the item.\n this._remove(record);\n }\n\n // See if we have evicted the item, which used to be at some anterior position of _itHead list.\n record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);\n if (record !== null) {\n // It is an item which we have evicted earlier: reinsert it back into the list.\n // But first we need to check if identity changed, so we can update in view if necessary.\n if (!Object.is(record.item, item)) this._addIdentityChange(record, item);\n\n this._reinsertAfter(record, previousRecord, index);\n } else {\n // Attempt to see if the item is at some posterior position of _itHead list.\n record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);\n if (record !== null) {\n // We have the item in _itHead at/after `index` position. We need to move it forward in the\n // collection.\n // But first we need to check if identity changed, so we can update in view if necessary.\n if (!Object.is(record.item, item)) this._addIdentityChange(record, item);\n\n this._moveAfter(record, previousRecord, index);\n } else {\n // It is a new item: add it.\n record =\n this._addAfter(new IterableChangeRecord_<V>(item, itemTrackBy), previousRecord, index);\n }\n }\n return record;\n }\n\n /**\n * This check is only needed if an array contains duplicates. (Short circuit of nothing dirty)\n *\n * Use case: `[a, a]` => `[b, a, a]`\n *\n * If we did not have this check then the insertion of `b` would:\n * 1) evict first `a`\n * 2) insert `b` at `0` index.\n * 3) leave `a` at index `1` as is. <-- this is wrong!\n * 3) reinsert `a` at index 2. <-- this is wrong!\n *\n * The correct behavior is:\n * 1) evict first `a`\n * 2) insert `b` at `0` index.\n * 3) reinsert `a` at index 1.\n * 3) move `a` at from `1` to `2`.\n *\n *\n * Double check that we have not evicted a duplicate item. We need to check if the item type may\n * have already been removed:\n * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted\n * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a\n * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a'\n * at the end.\n *\n * @internal\n */\n _verifyReinsertion(record: IterableChangeRecord_<V>, item: V, itemTrackBy: any, index: number):\n IterableChangeRecord_<V> {\n let reinsertRecord: IterableChangeRecord_<V>|null =\n this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);\n if (reinsertRecord !== null) {\n record = this._reinsertAfter(reinsertRecord, record._prev!, index);\n } else if (record.currentIndex != index) {\n record.currentIndex = index;\n this._addToMoves(record, index);\n }\n return record;\n }\n\n /**\n * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection\n *\n * - `record` The first excess {@link IterableChangeRecord_}.\n *\n * @internal\n */\n _truncate(record: IterableChangeRecord_<V>|null) {\n // Anything after that needs to be removed;\n while (record !== null) {\n const nextRecord: IterableChangeRecord_<V>|null = record._next;\n this._addToRemovals(this._unlink(record));\n record = nextRecord;\n }\n if (this._unlinkedRecords !== null) {\n this._unlinkedRecords.clear();\n }\n\n if (this._additionsTail !== null) {\n this._additionsTail._nextAdded = null;\n }\n if (this._movesTail !== null) {\n this._movesTail._nextMoved = null;\n }\n if (this._itTail !== null) {\n this._itTail._next = null;\n }\n if (this._removalsTail !== null) {\n this._removalsTail._nextRemoved = null;\n }\n if (this._identityChangesTail !== null) {\n this._identityChangesTail._nextIdentityChange = null;\n }\n }\n\n /** @internal */\n _reinsertAfter(\n record: IterableChangeRecord_<V>, prevRecord: IterableChangeRecord_<V>|null,\n index: number): IterableChangeRecord_<V> {\n if (this._unlinkedRecords !== null) {\n this._unlinkedRecords.remove(record);\n }\n const prev = record._prevRemoved;\n const next = record._nextRemoved;\n\n if (prev === null) {\n this._removalsHead = next;\n } else {\n prev._nextRemoved = next;\n }\n if (next === null) {\n this._removalsTail = prev;\n } else {\n next._prevRemoved = prev;\n }\n\n this._insertAfter(record, prevRecord, index);\n this._addToMoves(record, index);\n return record;\n }\n\n /** @internal */\n _moveAfter(\n record: IterableChangeRecord_<V>, prevRecord: IterableChangeRecord_<V>|null,\n index: number): IterableChangeRecord_<V> {\n this._unlink(record);\n this._insertAfter(record, prevRecord, index);\n this._addToMoves(record, index);\n return record;\n }\n\n /** @internal */\n _addAfter(\n record: IterableChangeRecord_<V>, prevRecord: IterableChangeRecord_<V>|null,\n index: number): IterableChangeRecord_<V> {\n this._insertAfter(record, prevRecord, index);\n\n if (this._additionsTail === null) {\n // TODO(vicb):\n // assert(this._additionsHead === null);\n this._additionsTail = this._additionsHead = record;\n } else {\n // TODO(vicb):\n // assert(_additionsTail._nextAdded === null);\n // assert(record._nextAdded === null);\n this._additionsTail = this._additionsTail._nextAdded = record;\n }\n return record;\n }\n\n /** @internal */\n _insertAfter(\n record: IterableChangeRecord_<V>, prevRecord: IterableChangeRecord_<V>|null,\n index: number): IterableChangeRecord_<V> {\n // TODO(vicb):\n // assert(record != prevRecord);\n // assert(record._next === null);\n // assert(record._prev === null);\n\n const next: IterableChangeRecord_<V>|null =\n prevRecord === null ? this._itHead : prevRecord._next;\n // TODO(vicb):\n // assert(next != record);\n // assert(prevRecord != record);\n record._next = next;\n record._prev = prevRecord;\n if (next === null) {\n this._itTail = record;\n } else {\n next._prev = record;\n }\n if (prevRecord === null) {\n this._itHead = record;\n } else {\n prevRecord._next = record;\n }\n\n if (this._linkedRecords === null) {\n this._linkedRecords = new _DuplicateMap<V>();\n }\n this._linkedRecords.put(record);\n\n record.currentIndex = index;\n return record;\n }\n\n /** @internal */\n _remove(record: IterableChangeRecord_<V>): IterableChangeRecord_<V> {\n return this._addToRemovals(this._unlink(record));\n }\n\n /** @internal */\n _unlink(record: IterableChangeRecord_<V>): IterableChangeRecord_<V> {\n if (this._linkedRecords !== null) {\n this._linkedRecords.remove(record);\n }\n\n const prev = record._prev;\n const next = record._next;\n\n // TODO(vicb):\n // assert((record._prev = null) === null);\n // assert((record._next = null) === null);\n\n if (prev === null) {\n this._itHead = next;\n } else {\n prev._next = next;\n }\n if (next === null) {\n this._itTail = prev;\n } else {\n next._prev = prev;\n }\n\n return record;\n }\n\n /** @internal */\n _addToMoves(record: IterableChangeRecord_<V>, toIndex: number): IterableChangeRecord_<V> {\n // TODO(vicb):\n // assert(record._nextMoved === null);\n\n if (record.previousIndex === toIndex) {\n return record;\n }\n\n if (this._movesTail === null) {\n // TODO(vicb):\n // assert(_movesHead === null);\n this._movesTail = this._movesHead = record;\n } else {\n // TODO(vicb):\n // assert(_movesTail._nextMoved === null);\n this._movesTail = this._movesTail._nextMoved = record;\n }\n\n return record;\n }\n\n private _addToRemovals(record: IterableChangeRecord_<V>): IterableChangeRecord_<V> {\n if (this._unlinkedRecords === null) {\n this._unlinkedRecords = new _DuplicateMap<V>();\n }\n this._unlinkedRecords.put(record);\n record.currentIndex = null;\n record._nextRemoved = null;\n\n if (this._removalsTail === null) {\n // TODO(vicb):\n // assert(_removalsHead === null);\n this._removalsTail = this._removalsHead = record;\n record._prevRemoved = null;\n } else {\n // TODO(vicb):\n // assert(_removalsTail._nextRemoved === null);\n // assert(record._nextRemoved === null);\n record._prevRemoved = this._removalsTail;\n this._removalsTail = this._removalsTail._nextRemoved = record;\n }\n return record;\n }\n\n /** @internal */\n _addIdentityChange(record: IterableChangeRecord_<V>, item: V) {\n record.item = item;\n if (this._identityChangesTail === null) {\n this._identityChangesTail = this._identityChangesHead = record;\n } else {\n this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;\n }\n return record;\n }\n}\n\nexport class IterableChangeRecord_<V> implements IterableChangeRecord<V> {\n currentIndex: number|null = null;\n previousIndex: number|null = null;\n\n /** @internal */\n _nextPrevious: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _prev: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _next: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _prevDup: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _nextDup: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _prevRemoved: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _nextRemoved: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _nextAdded: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _nextMoved: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _nextIdentityChange: IterableChangeRecord_<V>|null = null;\n\n\n constructor(public item: V, public trackById: any) {}\n}\n\n// A linked list of IterableChangeRecords with the same IterableChangeRecord_.item\nclass _DuplicateItemRecordList<V> {\n /** @internal */\n _head: IterableChangeRecord_<V>|null = null;\n /** @internal */\n _tail: IterableChangeRecord_<V>|null = null;\n\n /**\n * Append the record to the list of duplicates.\n *\n * Note: by design all records in the list of duplicates hold the same value in record.item.\n */\n add(record: IterableChangeRecord_<V>): void {\n if (this._head === null) {\n this._head = this._tail = record;\n record._nextDup = null;\n record._prevDup = null;\n } else {\n // TODO(vicb):\n // assert(record.item == _head.item ||\n // record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN);\n this._tail!._nextDup = record;\n record._prevDup = this._tail;\n record._nextDup = null;\n this._tail = record;\n }\n }\n\n // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and\n // IterableChangeRecord_.currentIndex >= atOrAfterIndex\n get(trackById: any, atOrAfterIndex: number|null): IterableChangeRecord_<V>|null {\n let record: IterableChangeRecord_<V>|null;\n for (record = this._head; record !== null; record = record._nextDup) {\n if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex!) &&\n Object.is(record.trackById, trackById)) {\n return record;\n }\n }\n return null;\n }\n\n /**\n * Remove one {@link IterableChangeRecord_} from the list of duplicates.\n *\n * Returns whether the list of duplicates is empty.\n */\n remove(record: IterableChangeRecord_<V>): boolean {\n // TODO(vicb):\n // assert(() {\n // // verify that the record being removed is in the list.\n // for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) {\n // if (identical(cursor, record)) return true;\n // }\n // return false;\n //});\n\n const prev: IterableChangeRecord_<V>|null = record._prevDup;\n const next: IterableChangeRecord_<V>|null = record._nextDup;\n if (prev === null) {\n this._head = next;\n } else {\n prev._nextDup = next;\n }\n if (next === null) {\n this._tail = prev;\n } else {\n next._prevDup = prev;\n }\n return this._head === null;\n }\n}\n\nclass _DuplicateMap<V> {\n map = new Map<any, _DuplicateItemRecordList<V>>();\n\n put(record: IterableChangeRecord_<V>) {\n const key = record.trackById;\n\n let duplicates = this.map.get(key);\n if (!duplicates) {\n duplicates = new _DuplicateItemRecordList<V>();\n this.map.set(key, duplicates);\n }\n duplicates.add(record);\n }\n\n /**\n * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we\n * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there.\n *\n * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we\n * have any more `a`s needs to return the second `a`.\n */\n get(trackById: any, atOrAfterIndex: number|null): IterableChangeRecord_<V>|null {\n const key = trackById;\n const recordList = this.map.get(key);\n return recordList ? recordList.get(trackById, atOrAfterIndex) : null;\n }\n\n /**\n * Removes a {@link IterableChangeRecord_} from the list of duplicates.\n *\n * The list of duplicates also is removed from the map if it gets empty.\n */\n remove(record: IterableChangeRecord_<V>): IterableChangeRecord_<V> {\n const key = record.trackById;\n const recordList: _DuplicateItemRecordList<V> = this.map.get(key)!;\n // Remove the list of duplicates when it gets empty\n if (recordList.remove(record)) {\n this.map.delete(key);\n }\n return record;\n }\n\n get isEmpty(): boolean {\n return this.map.size === 0;\n }\n\n clear() {\n this.map.clear();\n }\n}\n\nfunction getPreviousIndex(item: any, addRemoveOffset: number, moveOffsets: number[]|null): number {\n const previousIndex = item.previousIndex;\n if (previousIndex === null) return previousIndex;\n let moveOffset = 0;\n if (moveOffsets && previousIndex < moveOffsets.length) {\n moveOffset = moveOffsets[previousIndex];\n }\n return previousIndex + addRemoveOffset + moveOffset;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {isJsObject} from '../../util/iterable';\nimport {stringify} from '../../util/stringify';\n\nimport {KeyValueChangeRecord, KeyValueChanges, KeyValueDiffer, KeyValueDifferFactory} from './keyvalue_differs';\n\n\nexport class DefaultKeyValueDifferFactory<K, V> implements KeyValueDifferFactory {\n constructor() {}\n supports(obj: any): boolean {\n return obj instanceof Map || isJsObject(obj);\n }\n\n create<K, V>(): KeyValueDiffer<K, V> {\n return new DefaultKeyValueDiffer<K, V>();\n }\n}\n\nexport class DefaultKeyValueDiffer<K, V> implements KeyValueDiffer<K, V>, KeyValueChanges<K, V> {\n private _records = new Map<K, KeyValueChangeRecord_<K, V>>();\n private _mapHead: KeyValueChangeRecord_<K, V>|null = null;\n // _appendAfter is used in the check loop\n private _appendAfter: KeyValueChangeRecord_<K, V>|null = null;\n private _previousMapHead: KeyValueChangeRecord_<K, V>|null = null;\n private _changesHead: KeyValueChangeRecord_<K, V>|null = null;\n private _changesTail: KeyValueChangeRecord_<K, V>|null = null;\n private _additionsHead: KeyValueChangeRecord_<K, V>|null = null;\n private _additionsTail: KeyValueChangeRecord_<K, V>|null = null;\n private _removalsHead: KeyValueChangeRecord_<K, V>|null = null;\n private _removalsTail: KeyValueChangeRecord_<K, V>|null = null;\n\n get isDirty(): boolean {\n return this._additionsHead !== null || this._changesHead !== null ||\n this._removalsHead !== null;\n }\n\n forEachItem(fn: (r: KeyValueChangeRecord<K, V>) => void) {\n let record: KeyValueChangeRecord_<K, V>|null;\n for (record = this._mapHead; record !== null; record = record._next) {\n fn(record);\n }\n }\n\n forEachPreviousItem(fn: (r: KeyValueChangeRecord<K, V>) => void) {\n let record: KeyValueChangeRecord_<K, V>|null;\n for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {\n fn(record);\n }\n }\n\n forEachChangedItem(fn: (r: KeyValueChangeRecord<K, V>) => void) {\n let record: KeyValueChangeRecord_<K, V>|null;\n for (record = this._changesHead; record !== null; record = record._nextChanged) {\n fn(record);\n }\n }\n\n forEachAddedItem(fn: (r: KeyValueChangeRecord<K, V>) => void) {\n let record: KeyValueChangeRecord_<K, V>|null;\n for (record = this._additionsHead; record !== null; record = record._nextAdded) {\n fn(record);\n }\n }\n\n forEachRemovedItem(fn: (r: KeyValueChangeRecord<K, V>) => void) {\n let record: KeyValueChangeRecord_<K, V>|null;\n for (record = this._removalsHead; record !== null; record = record._nextRemoved) {\n fn(record);\n }\n }\n\n diff(map?: Map<any, any>|{[k: string]: any}|null): any {\n if (!map) {\n map = new Map();\n } else if (!(map instanceof Map || isJsObject(map))) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_DIFFER_INPUT,\n ngDevMode &&\n `Error trying to diff '${stringify(map)}'. Only maps and objects are allowed`);\n }\n\n return this.check(map) ? this : null;\n }\n\n onDestroy() {}\n\n /**\n * Check the current state of the map vs the previous.\n * The algorithm is optimised for when the keys do no change.\n */\n check(map: Map<any, any>|{[k: string]: any}): boolean {\n this._reset();\n\n let insertBefore = this._mapHead;\n this._appendAfter = null;\n\n this._forEach(map, (value: any, key: any) => {\n if (insertBefore && insertBefore.key === key) {\n this._maybeAddToChanges(insertBefore, value);\n this._appendAfter = insertBefore;\n insertBefore = insertBefore._next;\n } else {\n const record = this._getOrCreateRecordForKey(key, value);\n insertBefore = this._insertBeforeOrAppend(insertBefore, record);\n }\n });\n\n // Items remaining at the end of the list have been deleted\n if (insertBefore) {\n if (insertBefore._prev) {\n insertBefore._prev._next = null;\n }\n\n this._removalsHead = insertBefore;\n\n for (let record: KeyValueChangeRecord_<K, V>|null = insertBefore; record !== null;\n record = record._nextRemoved) {\n if (record === this._mapHead) {\n this._mapHead = null;\n }\n this._records.delete(record.key);\n record._nextRemoved = record._next;\n record.previousValue = record.currentValue;\n record.currentValue = null;\n record._prev = null;\n record._next = null;\n }\n }\n\n // Make sure tails have no next records from previous runs\n if (this._changesTail) this._changesTail._nextChanged = null;\n if (this._additionsTail) this._additionsTail._nextAdded = null;\n\n return this.isDirty;\n }\n\n /**\n * Inserts a record before `before` or append at the end of the list when `before` is null.\n *\n * Notes:\n * - This method appends at `this._appendAfter`,\n * - This method updates `this._appendAfter`,\n * - The return value is the new value for the insertion pointer.\n */\n private _insertBeforeOrAppend(\n before: KeyValueChangeRecord_<K, V>|null,\n record: KeyValueChangeRecord_<K, V>): KeyValueChangeRecord_<K, V>|null {\n if (before) {\n const prev = before._prev;\n record._next = before;\n record._prev = prev;\n before._prev = record;\n if (prev) {\n prev._next = record;\n }\n if (before === this._mapHead) {\n this._mapHead = record;\n }\n\n this._appendAfter = before;\n return before;\n }\n\n if (this._appendAfter) {\n this._appendAfter._next = record;\n record._prev = this._appendAfter;\n } else {\n this._mapHead = record;\n }\n\n this._appendAfter = record;\n return null;\n }\n\n private _getOrCreateRecordForKey(key: K, value: V): KeyValueChangeRecord_<K, V> {\n if (this._records.has(key)) {\n const record = this._records.get(key)!;\n this._maybeAddToChanges(record, value);\n const prev = record._prev;\n const next = record._next;\n if (prev) {\n prev._next = next;\n }\n if (next) {\n next._prev = prev;\n }\n record._next = null;\n record._prev = null;\n\n return record;\n }\n\n const record = new KeyValueChangeRecord_<K, V>(key);\n this._records.set(key, record);\n record.currentValue = value;\n this._addToAdditions(record);\n return record;\n }\n\n /** @internal */\n _reset() {\n if (this.isDirty) {\n let record: KeyValueChangeRecord_<K, V>|null;\n // let `_previousMapHead` contain the state of the map before the changes\n this._previousMapHead = this._mapHead;\n for (record = this._previousMapHead; record !== null; record = record._next) {\n record._nextPrevious = record._next;\n }\n\n // Update `record.previousValue` with the value of the item before the changes\n // We need to update all changed items (that's those which have been added and changed)\n for (record = this._changesHead; record !== null; record = record._nextChanged) {\n record.previousValue = record.currentValue;\n }\n for (record = this._additionsHead; record != null; record = record._nextAdded) {\n record.previousValue = record.currentValue;\n }\n\n this._changesHead = this._changesTail = null;\n this._additionsHead = this._additionsTail = null;\n this._removalsHead = null;\n }\n }\n\n // Add the record or a given key to the list of changes only when the value has actually changed\n private _maybeAddToChanges(record: KeyValueChangeRecord_<K, V>, newValue: any): void {\n if (!Object.is(newValue, record.currentValue)) {\n record.previousValue = record.currentValue;\n record.currentValue = newValue;\n this._addToChanges(record);\n }\n }\n\n private _addToAdditions(record: KeyValueChangeRecord_<K, V>) {\n if (this._additionsHead === null) {\n this._additionsHead = this._additionsTail = record;\n } else {\n this._additionsTail!._nextAdded = record;\n this._additionsTail = record;\n }\n }\n\n private _addToChanges(record: KeyValueChangeRecord_<K, V>) {\n if (this._changesHead === null) {\n this._changesHead = this._changesTail = record;\n } else {\n this._changesTail!._nextChanged = record;\n this._changesTail = record;\n }\n }\n\n /** @internal */\n private _forEach<K, V>(obj: Map<K, V>|{[k: string]: V}, fn: (v: V, k: any) => void) {\n if (obj instanceof Map) {\n obj.forEach(fn);\n } else {\n Object.keys(obj).forEach(k => fn(obj[k], k));\n }\n }\n}\n\nclass KeyValueChangeRecord_<K, V> implements KeyValueChangeRecord<K, V> {\n previousValue: V|null = null;\n currentValue: V|null = null;\n\n /** @internal */\n _nextPrevious: KeyValueChangeRecord_<K, V>|null = null;\n /** @internal */\n _next: KeyValueChangeRecord_<K, V>|null = null;\n /** @internal */\n _prev: KeyValueChangeRecord_<K, V>|null = null;\n /** @internal */\n _nextAdded: KeyValueChangeRecord_<K, V>|null = null;\n /** @internal */\n _nextRemoved: KeyValueChangeRecord_<K, V>|null = null;\n /** @internal */\n _nextChanged: KeyValueChangeRecord_<K, V>|null = null;\n\n constructor(public key: K) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵɵdefineInjectable} from '../../di/interface/defs';\nimport {StaticProvider} from '../../di/interface/provider';\nimport {Optional, SkipSelf} from '../../di/metadata';\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\nimport {DefaultIterableDifferFactory} from '../differs/default_iterable_differ';\n\n\n\n/**\n * A type describing supported iterable types.\n *\n * @publicApi\n */\nexport type NgIterable<T> = Array<T>|Iterable<T>;\n\n/**\n * A strategy for tracking changes over time to an iterable. Used by {@link NgForOf} to\n * respond to changes in an iterable by effecting equivalent changes in the DOM.\n *\n * @publicApi\n */\nexport interface IterableDiffer<V> {\n /**\n * Compute a difference between the previous state and the new `object` state.\n *\n * @param object containing the new value.\n * @returns an object describing the difference. The return value is only valid until the next\n * `diff()` invocation.\n */\n diff(object: NgIterable<V>|undefined|null): IterableChanges<V>|null;\n}\n\n/**\n * An object describing the changes in the `Iterable` collection since last time\n * `IterableDiffer#diff()` was invoked.\n *\n * @publicApi\n */\nexport interface IterableChanges<V> {\n /**\n * Iterate over all changes. `IterableChangeRecord` will contain information about changes\n * to each item.\n */\n forEachItem(fn: (record: IterableChangeRecord<V>) => void): void;\n\n /**\n * Iterate over a set of operations which when applied to the original `Iterable` will produce the\n * new `Iterable`.\n *\n * NOTE: These are not necessarily the actual operations which were applied to the original\n * `Iterable`, rather these are a set of computed operations which may not be the same as the\n * ones applied.\n *\n * @param record A change which needs to be applied\n * @param previousIndex The `IterableChangeRecord#previousIndex` of the `record` refers to the\n * original `Iterable` location, where as `previousIndex` refers to the transient location\n * of the item, after applying the operations up to this point.\n * @param currentIndex The `IterableChangeRecord#currentIndex` of the `record` refers to the\n * original `Iterable` location, where as `currentIndex` refers to the transient location\n * of the item, after applying the operations up to this point.\n */\n forEachOperation(\n fn:\n (record: IterableChangeRecord<V>, previousIndex: number|null,\n currentIndex: number|null) => void): void;\n\n /**\n * Iterate over changes in the order of original `Iterable` showing where the original items\n * have moved.\n */\n forEachPreviousItem(fn: (record: IterableChangeRecord<V>) => void): void;\n\n /** Iterate over all added items. */\n forEachAddedItem(fn: (record: IterableChangeRecord<V>) => void): void;\n\n /** Iterate over all moved items. */\n forEachMovedItem(fn: (record: IterableChangeRecord<V>) => void): void;\n\n /** Iterate over all removed items. */\n forEachRemovedItem(fn: (record: IterableChangeRecord<V>) => void): void;\n\n /**\n * Iterate over all items which had their identity (as computed by the `TrackByFunction`)\n * changed.\n */\n forEachIdentityChange(fn: (record: IterableChangeRecord<V>) => void): void;\n}\n\n/**\n * Record representing the item change information.\n *\n * @publicApi\n */\nexport interface IterableChangeRecord<V> {\n /** Current index of the item in `Iterable` or null if removed. */\n readonly currentIndex: number|null;\n\n /** Previous index of the item in `Iterable` or null if added. */\n readonly previousIndex: number|null;\n\n /** The item. */\n readonly item: V;\n\n /** Track by identity as computed by the `TrackByFunction`. */\n readonly trackById: any;\n}\n\n/**\n * A function optionally passed into the `NgForOf` directive to customize how `NgForOf` uniquely\n * identifies items in an iterable.\n *\n * `NgForOf` needs to uniquely identify items in the iterable to correctly perform DOM updates\n * when items in the iterable are reordered, new items are added, or existing items are removed.\n *\n *\n * In all of these scenarios it is usually desirable to only update the DOM elements associated\n * with the items affected by the change. This behavior is important to:\n *\n * - preserve any DOM-specific UI state (like cursor position, focus, text selection) when the\n * iterable is modified\n * - enable animation of item addition, removal, and iterable reordering\n * - preserve the value of the `<select>` element when nested `<option>` elements are dynamically\n * populated using `NgForOf` and the bound iterable is updated\n *\n * A common use for custom `trackBy` functions is when the model that `NgForOf` iterates over\n * contains a property with a unique identifier. For example, given a model:\n *\n * ```ts\n * class User {\n * id: number;\n * name: string;\n * ...\n * }\n * ```\n * a custom `trackBy` function could look like the following:\n * ```ts\n * function userTrackBy(index, user) {\n * return user.id;\n * }\n * ```\n *\n * A custom `trackBy` function must have several properties:\n *\n * - be [idempotent](https://en.wikipedia.org/wiki/Idempotence) (be without side effects, and always\n * return the same value for a given input)\n * - return unique value for all unique inputs\n * - be fast\n *\n * @see [`NgForOf#ngForTrackBy`](api/common/NgForOf#ngForTrackBy)\n * @publicApi\n */\nexport interface TrackByFunction<T> {\n // Note: the type parameter `U` enables more accurate template type checking in case a trackBy\n // function is declared using a base type of the iterated type. The `U` type gives TypeScript\n // additional freedom to infer a narrower type for the `item` parameter type, instead of imposing\n // the trackBy's declared item type as the inferred type for `T`.\n // See https://github.com/angular/angular/issues/40125\n\n /**\n * @param index The index of the item within the iterable.\n * @param item The item in the iterable.\n */\n <U extends T>(index: number, item: T&U): any;\n}\n\n/**\n * Provides a factory for {@link IterableDiffer}.\n *\n * @publicApi\n */\nexport interface IterableDifferFactory {\n supports(objects: any): boolean;\n create<V>(trackByFn?: TrackByFunction<V>): IterableDiffer<V>;\n}\n\nexport function defaultIterableDiffersFactory() {\n return new IterableDiffers([new DefaultIterableDifferFactory()]);\n}\n\n/**\n * A repository of different iterable diffing strategies used by NgFor, NgClass, and others.\n *\n * @publicApi\n */\nexport class IterableDiffers {\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable(\n {token: IterableDiffers, providedIn: 'root', factory: defaultIterableDiffersFactory});\n\n /**\n * @deprecated v4.0.0 - Should be private\n */\n factories: IterableDifferFactory[];\n constructor(factories: IterableDifferFactory[]) {\n this.factories = factories;\n }\n\n static create(factories: IterableDifferFactory[], parent?: IterableDiffers): IterableDiffers {\n if (parent != null) {\n const copied = parent.factories.slice();\n factories = factories.concat(copied);\n }\n\n return new IterableDiffers(factories);\n }\n\n /**\n * Takes an array of {@link IterableDifferFactory} and returns a provider used to extend the\n * inherited {@link IterableDiffers} instance with the provided factories and return a new\n * {@link IterableDiffers} instance.\n *\n * @usageNotes\n * ### Example\n *\n * The following example shows how to extend an existing list of factories,\n * which will only be applied to the injector for this component and its children.\n * This step is all that's required to make a new {@link IterableDiffer} available.\n *\n * ```\n * @Component({\n * viewProviders: [\n * IterableDiffers.extend([new ImmutableListDiffer()])\n * ]\n * })\n * ```\n */\n static extend(factories: IterableDifferFactory[]): StaticProvider {\n return {\n provide: IterableDiffers,\n useFactory: (parent: IterableDiffers|null) => {\n // if parent is null, it means that we are in the root injector and we have just overridden\n // the default injection mechanism for IterableDiffers, in such a case just assume\n // `defaultIterableDiffersFactory`.\n return IterableDiffers.create(factories, parent || defaultIterableDiffersFactory());\n },\n // Dependency technically isn't optional, but we can provide a better error message this way.\n deps: [[IterableDiffers, new SkipSelf(), new Optional()]]\n };\n }\n\n find(iterable: any): IterableDifferFactory {\n const factory = this.factories.find(f => f.supports(iterable));\n if (factory != null) {\n return factory;\n } else {\n throw new RuntimeError(\n RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY,\n ngDevMode &&\n `Cannot find a differ supporting object '${iterable}' of type '${\n getTypeNameForDebugging(iterable)}'`);\n }\n }\n}\n\nexport function getTypeNameForDebugging(type: any): string {\n return type['name'] || typeof type;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Optional, SkipSelf, StaticProvider, ɵɵdefineInjectable} from '../../di';\nimport {RuntimeError, RuntimeErrorCode} from '../../errors';\n\nimport {DefaultKeyValueDifferFactory} from './default_keyvalue_differ';\n\n\n/**\n * A differ that tracks changes made to an object over time.\n *\n * @publicApi\n */\nexport interface KeyValueDiffer<K, V> {\n /**\n * Compute a difference between the previous state and the new `object` state.\n *\n * @param object containing the new value.\n * @returns an object describing the difference. The return value is only valid until the next\n * `diff()` invocation.\n */\n diff(object: Map<K, V>): KeyValueChanges<K, V>|null;\n\n /**\n * Compute a difference between the previous state and the new `object` state.\n *\n * @param object containing the new value.\n * @returns an object describing the difference. The return value is only valid until the next\n * `diff()` invocation.\n */\n diff(object: {[key: string]: V}): KeyValueChanges<string, V>|null;\n // TODO(TS2.1): diff<KP extends string>(this: KeyValueDiffer<KP, V>, object: Record<KP, V>):\n // KeyValueDiffer<KP, V>;\n}\n\n/**\n * An object describing the changes in the `Map` or `{[k:string]: string}` since last time\n * `KeyValueDiffer#diff()` was invoked.\n *\n * @publicApi\n */\nexport interface KeyValueChanges<K, V> {\n /**\n * Iterate over all changes. `KeyValueChangeRecord` will contain information about changes\n * to each item.\n */\n forEachItem(fn: (r: KeyValueChangeRecord<K, V>) => void): void;\n\n /**\n * Iterate over changes in the order of original Map showing where the original items\n * have moved.\n */\n forEachPreviousItem(fn: (r: KeyValueChangeRecord<K, V>) => void): void;\n\n /**\n * Iterate over all keys for which values have changed.\n */\n forEachChangedItem(fn: (r: KeyValueChangeRecord<K, V>) => void): void;\n\n /**\n * Iterate over all added items.\n */\n forEachAddedItem(fn: (r: KeyValueChangeRecord<K, V>) => void): void;\n\n /**\n * Iterate over all removed items.\n */\n forEachRemovedItem(fn: (r: KeyValueChangeRecord<K, V>) => void): void;\n}\n\n/**\n * Record representing the item change information.\n *\n * @publicApi\n */\nexport interface KeyValueChangeRecord<K, V> {\n /**\n * Current key in the Map.\n */\n readonly key: K;\n\n /**\n * Current value for the key or `null` if removed.\n */\n readonly currentValue: V|null;\n\n /**\n * Previous value for the key or `null` if added.\n */\n readonly previousValue: V|null;\n}\n\n/**\n * Provides a factory for {@link KeyValueDiffer}.\n *\n * @publicApi\n */\nexport interface KeyValueDifferFactory {\n /**\n * Test to see if the differ knows how to diff this kind of object.\n */\n supports(objects: any): boolean;\n\n /**\n * Create a `KeyValueDiffer`.\n */\n create<K, V>(): KeyValueDiffer<K, V>;\n}\n\nexport function defaultKeyValueDiffersFactory() {\n return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);\n}\n\n/**\n * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.\n *\n * @publicApi\n */\nexport class KeyValueDiffers {\n /** @nocollapse */\n static ɵprov = /** @pureOrBreakMyCode */ ɵɵdefineInjectable(\n {token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory});\n\n /**\n * @deprecated v4.0.0 - Should be private.\n */\n factories: KeyValueDifferFactory[];\n\n constructor(factories: KeyValueDifferFactory[]) {\n this.factories = factories;\n }\n\n static create<S>(factories: KeyValueDifferFactory[], parent?: KeyValueDiffers): KeyValueDiffers {\n if (parent) {\n const copied = parent.factories.slice();\n factories = factories.concat(copied);\n }\n return new KeyValueDiffers(factories);\n }\n\n /**\n * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the\n * inherited {@link KeyValueDiffers} instance with the provided factories and return a new\n * {@link KeyValueDiffers} instance.\n *\n * @usageNotes\n * ### Example\n *\n * The following example shows how to extend an existing list of factories,\n * which will only be applied to the injector for this component and its children.\n * This step is all that's required to make a new {@link KeyValueDiffer} available.\n *\n * ```\n * @Component({\n * viewProviders: [\n * KeyValueDiffers.extend([new ImmutableMapDiffer()])\n * ]\n * })\n * ```\n */\n static extend<S>(factories: KeyValueDifferFactory[]): StaticProvider {\n return {\n provide: KeyValueDiffers,\n useFactory: (parent: KeyValueDiffers) => {\n // if parent is null, it means that we are in the root injector and we have just overridden\n // the default injection mechanism for KeyValueDiffers, in such a case just assume\n // `defaultKeyValueDiffersFactory`.\n return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());\n },\n // Dependency technically isn't optional, but we can provide a better error message this way.\n deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]\n };\n }\n\n find(kv: any): KeyValueDifferFactory {\n const factory = this.factories.find(f => f.supports(kv));\n if (factory) {\n return factory;\n }\n throw new RuntimeError(\n RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY,\n ngDevMode && `Cannot find a differ supporting object '${kv}'`);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DefaultIterableDifferFactory} from './differs/default_iterable_differ';\nimport {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';\nimport {IterableDifferFactory, IterableDiffers} from './differs/iterable_differs';\nimport {KeyValueDifferFactory, KeyValueDiffers} from './differs/keyvalue_differs';\n\nexport {SimpleChange, SimpleChanges} from '../interface/simple_change';\nexport {devModeEqual} from '../util/comparison';\nexport {ChangeDetectorRef} from './change_detector_ref';\nexport {ChangeDetectionStrategy} from './constants';\nexport {DefaultIterableDiffer, DefaultIterableDifferFactory} from './differs/default_iterable_differ';\nexport {DefaultKeyValueDifferFactory} from './differs/default_keyvalue_differ';\nexport {IterableChangeRecord, IterableChanges, IterableDiffer, IterableDifferFactory, IterableDiffers, NgIterable, TrackByFunction} from './differs/iterable_differs';\nexport {KeyValueChangeRecord, KeyValueChanges, KeyValueDiffer, KeyValueDifferFactory, KeyValueDiffers} from './differs/keyvalue_differs';\nexport {PipeTransform} from './pipe_transform';\n\n\n\n/**\n * Structural diffing for `Object`s and `Map`s.\n */\nconst keyValDiff: KeyValueDifferFactory[] = [new DefaultKeyValueDifferFactory()];\n\n/**\n * Structural diffing for `Iterable` types such as `Array`s.\n */\nconst iterableDiff: IterableDifferFactory[] = [new DefaultIterableDifferFactory()];\n\nexport const defaultIterableDiffers = new IterableDiffers(iterableDiff);\n\nexport const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {createPlatformFactory, PlatformRef} from './application_ref';\nimport {StaticProvider} from './di';\n\n/**\n * This platform has to be included in any other platform\n *\n * @publicApi\n */\nexport const platformCore: (extraProviders?: StaticProvider[]|undefined) => PlatformRef =\n createPlatformFactory(null, 'core', []);\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ApplicationRef} from './application_ref';\nimport {NgModule} from './metadata';\n\n/**\n * Re-exported by `BrowserModule`, which is included automatically in the root\n * `AppModule` when you create a new app with the CLI `new` command. Eagerly injects\n * `ApplicationRef` to instantiate it.\n *\n * @publicApi\n */\n@NgModule()\nexport class ApplicationModule {\n // Inject ApplicationRef to make it eager...\n constructor(appRef: ApplicationRef) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Coerces a value (typically a string) to a boolean. */\nexport function coerceToBoolean(value: unknown): boolean {\n return typeof value === 'boolean' ? value : (value != null && value !== 'false');\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector} from '../di/injector';\nimport {EnvironmentInjector, getNullInjector} from '../di/r3_injector';\nimport {Type} from '../interface/type';\nimport {ComponentRef} from '../linker/component_factory';\n\nimport {ComponentFactory} from './component_ref';\nimport {getComponentDef} from './definition';\nimport {assertComponentDef} from './errors';\n\n/**\n * Creates a `ComponentRef` instance based on provided component type and a set of options.\n *\n * @usageNotes\n *\n * The example below demonstrates how the `createComponent` function can be used\n * to create an instance of a ComponentRef dynamically and attach it to an ApplicationRef,\n * so that it gets included into change detection cycles.\n *\n * Note: the example uses standalone components, but the function can also be used for\n * non-standalone components (declared in an NgModule) as well.\n *\n * ```typescript\n * @Component({\n * standalone: true,\n * template: `Hello {{ name }}!`\n * })\n * class HelloComponent {\n * name = 'Angular';\n * }\n *\n * @Component({\n * standalone: true,\n * template: `<div id=\"hello-component-host\"></div>`\n * })\n * class RootComponent {}\n *\n * // Bootstrap an application.\n * const applicationRef = await bootstrapApplication(RootComponent);\n *\n * // Locate a DOM node that would be used as a host.\n * const host = document.getElementById('hello-component-host');\n *\n * // Get an `EnvironmentInjector` instance from the `ApplicationRef`.\n * const environmentInjector = applicationRef.injector;\n *\n * // We can now create a `ComponentRef` instance.\n * const componentRef = createComponent(HelloComponent, {host, environmentInjector});\n *\n * // Last step is to register the newly created ref using the `ApplicationRef` instance\n * // to include the component view into change detection cycles.\n * applicationRef.attachView(componentRef.hostView);\n * ```\n *\n * @param component Component class reference.\n * @param options Set of options to use:\n * * `environmentInjector`: An `EnvironmentInjector` instance to be used for the component, see\n * additional info about it at https://angular.io/guide/standalone-components#environment-injectors.\n * * `hostElement` (optional): A DOM node that should act as a host node for the component. If not\n * provided, Angular creates one based on the tag name used in the component selector (and falls\n * back to using `div` if selector doesn't have tag name info).\n * * `elementInjector` (optional): An `ElementInjector` instance, see additional info about it at\n * https://angular.io/guide/hierarchical-dependency-injection#elementinjector.\n * * `projectableNodes` (optional): A list of DOM nodes that should be projected through\n * [`<ng-content>`](api/core/ng-content) of the new component instance.\n * @returns ComponentRef instance that represents a given Component.\n *\n * @publicApi\n */\nexport function createComponent<C>(component: Type<C>, options: {\n environmentInjector: EnvironmentInjector,\n hostElement?: Element,\n elementInjector?: Injector,\n projectableNodes?: Node[][],\n}): ComponentRef<C> {\n ngDevMode && assertComponentDef(component);\n const componentDef = getComponentDef(component)!;\n const elementInjector = options.elementInjector || getNullInjector();\n const factory = new ComponentFactory<C>(componentDef);\n return factory.create(\n elementInjector, options.projectableNodes, options.hostElement, options.environmentInjector);\n}\n\n/**\n * An interface that describes the subset of component metadata\n * that can be retrieved using the `reflectComponentType` function.\n *\n * @publicApi\n */\nexport interface ComponentMirror<C> {\n /**\n * The component's HTML selector.\n */\n get selector(): string;\n /**\n * The type of component the factory will create.\n */\n get type(): Type<C>;\n /**\n * The inputs of the component.\n */\n get inputs(): ReadonlyArray<{readonly propName: string, readonly templateName: string}>;\n /**\n * The outputs of the component.\n */\n get outputs(): ReadonlyArray<{readonly propName: string, readonly templateName: string}>;\n /**\n * Selector for all <ng-content> elements in the component.\n */\n get ngContentSelectors(): ReadonlyArray<string>;\n /**\n * Whether this component is marked as standalone.\n * Note: an extra flag, not present in `ComponentFactory`.\n */\n get isStandalone(): boolean;\n}\n\n/**\n * Creates an object that allows to retrieve component metadata.\n *\n * @usageNotes\n *\n * The example below demonstrates how to use the function and how the fields\n * of the returned object map to the component metadata.\n *\n * ```typescript\n * @Component({\n * standalone: true,\n * selector: 'foo-component',\n * template: `\n * <ng-content></ng-content>\n * <ng-content select=\"content-selector-a\"></ng-content>\n * `,\n * })\n * class FooComponent {\n * @Input('inputName') inputPropName: string;\n * @Output('outputName') outputPropName = new EventEmitter<void>();\n * }\n *\n * const mirror = reflectComponentType(FooComponent);\n * expect(mirror.type).toBe(FooComponent);\n * expect(mirror.selector).toBe('foo-component');\n * expect(mirror.isStandalone).toBe(true);\n * expect(mirror.inputs).toEqual([{propName: 'inputName', templateName: 'inputPropName'}]);\n * expect(mirror.outputs).toEqual([{propName: 'outputName', templateName: 'outputPropName'}]);\n * expect(mirror.ngContentSelectors).toEqual([\n * '*', // first `<ng-content>` in a template, the selector defaults to `*`\n * 'content-selector-a' // second `<ng-content>` in a template\n * ]);\n * ```\n *\n * @param component Component class reference.\n * @returns An object that allows to retrieve component metadata.\n *\n * @publicApi\n */\nexport function reflectComponentType<C>(component: Type<C>): ComponentMirror<C>|null {\n const componentDef = getComponentDef(component);\n if (!componentDef) return null;\n\n const factory = new ComponentFactory<C>(componentDef);\n return {\n get selector(): string {\n return factory.selector;\n },\n get type(): Type<C> {\n return factory.componentType;\n },\n get inputs(): ReadonlyArray<{propName: string, templateName: string}> {\n return factory.inputs;\n },\n get outputs(): ReadonlyArray<{propName: string, templateName: string}> {\n return factory.outputs;\n },\n get ngContentSelectors(): ReadonlyArray<string> {\n return factory.ngContentSelectors;\n },\n get isStandalone(): boolean {\n return componentDef.standalone;\n },\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, ElementRef, InjectionToken, Renderer2} from '@angular/core';\n\n/**\n * @description\n * Defines an interface that acts as a bridge between the Angular forms API and a\n * native element in the DOM.\n *\n * Implement this interface to create a custom form control directive\n * that integrates with Angular forms.\n *\n * @see DefaultValueAccessor\n *\n * @publicApi\n */\nexport interface ControlValueAccessor {\n /**\n * @description\n * Writes a new value to the element.\n *\n * This method is called by the forms API to write to the view when programmatic\n * changes from model to view are requested.\n *\n * @usageNotes\n * ### Write a value to the element\n *\n * The following example writes a value to the native DOM element.\n *\n * ```ts\n * writeValue(value: any): void {\n * this._renderer.setProperty(this._elementRef.nativeElement, 'value', value);\n * }\n * ```\n *\n * @param obj The new value for the element\n */\n writeValue(obj: any): void;\n\n /**\n * @description\n * Registers a callback function that is called when the control's value\n * changes in the UI.\n *\n * This method is called by the forms API on initialization to update the form\n * model when values propagate from the view to the model.\n *\n * When implementing the `registerOnChange` method in your own value accessor,\n * save the given function so your class calls it at the appropriate time.\n *\n * @usageNotes\n * ### Store the change function\n *\n * The following example stores the provided function as an internal method.\n *\n * ```ts\n * registerOnChange(fn: (_: any) => void): void {\n * this._onChange = fn;\n * }\n * ```\n *\n * When the value changes in the UI, call the registered\n * function to allow the forms API to update itself:\n *\n * ```ts\n * host: {\n * '(change)': '_onChange($event.target.value)'\n * }\n * ```\n *\n * @param fn The callback function to register\n */\n registerOnChange(fn: any): void;\n\n /**\n * @description\n * Registers a callback function that is called by the forms API on initialization\n * to update the form model on blur.\n *\n * When implementing `registerOnTouched` in your own value accessor, save the given\n * function so your class calls it when the control should be considered\n * blurred or \"touched\".\n *\n * @usageNotes\n * ### Store the callback function\n *\n * The following example stores the provided function as an internal method.\n *\n * ```ts\n * registerOnTouched(fn: any): void {\n * this._onTouched = fn;\n * }\n * ```\n *\n * On blur (or equivalent), your class should call the registered function to allow\n * the forms API to update itself:\n *\n * ```ts\n * host: {\n * '(blur)': '_onTouched()'\n * }\n * ```\n *\n * @param fn The callback function to register\n */\n registerOnTouched(fn: any): void;\n\n /**\n * @description\n * Function that is called by the forms API when the control status changes to\n * or from 'DISABLED'. Depending on the status, it enables or disables the\n * appropriate DOM element.\n *\n * @usageNotes\n * The following is an example of writing the disabled property to a native DOM element:\n *\n * ```ts\n * setDisabledState(isDisabled: boolean): void {\n * this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n * }\n * ```\n *\n * @param isDisabled The disabled status to set on the element\n */\n setDisabledState?(isDisabled: boolean): void;\n}\n\n/**\n * Base class for all ControlValueAccessor classes defined in Forms package.\n * Contains common logic and utility functions.\n *\n * Note: this is an *internal-only* class and should not be extended or used directly in\n * applications code.\n */\n@Directive()\nexport class BaseControlValueAccessor {\n /**\n * The registered callback function called when a change or input event occurs on the input\n * element.\n * @nodoc\n */\n onChange = (_: any) => {};\n\n /**\n * The registered callback function called when a blur event occurs on the input element.\n * @nodoc\n */\n onTouched = () => {};\n\n constructor(private _renderer: Renderer2, private _elementRef: ElementRef) {}\n\n /**\n * Helper method that sets a property on a target element using the current Renderer\n * implementation.\n * @nodoc\n */\n protected setProperty(key: string, value: any): void {\n this._renderer.setProperty(this._elementRef.nativeElement, key, value);\n }\n\n /**\n * Registers a function called when the control is touched.\n * @nodoc\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * Registers a function called when the control value changes.\n * @nodoc\n */\n registerOnChange(fn: (_: any) => {}): void {\n this.onChange = fn;\n }\n\n /**\n * Sets the \"disabled\" property on the range input element.\n * @nodoc\n */\n setDisabledState(isDisabled: boolean): void {\n this.setProperty('disabled', isDisabled);\n }\n}\n\n/**\n * Base class for all built-in ControlValueAccessor classes (except DefaultValueAccessor, which is\n * used in case no other CVAs can be found). We use this class to distinguish between default CVA,\n * built-in CVAs and custom CVAs, so that Forms logic can recognize built-in CVAs and treat custom\n * ones with higher priority (when both built-in and custom CVAs are present).\n *\n * Note: this is an *internal-only* class and should not be extended or used directly in\n * applications code.\n */\n@Directive()\nexport class BuiltInControlValueAccessor extends BaseControlValueAccessor {\n}\n\n/**\n * Used to provide a `ControlValueAccessor` for form controls.\n *\n * See `DefaultValueAccessor` for how to implement one.\n *\n * @publicApi\n */\nexport const NG_VALUE_ACCESSOR =\n new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, forwardRef, Provider} from '@angular/core';\n\nimport {BuiltInControlValueAccessor, ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';\n\nconst CHECKBOX_VALUE_ACCESSOR: Provider = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => CheckboxControlValueAccessor),\n multi: true,\n};\n\n/**\n * @description\n * A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input\n * element.\n *\n * @usageNotes\n *\n * ### Using a checkbox with a reactive form.\n *\n * The following example shows how to use a checkbox with a reactive form.\n *\n * ```ts\n * const rememberLoginControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"checkbox\" [formControl]=\"rememberLoginControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]',\n host: {'(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()'},\n providers: [CHECKBOX_VALUE_ACCESSOR]\n})\nexport class CheckboxControlValueAccessor extends BuiltInControlValueAccessor implements\n ControlValueAccessor {\n /**\n * Sets the \"checked\" property on the input element.\n * @nodoc\n */\n writeValue(value: any): void {\n this.setProperty('checked', value);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵgetDOM as getDOM} from '@angular/common';\nimport {Directive, ElementRef, forwardRef, Inject, InjectionToken, Optional, Renderer2} from '@angular/core';\n\nimport {BaseControlValueAccessor, ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';\n\nexport const DEFAULT_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DefaultValueAccessor),\n multi: true\n};\n\n/**\n * We must check whether the agent is Android because composition events\n * behave differently between iOS and Android.\n */\nfunction _isAndroid(): boolean {\n const userAgent = getDOM() ? getDOM().getUserAgent() : '';\n return /android (\\d+)/.test(userAgent.toLowerCase());\n}\n\n/**\n * @description\n * Provide this token to control if form directives buffer IME input until\n * the \"compositionend\" event occurs.\n * @publicApi\n */\nexport const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>('CompositionEventMode');\n\n/**\n * The default `ControlValueAccessor` for writing a value and listening to changes on input\n * elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and\n * `NgModel` directives.\n *\n * {@searchKeywords ngDefaultControl}\n *\n * @usageNotes\n *\n * ### Using the default value accessor\n *\n * The following example shows how to use an input element that activates the default value accessor\n * (in this case, a text field).\n *\n * ```ts\n * const firstNameControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"text\" [formControl]=\"firstNameControl\">\n * ```\n *\n * This value accessor is used by default for `<input type=\"text\">` and `<textarea>` elements, but\n * you could also use it for custom components that have similar behavior and do not require special\n * processing. In order to attach the default value accessor to a custom element, add the\n * `ngDefaultControl` attribute as shown below.\n *\n * ```\n * <custom-input-component ngDefaultControl [(ngModel)]=\"value\"></custom-input-component>\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n 'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',\n // TODO: vsavkin replace the above selector with the one below it once\n // https://github.com/angular/angular/issues/3011 is implemented\n // selector: '[ngModel],[formControl],[formControlName]',\n host: {\n '(input)': '$any(this)._handleInput($event.target.value)',\n '(blur)': 'onTouched()',\n '(compositionstart)': '$any(this)._compositionStart()',\n '(compositionend)': '$any(this)._compositionEnd($event.target.value)'\n },\n providers: [DEFAULT_VALUE_ACCESSOR]\n})\nexport class DefaultValueAccessor extends BaseControlValueAccessor implements ControlValueAccessor {\n /** Whether the user is creating a composition string (IME events). */\n private _composing = false;\n\n constructor(\n renderer: Renderer2, elementRef: ElementRef,\n @Optional() @Inject(COMPOSITION_BUFFER_MODE) private _compositionMode: boolean) {\n super(renderer, elementRef);\n if (this._compositionMode == null) {\n this._compositionMode = !_isAndroid();\n }\n }\n\n /**\n * Sets the \"value\" property on the input element.\n * @nodoc\n */\n writeValue(value: any): void {\n const normalizedValue = value == null ? '' : value;\n this.setProperty('value', normalizedValue);\n }\n\n /** @internal */\n _handleInput(value: any): void {\n if (!this._compositionMode || (this._compositionMode && !this._composing)) {\n this.onChange(value);\n }\n }\n\n /** @internal */\n _compositionStart(): void {\n this._composing = true;\n }\n\n /** @internal */\n _compositionEnd(value: any): void {\n this._composing = false;\n this._compositionMode && this.onChange(value);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken, ɵisObservable as isObservable, ɵisPromise as isPromise, ɵRuntimeError as RuntimeError} from '@angular/core';\nimport {forkJoin, from, Observable} from 'rxjs';\nimport {map} from 'rxjs/operators';\n\nimport {AsyncValidator, AsyncValidatorFn, ValidationErrors, Validator, ValidatorFn} from './directives/validators';\nimport {RuntimeErrorCode} from './errors';\nimport {AbstractControl} from './model/abstract_model';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\nfunction isEmptyInputValue(value: any): boolean {\n /**\n * Check if the object is a string or array before evaluating the length attribute.\n * This avoids falsely rejecting objects that contain a custom length attribute.\n * For example, the object {id: 1, length: 0, width: 0} should not be returned as empty.\n */\n return value == null ||\n ((typeof value === 'string' || Array.isArray(value)) && value.length === 0);\n}\n\nfunction hasValidLength(value: any): boolean {\n // non-strict comparison is intentional, to check for both `null` and `undefined` values\n return value != null && typeof value.length === 'number';\n}\n\n/**\n * @description\n * An `InjectionToken` for registering additional synchronous validators used with\n * `AbstractControl`s.\n *\n * @see `NG_ASYNC_VALIDATORS`\n *\n * @usageNotes\n *\n * ### Providing a custom validator\n *\n * The following example registers a custom validator directive. Adding the validator to the\n * existing collection of validators requires the `multi: true` option.\n *\n * ```typescript\n * @Directive({\n * selector: '[customValidator]',\n * providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]\n * })\n * class CustomValidatorDirective implements Validator {\n * validate(control: AbstractControl): ValidationErrors | null {\n * return { 'custom': true };\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport const NG_VALIDATORS = new InjectionToken<Array<Validator|Function>>('NgValidators');\n\n/**\n * @description\n * An `InjectionToken` for registering additional asynchronous validators used with\n * `AbstractControl`s.\n *\n * @see `NG_VALIDATORS`\n *\n * @usageNotes\n *\n * ### Provide a custom async validator directive\n *\n * The following example implements the `AsyncValidator` interface to create an\n * async validator directive with a custom error key.\n *\n * ```typescript\n * @Directive({\n * selector: '[customAsyncValidator]',\n * providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi:\n * true}]\n * })\n * class CustomAsyncValidatorDirective implements AsyncValidator {\n * validate(control: AbstractControl): Promise<ValidationErrors|null> {\n * return Promise.resolve({'custom': true});\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport const NG_ASYNC_VALIDATORS =\n new InjectionToken<Array<Validator|Function>>('NgAsyncValidators');\n\n/**\n * A regular expression that matches valid e-mail addresses.\n *\n * At a high level, this regexp matches e-mail addresses of the format `local-part@tld`, where:\n * - `local-part` consists of one or more of the allowed characters (alphanumeric and some\n * punctuation symbols).\n * - `local-part` cannot begin or end with a period (`.`).\n * - `local-part` cannot be longer than 64 characters.\n * - `tld` consists of one or more `labels` separated by periods (`.`). For example `localhost` or\n * `foo.com`.\n * - A `label` consists of one or more of the allowed characters (alphanumeric, dashes (`-`) and\n * periods (`.`)).\n * - A `label` cannot begin or end with a dash (`-`) or a period (`.`).\n * - A `label` cannot be longer than 63 characters.\n * - The whole address cannot be longer than 254 characters.\n *\n * ## Implementation background\n *\n * This regexp was ported over from AngularJS (see there for git history):\n * https://github.com/angular/angular.js/blob/c133ef836/src/ng/directive/input.js#L27\n * It is based on the\n * [WHATWG version](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with\n * some enhancements to incorporate more RFC rules (such as rules related to domain names and the\n * lengths of different parts of the address). The main differences from the WHATWG version are:\n * - Disallow `local-part` to begin or end with a period (`.`).\n * - Disallow `local-part` length to exceed 64 characters.\n * - Disallow total address length to exceed 254 characters.\n *\n * See [this commit](https://github.com/angular/angular.js/commit/f3f5cf72e) for more details.\n */\nconst EMAIL_REGEXP =\n /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n\n/**\n * @description\n * Provides a set of built-in validators that can be used by form controls.\n *\n * A validator is a function that processes a `FormControl` or collection of\n * controls and returns an error map or null. A null map means that validation has passed.\n *\n * @see [Form Validation](/guide/form-validation)\n *\n * @publicApi\n */\nexport class Validators {\n /**\n * @description\n * Validator that requires the control's value to be greater than or equal to the provided number.\n *\n * @usageNotes\n *\n * ### Validate against a minimum of 3\n *\n * ```typescript\n * const control = new FormControl(2, Validators.min(3));\n *\n * console.log(control.errors); // {min: {min: 3, actual: 2}}\n * ```\n *\n * @returns A validator function that returns an error map with the\n * `min` property if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static min(min: number): ValidatorFn {\n return minValidator(min);\n }\n\n /**\n * @description\n * Validator that requires the control's value to be less than or equal to the provided number.\n *\n * @usageNotes\n *\n * ### Validate against a maximum of 15\n *\n * ```typescript\n * const control = new FormControl(16, Validators.max(15));\n *\n * console.log(control.errors); // {max: {max: 15, actual: 16}}\n * ```\n *\n * @returns A validator function that returns an error map with the\n * `max` property if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static max(max: number): ValidatorFn {\n return maxValidator(max);\n }\n\n /**\n * @description\n * Validator that requires the control have a non-empty value.\n *\n * @usageNotes\n *\n * ### Validate that the field is non-empty\n *\n * ```typescript\n * const control = new FormControl('', Validators.required);\n *\n * console.log(control.errors); // {required: true}\n * ```\n *\n * @returns An error map with the `required` property\n * if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static required(control: AbstractControl): ValidationErrors|null {\n return requiredValidator(control);\n }\n\n /**\n * @description\n * Validator that requires the control's value be true. This validator is commonly\n * used for required checkboxes.\n *\n * @usageNotes\n *\n * ### Validate that the field value is true\n *\n * ```typescript\n * const control = new FormControl('some value', Validators.requiredTrue);\n *\n * console.log(control.errors); // {required: true}\n * ```\n *\n * @returns An error map that contains the `required` property\n * set to `true` if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static requiredTrue(control: AbstractControl): ValidationErrors|null {\n return requiredTrueValidator(control);\n }\n\n /**\n * @description\n * Validator that requires the control's value pass an email validation test.\n *\n * Tests the value using a [regular\n * expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)\n * pattern suitable for common use cases. The pattern is based on the definition of a valid email\n * address in the [WHATWG HTML\n * specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with\n * some enhancements to incorporate more RFC rules (such as rules related to domain names and the\n * lengths of different parts of the address).\n *\n * The differences from the WHATWG version include:\n * - Disallow `local-part` (the part before the `@` symbol) to begin or end with a period (`.`).\n * - Disallow `local-part` to be longer than 64 characters.\n * - Disallow the whole address to be longer than 254 characters.\n *\n * If this pattern does not satisfy your business needs, you can use `Validators.pattern()` to\n * validate the value against a different pattern.\n *\n * @usageNotes\n *\n * ### Validate that the field matches a valid email pattern\n *\n * ```typescript\n * const control = new FormControl('bad@', Validators.email);\n *\n * console.log(control.errors); // {email: true}\n * ```\n *\n * @returns An error map with the `email` property\n * if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static email(control: AbstractControl): ValidationErrors|null {\n return emailValidator(control);\n }\n\n /**\n * @description\n * Validator that requires the length of the control's value to be greater than or equal\n * to the provided minimum length. This validator is also provided by default if you use the\n * the HTML5 `minlength` attribute. Note that the `minLength` validator is intended to be used\n * only for types that have a numeric `length` property, such as strings or arrays. The\n * `minLength` validator logic is also not invoked for values when their `length` property is 0\n * (for example in case of an empty string or an empty array), to support optional controls. You\n * can use the standard `required` validator if empty values should not be considered valid.\n *\n * @usageNotes\n *\n * ### Validate that the field has a minimum of 3 characters\n *\n * ```typescript\n * const control = new FormControl('ng', Validators.minLength(3));\n *\n * console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}}\n * ```\n *\n * ```html\n * <input minlength=\"5\">\n * ```\n *\n * @returns A validator function that returns an error map with the\n * `minlength` property if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static minLength(minLength: number): ValidatorFn {\n return minLengthValidator(minLength);\n }\n\n /**\n * @description\n * Validator that requires the length of the control's value to be less than or equal\n * to the provided maximum length. This validator is also provided by default if you use the\n * the HTML5 `maxlength` attribute. Note that the `maxLength` validator is intended to be used\n * only for types that have a numeric `length` property, such as strings or arrays.\n *\n * @usageNotes\n *\n * ### Validate that the field has maximum of 5 characters\n *\n * ```typescript\n * const control = new FormControl('Angular', Validators.maxLength(5));\n *\n * console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}}\n * ```\n *\n * ```html\n * <input maxlength=\"5\">\n * ```\n *\n * @returns A validator function that returns an error map with the\n * `maxlength` property if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static maxLength(maxLength: number): ValidatorFn {\n return maxLengthValidator(maxLength);\n }\n\n /**\n * @description\n * Validator that requires the control's value to match a regex pattern. This validator is also\n * provided by default if you use the HTML5 `pattern` attribute.\n *\n * @usageNotes\n *\n * ### Validate that the field only contains letters or spaces\n *\n * ```typescript\n * const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*'));\n *\n * console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}}\n * ```\n *\n * ```html\n * <input pattern=\"[a-zA-Z ]*\">\n * ```\n *\n * ### Pattern matching with the global or sticky flag\n *\n * `RegExp` objects created with the `g` or `y` flags that are passed into `Validators.pattern`\n * can produce different results on the same input when validations are run consecutively. This is\n * due to how the behavior of `RegExp.prototype.test` is\n * specified in [ECMA-262](https://tc39.es/ecma262/#sec-regexpbuiltinexec)\n * (`RegExp` preserves the index of the last match when the global or sticky flag is used).\n * Due to this behavior, it is recommended that when using\n * `Validators.pattern` you **do not** pass in a `RegExp` object with either the global or sticky\n * flag enabled.\n *\n * ```typescript\n * // Not recommended (since the `g` flag is used)\n * const controlOne = new FormControl('1', Validators.pattern(/foo/g));\n *\n * // Good\n * const controlTwo = new FormControl('1', Validators.pattern(/foo/));\n * ```\n *\n * @param pattern A regular expression to be used as is to test the values, or a string.\n * If a string is passed, the `^` character is prepended and the `$` character is\n * appended to the provided string (if not already present), and the resulting regular\n * expression is used to test the values.\n *\n * @returns A validator function that returns an error map with the\n * `pattern` property if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static pattern(pattern: string|RegExp): ValidatorFn {\n return patternValidator(pattern);\n }\n\n /**\n * @description\n * Validator that performs no operation.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static nullValidator(control: AbstractControl): ValidationErrors|null {\n return nullValidator(control);\n }\n\n /**\n * @description\n * Compose multiple validators into a single function that returns the union\n * of the individual error maps for the provided control.\n *\n * @returns A validator function that returns an error map with the\n * merged error maps of the validators if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static compose(validators: null): null;\n static compose(validators: (ValidatorFn|null|undefined)[]): ValidatorFn|null;\n static compose(validators: (ValidatorFn|null|undefined)[]|null): ValidatorFn|null {\n return compose(validators);\n }\n\n /**\n * @description\n * Compose multiple async validators into a single function that returns the union\n * of the individual error objects for the provided control.\n *\n * @returns A validator function that returns an error map with the\n * merged error objects of the async validators if the validation check fails, otherwise `null`.\n *\n * @see `updateValueAndValidity()`\n *\n */\n static composeAsync(validators: (AsyncValidatorFn|null)[]): AsyncValidatorFn|null {\n return composeAsync(validators);\n }\n}\n\n/**\n * Validator that requires the control's value to be greater than or equal to the provided number.\n * See `Validators.min` for additional information.\n */\nexport function minValidator(min: number): ValidatorFn {\n return (control: AbstractControl): ValidationErrors|null => {\n if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) {\n return null; // don't validate empty values to allow optional controls\n }\n const value = parseFloat(control.value);\n // Controls with NaN values after parsing should be treated as not having a\n // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min\n return !isNaN(value) && value < min ? {'min': {'min': min, 'actual': control.value}} : null;\n };\n}\n\n/**\n * Validator that requires the control's value to be less than or equal to the provided number.\n * See `Validators.max` for additional information.\n */\nexport function maxValidator(max: number): ValidatorFn {\n return (control: AbstractControl): ValidationErrors|null => {\n if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {\n return null; // don't validate empty values to allow optional controls\n }\n const value = parseFloat(control.value);\n // Controls with NaN values after parsing should be treated as not having a\n // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max\n return !isNaN(value) && value > max ? {'max': {'max': max, 'actual': control.value}} : null;\n };\n}\n\n/**\n * Validator that requires the control have a non-empty value.\n * See `Validators.required` for additional information.\n */\nexport function requiredValidator(control: AbstractControl): ValidationErrors|null {\n return isEmptyInputValue(control.value) ? {'required': true} : null;\n}\n\n/**\n * Validator that requires the control's value be true. This validator is commonly\n * used for required checkboxes.\n * See `Validators.requiredTrue` for additional information.\n */\nexport function requiredTrueValidator(control: AbstractControl): ValidationErrors|null {\n return control.value === true ? null : {'required': true};\n}\n\n/**\n * Validator that requires the control's value pass an email validation test.\n * See `Validators.email` for additional information.\n */\nexport function emailValidator(control: AbstractControl): ValidationErrors|null {\n if (isEmptyInputValue(control.value)) {\n return null; // don't validate empty values to allow optional controls\n }\n return EMAIL_REGEXP.test(control.value) ? null : {'email': true};\n}\n\n/**\n * Validator that requires the length of the control's value to be greater than or equal\n * to the provided minimum length. See `Validators.minLength` for additional information.\n */\nexport function minLengthValidator(minLength: number): ValidatorFn {\n return (control: AbstractControl): ValidationErrors|null => {\n if (isEmptyInputValue(control.value) || !hasValidLength(control.value)) {\n // don't validate empty values to allow optional controls\n // don't validate values without `length` property\n return null;\n }\n\n return control.value.length < minLength ?\n {'minlength': {'requiredLength': minLength, 'actualLength': control.value.length}} :\n null;\n };\n}\n\n/**\n * Validator that requires the length of the control's value to be less than or equal\n * to the provided maximum length. See `Validators.maxLength` for additional information.\n */\nexport function maxLengthValidator(maxLength: number): ValidatorFn {\n return (control: AbstractControl): ValidationErrors|null => {\n return hasValidLength(control.value) && control.value.length > maxLength ?\n {'maxlength': {'requiredLength': maxLength, 'actualLength': control.value.length}} :\n null;\n };\n}\n\n/**\n * Validator that requires the control's value to match a regex pattern.\n * See `Validators.pattern` for additional information.\n */\nexport function patternValidator(pattern: string|RegExp): ValidatorFn {\n if (!pattern) return nullValidator;\n let regex: RegExp;\n let regexStr: string;\n if (typeof pattern === 'string') {\n regexStr = '';\n\n if (pattern.charAt(0) !== '^') regexStr += '^';\n\n regexStr += pattern;\n\n if (pattern.charAt(pattern.length - 1) !== '$') regexStr += '$';\n\n regex = new RegExp(regexStr);\n } else {\n regexStr = pattern.toString();\n regex = pattern;\n }\n return (control: AbstractControl): ValidationErrors|null => {\n if (isEmptyInputValue(control.value)) {\n return null; // don't validate empty values to allow optional controls\n }\n const value: string = control.value;\n return regex.test(value) ? null :\n {'pattern': {'requiredPattern': regexStr, 'actualValue': value}};\n };\n}\n\n/**\n * Function that has `ValidatorFn` shape, but performs no operation.\n */\nexport function nullValidator(control: AbstractControl): ValidationErrors|null {\n return null;\n}\n\nfunction isPresent(o: any): boolean {\n return o != null;\n}\n\nexport function toObservable(value: any): Observable<any> {\n const obs = isPromise(value) ? from(value) : value;\n if (NG_DEV_MODE && !(isObservable(obs))) {\n let errorMessage = `Expected async validator to return Promise or Observable.`;\n // A synchronous validator will return object or null.\n if (typeof value === 'object') {\n errorMessage +=\n ' Are you using a synchronous validator where an async validator is expected?';\n }\n throw new RuntimeError(RuntimeErrorCode.WRONG_VALIDATOR_RETURN_TYPE, errorMessage);\n }\n return obs;\n}\n\nfunction mergeErrors(arrayOfErrors: (ValidationErrors|null)[]): ValidationErrors|null {\n let res: {[key: string]: any} = {};\n arrayOfErrors.forEach((errors: ValidationErrors|null) => {\n res = errors != null ? {...res!, ...errors} : res!;\n });\n\n return Object.keys(res).length === 0 ? null : res;\n}\n\ntype GenericValidatorFn = (control: AbstractControl) => any;\n\nfunction executeValidators<V extends GenericValidatorFn>(\n control: AbstractControl, validators: V[]): ReturnType<V>[] {\n return validators.map(validator => validator(control));\n}\n\nfunction isValidatorFn<V>(validator: V|Validator|AsyncValidator): validator is V {\n return !(validator as Validator).validate;\n}\n\n/**\n * Given the list of validators that may contain both functions as well as classes, return the list\n * of validator functions (convert validator classes into validator functions). This is needed to\n * have consistent structure in validators list before composing them.\n *\n * @param validators The set of validators that may contain validators both in plain function form\n * as well as represented as a validator class.\n */\nexport function normalizeValidators<V>(validators: (V|Validator|AsyncValidator)[]): V[] {\n return validators.map(validator => {\n return isValidatorFn<V>(validator) ?\n validator :\n ((c: AbstractControl) => validator.validate(c)) as unknown as V;\n });\n}\n\n/**\n * Merges synchronous validators into a single validator function.\n * See `Validators.compose` for additional information.\n */\nfunction compose(validators: (ValidatorFn|null|undefined)[]|null): ValidatorFn|null {\n if (!validators) return null;\n const presentValidators: ValidatorFn[] = validators.filter(isPresent) as any;\n if (presentValidators.length == 0) return null;\n\n return function(control: AbstractControl) {\n return mergeErrors(executeValidators<ValidatorFn>(control, presentValidators));\n };\n}\n\n/**\n * Accepts a list of validators of different possible shapes (`Validator` and `ValidatorFn`),\n * normalizes the list (converts everything to `ValidatorFn`) and merges them into a single\n * validator function.\n */\nexport function composeValidators(validators: Array<Validator|ValidatorFn>): ValidatorFn|null {\n return validators != null ? compose(normalizeValidators<ValidatorFn>(validators)) : null;\n}\n\n/**\n * Merges asynchronous validators into a single validator function.\n * See `Validators.composeAsync` for additional information.\n */\nfunction composeAsync(validators: (AsyncValidatorFn|null)[]): AsyncValidatorFn|null {\n if (!validators) return null;\n const presentValidators: AsyncValidatorFn[] = validators.filter(isPresent) as any;\n if (presentValidators.length == 0) return null;\n\n return function(control: AbstractControl) {\n const observables =\n executeValidators<AsyncValidatorFn>(control, presentValidators).map(toObservable);\n return forkJoin(observables).pipe(map(mergeErrors));\n };\n}\n\n/**\n * Accepts a list of async validators of different possible shapes (`AsyncValidator` and\n * `AsyncValidatorFn`), normalizes the list (converts everything to `AsyncValidatorFn`) and merges\n * them into a single validator function.\n */\nexport function composeAsyncValidators(validators: Array<AsyncValidator|AsyncValidatorFn>):\n AsyncValidatorFn|null {\n return validators != null ? composeAsync(normalizeValidators<AsyncValidatorFn>(validators)) :\n null;\n}\n\n/**\n * Merges raw control validators with a given directive validator and returns the combined list of\n * validators as an array.\n */\nexport function mergeValidators<V>(controlValidators: V|V[]|null, dirValidator: V): V[] {\n if (controlValidators === null) return [dirValidator];\n return Array.isArray(controlValidators) ? [...controlValidators, dirValidator] :\n [controlValidators, dirValidator];\n}\n\n/**\n * Retrieves the list of raw synchronous validators attached to a given control.\n */\nexport function getControlValidators(control: AbstractControl): ValidatorFn|ValidatorFn[]|null {\n return (control as any)._rawValidators as ValidatorFn | ValidatorFn[] | null;\n}\n\n/**\n * Retrieves the list of raw asynchronous validators attached to a given control.\n */\nexport function getControlAsyncValidators(control: AbstractControl): AsyncValidatorFn|\n AsyncValidatorFn[]|null {\n return (control as any)._rawAsyncValidators as AsyncValidatorFn | AsyncValidatorFn[] | null;\n}\n\n/**\n * Accepts a singleton validator, an array, or null, and returns an array type with the provided\n * validators.\n *\n * @param validators A validator, validators, or null.\n * @returns A validators array.\n */\nexport function makeValidatorsArray<T extends ValidatorFn|AsyncValidatorFn>(validators: T|T[]|\n null): T[] {\n if (!validators) return [];\n return Array.isArray(validators) ? validators : [validators];\n}\n\n/**\n * Determines whether a validator or validators array has a given validator.\n *\n * @param validators The validator or validators to compare against.\n * @param validator The validator to check.\n * @returns Whether the validator is present.\n */\nexport function hasValidator<T extends ValidatorFn|AsyncValidatorFn>(\n validators: T|T[]|null, validator: T): boolean {\n return Array.isArray(validators) ? validators.includes(validator) : validators === validator;\n}\n\n/**\n * Combines two arrays of validators into one. If duplicates are provided, only one will be added.\n *\n * @param validators The new validators.\n * @param currentValidators The base array of current validators.\n * @returns An array of validators.\n */\nexport function addValidators<T extends ValidatorFn|AsyncValidatorFn>(\n validators: T|T[], currentValidators: T|T[]|null): T[] {\n const current = makeValidatorsArray(currentValidators);\n const validatorsToAdd = makeValidatorsArray(validators);\n validatorsToAdd.forEach((v: T) => {\n // Note: if there are duplicate entries in the new validators array,\n // only the first one would be added to the current list of validators.\n // Duplicate ones would be ignored since `hasValidator` would detect\n // the presence of a validator function and we update the current list in place.\n if (!hasValidator(current, v)) {\n current.push(v);\n }\n });\n return current;\n}\n\nexport function removeValidators<T extends ValidatorFn|AsyncValidatorFn>(\n validators: T|T[], currentValidators: T|T[]|null): T[] {\n return makeValidatorsArray(currentValidators).filter(v => !hasValidator(validators, v));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Observable} from 'rxjs';\n\nimport {AbstractControl} from '../model/abstract_model';\nimport {composeAsyncValidators, composeValidators} from '../validators';\n\nimport {AsyncValidator, AsyncValidatorFn, ValidationErrors, Validator, ValidatorFn} from './validators';\n\n\n/**\n * @description\n * Base class for control directives.\n *\n * This class is only used internally in the `ReactiveFormsModule` and the `FormsModule`.\n *\n * @publicApi\n */\nexport abstract class AbstractControlDirective {\n /**\n * @description\n * A reference to the underlying control.\n *\n * @returns the control that backs this directive. Most properties fall through to that instance.\n */\n abstract get control(): AbstractControl|null;\n\n /**\n * @description\n * Reports the value of the control if it is present, otherwise null.\n */\n get value(): any {\n return this.control ? this.control.value : null;\n }\n\n /**\n * @description\n * Reports whether the control is valid. A control is considered valid if no\n * validation errors exist with the current value.\n * If the control is not present, null is returned.\n */\n get valid(): boolean|null {\n return this.control ? this.control.valid : null;\n }\n\n /**\n * @description\n * Reports whether the control is invalid, meaning that an error exists in the input value.\n * If the control is not present, null is returned.\n */\n get invalid(): boolean|null {\n return this.control ? this.control.invalid : null;\n }\n\n /**\n * @description\n * Reports whether a control is pending, meaning that that async validation is occurring and\n * errors are not yet available for the input value. If the control is not present, null is\n * returned.\n */\n get pending(): boolean|null {\n return this.control ? this.control.pending : null;\n }\n\n /**\n * @description\n * Reports whether the control is disabled, meaning that the control is disabled\n * in the UI and is exempt from validation checks and excluded from aggregate\n * values of ancestor controls. If the control is not present, null is returned.\n */\n get disabled(): boolean|null {\n return this.control ? this.control.disabled : null;\n }\n\n /**\n * @description\n * Reports whether the control is enabled, meaning that the control is included in ancestor\n * calculations of validity or value. If the control is not present, null is returned.\n */\n get enabled(): boolean|null {\n return this.control ? this.control.enabled : null;\n }\n\n /**\n * @description\n * Reports the control's validation errors. If the control is not present, null is returned.\n */\n get errors(): ValidationErrors|null {\n return this.control ? this.control.errors : null;\n }\n\n /**\n * @description\n * Reports whether the control is pristine, meaning that the user has not yet changed\n * the value in the UI. If the control is not present, null is returned.\n */\n get pristine(): boolean|null {\n return this.control ? this.control.pristine : null;\n }\n\n /**\n * @description\n * Reports whether the control is dirty, meaning that the user has changed\n * the value in the UI. If the control is not present, null is returned.\n */\n get dirty(): boolean|null {\n return this.control ? this.control.dirty : null;\n }\n\n /**\n * @description\n * Reports whether the control is touched, meaning that the user has triggered\n * a `blur` event on it. If the control is not present, null is returned.\n */\n get touched(): boolean|null {\n return this.control ? this.control.touched : null;\n }\n\n /**\n * @description\n * Reports the validation status of the control. Possible values include:\n * 'VALID', 'INVALID', 'DISABLED', and 'PENDING'.\n * If the control is not present, null is returned.\n */\n get status(): string|null {\n return this.control ? this.control.status : null;\n }\n\n /**\n * @description\n * Reports whether the control is untouched, meaning that the user has not yet triggered\n * a `blur` event on it. If the control is not present, null is returned.\n */\n get untouched(): boolean|null {\n return this.control ? this.control.untouched : null;\n }\n\n /**\n * @description\n * Returns a multicasting observable that emits a validation status whenever it is\n * calculated for the control. If the control is not present, null is returned.\n */\n get statusChanges(): Observable<any>|null {\n return this.control ? this.control.statusChanges : null;\n }\n\n /**\n * @description\n * Returns a multicasting observable of value changes for the control that emits every time the\n * value of the control changes in the UI or programmatically.\n * If the control is not present, null is returned.\n */\n get valueChanges(): Observable<any>|null {\n return this.control ? this.control.valueChanges : null;\n }\n\n /**\n * @description\n * Returns an array that represents the path from the top-level form to this control.\n * Each index is the string name of the control on that level.\n */\n get path(): string[]|null {\n return null;\n }\n\n /**\n * Contains the result of merging synchronous validators into a single validator function\n * (combined using `Validators.compose`).\n */\n private _composedValidatorFn: ValidatorFn|null|undefined;\n\n /**\n * Contains the result of merging asynchronous validators into a single validator function\n * (combined using `Validators.composeAsync`).\n */\n private _composedAsyncValidatorFn: AsyncValidatorFn|null|undefined;\n\n /**\n * Set of synchronous validators as they were provided while calling `setValidators` function.\n * @internal\n */\n _rawValidators: Array<Validator|ValidatorFn> = [];\n\n /**\n * Set of asynchronous validators as they were provided while calling `setAsyncValidators`\n * function.\n * @internal\n */\n _rawAsyncValidators: Array<AsyncValidator|AsyncValidatorFn> = [];\n\n /**\n * Sets synchronous validators for this directive.\n * @internal\n */\n _setValidators(validators: Array<Validator|ValidatorFn>|undefined): void {\n this._rawValidators = validators || [];\n this._composedValidatorFn = composeValidators(this._rawValidators);\n }\n\n /**\n * Sets asynchronous validators for this directive.\n * @internal\n */\n _setAsyncValidators(validators: Array<AsyncValidator|AsyncValidatorFn>|undefined): void {\n this._rawAsyncValidators = validators || [];\n this._composedAsyncValidatorFn = composeAsyncValidators(this._rawAsyncValidators);\n }\n\n /**\n * @description\n * Synchronous validator function composed of all the synchronous validators registered with this\n * directive.\n */\n get validator(): ValidatorFn|null {\n return this._composedValidatorFn || null;\n }\n\n /**\n * @description\n * Asynchronous validator function composed of all the asynchronous validators registered with\n * this directive.\n */\n get asyncValidator(): AsyncValidatorFn|null {\n return this._composedAsyncValidatorFn || null;\n }\n\n /*\n * The set of callbacks to be invoked when directive instance is being destroyed.\n */\n private _onDestroyCallbacks: (() => void)[] = [];\n\n /**\n * Internal function to register callbacks that should be invoked\n * when directive instance is being destroyed.\n * @internal\n */\n _registerOnDestroy(fn: () => void): void {\n this._onDestroyCallbacks.push(fn);\n }\n\n /**\n * Internal function to invoke all registered \"on destroy\" callbacks.\n * Note: calling this function also clears the list of callbacks.\n * @internal\n */\n _invokeOnDestroyCallbacks(): void {\n this._onDestroyCallbacks.forEach(fn => fn());\n this._onDestroyCallbacks = [];\n }\n\n /**\n * @description\n * Resets the control with the provided value if the control is present.\n */\n reset(value: any = undefined): void {\n if (this.control) this.control.reset(value);\n }\n\n /**\n * @description\n * Reports whether the control with the given path has the error specified.\n *\n * @param errorCode The code of the error to check\n * @param path A list of control names that designates how to move from the current control\n * to the control that should be queried for errors.\n *\n * @usageNotes\n * For example, for the following `FormGroup`:\n *\n * ```\n * form = new FormGroup({\n * address: new FormGroup({ street: new FormControl() })\n * });\n * ```\n *\n * The path to the 'street' control from the root form would be 'address' -> 'street'.\n *\n * It can be provided to this method in one of two formats:\n *\n * 1. An array of string control names, e.g. `['address', 'street']`\n * 1. A period-delimited list of control names in one string, e.g. `'address.street'`\n *\n * If no path is given, this method checks for the error on the current control.\n *\n * @returns whether the given error is present in the control at the given path.\n *\n * If the control is not present, false is returned.\n */\n hasError(errorCode: string, path?: Array<string|number>|string): boolean {\n return this.control ? this.control.hasError(errorCode, path) : false;\n }\n\n /**\n * @description\n * Reports error data for the control with the given path.\n *\n * @param errorCode The code of the error to check\n * @param path A list of control names that designates how to move from the current control\n * to the control that should be queried for errors.\n *\n * @usageNotes\n * For example, for the following `FormGroup`:\n *\n * ```\n * form = new FormGroup({\n * address: new FormGroup({ street: new FormControl() })\n * });\n * ```\n *\n * The path to the 'street' control from the root form would be 'address' -> 'street'.\n *\n * It can be provided to this method in one of two formats:\n *\n * 1. An array of string control names, e.g. `['address', 'street']`\n * 1. A period-delimited list of control names in one string, e.g. `'address.street'`\n *\n * @returns error data for that particular error. If the control or error is not present,\n * null is returned.\n */\n getError(errorCode: string, path?: Array<string|number>|string): any {\n return this.control ? this.control.getError(errorCode, path) : null;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AbstractControlDirective} from './abstract_control_directive';\nimport {Form} from './form_interface';\n\n\n/**\n * @description\n * A base class for directives that contain multiple registered instances of `NgControl`.\n * Only used by the forms module.\n *\n * @publicApi\n */\nexport abstract class ControlContainer extends AbstractControlDirective {\n /**\n * @description\n * The name for the control\n */\n // TODO(issue/24571): remove '!'.\n name!: string|number|null;\n\n /**\n * @description\n * The top-level form directive for the control.\n */\n get formDirective(): Form|null {\n return null;\n }\n\n /**\n * @description\n * The path to this group.\n */\n override get path(): string[]|null {\n return null;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AbstractControlDirective} from './abstract_control_directive';\nimport {ControlContainer} from './control_container';\nimport {ControlValueAccessor} from './control_value_accessor';\n\n\n/**\n * @description\n * A base class that all `FormControl`-based directives extend. It binds a `FormControl`\n * object to a DOM element.\n *\n * @publicApi\n */\nexport abstract class NgControl extends AbstractControlDirective {\n /**\n * @description\n * The parent form for the control.\n *\n * @internal\n */\n _parent: ControlContainer|null = null;\n\n /**\n * @description\n * The name for the control\n */\n name: string|number|null = null;\n\n /**\n * @description\n * The value accessor for the control\n */\n valueAccessor: ControlValueAccessor|null = null;\n\n /**\n * @description\n * The callback method to update the model from the view when requested\n *\n * @param newValue The new value for the view\n */\n abstract viewToModelUpdate(newValue: any): void;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, Optional, Self} from '@angular/core';\n\nimport {AbstractControlDirective} from './abstract_control_directive';\nimport {ControlContainer} from './control_container';\nimport {NgControl} from './ng_control';\n\n// DO NOT REFACTOR!\n// Each status is represented by a separate function to make sure that\n// advanced Closure Compiler optimizations related to property renaming\n// can work correctly.\nexport class AbstractControlStatus {\n private _cd: AbstractControlDirective|null;\n\n constructor(cd: AbstractControlDirective|null) {\n this._cd = cd;\n }\n\n protected get isTouched() {\n return !!this._cd?.control?.touched;\n }\n\n protected get isUntouched() {\n return !!this._cd?.control?.untouched;\n }\n\n protected get isPristine() {\n return !!this._cd?.control?.pristine;\n }\n\n protected get isDirty() {\n return !!this._cd?.control?.dirty;\n }\n\n protected get isValid() {\n return !!this._cd?.control?.valid;\n }\n\n protected get isInvalid() {\n return !!this._cd?.control?.invalid;\n }\n\n protected get isPending() {\n return !!this._cd?.control?.pending;\n }\n\n protected get isSubmitted() {\n // We check for the `submitted` field from `NgForm` and `FormGroupDirective` classes, but\n // we avoid instanceof checks to prevent non-tree-shakable references to those types.\n return !!(this._cd as unknown as {submitted: boolean} | null)?.submitted;\n }\n}\n\nexport const ngControlStatusHost = {\n '[class.ng-untouched]': 'isUntouched',\n '[class.ng-touched]': 'isTouched',\n '[class.ng-pristine]': 'isPristine',\n '[class.ng-dirty]': 'isDirty',\n '[class.ng-valid]': 'isValid',\n '[class.ng-invalid]': 'isInvalid',\n '[class.ng-pending]': 'isPending',\n};\n\nexport const ngGroupStatusHost = {\n ...ngControlStatusHost,\n '[class.ng-submitted]': 'isSubmitted',\n};\n\n/**\n * @description\n * Directive automatically applied to Angular form controls that sets CSS classes\n * based on control status.\n *\n * @usageNotes\n *\n * ### CSS classes applied\n *\n * The following classes are applied as the properties become true:\n *\n * * ng-valid\n * * ng-invalid\n * * ng-pending\n * * ng-pristine\n * * ng-dirty\n * * ng-untouched\n * * ng-touched\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({selector: '[formControlName],[ngModel],[formControl]', host: ngControlStatusHost})\nexport class NgControlStatus extends AbstractControlStatus {\n constructor(@Self() cd: NgControl) {\n super(cd);\n }\n}\n\n/**\n * @description\n * Directive automatically applied to Angular form groups that sets CSS classes\n * based on control status (valid/invalid/dirty/etc). On groups, this includes the additional\n * class ng-submitted.\n *\n * @see `NgControlStatus`\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n '[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',\n host: ngGroupStatusHost\n})\nexport class NgControlStatusGroup extends AbstractControlStatus {\n constructor(@Optional() @Self() cd: ControlContainer) {\n super(cd);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\n\nimport {formArrayNameExample, formControlNameExample, formGroupNameExample, ngModelGroupExample} from './error_examples';\n\n\nexport function controlParentException(): Error {\n return new RuntimeError(\n RuntimeErrorCode.FORM_CONTROL_NAME_MISSING_PARENT,\n `formControlName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n ${formControlNameExample}`);\n}\n\nexport function ngModelGroupException(): Error {\n return new RuntimeError(\n RuntimeErrorCode.FORM_CONTROL_NAME_INSIDE_MODEL_GROUP,\n `formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents\n that also have a \"form\" prefix: formGroupName, formArrayName, or formGroup.\n\n Option 1: Update the parent to be formGroupName (reactive form strategy)\n\n ${formGroupNameExample}\n\n Option 2: Use ngModel instead of formControlName (template-driven strategy)\n\n ${ngModelGroupExample}`);\n}\n\nexport function missingFormException(): Error {\n return new RuntimeError(\n RuntimeErrorCode.FORM_GROUP_MISSING_INSTANCE,\n `formGroup expects a FormGroup instance. Please pass one in.\n\n Example:\n\n ${formControlNameExample}`);\n}\n\nexport function groupParentException(): Error {\n return new RuntimeError(\n RuntimeErrorCode.FORM_GROUP_NAME_MISSING_PARENT,\n `formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n ${formGroupNameExample}`);\n}\n\nexport function arrayParentException(): Error {\n return new RuntimeError(\n RuntimeErrorCode.FORM_ARRAY_NAME_MISSING_PARENT,\n `formArrayName must be used with a parent formGroup directive. You'll want to add a formGroup\n directive and pass it an existing FormGroup instance (you can create one in your class).\n\n Example:\n\n ${formArrayNameExample}`);\n}\n\nexport const disabledAttrWarning = `\n It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true\n when you set up this control in your component class, the disabled attribute will actually be set in the DOM for\n you. We recommend using this approach to avoid 'changed after checked' errors.\n\n Example:\n // Specify the \\`disabled\\` property at control creation time:\n form = new FormGroup({\n first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),\n last: new FormControl('Drew', Validators.required)\n });\n\n // Controls can also be enabled/disabled after creation:\n form.get('first')?.enable();\n form.get('last')?.disable();\n`;\n\nexport const asyncValidatorsDroppedWithOptsWarning = `\n It looks like you're constructing using a FormControl with both an options argument and an\n async validators argument. Mixing these arguments will cause your async validators to be dropped.\n You should either put all your validators in the options object, or in separate validators\n arguments. For example:\n\n // Using validators arguments\n fc = new FormControl(42, Validators.required, myAsyncValidator);\n\n // Using AbstractControlOptions\n fc = new FormControl(42, {validators: Validators.required, asyncValidators: myAV});\n\n // Do NOT mix them: async validators will be dropped!\n fc = new FormControl(42, {validators: Validators.required}, /* Oops! */ myAsyncValidator);\n`;\n\nexport function ngModelWarning(directiveName: string): string {\n return `\n It looks like you're using ngModel on the same form field as ${directiveName}.\n Support for using the ngModel input property and ngModelChange event with\n reactive form directives has been deprecated in Angular v6 and will be removed\n in a future version of Angular.\n\n For more information on this, see our API docs here:\n https://angular.io/api/forms/${\n directiveName === 'formControl' ? 'FormControlDirective' : 'FormControlName'}#use-with-ngmodel\n `;\n}\n\nfunction describeKey(isFormGroup: boolean, key: string|number): string {\n return isFormGroup ? `with name: '${key}'` : `at index: ${key}`;\n}\n\nexport function noControlsError(isFormGroup: boolean): string {\n return `\n There are no form controls registered with this ${\n isFormGroup ? 'group' : 'array'} yet. If you're using ngModel,\n you may want to check next tick (e.g. use setTimeout).\n `;\n}\n\nexport function missingControlError(isFormGroup: boolean, key: string|number): string {\n return `Cannot find form control ${describeKey(isFormGroup, key)}`;\n}\n\nexport function missingControlValueError(isFormGroup: boolean, key: string|number): string {\n return `Must supply a value for form control ${describeKey(isFormGroup, key)}`;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EventEmitter, ɵRuntimeError as RuntimeError} from '@angular/core';\nimport {Observable} from 'rxjs';\n\nimport {asyncValidatorsDroppedWithOptsWarning, missingControlError, missingControlValueError, noControlsError} from '../directives/reactive_errors';\nimport {AsyncValidatorFn, ValidationErrors, ValidatorFn} from '../directives/validators';\nimport {RuntimeErrorCode} from '../errors';\nimport {FormArray, FormGroup} from '../forms';\nimport {addValidators, composeAsyncValidators, composeValidators, hasValidator, removeValidators, toObservable} from '../validators';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * Reports that a control is valid, meaning that no errors exist in the input value.\n *\n * @see `status`\n */\nexport const VALID = 'VALID';\n\n/**\n * Reports that a control is invalid, meaning that an error exists in the input value.\n *\n * @see `status`\n */\nexport const INVALID = 'INVALID';\n\n/**\n * Reports that a control is pending, meaning that that async validation is occurring and\n * errors are not yet available for the input value.\n *\n * @see `markAsPending`\n * @see `status`\n */\nexport const PENDING = 'PENDING';\n\n/**\n * Reports that a control is disabled, meaning that the control is exempt from ancestor\n * calculations of validity or value.\n *\n * @see `markAsDisabled`\n * @see `status`\n */\nexport const DISABLED = 'DISABLED';\n\n/**\n * A form can have several different statuses. Each\n * possible status is returned as a string literal.\n *\n * * **VALID**: Reports that a control is valid, meaning that no errors exist in the input\n * value.\n * * **INVALID**: Reports that a control is invalid, meaning that an error exists in the input\n * value.\n * * **PENDING**: Reports that a control is pending, meaning that that async validation is\n * occurring and errors are not yet available for the input value.\n * * **DISABLED**: Reports that a control is\n * disabled, meaning that the control is exempt from ancestor calculations of validity or value.\n *\n * @publicApi\n */\nexport type FormControlStatus = 'VALID'|'INVALID'|'PENDING'|'DISABLED';\n\n/**\n * Gets validators from either an options object or given validators.\n */\nexport function pickValidators(validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|\n null): ValidatorFn|ValidatorFn[]|null {\n return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.validators : validatorOrOpts) || null;\n}\n\n/**\n * Creates validator function by combining provided validators.\n */\nfunction coerceToValidator(validator: ValidatorFn|ValidatorFn[]|null): ValidatorFn|null {\n return Array.isArray(validator) ? composeValidators(validator) : validator || null;\n}\n\n/**\n * Gets async validators from either an options object or given validators.\n */\nexport function pickAsyncValidators(\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null,\n validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null): AsyncValidatorFn|\n AsyncValidatorFn[]|null {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (isOptionsObj(validatorOrOpts) && asyncValidator) {\n console.warn(asyncValidatorsDroppedWithOptsWarning);\n }\n }\n return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.asyncValidators : asyncValidator) || null;\n}\n\n/**\n * Creates async validator function by combining provided async validators.\n */\nfunction coerceToAsyncValidator(asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|\n null): AsyncValidatorFn|null {\n return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) :\n asyncValidator || null;\n}\n\nexport type FormHooks = 'change'|'blur'|'submit';\n\n/**\n * Interface for options provided to an `AbstractControl`.\n *\n * @publicApi\n */\nexport interface AbstractControlOptions {\n /**\n * @description\n * The list of validators applied to a control.\n */\n validators?: ValidatorFn|ValidatorFn[]|null;\n /**\n * @description\n * The list of async validators applied to control.\n */\n asyncValidators?: AsyncValidatorFn|AsyncValidatorFn[]|null;\n /**\n * @description\n * The event name for control to update upon.\n */\n updateOn?: 'change'|'blur'|'submit';\n}\n\nexport function isOptionsObj(validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|\n null): validatorOrOpts is AbstractControlOptions {\n return validatorOrOpts != null && !Array.isArray(validatorOrOpts) &&\n typeof validatorOrOpts === 'object';\n}\n\nexport function assertControlPresent(parent: any, isGroup: boolean, key: string|number): void {\n const controls = parent.controls as {[key: string|number]: unknown};\n const collection = isGroup ? Object.keys(controls) : controls;\n if (!collection.length) {\n throw new RuntimeError(\n RuntimeErrorCode.NO_CONTROLS, NG_DEV_MODE ? noControlsError(isGroup) : '');\n }\n if (!controls[key]) {\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_CONTROL, NG_DEV_MODE ? missingControlError(isGroup, key) : '');\n }\n}\n\nexport function assertAllValuesPresent(control: any, isGroup: boolean, value: any): void {\n control._forEachChild((_: unknown, key: string|number) => {\n if (value[key] === undefined) {\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_CONTROL_VALUE,\n NG_DEV_MODE ? missingControlValueError(isGroup, key) : '');\n }\n });\n}\n\n// IsAny checks if T is `any`, by checking a condition that couldn't possibly be true otherwise.\nexport type ɵIsAny<T, Y, N> = 0 extends(1&T) ? Y : N;\n\n/**\n * `TypedOrUntyped` allows one of two different types to be selected, depending on whether the Forms\n * class it's applied to is typed or not.\n *\n * This is for internal Angular usage to support typed forms; do not directly use it.\n */\nexport type ɵTypedOrUntyped<T, Typed, Untyped> = ɵIsAny<T, Untyped, Typed>;\n\n/**\n * Value gives the value type corresponding to a control type.\n *\n * Note that the resulting type will follow the same rules as `.value` on your control, group, or\n * array, including `undefined` for each group element which might be disabled.\n *\n * If you are trying to extract a value type for a data model, you probably want {@link RawValue},\n * which will not have `undefined` in group keys.\n *\n * @usageNotes\n *\n * ### `FormControl` value type\n *\n * You can extract the value type of a single control:\n *\n * ```ts\n * type NameControl = FormControl<string>;\n * type NameValue = Value<NameControl>;\n * ```\n *\n * The resulting type is `string`.\n *\n * ### `FormGroup` value type\n *\n * Imagine you have an interface defining the controls in your group. You can extract the shape of\n * the values as follows:\n *\n * ```ts\n * interface PartyFormControls {\n * address: FormControl<string>;\n * }\n *\n * // Value operates on controls; the object must be wrapped in a FormGroup.\n * type PartyFormValues = Value<FormGroup<PartyFormControls>>;\n * ```\n *\n * The resulting type is `{address: string|undefined}`.\n *\n * ### `FormArray` value type\n *\n * You can extract values from FormArrays as well:\n *\n * ```ts\n * type GuestNamesControls = FormArray<FormControl<string>>;\n *\n * type NamesValues = Value<GuestNamesControls>;\n * ```\n *\n * The resulting type is `string[]`.\n *\n * **Internal: not for public use.**\n */\nexport type ɵValue<T extends AbstractControl|undefined> =\n T extends AbstractControl<any, any>? T['value'] : never;\n\n/**\n * RawValue gives the raw value type corresponding to a control type.\n *\n * Note that the resulting type will follow the same rules as `.getRawValue()` on your control,\n * group, or array. This means that all controls inside a group will be required, not optional,\n * regardless of their disabled state.\n *\n * You may also wish to use {@link ɵValue}, which will have `undefined` in group keys (which can be\n * disabled).\n *\n * @usageNotes\n *\n * ### `FormGroup` raw value type\n *\n * Imagine you have an interface defining the controls in your group. You can extract the shape of\n * the raw values as follows:\n *\n * ```ts\n * interface PartyFormControls {\n * address: FormControl<string>;\n * }\n *\n * // RawValue operates on controls; the object must be wrapped in a FormGroup.\n * type PartyFormValues = RawValue<FormGroup<PartyFormControls>>;\n * ```\n *\n * The resulting type is `{address: string}`. (Note the absence of `undefined`.)\n *\n * **Internal: not for public use.**\n */\nexport type ɵRawValue<T extends AbstractControl|undefined> = T extends AbstractControl<any, any>?\n (T['setValue'] extends((v: infer R) => void) ? R : never) :\n never;\n\n// Disable clang-format to produce clearer formatting for these multiline types.\n// clang-format off\n\n/**\n * Tokenize splits a string literal S by a delimiter D.\n */\nexport type ɵTokenize<S extends string, D extends string> =\n string extends S ? string[] : /* S must be a literal */\n S extends `${infer T}${D}${infer U}` ? [T, ...ɵTokenize<U, D>] :\n [S] /* Base case */\n ;\n\n/**\n * CoerceStrArrToNumArr accepts an array of strings, and converts any numeric string to a number.\n */\nexport type ɵCoerceStrArrToNumArr<S> =\n// Extract the head of the array.\n S extends [infer Head, ...infer Tail] ?\n // Using a template literal type, coerce the head to `number` if possible.\n // Then, recurse on the tail.\n Head extends `${number}` ?\n [number, ...ɵCoerceStrArrToNumArr<Tail>] :\n [Head, ...ɵCoerceStrArrToNumArr<Tail>] :\n [];\n\n/**\n * Navigate takes a type T and an array K, and returns the type of T[K[0]][K[1]][K[2]]...\n */\nexport type ɵNavigate<T, K extends(Array<string|number>)> =\n T extends object ? /* T must be indexable (object or array) */\n (K extends [infer Head, ...infer Tail] ? /* Split K into head and tail */\n (Head extends keyof T ? /* head(K) must index T */\n (Tail extends(string|number)[] ? /* tail(K) must be an array */\n [] extends Tail ? T[Head] : /* base case: K can be split, but Tail is empty */\n (ɵNavigate<T[Head], Tail>) /* explore T[head(K)] by tail(K) */ :\n any) /* tail(K) was not an array, give up */ :\n never) /* head(K) does not index T, give up */ :\n any) /* K cannot be split, give up */ :\n any /* T is not indexable, give up */\n ;\n\n/**\n * ɵWriteable removes readonly from all keys.\n */\nexport type ɵWriteable<T> = {\n -readonly[P in keyof T]: T[P]\n};\n\n/**\n * GetProperty takes a type T and some property names or indices K.\n * If K is a dot-separated string, it is tokenized into an array before proceeding.\n * Then, the type of the nested property at K is computed: T[K[0]][K[1]][K[2]]...\n * This works with both objects, which are indexed by property name, and arrays, which are indexed\n * numerically.\n *\n * For internal use only.\n */\nexport type ɵGetProperty<T, K> =\n // K is a string\n K extends string ? ɵGetProperty<T, ɵCoerceStrArrToNumArr<ɵTokenize<K, '.'>>> :\n // Is is an array\n ɵWriteable<K> extends Array<string|number> ? ɵNavigate<T, ɵWriteable<K>> :\n // Fall through permissively if we can't calculate the type of K.\n any;\n\n// clang-format on\n\n/**\n * This is the base class for `FormControl`, `FormGroup`, and `FormArray`.\n *\n * It provides some of the shared behavior that all controls and groups of controls have, like\n * running validators, calculating status, and resetting state. It also defines the properties\n * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be\n * instantiated directly.\n *\n * The first type parameter TValue represents the value type of the control (`control.value`).\n * The optional type parameter TRawValue represents the raw value type (`control.getRawValue()`).\n *\n * @see [Forms Guide](/guide/forms)\n * @see [Reactive Forms Guide](/guide/reactive-forms)\n * @see [Dynamic Forms Guide](/guide/dynamic-form)\n *\n * @publicApi\n */\nexport abstract class AbstractControl<TValue = any, TRawValue extends TValue = TValue> {\n /** @internal */\n _pendingDirty = false;\n\n /**\n * Indicates that a control has its own pending asynchronous validation in progress.\n *\n * @internal\n */\n _hasOwnPendingAsyncValidator = false;\n\n /** @internal */\n _pendingTouched = false;\n\n /** @internal */\n _onCollectionChange = () => {};\n\n /** @internal */\n _updateOn?: FormHooks;\n\n private _parent: FormGroup|FormArray|null = null;\n private _asyncValidationSubscription: any;\n\n /**\n * Contains the result of merging synchronous validators into a single validator function\n * (combined using `Validators.compose`).\n *\n * @internal\n */\n private _composedValidatorFn!: ValidatorFn|null;\n\n /**\n * Contains the result of merging asynchronous validators into a single validator function\n * (combined using `Validators.composeAsync`).\n *\n * @internal\n */\n private _composedAsyncValidatorFn!: AsyncValidatorFn|null;\n\n /**\n * Synchronous validators as they were provided:\n * - in `AbstractControl` constructor\n * - as an argument while calling `setValidators` function\n * - while calling the setter on the `validator` field (e.g. `control.validator = validatorFn`)\n *\n * @internal\n */\n private _rawValidators!: ValidatorFn|ValidatorFn[]|null;\n\n /**\n * Asynchronous validators as they were provided:\n * - in `AbstractControl` constructor\n * - as an argument while calling `setAsyncValidators` function\n * - while calling the setter on the `asyncValidator` field (e.g. `control.asyncValidator =\n * asyncValidatorFn`)\n *\n * @internal\n */\n private _rawAsyncValidators!: AsyncValidatorFn|AsyncValidatorFn[]|null;\n\n /**\n * The current value of the control.\n *\n * * For a `FormControl`, the current value.\n * * For an enabled `FormGroup`, the values of enabled controls as an object\n * with a key-value pair for each member of the group.\n * * For a disabled `FormGroup`, the values of all controls as an object\n * with a key-value pair for each member of the group.\n * * For a `FormArray`, the values of enabled controls as an array.\n *\n */\n public readonly value!: TValue;\n\n /**\n * Initialize the AbstractControl instance.\n *\n * @param validators The function or array of functions that is used to determine the validity of\n * this control synchronously.\n * @param asyncValidators The function or array of functions that is used to determine validity of\n * this control asynchronously.\n */\n constructor(\n validators: ValidatorFn|ValidatorFn[]|null,\n asyncValidators: AsyncValidatorFn|AsyncValidatorFn[]|null) {\n this._assignValidators(validators);\n this._assignAsyncValidators(asyncValidators);\n }\n\n /**\n * Returns the function that is used to determine the validity of this control synchronously.\n * If multiple validators have been added, this will be a single composed function.\n * See `Validators.compose()` for additional information.\n */\n get validator(): ValidatorFn|null {\n return this._composedValidatorFn;\n }\n set validator(validatorFn: ValidatorFn|null) {\n this._rawValidators = this._composedValidatorFn = validatorFn;\n }\n\n /**\n * Returns the function that is used to determine the validity of this control asynchronously.\n * If multiple validators have been added, this will be a single composed function.\n * See `Validators.compose()` for additional information.\n */\n get asyncValidator(): AsyncValidatorFn|null {\n return this._composedAsyncValidatorFn;\n }\n set asyncValidator(asyncValidatorFn: AsyncValidatorFn|null) {\n this._rawAsyncValidators = this._composedAsyncValidatorFn = asyncValidatorFn;\n }\n\n /**\n * The parent control.\n */\n get parent(): FormGroup|FormArray|null {\n return this._parent;\n }\n\n /**\n * The validation status of the control.\n *\n * @see `FormControlStatus`\n *\n * These status values are mutually exclusive, so a control cannot be\n * both valid AND invalid or invalid AND disabled.\n */\n public readonly status!: FormControlStatus;\n\n /**\n * A control is `valid` when its `status` is `VALID`.\n *\n * @see {@link AbstractControl.status}\n *\n * @returns True if the control has passed all of its validation tests,\n * false otherwise.\n */\n get valid(): boolean {\n return this.status === VALID;\n }\n\n /**\n * A control is `invalid` when its `status` is `INVALID`.\n *\n * @see {@link AbstractControl.status}\n *\n * @returns True if this control has failed one or more of its validation checks,\n * false otherwise.\n */\n get invalid(): boolean {\n return this.status === INVALID;\n }\n\n /**\n * A control is `pending` when its `status` is `PENDING`.\n *\n * @see {@link AbstractControl.status}\n *\n * @returns True if this control is in the process of conducting a validation check,\n * false otherwise.\n */\n get pending(): boolean {\n return this.status == PENDING;\n }\n\n /**\n * A control is `disabled` when its `status` is `DISABLED`.\n *\n * Disabled controls are exempt from validation checks and\n * are not included in the aggregate value of their ancestor\n * controls.\n *\n * @see {@link AbstractControl.status}\n *\n * @returns True if the control is disabled, false otherwise.\n */\n get disabled(): boolean {\n return this.status === DISABLED;\n }\n\n /**\n * A control is `enabled` as long as its `status` is not `DISABLED`.\n *\n * @returns True if the control has any status other than 'DISABLED',\n * false if the status is 'DISABLED'.\n *\n * @see {@link AbstractControl.status}\n *\n */\n get enabled(): boolean {\n return this.status !== DISABLED;\n }\n\n /**\n * An object containing any errors generated by failing validation,\n * or null if there are no errors.\n */\n public readonly errors!: ValidationErrors|null;\n\n /**\n * A control is `pristine` if the user has not yet changed\n * the value in the UI.\n *\n * @returns True if the user has not yet changed the value in the UI; compare `dirty`.\n * Programmatic changes to a control's value do not mark it dirty.\n */\n public readonly pristine: boolean = true;\n\n /**\n * A control is `dirty` if the user has changed the value\n * in the UI.\n *\n * @returns True if the user has changed the value of this control in the UI; compare `pristine`.\n * Programmatic changes to a control's value do not mark it dirty.\n */\n get dirty(): boolean {\n return !this.pristine;\n }\n\n /**\n * True if the control is marked as `touched`.\n *\n * A control is marked `touched` once the user has triggered\n * a `blur` event on it.\n */\n public readonly touched: boolean = false;\n\n /**\n * True if the control has not been marked as touched\n *\n * A control is `untouched` if the user has not yet triggered\n * a `blur` event on it.\n */\n get untouched(): boolean {\n return !this.touched;\n }\n\n /**\n * A multicasting observable that emits an event every time the value of the control changes, in\n * the UI or programmatically. It also emits an event each time you call enable() or disable()\n * without passing along {emitEvent: false} as a function argument.\n */\n public readonly valueChanges!: Observable<TValue>;\n\n /**\n * A multicasting observable that emits an event every time the validation `status` of the control\n * recalculates.\n *\n * @see `FormControlStatus`\n * @see {@link AbstractControl.status}\n *\n */\n public readonly statusChanges!: Observable<FormControlStatus>;\n\n /**\n * Reports the update strategy of the `AbstractControl` (meaning\n * the event on which the control updates itself).\n * Possible values: `'change'` | `'blur'` | `'submit'`\n * Default value: `'change'`\n */\n get updateOn(): FormHooks {\n return this._updateOn ? this._updateOn : (this.parent ? this.parent.updateOn : 'change');\n }\n\n /**\n * Sets the synchronous validators that are active on this control. Calling\n * this overwrites any existing synchronous validators.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * If you want to add a new validator without affecting existing ones, consider\n * using `addValidators()` method instead.\n */\n setValidators(validators: ValidatorFn|ValidatorFn[]|null): void {\n this._assignValidators(validators);\n }\n\n /**\n * Sets the asynchronous validators that are active on this control. Calling this\n * overwrites any existing asynchronous validators.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * If you want to add a new validator without affecting existing ones, consider\n * using `addAsyncValidators()` method instead.\n */\n setAsyncValidators(validators: AsyncValidatorFn|AsyncValidatorFn[]|null): void {\n this._assignAsyncValidators(validators);\n }\n\n /**\n * Add a synchronous validator or validators to this control, without affecting other validators.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * Adding a validator that already exists will have no effect. If duplicate validator functions\n * are present in the `validators` array, only the first instance would be added to a form\n * control.\n *\n * @param validators The new validator function or functions to add to this control.\n */\n addValidators(validators: ValidatorFn|ValidatorFn[]): void {\n this.setValidators(addValidators(validators, this._rawValidators));\n }\n\n /**\n * Add an asynchronous validator or validators to this control, without affecting other\n * validators.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * Adding a validator that already exists will have no effect.\n *\n * @param validators The new asynchronous validator function or functions to add to this control.\n */\n addAsyncValidators(validators: AsyncValidatorFn|AsyncValidatorFn[]): void {\n this.setAsyncValidators(addValidators(validators, this._rawAsyncValidators));\n }\n\n /**\n * Remove a synchronous validator from this control, without affecting other validators.\n * Validators are compared by function reference; you must pass a reference to the exact same\n * validator function as the one that was originally set. If a provided validator is not found,\n * it is ignored.\n *\n * @usageNotes\n *\n * ### Reference to a ValidatorFn\n *\n * ```\n * // Reference to the RequiredValidator\n * const ctrl = new FormControl<string | null>('', Validators.required);\n * ctrl.removeValidators(Validators.required);\n *\n * // Reference to anonymous function inside MinValidator\n * const minValidator = Validators.min(3);\n * const ctrl = new FormControl<string | null>('', minValidator);\n * expect(ctrl.hasValidator(minValidator)).toEqual(true)\n * expect(ctrl.hasValidator(Validators.min(3))).toEqual(false)\n *\n * ctrl.removeValidators(minValidator);\n * ```\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * @param validators The validator or validators to remove.\n */\n removeValidators(validators: ValidatorFn|ValidatorFn[]): void {\n this.setValidators(removeValidators(validators, this._rawValidators));\n }\n\n /**\n * Remove an asynchronous validator from this control, without affecting other validators.\n * Validators are compared by function reference; you must pass a reference to the exact same\n * validator function as the one that was originally set. If a provided validator is not found, it\n * is ignored.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n * @param validators The asynchronous validator or validators to remove.\n */\n removeAsyncValidators(validators: AsyncValidatorFn|AsyncValidatorFn[]): void {\n this.setAsyncValidators(removeValidators(validators, this._rawAsyncValidators));\n }\n\n /**\n * Check whether a synchronous validator function is present on this control. The provided\n * validator must be a reference to the exact same function that was provided.\n *\n * @usageNotes\n *\n * ### Reference to a ValidatorFn\n *\n * ```\n * // Reference to the RequiredValidator\n * const ctrl = new FormControl<number | null>(0, Validators.required);\n * expect(ctrl.hasValidator(Validators.required)).toEqual(true)\n *\n * // Reference to anonymous function inside MinValidator\n * const minValidator = Validators.min(3);\n * const ctrl = new FormControl<number | null>(0, minValidator);\n * expect(ctrl.hasValidator(minValidator)).toEqual(true)\n * expect(ctrl.hasValidator(Validators.min(3))).toEqual(false)\n * ```\n *\n * @param validator The validator to check for presence. Compared by function reference.\n * @returns Whether the provided validator was found on this control.\n */\n hasValidator(validator: ValidatorFn): boolean {\n return hasValidator(this._rawValidators, validator);\n }\n\n /**\n * Check whether an asynchronous validator function is present on this control. The provided\n * validator must be a reference to the exact same function that was provided.\n *\n * @param validator The asynchronous validator to check for presence. Compared by function\n * reference.\n * @returns Whether the provided asynchronous validator was found on this control.\n */\n hasAsyncValidator(validator: AsyncValidatorFn): boolean {\n return hasValidator(this._rawAsyncValidators, validator);\n }\n\n /**\n * Empties out the synchronous validator list.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n */\n clearValidators(): void {\n this.validator = null;\n }\n\n /**\n * Empties out the async validator list.\n *\n * When you add or remove a validator at run time, you must call\n * `updateValueAndValidity()` for the new validation to take effect.\n *\n */\n clearAsyncValidators(): void {\n this.asyncValidator = null;\n }\n\n /**\n * Marks the control as `touched`. A control is touched by focus and\n * blur events that do not change the value.\n *\n * @see `markAsUntouched()`\n * @see `markAsDirty()`\n * @see `markAsPristine()`\n *\n * @param opts Configuration options that determine how the control propagates changes\n * and emits events after marking is applied.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n */\n markAsTouched(opts: {onlySelf?: boolean} = {}): void {\n (this as {touched: boolean}).touched = true;\n\n if (this._parent && !opts.onlySelf) {\n this._parent.markAsTouched(opts);\n }\n }\n\n /**\n * Marks the control and all its descendant controls as `touched`.\n * @see `markAsTouched()`\n */\n markAllAsTouched(): void {\n this.markAsTouched({onlySelf: true});\n\n this._forEachChild((control: AbstractControl) => control.markAllAsTouched());\n }\n\n /**\n * Marks the control as `untouched`.\n *\n * If the control has any children, also marks all children as `untouched`\n * and recalculates the `touched` status of all parent controls.\n *\n * @see `markAsTouched()`\n * @see `markAsDirty()`\n * @see `markAsPristine()`\n *\n * @param opts Configuration options that determine how the control propagates changes\n * and emits events after the marking is applied.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n */\n markAsUntouched(opts: {onlySelf?: boolean} = {}): void {\n (this as {touched: boolean}).touched = false;\n this._pendingTouched = false;\n\n this._forEachChild((control: AbstractControl) => {\n control.markAsUntouched({onlySelf: true});\n });\n\n if (this._parent && !opts.onlySelf) {\n this._parent._updateTouched(opts);\n }\n }\n\n /**\n * Marks the control as `dirty`. A control becomes dirty when\n * the control's value is changed through the UI; compare `markAsTouched`.\n *\n * @see `markAsTouched()`\n * @see `markAsUntouched()`\n * @see `markAsPristine()`\n *\n * @param opts Configuration options that determine how the control propagates changes\n * and emits events after marking is applied.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n */\n markAsDirty(opts: {onlySelf?: boolean} = {}): void {\n (this as {pristine: boolean}).pristine = false;\n\n if (this._parent && !opts.onlySelf) {\n this._parent.markAsDirty(opts);\n }\n }\n\n /**\n * Marks the control as `pristine`.\n *\n * If the control has any children, marks all children as `pristine`,\n * and recalculates the `pristine` status of all parent\n * controls.\n *\n * @see `markAsTouched()`\n * @see `markAsUntouched()`\n * @see `markAsDirty()`\n *\n * @param opts Configuration options that determine how the control emits events after\n * marking is applied.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n */\n markAsPristine(opts: {onlySelf?: boolean} = {}): void {\n (this as {pristine: boolean}).pristine = true;\n this._pendingDirty = false;\n\n this._forEachChild((control: AbstractControl) => {\n control.markAsPristine({onlySelf: true});\n });\n\n if (this._parent && !opts.onlySelf) {\n this._parent._updatePristine(opts);\n }\n }\n\n /**\n * Marks the control as `pending`.\n *\n * A control is pending while the control performs async validation.\n *\n * @see {@link AbstractControl.status}\n *\n * @param opts Configuration options that determine how the control propagates changes and\n * emits events after marking is applied.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n * * `emitEvent`: When true or not supplied (the default), the `statusChanges`\n * observable emits an event with the latest status the control is marked pending.\n * When false, no events are emitted.\n *\n */\n markAsPending(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n (this as {status: FormControlStatus}).status = PENDING;\n\n if (opts.emitEvent !== false) {\n (this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);\n }\n\n if (this._parent && !opts.onlySelf) {\n this._parent.markAsPending(opts);\n }\n }\n\n /**\n * Disables the control. This means the control is exempt from validation checks and\n * excluded from the aggregate value of any parent. Its status is `DISABLED`.\n *\n * If the control has children, all children are also disabled.\n *\n * @see {@link AbstractControl.status}\n *\n * @param opts Configuration options that determine how the control propagates\n * changes and emits events after the control is disabled.\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control is disabled.\n * When false, no events are emitted.\n */\n disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n // If parent has been marked artificially dirty we don't want to re-calculate the\n // parent's dirtiness based on the children.\n const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);\n\n (this as {status: FormControlStatus}).status = DISABLED;\n (this as {errors: ValidationErrors | null}).errors = null;\n this._forEachChild((control: AbstractControl) => {\n control.disable({...opts, onlySelf: true});\n });\n this._updateValue();\n\n if (opts.emitEvent !== false) {\n (this.valueChanges as EventEmitter<TValue>).emit(this.value);\n (this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);\n }\n\n this._updateAncestors({...opts, skipPristineCheck});\n this._onDisabledChange.forEach((changeFn) => changeFn(true));\n }\n\n /**\n * Enables the control. This means the control is included in validation checks and\n * the aggregate value of its parent. Its status recalculates based on its value and\n * its validators.\n *\n * By default, if the control has children, all children are enabled.\n *\n * @see {@link AbstractControl.status}\n *\n * @param opts Configure options that control how the control propagates changes and\n * emits events when marked as untouched\n * * `onlySelf`: When true, mark only this control. When false or not supplied,\n * marks all direct ancestors. Default is false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control is enabled.\n * When false, no events are emitted.\n */\n enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n // If parent has been marked artificially dirty we don't want to re-calculate the\n // parent's dirtiness based on the children.\n const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);\n\n (this as {status: FormControlStatus}).status = VALID;\n this._forEachChild((control: AbstractControl) => {\n control.enable({...opts, onlySelf: true});\n });\n this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});\n\n this._updateAncestors({...opts, skipPristineCheck});\n this._onDisabledChange.forEach((changeFn) => changeFn(false));\n }\n\n private _updateAncestors(\n opts: {onlySelf?: boolean, emitEvent?: boolean, skipPristineCheck?: boolean}): void {\n if (this._parent && !opts.onlySelf) {\n this._parent.updateValueAndValidity(opts);\n if (!opts.skipPristineCheck) {\n this._parent._updatePristine();\n }\n this._parent._updateTouched();\n }\n }\n\n /**\n * Sets the parent of the control\n *\n * @param parent The new parent.\n */\n setParent(parent: FormGroup|FormArray|null): void {\n this._parent = parent;\n }\n\n /**\n * Sets the value of the control. Abstract method (implemented in sub-classes).\n */\n abstract setValue(value: TRawValue, options?: Object): void;\n\n /**\n * Patches the value of the control. Abstract method (implemented in sub-classes).\n */\n abstract patchValue(value: TValue, options?: Object): void;\n\n /**\n * Resets the control. Abstract method (implemented in sub-classes).\n */\n abstract reset(value?: TValue, options?: Object): void;\n\n /**\n * The raw value of this control. For most control implementations, the raw value will include\n * disabled children.\n */\n getRawValue(): any {\n return this.value;\n }\n\n /**\n * Recalculates the value and validation status of the control.\n *\n * By default, it also updates the value and validity of its ancestors.\n *\n * @param opts Configuration options determine how the control propagates changes and emits events\n * after updates and validity checks are applied.\n * * `onlySelf`: When true, only update this control. When false or not supplied,\n * update all direct ancestors. Default is false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control is updated.\n * When false, no events are emitted.\n */\n updateValueAndValidity(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n this._setInitialStatus();\n this._updateValue();\n\n if (this.enabled) {\n this._cancelExistingSubscription();\n (this as {errors: ValidationErrors | null}).errors = this._runValidator();\n (this as {status: FormControlStatus}).status = this._calculateStatus();\n\n if (this.status === VALID || this.status === PENDING) {\n this._runAsyncValidator(opts.emitEvent);\n }\n }\n\n if (opts.emitEvent !== false) {\n (this.valueChanges as EventEmitter<TValue>).emit(this.value);\n (this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);\n }\n\n if (this._parent && !opts.onlySelf) {\n this._parent.updateValueAndValidity(opts);\n }\n }\n\n /** @internal */\n _updateTreeValidity(opts: {emitEvent?: boolean} = {emitEvent: true}): void {\n this._forEachChild((ctrl: AbstractControl) => ctrl._updateTreeValidity(opts));\n this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});\n }\n\n private _setInitialStatus() {\n (this as {status: FormControlStatus}).status = this._allControlsDisabled() ? DISABLED : VALID;\n }\n\n private _runValidator(): ValidationErrors|null {\n return this.validator ? this.validator(this) : null;\n }\n\n private _runAsyncValidator(emitEvent?: boolean): void {\n if (this.asyncValidator) {\n (this as {status: FormControlStatus}).status = PENDING;\n this._hasOwnPendingAsyncValidator = true;\n const obs = toObservable(this.asyncValidator(this));\n this._asyncValidationSubscription = obs.subscribe((errors: ValidationErrors|null) => {\n this._hasOwnPendingAsyncValidator = false;\n // This will trigger the recalculation of the validation status, which depends on\n // the state of the asynchronous validation (whether it is in progress or not). So, it is\n // necessary that we have updated the `_hasOwnPendingAsyncValidator` boolean flag first.\n this.setErrors(errors, {emitEvent});\n });\n }\n }\n\n private _cancelExistingSubscription(): void {\n if (this._asyncValidationSubscription) {\n this._asyncValidationSubscription.unsubscribe();\n this._hasOwnPendingAsyncValidator = false;\n }\n }\n\n /**\n * Sets errors on a form control when running validations manually, rather than automatically.\n *\n * Calling `setErrors` also updates the validity of the parent control.\n *\n * @param opts Configuration options that determine how the control propagates\n * changes and emits events after the control errors are set.\n * * `emitEvent`: When true or not supplied (the default), the `statusChanges`\n * observable emits an event after the errors are set.\n *\n * @usageNotes\n *\n * ### Manually set the errors for a control\n *\n * ```\n * const login = new FormControl('someLogin');\n * login.setErrors({\n * notUnique: true\n * });\n *\n * expect(login.valid).toEqual(false);\n * expect(login.errors).toEqual({ notUnique: true });\n *\n * login.setValue('someOtherLogin');\n *\n * expect(login.valid).toEqual(true);\n * ```\n */\n setErrors(errors: ValidationErrors|null, opts: {emitEvent?: boolean} = {}): void {\n (this as {errors: ValidationErrors | null}).errors = errors;\n this._updateControlsErrors(opts.emitEvent !== false);\n }\n\n /**\n * Retrieves a child control given the control's name or path.\n *\n * This signature for get supports strings and `const` arrays (`.get(['foo', 'bar'] as const)`).\n */\n get<P extends string|(readonly(string|number)[])>(path: P):\n AbstractControl<ɵGetProperty<TRawValue, P>>|null;\n\n /**\n * Retrieves a child control given the control's name or path.\n *\n * This signature for `get` supports non-const (mutable) arrays. Inferred type\n * information will not be as robust, so prefer to pass a `readonly` array if possible.\n */\n get<P extends string|Array<string|number>>(path: P):\n AbstractControl<ɵGetProperty<TRawValue, P>>|null;\n\n /**\n * Retrieves a child control given the control's name or path.\n *\n * @param path A dot-delimited string or array of string/number values that define the path to the\n * control. If a string is provided, passing it as a string literal will result in improved type\n * information. Likewise, if an array is provided, passing it `as const` will cause improved type\n * information to be available.\n *\n * @usageNotes\n * ### Retrieve a nested control\n *\n * For example, to get a `name` control nested within a `person` sub-group:\n *\n * * `this.form.get('person.name');`\n *\n * -OR-\n *\n * * `this.form.get(['person', 'name'] as const);` // `as const` gives improved typings\n *\n * ### Retrieve a control in a FormArray\n *\n * When accessing an element inside a FormArray, you can use an element index.\n * For example, to get a `price` control from the first element in an `items` array you can use:\n *\n * * `this.form.get('items.0.price');`\n *\n * -OR-\n *\n * * `this.form.get(['items', 0, 'price']);`\n */\n get<P extends string|((string | number)[])>(path: P):\n AbstractControl<ɵGetProperty<TRawValue, P>>|null {\n let currPath: Array<string|number>|string = path;\n if (currPath == null) return null;\n if (!Array.isArray(currPath)) currPath = currPath.split('.');\n if (currPath.length === 0) return null;\n return currPath.reduce(\n (control: AbstractControl|null, name) => control && control._find(name), this);\n }\n\n /**\n * @description\n * Reports error data for the control with the given path.\n *\n * @param errorCode The code of the error to check\n * @param path A list of control names that designates how to move from the current control\n * to the control that should be queried for errors.\n *\n * @usageNotes\n * For example, for the following `FormGroup`:\n *\n * ```\n * form = new FormGroup({\n * address: new FormGroup({ street: new FormControl() })\n * });\n * ```\n *\n * The path to the 'street' control from the root form would be 'address' -> 'street'.\n *\n * It can be provided to this method in one of two formats:\n *\n * 1. An array of string control names, e.g. `['address', 'street']`\n * 1. A period-delimited list of control names in one string, e.g. `'address.street'`\n *\n * @returns error data for that particular error. If the control or error is not present,\n * null is returned.\n */\n getError(errorCode: string, path?: Array<string|number>|string): any {\n const control = path ? this.get(path) : this;\n return control && control.errors ? control.errors[errorCode] : null;\n }\n\n /**\n * @description\n * Reports whether the control with the given path has the error specified.\n *\n * @param errorCode The code of the error to check\n * @param path A list of control names that designates how to move from the current control\n * to the control that should be queried for errors.\n *\n * @usageNotes\n * For example, for the following `FormGroup`:\n *\n * ```\n * form = new FormGroup({\n * address: new FormGroup({ street: new FormControl() })\n * });\n * ```\n *\n * The path to the 'street' control from the root form would be 'address' -> 'street'.\n *\n * It can be provided to this method in one of two formats:\n *\n * 1. An array of string control names, e.g. `['address', 'street']`\n * 1. A period-delimited list of control names in one string, e.g. `'address.street'`\n *\n * If no path is given, this method checks for the error on the current control.\n *\n * @returns whether the given error is present in the control at the given path.\n *\n * If the control is not present, false is returned.\n */\n hasError(errorCode: string, path?: Array<string|number>|string): boolean {\n return !!this.getError(errorCode, path);\n }\n\n /**\n * Retrieves the top-level ancestor of this control.\n */\n get root(): AbstractControl {\n let x: AbstractControl = this;\n\n while (x._parent) {\n x = x._parent;\n }\n\n return x;\n }\n\n /** @internal */\n _updateControlsErrors(emitEvent: boolean): void {\n (this as {status: FormControlStatus}).status = this._calculateStatus();\n\n if (emitEvent) {\n (this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);\n }\n\n if (this._parent) {\n this._parent._updateControlsErrors(emitEvent);\n }\n }\n\n /** @internal */\n _initObservables() {\n (this as {valueChanges: Observable<TValue>}).valueChanges = new EventEmitter();\n (this as {statusChanges: Observable<FormControlStatus>}).statusChanges = new EventEmitter();\n }\n\n\n private _calculateStatus(): FormControlStatus {\n if (this._allControlsDisabled()) return DISABLED;\n if (this.errors) return INVALID;\n if (this._hasOwnPendingAsyncValidator || this._anyControlsHaveStatus(PENDING)) return PENDING;\n if (this._anyControlsHaveStatus(INVALID)) return INVALID;\n return VALID;\n }\n\n /** @internal */\n abstract _updateValue(): void;\n\n /** @internal */\n abstract _forEachChild(cb: (c: AbstractControl) => void): void;\n\n /** @internal */\n abstract _anyControls(condition: (c: AbstractControl) => boolean): boolean;\n\n /** @internal */\n abstract _allControlsDisabled(): boolean;\n\n /** @internal */\n abstract _syncPendingControls(): boolean;\n\n /** @internal */\n _anyControlsHaveStatus(status: FormControlStatus): boolean {\n return this._anyControls((control: AbstractControl) => control.status === status);\n }\n\n /** @internal */\n _anyControlsDirty(): boolean {\n return this._anyControls((control: AbstractControl) => control.dirty);\n }\n\n /** @internal */\n _anyControlsTouched(): boolean {\n return this._anyControls((control: AbstractControl) => control.touched);\n }\n\n /** @internal */\n _updatePristine(opts: {onlySelf?: boolean} = {}): void {\n (this as {pristine: boolean}).pristine = !this._anyControlsDirty();\n\n if (this._parent && !opts.onlySelf) {\n this._parent._updatePristine(opts);\n }\n }\n\n /** @internal */\n _updateTouched(opts: {onlySelf?: boolean} = {}): void {\n (this as {touched: boolean}).touched = this._anyControlsTouched();\n\n if (this._parent && !opts.onlySelf) {\n this._parent._updateTouched(opts);\n }\n }\n\n /** @internal */\n _onDisabledChange: Array<(isDisabled: boolean) => void> = [];\n\n /** @internal */\n _registerOnCollectionChange(fn: () => void): void {\n this._onCollectionChange = fn;\n }\n\n /** @internal */\n _setUpdateStrategy(opts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null): void {\n if (isOptionsObj(opts) && opts.updateOn != null) {\n this._updateOn = opts.updateOn!;\n }\n }\n /**\n * Check to see if parent has been marked artificially dirty.\n *\n * @internal\n */\n private _parentMarkedDirty(onlySelf?: boolean): boolean {\n const parentDirty = this._parent && this._parent.dirty;\n return !onlySelf && !!parentDirty && !this._parent!._anyControlsDirty();\n }\n\n /** @internal */\n _find(name: string|number): AbstractControl|null {\n return null;\n }\n\n /**\n * Internal implementation of the `setValidators` method. Needs to be separated out into a\n * different method, because it is called in the constructor and it can break cases where\n * a control is extended.\n */\n private _assignValidators(validators: ValidatorFn|ValidatorFn[]|null): void {\n this._rawValidators = Array.isArray(validators) ? validators.slice() : validators;\n this._composedValidatorFn = coerceToValidator(this._rawValidators);\n }\n\n /**\n * Internal implementation of the `setAsyncValidators` method. Needs to be separated out into a\n * different method, because it is called in the constructor and it can break cases where\n * a control is extended.\n */\n private _assignAsyncValidators(validators: AsyncValidatorFn|AsyncValidatorFn[]|null): void {\n this._rawAsyncValidators = Array.isArray(validators) ? validators.slice() : validators;\n this._composedAsyncValidatorFn = coerceToAsyncValidator(this._rawAsyncValidators);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AsyncValidatorFn, ValidatorFn} from '../directives/validators';\n\nimport {AbstractControl, AbstractControlOptions, assertAllValuesPresent, assertControlPresent, pickAsyncValidators, pickValidators, ɵRawValue, ɵTypedOrUntyped, ɵValue} from './abstract_model';\n\n/**\n * FormGroupValue extracts the type of `.value` from a FormGroup's inner object type. The untyped\n * case falls back to {[key: string]: any}.\n *\n * Angular uses this type internally to support Typed Forms; do not use it directly.\n *\n * For internal use only.\n */\nexport type ɵFormGroupValue<T extends {[K in keyof T]?: AbstractControl<any>}> =\n ɵTypedOrUntyped<T, Partial<{[K in keyof T]: ɵValue<T[K]>}>, {[key: string]: any}>;\n\n/**\n * FormGroupRawValue extracts the type of `.getRawValue()` from a FormGroup's inner object type. The\n * untyped case falls back to {[key: string]: any}.\n *\n * Angular uses this type internally to support Typed Forms; do not use it directly.\n *\n * For internal use only.\n */\nexport type ɵFormGroupRawValue<T extends {[K in keyof T]?: AbstractControl<any>}> =\n ɵTypedOrUntyped<T, {[K in keyof T]: ɵRawValue<T[K]>}, {[key: string]: any}>;\n\n/**\n * OptionalKeys returns the union of all optional keys in the object.\n *\n * Angular uses this type internally to support Typed Forms; do not use it directly.\n */\nexport type ɵOptionalKeys<T> = {\n [K in keyof T] -?: undefined extends T[K] ? K : never\n}[keyof T];\n\n/**\n * Tracks the value and validity state of a group of `FormControl` instances.\n *\n * A `FormGroup` aggregates the values of each child `FormControl` into one object,\n * with each control name as the key. It calculates its status by reducing the status values\n * of its children. For example, if one of the controls in a group is invalid, the entire\n * group becomes invalid.\n *\n * `FormGroup` is one of the four fundamental building blocks used to define forms in Angular,\n * along with `FormControl`, `FormArray`, and `FormRecord`.\n *\n * When instantiating a `FormGroup`, pass in a collection of child controls as the first\n * argument. The key for each child registers the name for the control.\n *\n * `FormGroup` is intended for use cases where the keys are known ahead of time.\n * If you need to dynamically add and remove controls, use {@link FormRecord} instead.\n *\n * `FormGroup` accepts an optional type parameter `TControl`, which is an object type with inner\n * control types as values.\n *\n * @usageNotes\n *\n * ### Create a form group with 2 controls\n *\n * ```\n * const form = new FormGroup({\n * first: new FormControl('Nancy', Validators.minLength(2)),\n * last: new FormControl('Drew'),\n * });\n *\n * console.log(form.value); // {first: 'Nancy', last; 'Drew'}\n * console.log(form.status); // 'VALID'\n * ```\n *\n * ### The type argument, and optional controls\n *\n * `FormGroup` accepts one generic argument, which is an object containing its inner controls.\n * This type will usually be inferred automatically, but you can always specify it explicitly if you\n * wish.\n *\n * If you have controls that are optional (i.e. they can be removed, you can use the `?` in the\n * type):\n *\n * ```\n * const form = new FormGroup<{\n * first: FormControl<string|null>,\n * middle?: FormControl<string|null>, // Middle name is optional.\n * last: FormControl<string|null>,\n * }>({\n * first: new FormControl('Nancy'),\n * last: new FormControl('Drew'),\n * });\n * ```\n *\n * ### Create a form group with a group-level validator\n *\n * You include group-level validators as the second arg, or group-level async\n * validators as the third arg. These come in handy when you want to perform validation\n * that considers the value of more than one child control.\n *\n * ```\n * const form = new FormGroup({\n * password: new FormControl('', Validators.minLength(2)),\n * passwordConfirm: new FormControl('', Validators.minLength(2)),\n * }, passwordMatchValidator);\n *\n *\n * function passwordMatchValidator(g: FormGroup) {\n * return g.get('password').value === g.get('passwordConfirm').value\n * ? null : {'mismatch': true};\n * }\n * ```\n *\n * Like `FormControl` instances, you choose to pass in\n * validators and async validators as part of an options object.\n *\n * ```\n * const form = new FormGroup({\n * password: new FormControl('')\n * passwordConfirm: new FormControl('')\n * }, { validators: passwordMatchValidator, asyncValidators: otherValidator });\n * ```\n *\n * ### Set the updateOn property for all controls in a form group\n *\n * The options object is used to set a default value for each child\n * control's `updateOn` property. If you set `updateOn` to `'blur'` at the\n * group level, all child controls default to 'blur', unless the child\n * has explicitly specified a different `updateOn` value.\n *\n * ```ts\n * const c = new FormGroup({\n * one: new FormControl()\n * }, { updateOn: 'blur' });\n * ```\n *\n * ### Using a FormGroup with optional controls\n *\n * It is possible to have optional controls in a FormGroup. An optional control can be removed later\n * using `removeControl`, and can be omitted when calling `reset`. Optional controls must be\n * declared optional in the group's type.\n *\n * ```ts\n * const c = new FormGroup<{one?: FormControl<string>}>({\n * one: new FormControl('')\n * });\n * ```\n *\n * Notice that `c.value.one` has type `string|null|undefined`. This is because calling `c.reset({})`\n * without providing the optional key `one` will cause it to become `null`.\n *\n * @publicApi\n */\nexport class FormGroup<TControl extends {[K in keyof TControl]: AbstractControl<any>} = any> extends\n AbstractControl<\n ɵTypedOrUntyped<TControl, ɵFormGroupValue<TControl>, any>,\n ɵTypedOrUntyped<TControl, ɵFormGroupRawValue<TControl>, any>> {\n /**\n * Creates a new `FormGroup` instance.\n *\n * @param controls A collection of child controls. The key for each child is the name\n * under which it is registered.\n *\n * @param validatorOrOpts A synchronous validator function, or an array of\n * such functions, or an `AbstractControlOptions` object that contains validation functions\n * and a validation trigger.\n *\n * @param asyncValidator A single async validator or array of async validator functions\n *\n */\n constructor(\n controls: TControl, validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null,\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) {\n super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));\n this.controls = controls;\n this._initObservables();\n this._setUpdateStrategy(validatorOrOpts);\n this._setUpControls();\n this.updateValueAndValidity({\n onlySelf: true,\n // If `asyncValidator` is present, it will trigger control status change from `PENDING` to\n // `VALID` or `INVALID`. The status should be broadcasted via the `statusChanges` observable,\n // so we set `emitEvent` to `true` to allow that during the control creation process.\n emitEvent: !!this.asyncValidator\n });\n }\n\n public controls: ɵTypedOrUntyped<TControl, TControl, {[key: string]: AbstractControl<any>}>;\n\n /**\n * Registers a control with the group's list of controls. In a strongly-typed group, the control\n * must be in the group's type (possibly as an optional key).\n *\n * This method does not update the value or validity of the control.\n * Use {@link FormGroup#addControl addControl} instead.\n *\n * @param name The control name to register in the collection\n * @param control Provides the control for the given name\n */\n registerControl<K extends string&keyof TControl>(name: K, control: TControl[K]): TControl[K];\n registerControl(\n this: FormGroup<{[key: string]: AbstractControl<any>}>, name: string,\n control: AbstractControl<any>): AbstractControl<any>;\n\n registerControl<K extends string&keyof TControl>(name: K, control: TControl[K]): TControl[K] {\n if (this.controls[name]) return (this.controls as any)[name];\n this.controls[name] = control;\n control.setParent(this as FormGroup);\n control._registerOnCollectionChange(this._onCollectionChange);\n return control;\n }\n\n /**\n * Add a control to this group. In a strongly-typed group, the control must be in the group's type\n * (possibly as an optional key).\n *\n * If a control with a given name already exists, it would *not* be replaced with a new one.\n * If you want to replace an existing control, use the {@link FormGroup#setControl setControl}\n * method instead. This method also updates the value and validity of the control.\n *\n * @param name The control name to add to the collection\n * @param control Provides the control for the given name\n * @param options Specifies whether this FormGroup instance should emit events after a new\n * control is added.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges` observables emit events with the latest status and value when the control is\n * added. When false, no events are emitted.\n */\n addControl(\n this: FormGroup<{[key: string]: AbstractControl<any>}>, name: string,\n control: AbstractControl, options?: {emitEvent?: boolean}): void;\n addControl<K extends string&keyof TControl>(name: K, control: Required<TControl>[K], options?: {\n emitEvent?: boolean\n }): void;\n\n addControl<K extends string&keyof TControl>(name: K, control: Required<TControl>[K], options: {\n emitEvent?: boolean\n } = {}): void {\n this.registerControl(name, control);\n this.updateValueAndValidity({emitEvent: options.emitEvent});\n this._onCollectionChange();\n }\n\n removeControl(this: FormGroup<{[key: string]: AbstractControl<any>}>, name: string, options?: {\n emitEvent?: boolean;\n }): void;\n removeControl<S extends string>(name: ɵOptionalKeys<TControl>&S, options?: {\n emitEvent?: boolean;\n }): void;\n\n /**\n * Remove a control from this group. In a strongly-typed group, required controls cannot be\n * removed.\n *\n * This method also updates the value and validity of the control.\n *\n * @param name The control name to remove from the collection\n * @param options Specifies whether this FormGroup instance should emit events after a\n * control is removed.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges` observables emit events with the latest status and value when the control is\n * removed. When false, no events are emitted.\n */\n removeControl(name: string, options: {emitEvent?: boolean;} = {}): void {\n if ((this.controls as any)[name])\n (this.controls as any)[name]._registerOnCollectionChange(() => {});\n delete ((this.controls as any)[name]);\n this.updateValueAndValidity({emitEvent: options.emitEvent});\n this._onCollectionChange();\n }\n\n /**\n * Replace an existing control. In a strongly-typed group, the control must be in the group's type\n * (possibly as an optional key).\n *\n * If a control with a given name does not exist in this `FormGroup`, it will be added.\n *\n * @param name The control name to replace in the collection\n * @param control Provides the control for the given name\n * @param options Specifies whether this FormGroup instance should emit events after an\n * existing control is replaced.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges` observables emit events with the latest status and value when the control is\n * replaced with a new one. When false, no events are emitted.\n */\n setControl<K extends string&keyof TControl>(name: K, control: TControl[K], options?: {\n emitEvent?: boolean\n }): void;\n setControl(\n this: FormGroup<{[key: string]: AbstractControl<any>}>, name: string,\n control: AbstractControl, options?: {emitEvent?: boolean}): void;\n\n setControl<K extends string&keyof TControl>(name: K, control: TControl[K], options: {\n emitEvent?: boolean\n } = {}): void {\n if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {});\n delete (this.controls[name]);\n if (control) this.registerControl(name, control);\n this.updateValueAndValidity({emitEvent: options.emitEvent});\n this._onCollectionChange();\n }\n\n /**\n * Check whether there is an enabled control with the given name in the group.\n *\n * Reports false for disabled controls. If you'd like to check for existence in the group\n * only, use {@link AbstractControl#get get} instead.\n *\n * @param controlName The control name to check for existence in the collection\n *\n * @returns false for disabled controls, true otherwise.\n */\n contains<K extends string>(controlName: K): boolean;\n contains(this: FormGroup<{[key: string]: AbstractControl<any>}>, controlName: string): boolean;\n\n contains<K extends string&keyof TControl>(controlName: K): boolean {\n return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled;\n }\n\n /**\n * Sets the value of the `FormGroup`. It accepts an object that matches\n * the structure of the group, with control names as keys.\n *\n * @usageNotes\n * ### Set the complete value for the form group\n *\n * ```\n * const form = new FormGroup({\n * first: new FormControl(),\n * last: new FormControl()\n * });\n *\n * console.log(form.value); // {first: null, last: null}\n *\n * form.setValue({first: 'Nancy', last: 'Drew'});\n * console.log(form.value); // {first: 'Nancy', last: 'Drew'}\n * ```\n *\n * @throws When strict checks fail, such as setting the value of a control\n * that doesn't exist or if you exclude a value of a control that does exist.\n *\n * @param value The new value for the control that matches the structure of the group.\n * @param options Configuration options that determine how the control propagates changes\n * and emits events after the value changes.\n * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity\n * updateValueAndValidity} method.\n *\n * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is\n * false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control value is updated.\n * When false, no events are emitted.\n */\n override setValue(value: ɵFormGroupRawValue<TControl>, options: {\n onlySelf?: boolean,\n emitEvent?: boolean\n } = {}): void {\n assertAllValuesPresent(this, true, value);\n (Object.keys(value) as Array<keyof TControl>).forEach(name => {\n assertControlPresent(this, true, name as any);\n (this.controls as any)[name].setValue(\n (value as any)[name], {onlySelf: true, emitEvent: options.emitEvent});\n });\n this.updateValueAndValidity(options);\n }\n\n /**\n * Patches the value of the `FormGroup`. It accepts an object with control\n * names as keys, and does its best to match the values to the correct controls\n * in the group.\n *\n * It accepts both super-sets and sub-sets of the group without throwing an error.\n *\n * @usageNotes\n * ### Patch the value for a form group\n *\n * ```\n * const form = new FormGroup({\n * first: new FormControl(),\n * last: new FormControl()\n * });\n * console.log(form.value); // {first: null, last: null}\n *\n * form.patchValue({first: 'Nancy'});\n * console.log(form.value); // {first: 'Nancy', last: null}\n * ```\n *\n * @param value The object that matches the structure of the group.\n * @param options Configuration options that determine how the control propagates changes and\n * emits events after the value is patched.\n * * `onlySelf`: When true, each change only affects this control and not its parent. Default is\n * true.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges` observables emit events with the latest status and value when the control value\n * is updated. When false, no events are emitted. The configuration options are passed to\n * the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method.\n */\n override patchValue(value: ɵFormGroupValue<TControl>, options: {\n onlySelf?: boolean,\n emitEvent?: boolean\n } = {}): void {\n // Even though the `value` argument type doesn't allow `null` and `undefined` values, the\n // `patchValue` can be called recursively and inner data structures might have these values, so\n // we just ignore such cases when a field containing FormGroup instance receives `null` or\n // `undefined` as a value.\n if (value == null /* both `null` and `undefined` */) return;\n (Object.keys(value) as Array<keyof TControl>).forEach(name => {\n // The compiler cannot see through the uninstantiated conditional type of `this.controls`, so\n // `as any` is required.\n const control = (this.controls as any)[name];\n if (control) {\n control.patchValue(\n /* Guaranteed to be present, due to the outer forEach. */ value\n [name as keyof ɵFormGroupValue<TControl>]!,\n {onlySelf: true, emitEvent: options.emitEvent});\n }\n });\n this.updateValueAndValidity(options);\n }\n\n /**\n * Resets the `FormGroup`, marks all descendants `pristine` and `untouched` and sets\n * the value of all descendants to their default values, or null if no defaults were provided.\n *\n * You reset to a specific form state by passing in a map of states\n * that matches the structure of your form, with control names as keys. The state\n * is a standalone value or a form state object with both a value and a disabled\n * status.\n *\n * @param value Resets the control with an initial value,\n * or an object that defines the initial value and disabled state.\n *\n * @param options Configuration options that determine how the control propagates changes\n * and emits events when the group is reset.\n * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is\n * false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control is reset.\n * When false, no events are emitted.\n * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity\n * updateValueAndValidity} method.\n *\n * @usageNotes\n *\n * ### Reset the form group values\n *\n * ```ts\n * const form = new FormGroup({\n * first: new FormControl('first name'),\n * last: new FormControl('last name')\n * });\n *\n * console.log(form.value); // {first: 'first name', last: 'last name'}\n *\n * form.reset({ first: 'name', last: 'last name' });\n *\n * console.log(form.value); // {first: 'name', last: 'last name'}\n * ```\n *\n * ### Reset the form group values and disabled status\n *\n * ```\n * const form = new FormGroup({\n * first: new FormControl('first name'),\n * last: new FormControl('last name')\n * });\n *\n * form.reset({\n * first: {value: 'name', disabled: true},\n * last: 'last'\n * });\n *\n * console.log(form.value); // {last: 'last'}\n * console.log(form.get('first').status); // 'DISABLED'\n * ```\n */\n override reset(\n value: ɵTypedOrUntyped<TControl, ɵFormGroupValue<TControl>, any> = {} as unknown as\n ɵFormGroupValue<TControl>,\n options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n this._forEachChild((control, name) => {\n control.reset((value as any)[name], {onlySelf: true, emitEvent: options.emitEvent});\n });\n this._updatePristine(options);\n this._updateTouched(options);\n this.updateValueAndValidity(options);\n }\n\n /**\n * The aggregate value of the `FormGroup`, including any disabled controls.\n *\n * Retrieves all values regardless of disabled status.\n */\n override getRawValue(): ɵTypedOrUntyped<TControl, ɵFormGroupRawValue<TControl>, any> {\n return this._reduceChildren({}, (acc, control, name) => {\n (acc as any)[name] = (control as any).getRawValue();\n return acc;\n }) as any;\n }\n\n /** @internal */\n override _syncPendingControls(): boolean {\n let subtreeUpdated = this._reduceChildren(false, (updated: boolean, child) => {\n return child._syncPendingControls() ? true : updated;\n });\n if (subtreeUpdated) this.updateValueAndValidity({onlySelf: true});\n return subtreeUpdated;\n }\n\n /** @internal */\n override _forEachChild(cb: (v: any, k: any) => void): void {\n Object.keys(this.controls).forEach(key => {\n // The list of controls can change (for ex. controls might be removed) while the loop\n // is running (as a result of invoking Forms API in `valueChanges` subscription), so we\n // have to null check before invoking the callback.\n const control = (this.controls as any)[key];\n control && cb(control, key);\n });\n }\n\n /** @internal */\n _setUpControls(): void {\n this._forEachChild((control) => {\n control.setParent(this);\n control._registerOnCollectionChange(this._onCollectionChange);\n });\n }\n\n /** @internal */\n override _updateValue(): void {\n (this as {value: any}).value = this._reduceValue();\n }\n\n /** @internal */\n override _anyControls(condition: (c: AbstractControl) => boolean): boolean {\n for (const [controlName, control] of Object.entries(this.controls)) {\n if (this.contains(controlName as any) && condition(control as any)) {\n return true;\n }\n }\n return false;\n }\n\n /** @internal */\n _reduceValue(): Partial<TControl> {\n let acc: Partial<TControl> = {};\n return this._reduceChildren(acc, (acc, control, name) => {\n if (control.enabled || this.disabled) {\n acc[name] = control.value;\n }\n return acc;\n });\n }\n\n /** @internal */\n _reduceChildren<T, K extends keyof TControl>(\n initValue: T, fn: (acc: T, control: TControl[K], name: K) => T): T {\n let res = initValue;\n this._forEachChild((control: TControl[K], name: K) => {\n res = fn(res, control, name);\n });\n return res;\n }\n\n /** @internal */\n override _allControlsDisabled(): boolean {\n for (const controlName of (Object.keys(this.controls) as Array<keyof TControl>)) {\n if ((this.controls as any)[controlName].enabled) {\n return false;\n }\n }\n return Object.keys(this.controls).length > 0 || this.disabled;\n }\n\n /** @internal */\n override _find(name: string|number): AbstractControl|null {\n return this.controls.hasOwnProperty(name as string) ?\n (this.controls as any)[name as keyof TControl] :\n null;\n }\n}\n\ninterface UntypedFormGroupCtor {\n new(controls: {[key: string]: AbstractControl},\n validatorOrOpts?: ValidatorFn|ValidatorFn[]|AbstractControlOptions|null,\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): UntypedFormGroup;\n\n /**\n * The presence of an explicit `prototype` property provides backwards-compatibility for apps that\n * manually inspect the prototype chain.\n */\n prototype: FormGroup<any>;\n}\n\n/**\n * UntypedFormGroup is a non-strongly-typed version of `FormGroup`.\n */\nexport type UntypedFormGroup = FormGroup<any>;\n\nexport const UntypedFormGroup: UntypedFormGroupCtor = FormGroup;\n\n/**\n * @description\n * Asserts that the given control is an instance of `FormGroup`\n *\n * @publicApi\n */\nexport const isFormGroup = (control: unknown): control is FormGroup => control instanceof FormGroup;\n\n/**\n * Tracks the value and validity state of a collection of `FormControl` instances, each of which has\n * the same value type.\n *\n * `FormRecord` is very similar to {@link FormGroup}, except it can be used with a dynamic keys,\n * with controls added and removed as needed.\n *\n * `FormRecord` accepts one generic argument, which describes the type of the controls it contains.\n *\n * @usageNotes\n *\n * ```\n * let numbers = new FormRecord({bill: new FormControl('415-123-456')});\n * numbers.addControl('bob', new FormControl('415-234-567'));\n * numbers.removeControl('bill');\n * ```\n *\n * @publicApi\n */\nexport class FormRecord<TControl extends AbstractControl = AbstractControl> extends\n FormGroup<{[key: string]: TControl}> {}\n\nexport interface FormRecord<TControl> {\n /**\n * Registers a control with the records's list of controls.\n *\n * See `FormGroup#registerControl` for additional information.\n */\n registerControl(name: string, control: TControl): TControl;\n\n /**\n * Add a control to this group.\n *\n * See `FormGroup#addControl` for additional information.\n */\n addControl(name: string, control: TControl, options?: {emitEvent?: boolean}): void;\n\n /**\n * Remove a control from this group.\n *\n * See `FormGroup#removeControl` for additional information.\n */\n removeControl(name: string, options?: {emitEvent?: boolean}): void;\n\n /**\n * Replace an existing control.\n *\n * See `FormGroup#setControl` for additional information.\n */\n setControl(name: string, control: TControl, options?: {emitEvent?: boolean}): void;\n\n /**\n * Check whether there is an enabled control with the given name in the group.\n *\n * See `FormGroup#contains` for additional information.\n */\n contains(controlName: string): boolean;\n\n /**\n * Sets the value of the `FormRecord`. It accepts an object that matches\n * the structure of the group, with control names as keys.\n *\n * See `FormGroup#setValue` for additional information.\n */\n setValue(value: {[key: string]: ɵValue<TControl>}, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean\n }): void;\n\n /**\n * Patches the value of the `FormRecord`. It accepts an object with control\n * names as keys, and does its best to match the values to the correct controls\n * in the group.\n *\n * See `FormGroup#patchValue` for additional information.\n */\n patchValue(value: {[key: string]: ɵValue<TControl>}, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean\n }): void;\n\n /**\n * Resets the `FormRecord`, marks all descendants `pristine` and `untouched` and sets\n * the value of all descendants to null.\n *\n * See `FormGroup#reset` for additional information.\n */\n reset(value?: {[key: string]: ɵValue<TControl>}, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean\n }): void;\n\n /**\n * The aggregate value of the `FormRecord`, including any disabled controls.\n *\n * See `FormGroup#getRawValue` for additional information.\n */\n getRawValue(): {[key: string]: ɵRawValue<TControl>};\n}\n\n/**\n * @description\n * Asserts that the given control is an instance of `FormRecord`\n *\n * @publicApi\n */\nexport const isFormRecord = (control: unknown): control is FormRecord =>\n control instanceof FormRecord;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Inject, InjectionToken, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\nimport {AbstractControl} from '../model/abstract_model';\nimport {FormArray} from '../model/form_array';\nimport {FormControl} from '../model/form_control';\nimport {FormGroup} from '../model/form_group';\nimport {getControlAsyncValidators, getControlValidators, mergeValidators} from '../validators';\n\nimport {AbstractControlDirective} from './abstract_control_directive';\nimport {AbstractFormGroupDirective} from './abstract_form_group_directive';\nimport {ControlContainer} from './control_container';\nimport {BuiltInControlValueAccessor, ControlValueAccessor} from './control_value_accessor';\nimport {DefaultValueAccessor} from './default_value_accessor';\nimport {NgControl} from './ng_control';\nimport {FormArrayName} from './reactive_directives/form_group_name';\nimport {ngModelWarning} from './reactive_errors';\nimport {AsyncValidatorFn, Validator, ValidatorFn} from './validators';\n\n/**\n * Token to provide to allow SetDisabledState to always be called when a CVA is added, regardless of\n * whether the control is disabled or enabled.\n *\n * @see `FormsModule.withConfig`\n */\nexport const CALL_SET_DISABLED_STATE = new InjectionToken(\n 'CallSetDisabledState', {providedIn: 'root', factory: () => setDisabledStateDefault});\n\n/**\n * The type for CALL_SET_DISABLED_STATE. If `always`, then ControlValueAccessor will always call\n * `setDisabledState` when attached, which is the most correct behavior. Otherwise, it will only be\n * called when disabled, which is the legacy behavior for compatibility.\n *\n * @publicApi\n * @see `FormsModule.withConfig`\n */\nexport type SetDisabledStateOption = 'whenDisabledForLegacyCode'|'always';\n\n/**\n * Whether to use the fixed setDisabledState behavior by default.\n */\nexport const setDisabledStateDefault: SetDisabledStateOption = 'always';\n\nexport function controlPath(name: string|null, parent: ControlContainer): string[] {\n return [...parent.path!, name!];\n}\n\n/**\n * Links a Form control and a Form directive by setting up callbacks (such as `onChange`) on both\n * instances. This function is typically invoked when form directive is being initialized.\n *\n * @param control Form control instance that should be linked.\n * @param dir Directive that should be linked with a given control.\n */\nexport function setUpControl(\n control: FormControl, dir: NgControl,\n callSetDisabledState: SetDisabledStateOption = setDisabledStateDefault): void {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!control) _throwError(dir, 'Cannot find control with');\n if (!dir.valueAccessor) _throwMissingValueAccessorError(dir);\n }\n\n setUpValidators(control, dir);\n\n dir.valueAccessor!.writeValue(control.value);\n\n // The legacy behavior only calls the CVA's `setDisabledState` if the control is disabled.\n // If the `callSetDisabledState` option is set to `always`, then this bug is fixed and\n // the method is always called.\n if (control.disabled || callSetDisabledState === 'always') {\n dir.valueAccessor!.setDisabledState?.(control.disabled);\n }\n\n setUpViewChangePipeline(control, dir);\n setUpModelChangePipeline(control, dir);\n\n setUpBlurPipeline(control, dir);\n\n setUpDisabledChangeHandler(control, dir);\n}\n\n/**\n * Reverts configuration performed by the `setUpControl` control function.\n * Effectively disconnects form control with a given form directive.\n * This function is typically invoked when corresponding form directive is being destroyed.\n *\n * @param control Form control which should be cleaned up.\n * @param dir Directive that should be disconnected from a given control.\n * @param validateControlPresenceOnChange Flag that indicates whether onChange handler should\n * contain asserts to verify that it's not called once directive is destroyed. We need this flag\n * to avoid potentially breaking changes caused by better control cleanup introduced in #39235.\n */\nexport function cleanUpControl(\n control: FormControl|null, dir: NgControl,\n validateControlPresenceOnChange: boolean = true): void {\n const noop = () => {\n if (validateControlPresenceOnChange && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n _noControlError(dir);\n }\n };\n\n // The `valueAccessor` field is typically defined on FromControl and FormControlName directive\n // instances and there is a logic in `selectValueAccessor` function that throws if it's not the\n // case. We still check the presence of `valueAccessor` before invoking its methods to make sure\n // that cleanup works correctly if app code or tests are setup to ignore the error thrown from\n // `selectValueAccessor`. See https://github.com/angular/angular/issues/40521.\n if (dir.valueAccessor) {\n dir.valueAccessor.registerOnChange(noop);\n dir.valueAccessor.registerOnTouched(noop);\n }\n\n cleanUpValidators(control, dir);\n\n if (control) {\n dir._invokeOnDestroyCallbacks();\n control._registerOnCollectionChange(() => {});\n }\n}\n\nfunction registerOnValidatorChange<V>(validators: (V|Validator)[], onChange: () => void): void {\n validators.forEach((validator: V|Validator) => {\n if ((<Validator>validator).registerOnValidatorChange)\n (<Validator>validator).registerOnValidatorChange!(onChange);\n });\n}\n\n/**\n * Sets up disabled change handler function on a given form control if ControlValueAccessor\n * associated with a given directive instance supports the `setDisabledState` call.\n *\n * @param control Form control where disabled change handler should be setup.\n * @param dir Corresponding directive instance associated with this control.\n */\nexport function setUpDisabledChangeHandler(control: FormControl, dir: NgControl): void {\n if (dir.valueAccessor!.setDisabledState) {\n const onDisabledChange = (isDisabled: boolean) => {\n dir.valueAccessor!.setDisabledState!(isDisabled);\n };\n control.registerOnDisabledChange(onDisabledChange);\n\n // Register a callback function to cleanup disabled change handler\n // from a control instance when a directive is destroyed.\n dir._registerOnDestroy(() => {\n control._unregisterOnDisabledChange(onDisabledChange);\n });\n }\n}\n\n/**\n * Sets up sync and async directive validators on provided form control.\n * This function merges validators from the directive into the validators of the control.\n *\n * @param control Form control where directive validators should be setup.\n * @param dir Directive instance that contains validators to be setup.\n */\nexport function setUpValidators(control: AbstractControl, dir: AbstractControlDirective): void {\n const validators = getControlValidators(control);\n if (dir.validator !== null) {\n control.setValidators(mergeValidators<ValidatorFn>(validators, dir.validator));\n } else if (typeof validators === 'function') {\n // If sync validators are represented by a single validator function, we force the\n // `Validators.compose` call to happen by executing the `setValidators` function with\n // an array that contains that function. We need this to avoid possible discrepancies in\n // validators behavior, so sync validators are always processed by the `Validators.compose`.\n // Note: we should consider moving this logic inside the `setValidators` function itself, so we\n // have consistent behavior on AbstractControl API level. The same applies to the async\n // validators logic below.\n control.setValidators([validators]);\n }\n\n const asyncValidators = getControlAsyncValidators(control);\n if (dir.asyncValidator !== null) {\n control.setAsyncValidators(\n mergeValidators<AsyncValidatorFn>(asyncValidators, dir.asyncValidator));\n } else if (typeof asyncValidators === 'function') {\n control.setAsyncValidators([asyncValidators]);\n }\n\n // Re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4\n const onValidatorChange = () => control.updateValueAndValidity();\n registerOnValidatorChange<ValidatorFn>(dir._rawValidators, onValidatorChange);\n registerOnValidatorChange<AsyncValidatorFn>(dir._rawAsyncValidators, onValidatorChange);\n}\n\n/**\n * Cleans up sync and async directive validators on provided form control.\n * This function reverts the setup performed by the `setUpValidators` function, i.e.\n * removes directive-specific validators from a given control instance.\n *\n * @param control Form control from where directive validators should be removed.\n * @param dir Directive instance that contains validators to be removed.\n * @returns true if a control was updated as a result of this action.\n */\nexport function cleanUpValidators(\n control: AbstractControl|null, dir: AbstractControlDirective): boolean {\n let isControlUpdated = false;\n if (control !== null) {\n if (dir.validator !== null) {\n const validators = getControlValidators(control);\n if (Array.isArray(validators) && validators.length > 0) {\n // Filter out directive validator function.\n const updatedValidators = validators.filter((validator) => validator !== dir.validator);\n if (updatedValidators.length !== validators.length) {\n isControlUpdated = true;\n control.setValidators(updatedValidators);\n }\n }\n }\n\n if (dir.asyncValidator !== null) {\n const asyncValidators = getControlAsyncValidators(control);\n if (Array.isArray(asyncValidators) && asyncValidators.length > 0) {\n // Filter out directive async validator function.\n const updatedAsyncValidators =\n asyncValidators.filter((asyncValidator) => asyncValidator !== dir.asyncValidator);\n if (updatedAsyncValidators.length !== asyncValidators.length) {\n isControlUpdated = true;\n control.setAsyncValidators(updatedAsyncValidators);\n }\n }\n }\n }\n\n // Clear onValidatorChange callbacks by providing a noop function.\n const noop = () => {};\n registerOnValidatorChange<ValidatorFn>(dir._rawValidators, noop);\n registerOnValidatorChange<AsyncValidatorFn>(dir._rawAsyncValidators, noop);\n\n return isControlUpdated;\n}\n\nfunction setUpViewChangePipeline(control: FormControl, dir: NgControl): void {\n dir.valueAccessor!.registerOnChange((newValue: any) => {\n control._pendingValue = newValue;\n control._pendingChange = true;\n control._pendingDirty = true;\n\n if (control.updateOn === 'change') updateControl(control, dir);\n });\n}\n\nfunction setUpBlurPipeline(control: FormControl, dir: NgControl): void {\n dir.valueAccessor!.registerOnTouched(() => {\n control._pendingTouched = true;\n\n if (control.updateOn === 'blur' && control._pendingChange) updateControl(control, dir);\n if (control.updateOn !== 'submit') control.markAsTouched();\n });\n}\n\nfunction updateControl(control: FormControl, dir: NgControl): void {\n if (control._pendingDirty) control.markAsDirty();\n control.setValue(control._pendingValue, {emitModelToViewChange: false});\n dir.viewToModelUpdate(control._pendingValue);\n control._pendingChange = false;\n}\n\nfunction setUpModelChangePipeline(control: FormControl, dir: NgControl): void {\n const onChange = (newValue?: any, emitModelEvent?: boolean) => {\n // control -> view\n dir.valueAccessor!.writeValue(newValue);\n\n // control -> ngModel\n if (emitModelEvent) dir.viewToModelUpdate(newValue);\n };\n control.registerOnChange(onChange);\n\n // Register a callback function to cleanup onChange handler\n // from a control instance when a directive is destroyed.\n dir._registerOnDestroy(() => {\n control._unregisterOnChange(onChange);\n });\n}\n\n/**\n * Links a FormGroup or FormArray instance and corresponding Form directive by setting up validators\n * present in the view.\n *\n * @param control FormGroup or FormArray instance that should be linked.\n * @param dir Directive that provides view validators.\n */\nexport function setUpFormContainer(\n control: FormGroup|FormArray, dir: AbstractFormGroupDirective|FormArrayName) {\n if (control == null && (typeof ngDevMode === 'undefined' || ngDevMode))\n _throwError(dir, 'Cannot find control with');\n setUpValidators(control, dir);\n}\n\n/**\n * Reverts the setup performed by the `setUpFormContainer` function.\n *\n * @param control FormGroup or FormArray instance that should be cleaned up.\n * @param dir Directive that provided view validators.\n * @returns true if a control was updated as a result of this action.\n */\nexport function cleanUpFormContainer(\n control: FormGroup|FormArray, dir: AbstractFormGroupDirective|FormArrayName): boolean {\n return cleanUpValidators(control, dir);\n}\n\nfunction _noControlError(dir: NgControl) {\n return _throwError(dir, 'There is no FormControl instance attached to form control element with');\n}\n\nfunction _throwError(dir: AbstractControlDirective, message: string): void {\n const messageEnd = _describeControlLocation(dir);\n throw new Error(`${message} ${messageEnd}`);\n}\n\nfunction _describeControlLocation(dir: AbstractControlDirective): string {\n const path = dir.path;\n if (path && path.length > 1) return `path: '${path.join(' -> ')}'`;\n if (path?.[0]) return `name: '${path}'`;\n return 'unspecified name attribute';\n}\n\nfunction _throwMissingValueAccessorError(dir: AbstractControlDirective) {\n const loc = _describeControlLocation(dir);\n throw new RuntimeError(\n RuntimeErrorCode.NG_MISSING_VALUE_ACCESSOR, `No value accessor for form control ${loc}.`);\n}\n\nfunction _throwInvalidValueAccessorError(dir: AbstractControlDirective) {\n const loc = _describeControlLocation(dir);\n throw new RuntimeError(\n RuntimeErrorCode.NG_VALUE_ACCESSOR_NOT_PROVIDED,\n `Value accessor was not provided as an array for form control with ${loc}. ` +\n `Check that the \\`NG_VALUE_ACCESSOR\\` token is configured as a \\`multi: true\\` provider.`);\n}\n\nexport function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean {\n if (!changes.hasOwnProperty('model')) return false;\n const change = changes['model'];\n\n if (change.isFirstChange()) return true;\n return !Object.is(viewModel, change.currentValue);\n}\n\nexport function isBuiltInAccessor(valueAccessor: ControlValueAccessor): boolean {\n // Check if a given value accessor is an instance of a class that directly extends\n // `BuiltInControlValueAccessor` one.\n return Object.getPrototypeOf(valueAccessor.constructor) === BuiltInControlValueAccessor;\n}\n\nexport function syncPendingControls(form: FormGroup, directives: Set<NgControl>|NgControl[]): void {\n form._syncPendingControls();\n directives.forEach((dir: NgControl) => {\n const control = dir.control as FormControl;\n if (control.updateOn === 'submit' && control._pendingChange) {\n dir.viewToModelUpdate(control._pendingValue);\n control._pendingChange = false;\n }\n });\n}\n\n// TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented\nexport function selectValueAccessor(\n dir: NgControl, valueAccessors: ControlValueAccessor[]): ControlValueAccessor|null {\n if (!valueAccessors) return null;\n\n if (!Array.isArray(valueAccessors) && (typeof ngDevMode === 'undefined' || ngDevMode))\n _throwInvalidValueAccessorError(dir);\n\n let defaultAccessor: ControlValueAccessor|undefined = undefined;\n let builtinAccessor: ControlValueAccessor|undefined = undefined;\n let customAccessor: ControlValueAccessor|undefined = undefined;\n\n valueAccessors.forEach((v: ControlValueAccessor) => {\n if (v.constructor === DefaultValueAccessor) {\n defaultAccessor = v;\n } else if (isBuiltInAccessor(v)) {\n if (builtinAccessor && (typeof ngDevMode === 'undefined' || ngDevMode))\n _throwError(dir, 'More than one built-in value accessor matches form control with');\n builtinAccessor = v;\n } else {\n if (customAccessor && (typeof ngDevMode === 'undefined' || ngDevMode))\n _throwError(dir, 'More than one custom value accessor matches form control with');\n customAccessor = v;\n }\n });\n\n if (customAccessor) return customAccessor;\n if (builtinAccessor) return builtinAccessor;\n if (defaultAccessor) return defaultAccessor;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n _throwError(dir, 'No valid value accessor for form control with');\n }\n return null;\n}\n\nexport function removeListItem<T>(list: T[], el: T): void {\n const index = list.indexOf(el);\n if (index > -1) list.splice(index, 1);\n}\n\n// TODO(kara): remove after deprecation period\nexport function _ngModelWarning(\n name: string, type: {_ngModelWarningSentOnce: boolean},\n instance: {_ngModelWarningSent: boolean}, warningConfig: string|null) {\n if (warningConfig === 'never') return;\n\n if (((warningConfig === null || warningConfig === 'once') && !type._ngModelWarningSentOnce) ||\n (warningConfig === 'always' && !instance._ngModelWarningSent)) {\n console.warn(ngModelWarning(name));\n type._ngModelWarningSentOnce = true;\n instance._ngModelWarningSent = true;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AfterViewInit, Directive, EventEmitter, forwardRef, Inject, Input, Optional, Provider, Self} from '@angular/core';\n\nimport {AbstractControl, FormHooks} from '../model/abstract_model';\nimport {FormControl} from '../model/form_control';\nimport {FormGroup} from '../model/form_group';\nimport {composeAsyncValidators, composeValidators, NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';\n\nimport {ControlContainer} from './control_container';\nimport {Form} from './form_interface';\nimport {NgControl} from './ng_control';\nimport {NgModel} from './ng_model';\nimport {NgModelGroup} from './ng_model_group';\nimport {CALL_SET_DISABLED_STATE, SetDisabledStateOption, setUpControl, setUpFormContainer, syncPendingControls} from './shared';\nimport {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from './validators';\n\nconst formDirectiveProvider: Provider = {\n provide: ControlContainer,\n useExisting: forwardRef(() => NgForm)\n};\n\nconst resolvedPromise = (() => Promise.resolve())();\n\n/**\n * @description\n * Creates a top-level `FormGroup` instance and binds it to a form\n * to track aggregate form value and validation status.\n *\n * As soon as you import the `FormsModule`, this directive becomes active by default on\n * all `<form>` tags. You don't need to add a special selector.\n *\n * You optionally export the directive into a local template variable using `ngForm` as the key\n * (ex: `#myForm=\"ngForm\"`). This is optional, but useful. Many properties from the underlying\n * `FormGroup` instance are duplicated on the directive itself, so a reference to it\n * gives you access to the aggregate value and validity status of the form, as well as\n * user interaction properties like `dirty` and `touched`.\n *\n * To register child controls with the form, use `NgModel` with a `name`\n * attribute. You may use `NgModelGroup` to create sub-groups within the form.\n *\n * If necessary, listen to the directive's `ngSubmit` event to be notified when the user has\n * triggered a form submission. The `ngSubmit` event emits the original form\n * submission event.\n *\n * In template driven forms, all `<form>` tags are automatically tagged as `NgForm`.\n * To import the `FormsModule` but skip its usage in some forms,\n * for example, to use native HTML5 validation, add the `ngNoForm` and the `<form>`\n * tags won't create an `NgForm` directive. In reactive forms, using `ngNoForm` is\n * unnecessary because the `<form>` tags are inert. In that case, you would\n * refrain from using the `formGroup` directive.\n *\n * @usageNotes\n *\n * ### Listening for form submission\n *\n * The following example shows how to capture the form values from the \"ngSubmit\" event.\n *\n * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}\n *\n * ### Setting the update options\n *\n * The following example shows you how to change the \"updateOn\" option from its default using\n * ngFormOptions.\n *\n * ```html\n * <form [ngFormOptions]=\"{updateOn: 'blur'}\">\n * <input name=\"one\" ngModel> <!-- this ngModel will update on blur -->\n * </form>\n * ```\n *\n * ### Native DOM validation UI\n *\n * In order to prevent the native DOM form validation UI from interfering with Angular's form\n * validation, Angular automatically adds the `novalidate` attribute on any `<form>` whenever\n * `FormModule` or `ReactiveFormModule` are imported into the application.\n * If you want to explicitly enable native DOM validation UI with Angular forms, you can add the\n * `ngNativeValidate` attribute to the `<form>` element:\n *\n * ```html\n * <form ngNativeValidate>\n * ...\n * </form>\n * ```\n *\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]',\n providers: [formDirectiveProvider],\n host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},\n outputs: ['ngSubmit'],\n exportAs: 'ngForm'\n})\nexport class NgForm extends ControlContainer implements Form, AfterViewInit {\n /**\n * @description\n * Returns whether the form submission has been triggered.\n */\n public readonly submitted: boolean = false;\n\n private _directives = new Set<NgModel>();\n\n /**\n * @description\n * The `FormGroup` instance created for this form.\n */\n form: FormGroup;\n\n /**\n * @description\n * Event emitter for the \"ngSubmit\" event\n */\n ngSubmit = new EventEmitter();\n\n /**\n * @description\n * Tracks options for the `NgForm` instance.\n *\n * **updateOn**: Sets the default `updateOn` value for all child `NgModels` below it\n * unless explicitly set by a child `NgModel` using `ngModelOptions`). Defaults to 'change'.\n * Possible values: `'change'` | `'blur'` | `'submit'`.\n *\n */\n // TODO(issue/24571): remove '!'.\n @Input('ngFormOptions') options!: {updateOn?: FormHooks};\n\n constructor(\n @Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator|ValidatorFn)[],\n @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:\n (AsyncValidator|AsyncValidatorFn)[],\n @Optional() @Inject(CALL_SET_DISABLED_STATE) private callSetDisabledState?:\n SetDisabledStateOption) {\n super();\n this.form =\n new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));\n }\n\n /** @nodoc */\n ngAfterViewInit() {\n this._setUpdateStrategy();\n }\n\n /**\n * @description\n * The directive instance.\n */\n override get formDirective(): Form {\n return this;\n }\n\n /**\n * @description\n * The internal `FormGroup` instance.\n */\n override get control(): FormGroup {\n return this.form;\n }\n\n /**\n * @description\n * Returns an array representing the path to this group. Because this directive\n * always lives at the top level of a form, it is always an empty array.\n */\n override get path(): string[] {\n return [];\n }\n\n /**\n * @description\n * Returns a map of the controls in this group.\n */\n get controls(): {[key: string]: AbstractControl} {\n return this.form.controls;\n }\n\n /**\n * @description\n * Method that sets up the control directive in this group, re-calculates its value\n * and validity, and adds the instance to the internal list of directives.\n *\n * @param dir The `NgModel` directive instance.\n */\n addControl(dir: NgModel): void {\n resolvedPromise.then(() => {\n const container = this._findContainer(dir.path);\n (dir as {control: FormControl}).control =\n <FormControl>container.registerControl(dir.name, dir.control);\n setUpControl(dir.control, dir, this.callSetDisabledState);\n dir.control.updateValueAndValidity({emitEvent: false});\n this._directives.add(dir);\n });\n }\n\n /**\n * @description\n * Retrieves the `FormControl` instance from the provided `NgModel` directive.\n *\n * @param dir The `NgModel` directive instance.\n */\n getControl(dir: NgModel): FormControl {\n return <FormControl>this.form.get(dir.path);\n }\n\n /**\n * @description\n * Removes the `NgModel` instance from the internal list of directives\n *\n * @param dir The `NgModel` directive instance.\n */\n removeControl(dir: NgModel): void {\n resolvedPromise.then(() => {\n const container = this._findContainer(dir.path);\n if (container) {\n container.removeControl(dir.name);\n }\n this._directives.delete(dir);\n });\n }\n\n /**\n * @description\n * Adds a new `NgModelGroup` directive instance to the form.\n *\n * @param dir The `NgModelGroup` directive instance.\n */\n addFormGroup(dir: NgModelGroup): void {\n resolvedPromise.then(() => {\n const container = this._findContainer(dir.path);\n const group = new FormGroup({});\n setUpFormContainer(group, dir);\n container.registerControl(dir.name, group);\n group.updateValueAndValidity({emitEvent: false});\n });\n }\n\n /**\n * @description\n * Removes the `NgModelGroup` directive instance from the form.\n *\n * @param dir The `NgModelGroup` directive instance.\n */\n removeFormGroup(dir: NgModelGroup): void {\n resolvedPromise.then(() => {\n const container = this._findContainer(dir.path);\n if (container) {\n container.removeControl(dir.name);\n }\n });\n }\n\n /**\n * @description\n * Retrieves the `FormGroup` for a provided `NgModelGroup` directive instance\n *\n * @param dir The `NgModelGroup` directive instance.\n */\n getFormGroup(dir: NgModelGroup): FormGroup {\n return <FormGroup>this.form.get(dir.path);\n }\n\n /**\n * Sets the new value for the provided `NgControl` directive.\n *\n * @param dir The `NgControl` directive instance.\n * @param value The new value for the directive's control.\n */\n updateModel(dir: NgControl, value: any): void {\n resolvedPromise.then(() => {\n const ctrl = <FormControl>this.form.get(dir.path!);\n ctrl.setValue(value);\n });\n }\n\n /**\n * @description\n * Sets the value for this `FormGroup`.\n *\n * @param value The new value\n */\n setValue(value: {[key: string]: any}): void {\n this.control.setValue(value);\n }\n\n /**\n * @description\n * Method called when the \"submit\" event is triggered on the form.\n * Triggers the `ngSubmit` emitter to emit the \"submit\" event as its payload.\n *\n * @param $event The \"submit\" event object\n */\n onSubmit($event: Event): boolean {\n (this as {submitted: boolean}).submitted = true;\n syncPendingControls(this.form, this._directives);\n this.ngSubmit.emit($event);\n // Forms with `method=\"dialog\"` have some special behavior\n // that won't reload the page and that shouldn't be prevented.\n return ($event?.target as HTMLFormElement | null)?.method === 'dialog';\n }\n\n /**\n * @description\n * Method called when the \"reset\" event is triggered on the form.\n */\n onReset(): void {\n this.resetForm();\n }\n\n /**\n * @description\n * Resets the form to an initial value and resets its submitted status.\n *\n * @param value The new value for the form.\n */\n resetForm(value: any = undefined): void {\n this.form.reset(value);\n (this as {submitted: boolean}).submitted = false;\n }\n\n private _setUpdateStrategy() {\n if (this.options && this.options.updateOn != null) {\n this.form._updateOn = this.options.updateOn;\n }\n }\n\n private _findContainer(path: string[]): FormGroup {\n path.pop();\n return path.length ? <FormGroup>this.form.get(path) : this.form;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport function removeListItem<T>(list: T[], el: T): void {\n const index = list.indexOf(el);\n if (index > -1) list.splice(index, 1);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AsyncValidatorFn, ValidatorFn} from '../directives/validators';\nimport {removeListItem} from '../util';\n\nimport {AbstractControl, AbstractControlOptions, isOptionsObj, pickAsyncValidators, pickValidators} from './abstract_model';\n\n/**\n * FormControlState is a boxed form value. It is an object with a `value` key and a `disabled` key.\n *\n * @publicApi\n */\nexport interface FormControlState<T> {\n value: T;\n disabled: boolean;\n}\n\n/**\n * Interface for options provided to a `FormControl`.\n *\n * This interface extends all options from {@link AbstractControlOptions}, plus some options\n * unique to `FormControl`.\n *\n * @publicApi\n */\nexport interface FormControlOptions extends AbstractControlOptions {\n /**\n * @description\n * Whether to use the initial value used to construct the `FormControl` as its default value\n * as well. If this option is false or not provided, the default value of a FormControl is `null`.\n * When a FormControl is reset without an explicit value, its value reverts to\n * its default value.\n */\n nonNullable?: boolean;\n\n /**\n * @deprecated Use `nonNullable` instead.\n */\n initialValueIsDefault?: boolean;\n}\n\n/**\n * Tracks the value and validation status of an individual form control.\n *\n * This is one of the four fundamental building blocks of Angular forms, along with\n * `FormGroup`, `FormArray` and `FormRecord`. It extends the `AbstractControl` class that\n * implements most of the base functionality for accessing the value, validation status,\n * user interactions and events.\n *\n * `FormControl` takes a single generic argument, which describes the type of its value. This\n * argument always implicitly includes `null` because the control can be reset. To change this\n * behavior, set `nonNullable` or see the usage notes below.\n *\n * See [usage examples below](#usage-notes).\n *\n * @see `AbstractControl`\n * @see [Reactive Forms Guide](guide/reactive-forms)\n * @see [Usage Notes](#usage-notes)\n *\n * @publicApi\n *\n * @overriddenImplementation ɵFormControlCtor\n *\n * @usageNotes\n *\n * ### Initializing Form Controls\n *\n * Instantiate a `FormControl`, with an initial value.\n *\n * ```ts\n * const control = new FormControl('some value');\n * console.log(control.value); // 'some value'\n * ```\n *\n * The following example initializes the control with a form state object. The `value`\n * and `disabled` keys are required in this case.\n *\n * ```ts\n * const control = new FormControl({ value: 'n/a', disabled: true });\n * console.log(control.value); // 'n/a'\n * console.log(control.status); // 'DISABLED'\n * ```\n *\n * The following example initializes the control with a synchronous validator.\n *\n * ```ts\n * const control = new FormControl('', Validators.required);\n * console.log(control.value); // ''\n * console.log(control.status); // 'INVALID'\n * ```\n *\n * The following example initializes the control using an options object.\n *\n * ```ts\n * const control = new FormControl('', {\n * validators: Validators.required,\n * asyncValidators: myAsyncValidator\n * });\n * ```\n *\n * ### The single type argument\n *\n * `FormControl` accepts a generic argument, which describes the type of its value.\n * In most cases, this argument will be inferred.\n *\n * If you are initializing the control to `null`, or you otherwise wish to provide a\n * wider type, you may specify the argument explicitly:\n *\n * ```\n * let fc = new FormControl<string|null>(null);\n * fc.setValue('foo');\n * ```\n *\n * You might notice that `null` is always added to the type of the control.\n * This is because the control will become `null` if you call `reset`. You can change\n * this behavior by setting `{nonNullable: true}`.\n *\n * ### Configure the control to update on a blur event\n *\n * Set the `updateOn` option to `'blur'` to update on the blur `event`.\n *\n * ```ts\n * const control = new FormControl('', { updateOn: 'blur' });\n * ```\n *\n * ### Configure the control to update on a submit event\n *\n * Set the `updateOn` option to `'submit'` to update on a submit `event`.\n *\n * ```ts\n * const control = new FormControl('', { updateOn: 'submit' });\n * ```\n *\n * ### Reset the control back to a specific value\n *\n * You reset to a specific form state by passing through a standalone\n * value or a form state object that contains both a value and a disabled state\n * (these are the only two properties that cannot be calculated).\n *\n * ```ts\n * const control = new FormControl('Nancy');\n *\n * console.log(control.value); // 'Nancy'\n *\n * control.reset('Drew');\n *\n * console.log(control.value); // 'Drew'\n * ```\n *\n * ### Reset the control to its initial value\n *\n * If you wish to always reset the control to its initial value (instead of null),\n * you can pass the `nonNullable` option:\n *\n * ```\n * const control = new FormControl('Nancy', {nonNullable: true});\n *\n * console.log(control.value); // 'Nancy'\n *\n * control.reset();\n *\n * console.log(control.value); // 'Nancy'\n * ```\n *\n * ### Reset the control back to an initial value and disabled\n *\n * ```\n * const control = new FormControl('Nancy');\n *\n * console.log(control.value); // 'Nancy'\n * console.log(control.status); // 'VALID'\n *\n * control.reset({ value: 'Drew', disabled: true });\n *\n * console.log(control.value); // 'Drew'\n * console.log(control.status); // 'DISABLED'\n * ```\n */\nexport interface FormControl<TValue = any> extends AbstractControl<TValue> {\n /**\n * The default value of this FormControl, used whenever the control is reset without an explicit\n * value. See {@link FormControlOptions#nonNullable} for more information on configuring\n * a default value.\n */\n readonly defaultValue: TValue;\n\n /** @internal */\n _onChange: Function[];\n\n /**\n * This field holds a pending value that has not yet been applied to the form's value.\n * @internal\n */\n _pendingValue: TValue;\n\n /** @internal */\n _pendingChange: boolean;\n\n /**\n * Sets a new value for the form control.\n *\n * @param value The new value for the control.\n * @param options Configuration options that determine how the control propagates changes\n * and emits events when the value changes.\n * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity\n * updateValueAndValidity} method.\n *\n * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is\n * false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control value is updated.\n * When false, no events are emitted.\n * * `emitModelToViewChange`: When true or not supplied (the default), each change triggers an\n * `onChange` event to\n * update the view.\n * * `emitViewToModelChange`: When true or not supplied (the default), each change triggers an\n * `ngModelChange`\n * event to update the model.\n *\n */\n setValue(value: TValue, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean,\n emitModelToViewChange?: boolean,\n emitViewToModelChange?: boolean\n }): void;\n\n /**\n * Patches the value of a control.\n *\n * This function is functionally the same as {@link FormControl#setValue setValue} at this level.\n * It exists for symmetry with {@link FormGroup#patchValue patchValue} on `FormGroups` and\n * `FormArrays`, where it does behave differently.\n *\n * @see `setValue` for options\n */\n patchValue(value: TValue, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean,\n emitModelToViewChange?: boolean,\n emitViewToModelChange?: boolean\n }): void;\n\n /**\n * Resets the form control, marking it `pristine` and `untouched`, and resetting\n * the value. The new value will be the provided value (if passed), `null`, or the initial value\n * if `nonNullable` was set in the constructor via {@link FormControlOptions}.\n *\n * ```ts\n * // By default, the control will reset to null.\n * const dog = new FormControl('spot');\n * dog.reset(); // dog.value is null\n *\n * // If this flag is set, the control will instead reset to the initial value.\n * const cat = new FormControl('tabby', {nonNullable: true});\n * cat.reset(); // cat.value is \"tabby\"\n *\n * // A value passed to reset always takes precedence.\n * const fish = new FormControl('finn', {nonNullable: true});\n * fish.reset('bubble'); // fish.value is \"bubble\"\n * ```\n *\n * @param formState Resets the control with an initial value,\n * or an object that defines the initial value and disabled state.\n *\n * @param options Configuration options that determine how the control propagates changes\n * and emits events after the value changes.\n *\n * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is\n * false.\n * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and\n * `valueChanges`\n * observables emit events with the latest status and value when the control is reset.\n * When false, no events are emitted.\n *\n */\n reset(formState?: TValue|FormControlState<TValue>, options?: {\n onlySelf?: boolean,\n emitEvent?: boolean\n }): void;\n\n /**\n * For a simple FormControl, the raw value is equivalent to the value.\n */\n getRawValue(): TValue;\n\n /**\n * @internal\n */\n _updateValue(): void;\n\n /**\n * @internal\n */\n _anyControls(condition: (c: AbstractControl) => boolean): boolean;\n\n /**\n * @internal\n */\n _allControlsDisabled(): boolean;\n\n\n /**\n * Register a listener for change events.\n *\n * @param fn The method that is called when the value changes\n */\n registerOnChange(fn: Function): void;\n\n\n /**\n * Internal function to unregister a change events listener.\n * @internal\n */\n _unregisterOnChange(fn: (value?: any, emitModelEvent?: boolean) => void): void;\n\n /**\n * Register a listener for disabled events.\n *\n * @param fn The method that is called when the disabled status changes.\n */\n registerOnDisabledChange(fn: (isDisabled: boolean) => void): void;\n\n /**\n * Internal function to unregister a disabled event listener.\n * @internal\n */\n _unregisterOnDisabledChange(fn: (isDisabled: boolean) => void): void;\n\n /**\n * @internal\n */\n _forEachChild(cb: (c: AbstractControl) => void): void;\n\n /** @internal */\n _syncPendingControls(): boolean;\n}\n\n// This internal interface is present to avoid a naming clash, resulting in the wrong `FormControl`\n// symbol being used.\ntype FormControlInterface<TValue = any> = FormControl<TValue>;\n\n/**\n * Various available constructors for `FormControl`.\n * Do not use this interface directly. Instead, use `FormControl`:\n * ```\n * const fc = new FormControl('foo');\n * ```\n * This symbol is prefixed with ɵ to make plain that it is an internal symbol.\n */\nexport interface ɵFormControlCtor {\n /**\n * Construct a FormControl with no initial value or validators.\n */\n new(): FormControl<any>;\n\n /**\n * Creates a new `FormControl` instance.\n *\n * @param formState Initializes the control with an initial value,\n * or an object that defines the initial value and disabled state.\n *\n * @param validatorOrOpts A synchronous validator function, or an array of\n * such functions, or a `FormControlOptions` object that contains validation functions\n * and a validation trigger.\n *\n * @param asyncValidator A single async validator or array of async validator functions\n */\n new<T = any>(value: FormControlState<T>|T, opts: FormControlOptions&{nonNullable: true}):\n FormControl<T>;\n\n /**\n * @deprecated Use `nonNullable` instead.\n */\n new<T = any>(value: FormControlState<T>|T, opts: FormControlOptions&{\n initialValueIsDefault: true\n }): FormControl<T>;\n\n /**\n * @deprecated When passing an `options` argument, the `asyncValidator` argument has no effect.\n */\n new<T = any>(\n value: FormControlState<T>|T, opts: FormControlOptions,\n asyncValidator: AsyncValidatorFn|AsyncValidatorFn[]): FormControl<T|null>;\n\n new<T = any>(\n value: FormControlState<T>|T,\n validatorOrOpts?: ValidatorFn|ValidatorFn[]|FormControlOptions|null,\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): FormControl<T|null>;\n\n /**\n * The presence of an explicit `prototype` property provides backwards-compatibility for apps that\n * manually inspect the prototype chain.\n */\n prototype: FormControl<any>;\n}\n\nfunction isFormControlState(formState: unknown): formState is FormControlState<unknown> {\n return typeof formState === 'object' && formState !== null &&\n Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState;\n}\n\nexport const FormControl: ɵFormControlCtor =\n (class FormControl<TValue = any> extends AbstractControl<\n TValue> implements FormControlInterface<TValue> {\n /** @publicApi */\n public readonly defaultValue: TValue = null as unknown as TValue;\n\n /** @internal */\n _onChange: Array<Function> = [];\n\n /** @internal */\n _pendingValue!: TValue;\n\n /** @internal */\n _pendingChange: boolean = false;\n\n constructor(\n // formState and defaultValue will only be null if T is nullable\n formState: FormControlState<TValue>|TValue = null as unknown as TValue,\n validatorOrOpts?: ValidatorFn|ValidatorFn[]|FormControlOptions|null,\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) {\n super(\n pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));\n this._applyFormState(formState);\n this._setUpdateStrategy(validatorOrOpts);\n this._initObservables();\n this.updateValueAndValidity({\n onlySelf: true,\n // If `asyncValidator` is present, it will trigger control status change from `PENDING` to\n // `VALID` or `INVALID`.\n // The status should be broadcasted via the `statusChanges` observable, so we set\n // `emitEvent` to `true` to allow that during the control creation process.\n emitEvent: !!this.asyncValidator\n });\n if (isOptionsObj(validatorOrOpts) &&\n (validatorOrOpts.nonNullable || validatorOrOpts.initialValueIsDefault)) {\n if (isFormControlState(formState)) {\n this.defaultValue = formState.value;\n } else {\n this.defaultValue = formState;\n }\n }\n }\n\n override setValue(value: TValue, options: {\n onlySelf?: boolean,\n emitEvent?: boolean,\n emitModelToViewChange?: boolean,\n emitViewToModelChange?: boolean\n } = {}): void {\n (this as {value: TValue}).value = this._pendingValue = value;\n if (this._onChange.length && options.emitModelToViewChange !== false) {\n this._onChange.forEach(\n (changeFn) => changeFn(this.value, options.emitViewToModelChange !== false));\n }\n this.updateValueAndValidity(options);\n }\n\n override patchValue(value: TValue, options: {\n onlySelf?: boolean,\n emitEvent?: boolean,\n emitModelToViewChange?: boolean,\n emitViewToModelChange?: boolean\n } = {}): void {\n this.setValue(value, options);\n }\n\n override reset(\n formState: TValue|FormControlState<TValue> = this.defaultValue,\n options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {\n this._applyFormState(formState);\n this.markAsPristine(options);\n this.markAsUntouched(options);\n this.setValue(this.value, options);\n this._pendingChange = false;\n }\n\n /** @internal */\n override _updateValue(): void {}\n\n /** @internal */\n override _anyControls(condition: (c: AbstractControl) => boolean): boolean {\n return false;\n }\n\n /** @internal */\n override _allControlsDisabled(): boolean {\n return this.disabled;\n }\n\n registerOnChange(fn: Function): void {\n this._onChange.push(fn);\n }\n\n /** @internal */\n _unregisterOnChange(fn: (value?: any, emitModelEvent?: boolean) => void): void {\n removeListItem(this._onChange, fn);\n }\n\n registerOnDisabledChange(fn: (isDisabled: boolean) => void): void {\n this._onDisabledChange.push(fn);\n }\n\n /** @internal */\n _unregisterOnDisabledChange(fn: (isDisabled: boolean) => void): void {\n removeListItem(this._onDisabledChange, fn);\n }\n\n /** @internal */\n override _forEachChild(cb: (c: AbstractControl) => void): void {}\n\n /** @internal */\n override _syncPendingControls(): boolean {\n if (this.updateOn === 'submit') {\n if (this._pendingDirty) this.markAsDirty();\n if (this._pendingTouched) this.markAsTouched();\n if (this._pendingChange) {\n this.setValue(this._pendingValue, {onlySelf: true, emitModelToViewChange: false});\n return true;\n }\n }\n return false;\n }\n\n private _applyFormState(formState: FormControlState<TValue>|TValue) {\n if (isFormControlState(formState)) {\n (this as {value: TValue}).value = this._pendingValue = formState.value;\n formState.disabled ? this.disable({onlySelf: true, emitEvent: false}) :\n this.enable({onlySelf: true, emitEvent: false});\n } else {\n (this as {value: TValue}).value = this._pendingValue = formState;\n }\n }\n });\n\ninterface UntypedFormControlCtor {\n new(): UntypedFormControl;\n\n new(formState?: any, validatorOrOpts?: ValidatorFn|ValidatorFn[]|FormControlOptions|null,\n asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): UntypedFormControl;\n\n /**\n * The presence of an explicit `prototype` property provides backwards-compatibility for apps that\n * manually inspect the prototype chain.\n */\n prototype: FormControl<any>;\n}\n\n/**\n * UntypedFormControl is a non-strongly-typed version of `FormControl`.\n */\nexport type UntypedFormControl = FormControl<any>;\n\nexport const UntypedFormControl: UntypedFormControlCtor = FormControl;\n\n/**\n * @description\n * Asserts that the given control is an instance of `FormControl`\n *\n * @publicApi\n */\nexport const isFormControl = (control: unknown): control is FormControl =>\n control instanceof FormControl;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef, Directive, EventEmitter, forwardRef, Host, Inject, Input, OnChanges, OnDestroy, Optional, Output, Provider, Self, SimpleChanges, ɵcoerceToBoolean as coerceToBoolean} from '@angular/core';\n\nimport {FormHooks} from '../model/abstract_model';\nimport {FormControl} from '../model/form_control';\nimport {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';\n\nimport {AbstractFormGroupDirective} from './abstract_form_group_directive';\nimport {ControlContainer} from './control_container';\nimport {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';\nimport {NgControl} from './ng_control';\nimport {NgForm} from './ng_form';\nimport {NgModelGroup} from './ng_model_group';\nimport {CALL_SET_DISABLED_STATE, controlPath, isPropertyUpdated, selectValueAccessor, SetDisabledStateOption, setUpControl} from './shared';\nimport {formGroupNameException, missingNameException, modelParentException} from './template_driven_errors';\nimport {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from './validators';\n\nconst formControlBinding: Provider = {\n provide: NgControl,\n useExisting: forwardRef(() => NgModel)\n};\n\n/**\n * `ngModel` forces an additional change detection run when its inputs change:\n * E.g.:\n * ```\n * <div>{{myModel.valid}}</div>\n * <input [(ngModel)]=\"myValue\" #myModel=\"ngModel\">\n * ```\n * I.e. `ngModel` can export itself on the element and then be used in the template.\n * Normally, this would result in expressions before the `input` that use the exported directive\n * to have an old value as they have been\n * dirty checked before. As this is a very common case for `ngModel`, we added this second change\n * detection run.\n *\n * Notes:\n * - this is just one extra run no matter how many `ngModel`s have been changed.\n * - this is a general problem when using `exportAs` for directives!\n */\nconst resolvedPromise = (() => Promise.resolve())();\n\n/**\n * @description\n * Creates a `FormControl` instance from a domain model and binds it\n * to a form control element.\n *\n * The `FormControl` instance tracks the value, user interaction, and\n * validation status of the control and keeps the view synced with the model. If used\n * within a parent form, the directive also registers itself with the form as a child\n * control.\n *\n * This directive is used by itself or as part of a larger form. Use the\n * `ngModel` selector to activate it.\n *\n * It accepts a domain model as an optional `Input`. If you have a one-way binding\n * to `ngModel` with `[]` syntax, changing the domain model's value in the component\n * class sets the value in the view. If you have a two-way binding with `[()]` syntax\n * (also known as 'banana-in-a-box syntax'), the value in the UI always syncs back to\n * the domain model in your class.\n *\n * To inspect the properties of the associated `FormControl` (like the validity state),\n * export the directive into a local template variable using `ngModel` as the key (ex:\n * `#myVar=\"ngModel\"`). You can then access the control using the directive's `control` property.\n * However, the most commonly used properties (like `valid` and `dirty`) also exist on the control\n * for direct access. See a full list of properties directly available in\n * `AbstractControlDirective`.\n *\n * @see `RadioControlValueAccessor`\n * @see `SelectControlValueAccessor`\n *\n * @usageNotes\n *\n * ### Using ngModel on a standalone control\n *\n * The following examples show a simple standalone control using `ngModel`:\n *\n * {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}\n *\n * When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute\n * so that the control can be registered with the parent form under that name.\n *\n * In the context of a parent form, it's often unnecessary to include one-way or two-way binding,\n * as the parent form syncs the value for you. You access its properties by exporting it into a\n * local template variable using `ngForm` such as (`#f=\"ngForm\"`). Use the variable where\n * needed on form submission.\n *\n * If you do need to populate initial values into your form, using a one-way binding for\n * `ngModel` tends to be sufficient as long as you use the exported form's value rather\n * than the domain model's value on submit.\n *\n * ### Using ngModel within a form\n *\n * The following example shows controls using `ngModel` within a form:\n *\n * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}\n *\n * ### Using a standalone ngModel within a group\n *\n * The following example shows you how to use a standalone ngModel control\n * within a form. This controls the display of the form, but doesn't contain form data.\n *\n * ```html\n * <form>\n * <input name=\"login\" ngModel placeholder=\"Login\">\n * <input type=\"checkbox\" ngModel [ngModelOptions]=\"{standalone: true}\"> Show more options?\n * </form>\n * <!-- form value: {login: ''} -->\n * ```\n *\n * ### Setting the ngModel `name` attribute through options\n *\n * The following example shows you an alternate way to set the name attribute. Here,\n * an attribute identified as name is used within a custom form control component. To still be able\n * to specify the NgModel's name, you must specify it using the `ngModelOptions` input instead.\n *\n * ```html\n * <form>\n * <my-custom-form-control name=\"Nancy\" ngModel [ngModelOptions]=\"{name: 'user'}\">\n * </my-custom-form-control>\n * </form>\n * <!-- form value: {user: ''} -->\n * ```\n *\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector: '[ngModel]:not([formControlName]):not([formControl])',\n providers: [formControlBinding],\n exportAs: 'ngModel'\n})\nexport class NgModel extends NgControl implements OnChanges, OnDestroy {\n public override readonly control: FormControl = new FormControl();\n\n // At runtime we coerce arbitrary values assigned to the \"disabled\" input to a \"boolean\".\n // This is not reflected in the type of the property because outside of templates, consumers\n // should only deal with booleans. In templates, a string is allowed for convenience and to\n // match the native \"disabled attribute\" semantics which can be observed on input elements.\n // This static member tells the compiler that values of type \"string\" can also be assigned\n // to the input in a template.\n /** @nodoc */\n static ngAcceptInputType_isDisabled: boolean|string;\n\n /** @internal */\n _registered = false;\n\n /**\n * Internal reference to the view model value.\n * @nodoc\n */\n viewModel: any;\n\n /**\n * @description\n * Tracks the name bound to the directive. If a parent form exists, it\n * uses this name as a key to retrieve this control's value.\n */\n // TODO(issue/24571): remove '!'.\n @Input() override name!: string;\n\n /**\n * @description\n * Tracks whether the control is disabled.\n */\n // TODO(issue/24571): remove '!'.\n @Input('disabled') isDisabled!: boolean;\n\n /**\n * @description\n * Tracks the value bound to this directive.\n */\n @Input('ngModel') model: any;\n\n /**\n * @description\n * Tracks the configuration options for this `ngModel` instance.\n *\n * **name**: An alternative to setting the name attribute on the form control element. See\n * the [example](api/forms/NgModel#using-ngmodel-on-a-standalone-control) for using `NgModel`\n * as a standalone control.\n *\n * **standalone**: When set to true, the `ngModel` will not register itself with its parent form,\n * and acts as if it's not in the form. Defaults to false. If no parent form exists, this option\n * has no effect.\n *\n * **updateOn**: Defines the event upon which the form control value and validity update.\n * Defaults to 'change'. Possible values: `'change'` | `'blur'` | `'submit'`.\n *\n */\n // TODO(issue/24571): remove '!'.\n @Input('ngModelOptions') options!: {name?: string, standalone?: boolean, updateOn?: FormHooks};\n\n /**\n * @description\n * Event emitter for producing the `ngModelChange` event after\n * the view model updates.\n */\n @Output('ngModelChange') update = new EventEmitter();\n\n constructor(\n @Optional() @Host() parent: ControlContainer,\n @Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator|ValidatorFn)[],\n @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:\n (AsyncValidator|AsyncValidatorFn)[],\n @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[],\n @Optional() @Inject(ChangeDetectorRef) private _changeDetectorRef?: ChangeDetectorRef|null,\n @Optional() @Inject(CALL_SET_DISABLED_STATE) private callSetDisabledState?:\n SetDisabledStateOption) {\n super();\n this._parent = parent;\n this._setValidators(validators);\n this._setAsyncValidators(asyncValidators);\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges) {\n this._checkForErrors();\n if (!this._registered || 'name' in changes) {\n if (this._registered) {\n this._checkName();\n if (this.formDirective) {\n // We can't call `formDirective.removeControl(this)`, because the `name` has already been\n // changed. We also can't reset the name temporarily since the logic in `removeControl`\n // is inside a promise and it won't run immediately. We work around it by giving it an\n // object with the same shape instead.\n const oldName = changes['name'].previousValue;\n this.formDirective.removeControl({name: oldName, path: this._getPath(oldName)});\n }\n }\n this._setUpControl();\n }\n if ('isDisabled' in changes) {\n this._updateDisabled(changes);\n }\n\n if (isPropertyUpdated(changes, this.viewModel)) {\n this._updateValue(this.model);\n this.viewModel = this.model;\n }\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n this.formDirective && this.formDirective.removeControl(this);\n }\n\n /**\n * @description\n * Returns an array that represents the path from the top-level form to this control.\n * Each index is the string name of the control on that level.\n */\n override get path(): string[] {\n return this._getPath(this.name);\n }\n\n /**\n * @description\n * The top-level directive for this control if present, otherwise null.\n */\n get formDirective(): any {\n return this._parent ? this._parent.formDirective : null;\n }\n\n /**\n * @description\n * Sets the new value for the view model and emits an `ngModelChange` event.\n *\n * @param newValue The new value emitted by `ngModelChange`.\n */\n override viewToModelUpdate(newValue: any): void {\n this.viewModel = newValue;\n this.update.emit(newValue);\n }\n\n private _setUpControl(): void {\n this._setUpdateStrategy();\n this._isStandalone() ? this._setUpStandalone() : this.formDirective.addControl(this);\n this._registered = true;\n }\n\n private _setUpdateStrategy(): void {\n if (this.options && this.options.updateOn != null) {\n this.control._updateOn = this.options.updateOn;\n }\n }\n\n private _isStandalone(): boolean {\n return !this._parent || !!(this.options && this.options.standalone);\n }\n\n private _setUpStandalone(): void {\n setUpControl(this.control, this, this.callSetDisabledState);\n this.control.updateValueAndValidity({emitEvent: false});\n }\n\n private _checkForErrors(): void {\n if (!this._isStandalone()) {\n this._checkParentType();\n }\n this._checkName();\n }\n\n private _checkParentType(): void {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!(this._parent instanceof NgModelGroup) &&\n this._parent instanceof AbstractFormGroupDirective) {\n throw formGroupNameException();\n } else if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) {\n throw modelParentException();\n }\n }\n }\n\n private _checkName(): void {\n if (this.options && this.options.name) this.name = this.options.name;\n\n if (!this._isStandalone() && !this.name && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw missingNameException();\n }\n }\n\n private _updateValue(value: any): void {\n resolvedPromise.then(() => {\n this.control.setValue(value, {emitViewToModelChange: false});\n this._changeDetectorRef?.markForCheck();\n });\n }\n\n private _updateDisabled(changes: SimpleChanges) {\n const disabledValue = changes['isDisabled'].currentValue;\n // checking for 0 to avoid breaking change\n const isDisabled = disabledValue !== 0 && coerceToBoolean(disabledValue);\n\n resolvedPromise.then(() => {\n if (isDisabled && !this.control.disabled) {\n this.control.disable();\n } else if (!isDisabled && this.control.disabled) {\n this.control.enable();\n }\n\n this._changeDetectorRef?.markForCheck();\n });\n }\n\n private _getPath(controlName: string): string[] {\n return this._parent ? controlPath(controlName, this._parent) : [controlName];\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive} from '@angular/core';\n\n/**\n * @description\n *\n * Adds `novalidate` attribute to all forms by default.\n *\n * `novalidate` is used to disable browser's native form validation.\n *\n * If you want to use native validation with Angular forms, just add `ngNativeValidate` attribute:\n *\n * ```\n * <form ngNativeValidate></form>\n * ```\n *\n * @publicApi\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n */\n@Directive({\n selector: 'form:not([ngNoForm]):not([ngNativeValidate])',\n host: {'novalidate': ''},\n})\nexport class ɵNgNoValidate {\n}\n\nexport {ɵNgNoValidate as NgNoValidate};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, ElementRef, forwardRef, inject, Injectable, Injector, Input, NgModule, OnDestroy, OnInit, Provider, Renderer2, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\n\nimport {BuiltInControlValueAccessor, ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';\nimport {NgControl} from './ng_control';\nimport {CALL_SET_DISABLED_STATE, setDisabledStateDefault, SetDisabledStateOption} from './shared';\n\nconst RADIO_VALUE_ACCESSOR: Provider = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => RadioControlValueAccessor),\n multi: true\n};\n\nfunction throwNameError() {\n throw new RuntimeError(RuntimeErrorCode.NAME_AND_FORM_CONTROL_NAME_MUST_MATCH, `\n If you define both a name and a formControlName attribute on your radio button, their values\n must match. Ex: <input type=\"radio\" formControlName=\"food\" name=\"food\">\n `);\n}\n\n/**\n * Internal-only NgModule that works as a host for the `RadioControlRegistry` tree-shakable\n * provider. Note: the `InternalFormsSharedModule` can not be used here directly, since it's\n * declared *after* the `RadioControlRegistry` class and the `providedIn` doesn't support\n * `forwardRef` logic.\n */\n@NgModule()\nexport class RadioControlRegistryModule {\n}\n\n/**\n * @description\n * Class used by Angular to track radio buttons. For internal use only.\n */\n@Injectable({providedIn: RadioControlRegistryModule})\nexport class RadioControlRegistry {\n private _accessors: any[] = [];\n\n /**\n * @description\n * Adds a control to the internal registry. For internal use only.\n */\n add(control: NgControl, accessor: RadioControlValueAccessor) {\n this._accessors.push([control, accessor]);\n }\n\n /**\n * @description\n * Removes a control from the internal registry. For internal use only.\n */\n remove(accessor: RadioControlValueAccessor) {\n for (let i = this._accessors.length - 1; i >= 0; --i) {\n if (this._accessors[i][1] === accessor) {\n this._accessors.splice(i, 1);\n return;\n }\n }\n }\n\n /**\n * @description\n * Selects a radio button. For internal use only.\n */\n select(accessor: RadioControlValueAccessor) {\n this._accessors.forEach((c) => {\n if (this._isSameGroup(c, accessor) && c[1] !== accessor) {\n c[1].fireUncheck(accessor.value);\n }\n });\n }\n\n private _isSameGroup(\n controlPair: [NgControl, RadioControlValueAccessor],\n accessor: RadioControlValueAccessor): boolean {\n if (!controlPair[0].control) return false;\n return controlPair[0]._parent === accessor._control._parent &&\n controlPair[1].name === accessor.name;\n }\n}\n\n/**\n * @description\n * The `ControlValueAccessor` for writing radio control values and listening to radio control\n * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and\n * `NgModel` directives.\n *\n * @usageNotes\n *\n * ### Using radio buttons with reactive form directives\n *\n * The follow example shows how to use radio buttons in a reactive form. When using radio buttons in\n * a reactive form, radio buttons in the same group should have the same `formControlName`.\n * Providing a `name` attribute is optional.\n *\n * {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',\n host: {'(change)': 'onChange()', '(blur)': 'onTouched()'},\n providers: [RADIO_VALUE_ACCESSOR]\n})\nexport class RadioControlValueAccessor extends BuiltInControlValueAccessor implements\n ControlValueAccessor, OnDestroy, OnInit {\n /** @internal */\n // TODO(issue/24571): remove '!'.\n _state!: boolean;\n /** @internal */\n // TODO(issue/24571): remove '!'.\n _control!: NgControl;\n /** @internal */\n // TODO(issue/24571): remove '!'.\n _fn!: Function;\n\n private setDisabledStateFired = false;\n\n /**\n * The registered callback function called when a change event occurs on the input element.\n * Note: we declare `onChange` here (also used as host listener) as a function with no arguments\n * to override the `onChange` function (which expects 1 argument) in the parent\n * `BaseControlValueAccessor` class.\n * @nodoc\n */\n override onChange = () => {};\n\n /**\n * @description\n * Tracks the name of the radio input element.\n */\n // TODO(issue/24571): remove '!'.\n @Input() name!: string;\n\n /**\n * @description\n * Tracks the name of the `FormControl` bound to the directive. The name corresponds\n * to a key in the parent `FormGroup` or `FormArray`.\n */\n // TODO(issue/24571): remove '!'.\n @Input() formControlName!: string;\n\n /**\n * @description\n * Tracks the value of the radio input element\n */\n @Input() value: any;\n\n private callSetDisabledState =\n inject(CALL_SET_DISABLED_STATE, {optional: true}) ?? setDisabledStateDefault;\n\n constructor(\n renderer: Renderer2, elementRef: ElementRef, private _registry: RadioControlRegistry,\n private _injector: Injector) {\n super(renderer, elementRef);\n }\n\n /** @nodoc */\n ngOnInit(): void {\n this._control = this._injector.get(NgControl);\n this._checkName();\n this._registry.add(this._control, this);\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n this._registry.remove(this);\n }\n\n /**\n * Sets the \"checked\" property value on the radio input element.\n * @nodoc\n */\n writeValue(value: any): void {\n this._state = value === this.value;\n this.setProperty('checked', this._state);\n }\n\n /**\n * Registers a function called when the control value changes.\n * @nodoc\n */\n override registerOnChange(fn: (_: any) => {}): void {\n this._fn = fn;\n this.onChange = () => {\n fn(this.value);\n this._registry.select(this);\n };\n }\n\n /** @nodoc */\n override setDisabledState(isDisabled: boolean): void {\n /**\n * `setDisabledState` is supposed to be called whenever the disabled state of a control changes,\n * including upon control creation. However, a longstanding bug caused the method to not fire\n * when an *enabled* control was attached. This bug was fixed in v15 in #47576.\n *\n * This had a side effect: previously, it was possible to instantiate a reactive form control\n * with `[attr.disabled]=true`, even though the the corresponding control was enabled in the\n * model. This resulted in a mismatch between the model and the DOM. Now, because\n * `setDisabledState` is always called, the value in the DOM will be immediately overwritten\n * with the \"correct\" enabled value.\n *\n * However, the fix also created an exceptional case: radio buttons. Because Reactive Forms\n * models the entire group of radio buttons as a single `FormControl`, there is no way to\n * control the disabled state for individual radios, so they can no longer be configured as\n * disabled. Thus, we keep the old behavior for radio buttons, so that `[attr.disabled]`\n * continues to work. Specifically, we drop the first call to `setDisabledState` if `disabled`\n * is `false`, and we are not in legacy mode.\n */\n if (this.setDisabledStateFired || isDisabled ||\n this.callSetDisabledState === 'whenDisabledForLegacyCode') {\n this.setProperty('disabled', isDisabled);\n }\n this.setDisabledStateFired = true;\n }\n\n /**\n * Sets the \"value\" on the radio input element and unchecks it.\n *\n * @param value\n */\n fireUncheck(value: any): void {\n this.writeValue(value);\n }\n\n private _checkName(): void {\n if (this.name && this.formControlName && this.name !== this.formControlName &&\n (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwNameError();\n }\n if (!this.name && this.formControlName) this.name = this.formControlName;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, EventEmitter, forwardRef, Inject, InjectionToken, Input, OnChanges, OnDestroy, Optional, Output, Provider, Self, SimpleChanges} from '@angular/core';\n\nimport {FormControl} from '../../model/form_control';\nimport {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';\nimport {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor';\nimport {NgControl} from '../ng_control';\nimport {disabledAttrWarning} from '../reactive_errors';\nimport {_ngModelWarning, CALL_SET_DISABLED_STATE, cleanUpControl, isPropertyUpdated, selectValueAccessor, SetDisabledStateOption, setUpControl} from '../shared';\nimport {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from '../validators';\n\n\n/**\n * Token to provide to turn off the ngModel warning on formControl and formControlName.\n */\nexport const NG_MODEL_WITH_FORM_CONTROL_WARNING =\n new InjectionToken('NgModelWithFormControlWarning');\n\nconst formControlBinding: Provider = {\n provide: NgControl,\n useExisting: forwardRef(() => FormControlDirective)\n};\n\n/**\n * @description\n * Synchronizes a standalone `FormControl` instance to a form control element.\n *\n * Note that support for using the `ngModel` input property and `ngModelChange` event with reactive\n * form directives was deprecated in Angular v6 and is scheduled for removal in\n * a future version of Angular.\n * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms).\n *\n * @see [Reactive Forms Guide](guide/reactive-forms)\n * @see `FormControl`\n * @see `AbstractControl`\n *\n * @usageNotes\n *\n * The following example shows how to register a standalone control and set its value.\n *\n * {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}\n *\n * @ngModule ReactiveFormsModule\n * @publicApi\n */\n@Directive({selector: '[formControl]', providers: [formControlBinding], exportAs: 'ngForm'})\nexport class FormControlDirective extends NgControl implements OnChanges, OnDestroy {\n /**\n * Internal reference to the view model value.\n * @nodoc\n */\n viewModel: any;\n\n /**\n * @description\n * Tracks the `FormControl` instance bound to the directive.\n */\n // TODO(issue/24571): remove '!'.\n @Input('formControl') form!: FormControl;\n\n /**\n * @description\n * Triggers a warning in dev mode that this input should not be used with reactive forms.\n */\n @Input('disabled')\n set isDisabled(isDisabled: boolean) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(disabledAttrWarning);\n }\n }\n\n // TODO(kara): remove next 4 properties once deprecation period is over\n\n /** @deprecated as of v6 */\n @Input('ngModel') model: any;\n\n /** @deprecated as of v6 */\n @Output('ngModelChange') update = new EventEmitter();\n\n /**\n * @description\n * Static property used to track whether any ngModel warnings have been sent across\n * all instances of FormControlDirective. Used to support warning config of \"once\".\n *\n * @internal\n */\n static _ngModelWarningSentOnce = false;\n\n /**\n * @description\n * Instance property used to track whether an ngModel warning has been sent out for this\n * particular `FormControlDirective` instance. Used to support warning config of \"always\".\n *\n * @internal\n */\n _ngModelWarningSent = false;\n\n constructor(\n @Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator|ValidatorFn)[],\n @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:\n (AsyncValidator|AsyncValidatorFn)[],\n @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[],\n @Optional() @Inject(NG_MODEL_WITH_FORM_CONTROL_WARNING) private _ngModelWarningConfig: string|\n null,\n @Optional() @Inject(CALL_SET_DISABLED_STATE) private callSetDisabledState?:\n SetDisabledStateOption) {\n super();\n this._setValidators(validators);\n this._setAsyncValidators(asyncValidators);\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges): void {\n if (this._isControlChanged(changes)) {\n const previousForm = changes['form'].previousValue;\n if (previousForm) {\n cleanUpControl(previousForm, this, /* validateControlPresenceOnChange */ false);\n }\n setUpControl(this.form, this, this.callSetDisabledState);\n this.form.updateValueAndValidity({emitEvent: false});\n }\n if (isPropertyUpdated(changes, this.viewModel)) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n _ngModelWarning('formControl', FormControlDirective, this, this._ngModelWarningConfig);\n }\n this.form.setValue(this.model);\n this.viewModel = this.model;\n }\n }\n\n /** @nodoc */\n ngOnDestroy() {\n if (this.form) {\n cleanUpControl(this.form, this, /* validateControlPresenceOnChange */ false);\n }\n }\n\n /**\n * @description\n * Returns an array that represents the path from the top-level form to this control.\n * Each index is the string name of the control on that level.\n */\n override get path(): string[] {\n return [];\n }\n\n /**\n * @description\n * The `FormControl` bound to this directive.\n */\n override get control(): FormControl {\n return this.form;\n }\n\n /**\n * @description\n * Sets the new value for the view model and emits an `ngModelChange` event.\n *\n * @param newValue The new value for the view model.\n */\n override viewToModelUpdate(newValue: any): void {\n this.viewModel = newValue;\n this.update.emit(newValue);\n }\n\n private _isControlChanged(changes: {[key: string]: any}): boolean {\n return changes.hasOwnProperty('form');\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, EventEmitter, forwardRef, Inject, Input, OnChanges, OnDestroy, Optional, Output, Provider, Self, SimpleChanges} from '@angular/core';\n\nimport {FormArray} from '../../model/form_array';\nimport {FormControl, isFormControl} from '../../model/form_control';\nimport {FormGroup} from '../../model/form_group';\nimport {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';\nimport {ControlContainer} from '../control_container';\nimport {Form} from '../form_interface';\nimport {missingFormException} from '../reactive_errors';\nimport {CALL_SET_DISABLED_STATE, cleanUpControl, cleanUpFormContainer, cleanUpValidators, removeListItem, SetDisabledStateOption, setUpControl, setUpFormContainer, setUpValidators, syncPendingControls} from '../shared';\nimport {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from '../validators';\n\nimport {FormControlName} from './form_control_name';\nimport {FormArrayName, FormGroupName} from './form_group_name';\n\nconst formDirectiveProvider: Provider = {\n provide: ControlContainer,\n useExisting: forwardRef(() => FormGroupDirective)\n};\n\n/**\n * @description\n *\n * Binds an existing `FormGroup` or `FormRecord` to a DOM element.\n *\n * This directive accepts an existing `FormGroup` instance. It will then use this\n * `FormGroup` instance to match any child `FormControl`, `FormGroup`/`FormRecord`,\n * and `FormArray` instances to child `FormControlName`, `FormGroupName`,\n * and `FormArrayName` directives.\n *\n * @see [Reactive Forms Guide](guide/reactive-forms)\n * @see `AbstractControl`\n *\n * @usageNotes\n * ### Register Form Group\n *\n * The following example registers a `FormGroup` with first name and last name controls,\n * and listens for the *ngSubmit* event when the button is clicked.\n *\n * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}\n *\n * @ngModule ReactiveFormsModule\n * @publicApi\n */\n@Directive({\n selector: '[formGroup]',\n providers: [formDirectiveProvider],\n host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},\n exportAs: 'ngForm'\n})\nexport class FormGroupDirective extends ControlContainer implements Form, OnChanges, OnDestroy {\n /**\n * @description\n * Reports whether the form submission has been triggered.\n */\n public readonly submitted: boolean = false;\n\n /**\n * Reference to an old form group input value, which is needed to cleanup old instance in case it\n * was replaced with a new one.\n */\n private _oldForm: FormGroup|undefined;\n\n /**\n * Callback that should be invoked when controls in FormGroup or FormArray collection change\n * (added or removed). This callback triggers corresponding DOM updates.\n */\n private readonly _onCollectionChange = () => this._updateDomValue();\n\n /**\n * @description\n * Tracks the list of added `FormControlName` instances\n */\n directives: FormControlName[] = [];\n\n /**\n * @description\n * Tracks the `FormGroup` bound to this directive.\n */\n @Input('formGroup') form: FormGroup = null!;\n\n /**\n * @description\n * Emits an event when the form submission has been triggered.\n */\n @Output() ngSubmit = new EventEmitter();\n\n constructor(\n @Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator|ValidatorFn)[],\n @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:\n (AsyncValidator|AsyncValidatorFn)[],\n @Optional() @Inject(CALL_SET_DISABLED_STATE) private callSetDisabledState?:\n SetDisabledStateOption) {\n super();\n this._setValidators(validators);\n this._setAsyncValidators(asyncValidators);\n }\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges): void {\n this._checkFormPresent();\n if (changes.hasOwnProperty('form')) {\n this._updateValidators();\n this._updateDomValue();\n this._updateRegistrations();\n this._oldForm = this.form;\n }\n }\n\n /** @nodoc */\n ngOnDestroy() {\n if (this.form) {\n cleanUpValidators(this.form, this);\n\n // Currently the `onCollectionChange` callback is rewritten each time the\n // `_registerOnCollectionChange` function is invoked. The implication is that cleanup should\n // happen *only* when the `onCollectionChange` callback was set by this directive instance.\n // Otherwise it might cause overriding a callback of some other directive instances. We should\n // consider updating this logic later to make it similar to how `onChange` callbacks are\n // handled, see https://github.com/angular/angular/issues/39732 for additional info.\n if (this.form._onCollectionChange === this._onCollectionChange) {\n this.form._registerOnCollectionChange(() => {});\n }\n }\n }\n\n /**\n * @description\n * Returns this directive's instance.\n */\n override get formDirective(): Form {\n return this;\n }\n\n /**\n * @description\n * Returns the `FormGroup` bound to this directive.\n */\n override get control(): FormGroup {\n return this.form;\n }\n\n /**\n * @description\n * Returns an array representing the path to this group. Because this directive\n * always lives at the top level of a form, it always an empty array.\n */\n override get path(): string[] {\n return [];\n }\n\n /**\n * @description\n * Method that sets up the control directive in this group, re-calculates its value\n * and validity, and adds the instance to the internal list of directives.\n *\n * @param dir The `FormControlName` directive instance.\n */\n addControl(dir: FormControlName): FormControl {\n const ctrl: any = this.form.get(dir.path);\n setUpControl(ctrl, dir, this.callSetDisabledState);\n ctrl.updateValueAndValidity({emitEvent: false});\n this.directives.push(dir);\n return ctrl;\n }\n\n /**\n * @description\n * Retrieves the `FormControl` instance from the provided `FormControlName` directive\n *\n * @param dir The `FormControlName` directive instance.\n */\n getControl(dir: FormControlName): FormControl {\n return <FormControl>this.form.get(dir.path);\n }\n\n /**\n * @description\n * Removes the `FormControlName` instance from the internal list of directives\n *\n * @param dir The `FormControlName` directive instance.\n */\n removeControl(dir: FormControlName): void {\n cleanUpControl(dir.control || null, dir, /* validateControlPresenceOnChange */ false);\n removeListItem(this.directives, dir);\n }\n\n /**\n * Adds a new `FormGroupName` directive instance to the form.\n *\n * @param dir The `FormGroupName` directive instance.\n */\n addFormGroup(dir: FormGroupName): void {\n this._setUpFormContainer(dir);\n }\n\n /**\n * Performs the necessary cleanup when a `FormGroupName` directive instance is removed from the\n * view.\n *\n * @param dir The `FormGroupName` directive instance.\n */\n removeFormGroup(dir: FormGroupName): void {\n this._cleanUpFormContainer(dir);\n }\n\n /**\n * @description\n * Retrieves the `FormGroup` for a provided `FormGroupName` directive instance\n *\n * @param dir The `FormGroupName` directive instance.\n */\n getFormGroup(dir: FormGroupName): FormGroup {\n return <FormGroup>this.form.get(dir.path);\n }\n\n /**\n * Performs the necessary setup when a `FormArrayName` directive instance is added to the view.\n *\n * @param dir The `FormArrayName` directive instance.\n */\n addFormArray(dir: FormArrayName): void {\n this._setUpFormContainer(dir);\n }\n\n /**\n * Performs the necessary cleanup when a `FormArrayName` directive instance is removed from the\n * view.\n *\n * @param dir The `FormArrayName` directive instance.\n */\n removeFormArray(dir: FormArrayName): void {\n this._cleanUpFormContainer(dir);\n }\n\n /**\n * @description\n * Retrieves the `FormArray` for a provided `FormArrayName` directive instance.\n *\n * @param dir The `FormArrayName` directive instance.\n */\n getFormArray(dir: FormArrayName): FormArray {\n return <FormArray>this.form.get(dir.path);\n }\n\n /**\n * Sets the new value for the provided `FormControlName` directive.\n *\n * @param dir The `FormControlName` directive instance.\n * @param value The new value for the directive's control.\n */\n updateModel(dir: FormControlName, value: any): void {\n const ctrl = <FormControl>this.form.get(dir.path);\n ctrl.setValue(value);\n }\n\n /**\n * @description\n * Method called with the \"submit\" event is triggered on the form.\n * Triggers the `ngSubmit` emitter to emit the \"submit\" event as its payload.\n *\n * @param $event The \"submit\" event object\n */\n onSubmit($event: Event): boolean {\n (this as {submitted: boolean}).submitted = true;\n syncPendingControls(this.form, this.directives);\n this.ngSubmit.emit($event);\n // Forms with `method=\"dialog\"` have some special behavior that won't reload the page and that\n // shouldn't be prevented. Note that we need to null check the `event` and the `target`, because\n // some internal apps call this method directly with the wrong arguments.\n return ($event?.target as HTMLFormElement | null)?.method === 'dialog';\n }\n\n /**\n * @description\n * Method called when the \"reset\" event is triggered on the form.\n */\n onReset(): void {\n this.resetForm();\n }\n\n /**\n * @description\n * Resets the form to an initial value and resets its submitted status.\n *\n * @param value The new value for the form.\n */\n resetForm(value: any = undefined): void {\n this.form.reset(value);\n (this as {submitted: boolean}).submitted = false;\n }\n\n /** @internal */\n _updateDomValue() {\n this.directives.forEach(dir => {\n const oldCtrl = dir.control;\n const newCtrl = this.form.get(dir.path);\n if (oldCtrl !== newCtrl) {\n // Note: the value of the `dir.control` may not be defined, for example when it's a first\n // `FormControl` that is added to a `FormGroup` instance (via `addControl` call).\n cleanUpControl(oldCtrl || null, dir);\n\n // Check whether new control at the same location inside the corresponding `FormGroup` is an\n // instance of `FormControl` and perform control setup only if that's the case.\n // Note: we don't need to clear the list of directives (`this.directives`) here, it would be\n // taken care of in the `removeControl` method invoked when corresponding `formControlName`\n // directive instance is being removed (invoked from `FormControlName.ngOnDestroy`).\n if (isFormControl(newCtrl)) {\n setUpControl(newCtrl, dir, this.callSetDisabledState);\n (dir as {control: FormControl}).control = newCtrl;\n }\n }\n });\n\n this.form._updateTreeValidity({emitEvent: false});\n }\n\n private _setUpFormContainer(dir: FormArrayName|FormGroupName): void {\n const ctrl: any = this.form.get(dir.path);\n setUpFormContainer(ctrl, dir);\n // NOTE: this operation looks unnecessary in case no new validators were added in\n // `setUpFormContainer` call. Consider updating this code to match the logic in\n // `_cleanUpFormContainer` function.\n ctrl.updateValueAndValidity({emitEvent: false});\n }\n\n private _cleanUpFormContainer(dir: FormArrayName|FormGroupName): void {\n if (this.form) {\n const ctrl: any = this.form.get(dir.path);\n if (ctrl) {\n const isControlUpdated = cleanUpFormContainer(ctrl, dir);\n if (isControlUpdated) {\n // Run validity check only in case a control was updated (i.e. view validators were\n // removed) as removing view validators might cause validity to change.\n ctrl.updateValueAndValidity({emitEvent: false});\n }\n }\n }\n }\n\n private _updateRegistrations() {\n this.form._registerOnCollectionChange(this._onCollectionChange);\n if (this._oldForm) {\n this._oldForm._registerOnCollectionChange(() => {});\n }\n }\n\n private _updateValidators() {\n setUpValidators(this.form, this);\n if (this._oldForm) {\n cleanUpValidators(this._oldForm, this);\n }\n }\n\n private _checkFormPresent() {\n if (!this.form && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw missingFormException();\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, EventEmitter, forwardRef, Host, Inject, Input, OnChanges, OnDestroy, Optional, Output, Provider, Self, SimpleChanges, SkipSelf} from '@angular/core';\n\nimport {FormControl} from '../../model/form_control';\nimport {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';\nimport {AbstractFormGroupDirective} from '../abstract_form_group_directive';\nimport {ControlContainer} from '../control_container';\nimport {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor';\nimport {NgControl} from '../ng_control';\nimport {controlParentException, disabledAttrWarning, ngModelGroupException} from '../reactive_errors';\nimport {_ngModelWarning, controlPath, isPropertyUpdated, selectValueAccessor} from '../shared';\nimport {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from '../validators';\n\nimport {NG_MODEL_WITH_FORM_CONTROL_WARNING} from './form_control_directive';\nimport {FormGroupDirective} from './form_group_directive';\nimport {FormArrayName, FormGroupName} from './form_group_name';\n\nconst controlNameBinding: Provider = {\n provide: NgControl,\n useExisting: forwardRef(() => FormControlName)\n};\n\n/**\n * @description\n * Syncs a `FormControl` in an existing `FormGroup` to a form control\n * element by name.\n *\n * @see [Reactive Forms Guide](guide/reactive-forms)\n * @see `FormControl`\n * @see `AbstractControl`\n *\n * @usageNotes\n *\n * ### Register `FormControl` within a group\n *\n * The following example shows how to register multiple form controls within a form group\n * and set their value.\n *\n * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}\n *\n * To see `formControlName` examples with different form control types, see:\n *\n * * Radio buttons: `RadioControlValueAccessor`\n * * Selects: `SelectControlValueAccessor`\n *\n * ### Use with ngModel is deprecated\n *\n * Support for using the `ngModel` input property and `ngModelChange` event with reactive\n * form directives has been deprecated in Angular v6 and is scheduled for removal in\n * a future version of Angular.\n *\n * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms).\n *\n * @ngModule ReactiveFormsModule\n * @publicApi\n */\n@Directive({selector: '[formControlName]', providers: [controlNameBinding]})\nexport class FormControlName extends NgControl implements OnChanges, OnDestroy {\n private _added = false;\n /**\n * Internal reference to the view model value.\n * @internal\n */\n viewModel: any;\n\n /**\n * @description\n * Tracks the `FormControl` instance bound to the directive.\n */\n // TODO(issue/24571): remove '!'.\n override readonly control!: FormControl;\n\n /**\n * @description\n * Tracks the name of the `FormControl` bound to the directive. The name corresponds\n * to a key in the parent `FormGroup` or `FormArray`.\n * Accepts a name as a string or a number.\n * The name in the form of a string is useful for individual forms,\n * while the numerical form allows for form controls to be bound\n * to indices when iterating over controls in a `FormArray`.\n */\n // TODO(issue/24571): remove '!'.\n @Input('formControlName') override name!: string|number|null;\n\n /**\n * @description\n * Triggers a warning in dev mode that this input should not be used with reactive forms.\n */\n @Input('disabled')\n set isDisabled(isDisabled: boolean) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n console.warn(disabledAttrWarning);\n }\n }\n\n // TODO(kara): remove next 4 properties once deprecation period is over\n\n /** @deprecated as of v6 */\n @Input('ngModel') model: any;\n\n /** @deprecated as of v6 */\n @Output('ngModelChange') update = new EventEmitter();\n\n /**\n * @description\n * Static property used to track whether any ngModel warnings have been sent across\n * all instances of FormControlName. Used to support warning config of \"once\".\n *\n * @internal\n */\n static _ngModelWarningSentOnce = false;\n\n /**\n * @description\n * Instance property used to track whether an ngModel warning has been sent out for this\n * particular FormControlName instance. Used to support warning config of \"always\".\n *\n * @internal\n */\n _ngModelWarningSent = false;\n\n constructor(\n @Optional() @Host() @SkipSelf() parent: ControlContainer,\n @Optional() @Self() @Inject(NG_VALIDATORS) validators: (Validator|ValidatorFn)[],\n @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:\n (AsyncValidator|AsyncValidatorFn)[],\n @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[],\n @Optional() @Inject(NG_MODEL_WITH_FORM_CONTROL_WARNING) private _ngModelWarningConfig: string|\n null) {\n super();\n this._parent = parent;\n this._setValidators(validators);\n this._setAsyncValidators(asyncValidators);\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges) {\n if (!this._added) this._setUpControl();\n if (isPropertyUpdated(changes, this.viewModel)) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n _ngModelWarning('formControlName', FormControlName, this, this._ngModelWarningConfig);\n }\n this.viewModel = this.model;\n this.formDirective.updateModel(this, this.model);\n }\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n if (this.formDirective) {\n this.formDirective.removeControl(this);\n }\n }\n\n /**\n * @description\n * Sets the new value for the view model and emits an `ngModelChange` event.\n *\n * @param newValue The new value for the view model.\n */\n override viewToModelUpdate(newValue: any): void {\n this.viewModel = newValue;\n this.update.emit(newValue);\n }\n\n /**\n * @description\n * Returns an array that represents the path from the top-level form to this control.\n * Each index is the string name of the control on that level.\n */\n override get path(): string[] {\n return controlPath(this.name == null ? this.name : this.name.toString(), this._parent!);\n }\n\n /**\n * @description\n * The top-level directive for this group if present, otherwise null.\n */\n get formDirective(): any {\n return this._parent ? this._parent.formDirective : null;\n }\n\n private _checkParentType(): void {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!(this._parent instanceof FormGroupName) &&\n this._parent instanceof AbstractFormGroupDirective) {\n throw ngModelGroupException();\n } else if (\n !(this._parent instanceof FormGroupName) &&\n !(this._parent instanceof FormGroupDirective) &&\n !(this._parent instanceof FormArrayName)) {\n throw controlParentException();\n }\n }\n }\n\n private _setUpControl() {\n this._checkParentType();\n (this as {control: FormControl}).control = this.formDirective.addControl(this);\n this._added = true;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, forwardRef, Input, OnChanges, Provider, SimpleChanges, ɵcoerceToBoolean as coerceToBoolean} from '@angular/core';\nimport {Observable} from 'rxjs';\n\nimport {AbstractControl} from '../model/abstract_model';\nimport {emailValidator, maxLengthValidator, maxValidator, minLengthValidator, minValidator, NG_VALIDATORS, nullValidator, patternValidator, requiredTrueValidator, requiredValidator} from '../validators';\n\n/**\n * Method that updates string to integer if not already a number\n *\n * @param value The value to convert to integer.\n * @returns value of parameter converted to number or integer.\n */\nfunction toInteger(value: string|number): number {\n return typeof value === 'number' ? value : parseInt(value, 10);\n}\n\n/**\n * Method that ensures that provided value is a float (and converts it to float if needed).\n *\n * @param value The value to convert to float.\n * @returns value of parameter converted to number or float.\n */\nfunction toFloat(value: string|number): number {\n return typeof value === 'number' ? value : parseFloat(value);\n}\n\n/**\n * @description\n * Defines the map of errors returned from failed validation checks.\n *\n * @publicApi\n */\nexport type ValidationErrors = {\n [key: string]: any\n};\n\n/**\n * @description\n * An interface implemented by classes that perform synchronous validation.\n *\n * @usageNotes\n *\n * ### Provide a custom validator\n *\n * The following example implements the `Validator` interface to create a\n * validator directive with a custom error key.\n *\n * ```typescript\n * @Directive({\n * selector: '[customValidator]',\n * providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}]\n * })\n * class CustomValidatorDirective implements Validator {\n * validate(control: AbstractControl): ValidationErrors|null {\n * return {'custom': true};\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport interface Validator {\n /**\n * @description\n * Method that performs synchronous validation against the provided control.\n *\n * @param control The control to validate against.\n *\n * @returns A map of validation errors if validation fails,\n * otherwise null.\n */\n validate(control: AbstractControl): ValidationErrors|null;\n\n /**\n * @description\n * Registers a callback function to call when the validator inputs change.\n *\n * @param fn The callback function\n */\n registerOnValidatorChange?(fn: () => void): void;\n}\n\n/**\n * A base class for Validator-based Directives. The class contains common logic shared across such\n * Directives.\n *\n * For internal use only, this class is not intended for use outside of the Forms package.\n */\n@Directive()\nabstract class AbstractValidatorDirective implements Validator, OnChanges {\n private _validator: ValidatorFn = nullValidator;\n private _onChange!: () => void;\n\n /**\n * A flag that tracks whether this validator is enabled.\n *\n * Marking it `internal` (vs `protected`), so that this flag can be used in host bindings of\n * directive classes that extend this base class.\n * @internal\n */\n _enabled?: boolean;\n\n /**\n * Name of an input that matches directive selector attribute (e.g. `minlength` for\n * `MinLengthDirective`). An input with a given name might contain configuration information (like\n * `minlength='10'`) or a flag that indicates whether validator should be enabled (like\n * `[required]='false'`).\n *\n * @internal\n */\n abstract inputName: string;\n\n /**\n * Creates an instance of a validator (specific to a directive that extends this base class).\n *\n * @internal\n */\n abstract createValidator(input: unknown): ValidatorFn;\n\n /**\n * Performs the necessary input normalization based on a specific logic of a Directive.\n * For example, the function might be used to convert string-based representation of the\n * `minlength` input to an integer value that can later be used in the `Validators.minLength`\n * validator.\n *\n * @internal\n */\n abstract normalizeInput(input: unknown): unknown;\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges): void {\n if (this.inputName in changes) {\n const input = this.normalizeInput(changes[this.inputName].currentValue);\n this._enabled = this.enabled(input);\n this._validator = this._enabled ? this.createValidator(input) : nullValidator;\n if (this._onChange) {\n this._onChange();\n }\n }\n }\n\n /** @nodoc */\n validate(control: AbstractControl): ValidationErrors|null {\n return this._validator(control);\n }\n\n /** @nodoc */\n registerOnValidatorChange(fn: () => void): void {\n this._onChange = fn;\n }\n\n /**\n * @description\n * Determines whether this validator should be active or not based on an input.\n * Base class implementation checks whether an input is defined (if the value is different from\n * `null` and `undefined`). Validator classes that extend this base class can override this\n * function with the logic specific to a particular validator directive.\n */\n enabled(input: unknown): boolean {\n return input != null /* both `null` and `undefined` */;\n }\n}\n\n/**\n * @description\n * Provider which adds `MaxValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const MAX_VALIDATOR: Provider = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => MaxValidator),\n multi: true\n};\n\n/**\n * A directive which installs the {@link MaxValidator} for any `formControlName`,\n * `formControl`, or control with `ngModel` that also has a `max` attribute.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a max validator\n *\n * The following example shows how to add a max validator to an input attached to an\n * ngModel binding.\n *\n * ```html\n * <input type=\"number\" ngModel max=\"4\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n 'input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]',\n providers: [MAX_VALIDATOR],\n host: {'[attr.max]': '_enabled ? max : null'}\n})\nexport class MaxValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the max bound to this directive.\n */\n @Input() max!: string|number|null;\n /** @internal */\n override inputName = 'max';\n /** @internal */\n override normalizeInput = (input: string|number): number => toFloat(input);\n /** @internal */\n override createValidator = (max: number): ValidatorFn => maxValidator(max);\n}\n\n/**\n * @description\n * Provider which adds `MinValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const MIN_VALIDATOR: Provider = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => MinValidator),\n multi: true\n};\n\n/**\n * A directive which installs the {@link MinValidator} for any `formControlName`,\n * `formControl`, or control with `ngModel` that also has a `min` attribute.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a min validator\n *\n * The following example shows how to add a min validator to an input attached to an\n * ngModel binding.\n *\n * ```html\n * <input type=\"number\" ngModel min=\"4\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector:\n 'input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]',\n providers: [MIN_VALIDATOR],\n host: {'[attr.min]': '_enabled ? min : null'}\n})\nexport class MinValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the min bound to this directive.\n */\n @Input() min!: string|number|null;\n /** @internal */\n override inputName = 'min';\n /** @internal */\n override normalizeInput = (input: string|number): number => toFloat(input);\n /** @internal */\n override createValidator = (min: number): ValidatorFn => minValidator(min);\n}\n\n/**\n * @description\n * An interface implemented by classes that perform asynchronous validation.\n *\n * @usageNotes\n *\n * ### Provide a custom async validator directive\n *\n * The following example implements the `AsyncValidator` interface to create an\n * async validator directive with a custom error key.\n *\n * ```typescript\n * import { of } from 'rxjs';\n *\n * @Directive({\n * selector: '[customAsyncValidator]',\n * providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi:\n * true}]\n * })\n * class CustomAsyncValidatorDirective implements AsyncValidator {\n * validate(control: AbstractControl): Observable<ValidationErrors|null> {\n * return of({'custom': true});\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport interface AsyncValidator extends Validator {\n /**\n * @description\n * Method that performs async validation against the provided control.\n *\n * @param control The control to validate against.\n *\n * @returns A promise or observable that resolves a map of validation errors\n * if validation fails, otherwise null.\n */\n validate(control: AbstractControl):\n Promise<ValidationErrors|null>|Observable<ValidationErrors|null>;\n}\n\n/**\n * @description\n * Provider which adds `RequiredValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const REQUIRED_VALIDATOR: Provider = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => RequiredValidator),\n multi: true\n};\n\n/**\n * @description\n * Provider which adds `CheckboxRequiredValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const CHECKBOX_REQUIRED_VALIDATOR: Provider = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => CheckboxRequiredValidator),\n multi: true\n};\n\n\n/**\n * @description\n * A directive that adds the `required` validator to any controls marked with the\n * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a required validator using template-driven forms\n *\n * ```\n * <input name=\"fullName\" ngModel required>\n * ```\n *\n * @ngModule FormsModule\n * @ngModule ReactiveFormsModule\n * @publicApi\n */\n@Directive({\n selector:\n ':not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]',\n providers: [REQUIRED_VALIDATOR],\n host: {'[attr.required]': '_enabled ? \"\" : null'}\n})\nexport class RequiredValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the required attribute bound to this directive.\n */\n @Input() required!: boolean|string;\n\n /** @internal */\n override inputName = 'required';\n\n /** @internal */\n override normalizeInput = coerceToBoolean;\n\n /** @internal */\n override createValidator = (input: boolean): ValidatorFn => requiredValidator;\n\n /** @nodoc */\n override enabled(input: boolean): boolean {\n return input;\n }\n}\n\n\n/**\n * A Directive that adds the `required` validator to checkbox controls marked with the\n * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a required checkbox validator using template-driven forms\n *\n * The following example shows how to add a checkbox required validator to an input attached to an\n * ngModel binding.\n *\n * ```\n * <input type=\"checkbox\" name=\"active\" ngModel required>\n * ```\n *\n * @publicApi\n * @ngModule FormsModule\n * @ngModule ReactiveFormsModule\n */\n@Directive({\n selector:\n 'input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]',\n providers: [CHECKBOX_REQUIRED_VALIDATOR],\n host: {'[attr.required]': '_enabled ? \"\" : null'}\n})\nexport class CheckboxRequiredValidator extends RequiredValidator {\n /** @internal */\n override createValidator = (input: unknown): ValidatorFn => requiredTrueValidator;\n}\n\n/**\n * @description\n * Provider which adds `EmailValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const EMAIL_VALIDATOR: any = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => EmailValidator),\n multi: true\n};\n\n/**\n * A directive that adds the `email` validator to controls marked with the\n * `email` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * The email validation is based on the WHATWG HTML specification with some enhancements to\n * incorporate more RFC rules. More information can be found on the [Validators.email\n * page](api/forms/Validators#email).\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding an email validator\n *\n * The following example shows how to add an email validator to an input attached to an ngModel\n * binding.\n *\n * ```\n * <input type=\"email\" name=\"email\" ngModel email>\n * <input type=\"email\" name=\"email\" ngModel email=\"true\">\n * <input type=\"email\" name=\"email\" ngModel [email]=\"true\">\n * ```\n *\n * @publicApi\n * @ngModule FormsModule\n * @ngModule ReactiveFormsModule\n */\n@Directive({\n selector: '[email][formControlName],[email][formControl],[email][ngModel]',\n providers: [EMAIL_VALIDATOR]\n})\nexport class EmailValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the email attribute bound to this directive.\n */\n @Input() email!: boolean|string;\n\n /** @internal */\n override inputName = 'email';\n\n /** @internal */\n override normalizeInput = coerceToBoolean;\n\n /** @internal */\n override createValidator = (input: number): ValidatorFn => emailValidator;\n\n /** @nodoc */\n override enabled(input: boolean): boolean {\n return input;\n }\n}\n\n/**\n * @description\n * A function that receives a control and synchronously returns a map of\n * validation errors if present, otherwise null.\n *\n * @publicApi\n */\nexport interface ValidatorFn {\n (control: AbstractControl): ValidationErrors|null;\n}\n\n/**\n * @description\n * A function that receives a control and returns a Promise or observable\n * that emits validation errors if present, otherwise null.\n *\n * @publicApi\n */\nexport interface AsyncValidatorFn {\n (control: AbstractControl): Promise<ValidationErrors|null>|Observable<ValidationErrors|null>;\n}\n\n/**\n * @description\n * Provider which adds `MinLengthValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const MIN_LENGTH_VALIDATOR: any = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => MinLengthValidator),\n multi: true\n};\n\n/**\n * A directive that adds minimum length validation to controls marked with the\n * `minlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a minimum length validator\n *\n * The following example shows how to add a minimum length validator to an input attached to an\n * ngModel binding.\n *\n * ```html\n * <input name=\"firstName\" ngModel minlength=\"4\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',\n providers: [MIN_LENGTH_VALIDATOR],\n host: {'[attr.minlength]': '_enabled ? minlength : null'}\n})\nexport class MinLengthValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the minimum length bound to this directive.\n */\n @Input() minlength!: string|number|null;\n\n /** @internal */\n override inputName = 'minlength';\n\n /** @internal */\n override normalizeInput = (input: string|number): number => toInteger(input);\n\n /** @internal */\n override createValidator = (minlength: number): ValidatorFn => minLengthValidator(minlength);\n}\n\n/**\n * @description\n * Provider which adds `MaxLengthValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const MAX_LENGTH_VALIDATOR: any = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => MaxLengthValidator),\n multi: true\n};\n\n/**\n * A directive that adds max length validation to controls marked with the\n * `maxlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a maximum length validator\n *\n * The following example shows how to add a maximum length validator to an input attached to an\n * ngModel binding.\n *\n * ```html\n * <input name=\"firstName\" ngModel maxlength=\"25\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector: '[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]',\n providers: [MAX_LENGTH_VALIDATOR],\n host: {'[attr.maxlength]': '_enabled ? maxlength : null'}\n})\nexport class MaxLengthValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the minimum length bound to this directive.\n */\n @Input() maxlength!: string|number|null;\n\n /** @internal */\n override inputName = 'maxlength';\n\n /** @internal */\n override normalizeInput = (input: string|number): number => toInteger(input);\n\n /** @internal */\n override createValidator = (maxlength: number): ValidatorFn => maxLengthValidator(maxlength);\n}\n\n/**\n * @description\n * Provider which adds `PatternValidator` to the `NG_VALIDATORS` multi-provider list.\n */\nexport const PATTERN_VALIDATOR: any = {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => PatternValidator),\n multi: true\n};\n\n\n/**\n * @description\n * A directive that adds regex pattern validation to controls marked with the\n * `pattern` attribute. The regex must match the entire control value.\n * The directive is provided with the `NG_VALIDATORS` multi-provider list.\n *\n * @see [Form Validation](guide/form-validation)\n *\n * @usageNotes\n *\n * ### Adding a pattern validator\n *\n * The following example shows how to add a pattern validator to an input attached to an\n * ngModel binding.\n *\n * ```html\n * <input name=\"firstName\" ngModel pattern=\"[a-zA-Z ]*\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n selector: '[pattern][formControlName],[pattern][formControl],[pattern][ngModel]',\n providers: [PATTERN_VALIDATOR],\n host: {'[attr.pattern]': '_enabled ? pattern : null'}\n})\nexport class PatternValidator extends AbstractValidatorDirective {\n /**\n * @description\n * Tracks changes to the pattern bound to this directive.\n */\n @Input()\n pattern!: string|RegExp; // This input is always defined, since the name matches selector.\n\n /** @internal */\n override inputName = 'pattern';\n\n /** @internal */\n override normalizeInput = (input: string|RegExp): string|RegExp => input;\n\n /** @internal */\n override createValidator = (input: string|RegExp): ValidatorFn => patternValidator(input);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule, Type} from '@angular/core';\n\nimport {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';\nimport {DefaultValueAccessor} from './directives/default_value_accessor';\nimport {NgControlStatus, NgControlStatusGroup} from './directives/ng_control_status';\nimport {NgForm} from './directives/ng_form';\nimport {NgModel} from './directives/ng_model';\nimport {NgModelGroup} from './directives/ng_model_group';\nimport {NgNoValidate} from './directives/ng_no_validate_directive';\nimport {NumberValueAccessor} from './directives/number_value_accessor';\nimport {RadioControlRegistryModule, RadioControlValueAccessor} from './directives/radio_control_value_accessor';\nimport {RangeValueAccessor} from './directives/range_value_accessor';\nimport {FormControlDirective} from './directives/reactive_directives/form_control_directive';\nimport {FormControlName} from './directives/reactive_directives/form_control_name';\nimport {FormGroupDirective} from './directives/reactive_directives/form_group_directive';\nimport {FormArrayName, FormGroupName} from './directives/reactive_directives/form_group_name';\nimport {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';\nimport {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';\nimport {CheckboxRequiredValidator, EmailValidator, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, PatternValidator, RequiredValidator} from './directives/validators';\n\nexport {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';\nexport {ControlValueAccessor} from './directives/control_value_accessor';\nexport {DefaultValueAccessor} from './directives/default_value_accessor';\nexport {NgControl} from './directives/ng_control';\nexport {NgControlStatus, NgControlStatusGroup} from './directives/ng_control_status';\nexport {NgForm} from './directives/ng_form';\nexport {NgModel} from './directives/ng_model';\nexport {NgModelGroup} from './directives/ng_model_group';\nexport {NumberValueAccessor} from './directives/number_value_accessor';\nexport {RadioControlValueAccessor} from './directives/radio_control_value_accessor';\nexport {RangeValueAccessor} from './directives/range_value_accessor';\nexport {FormControlDirective, NG_MODEL_WITH_FORM_CONTROL_WARNING} from './directives/reactive_directives/form_control_directive';\nexport {FormControlName} from './directives/reactive_directives/form_control_name';\nexport {FormGroupDirective} from './directives/reactive_directives/form_group_directive';\nexport {FormArrayName, FormGroupName} from './directives/reactive_directives/form_group_name';\nexport {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';\nexport {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';\nexport {CALL_SET_DISABLED_STATE} from './directives/shared';\n\nexport const SHARED_FORM_DIRECTIVES: Type<any>[] = [\n NgNoValidate,\n NgSelectOption,\n NgSelectMultipleOption,\n DefaultValueAccessor,\n NumberValueAccessor,\n RangeValueAccessor,\n CheckboxControlValueAccessor,\n SelectControlValueAccessor,\n SelectMultipleControlValueAccessor,\n RadioControlValueAccessor,\n NgControlStatus,\n NgControlStatusGroup,\n RequiredValidator,\n MinLengthValidator,\n MaxLengthValidator,\n PatternValidator,\n CheckboxRequiredValidator,\n EmailValidator,\n MinValidator,\n MaxValidator,\n];\n\nexport const TEMPLATE_DRIVEN_DIRECTIVES: Type<any>[] = [NgModel, NgModelGroup, NgForm];\n\nexport const REACTIVE_DRIVEN_DIRECTIVES: Type<any>[] =\n [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName];\n\n/**\n * Internal module used for sharing directives between FormsModule and ReactiveFormsModule\n */\n@NgModule({\n declarations: SHARED_FORM_DIRECTIVES,\n imports: [RadioControlRegistryModule],\n exports: SHARED_FORM_DIRECTIVES,\n})\nexport class ɵInternalFormsSharedModule {\n}\n\nexport {ɵInternalFormsSharedModule as InternalFormsSharedModule};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ModuleWithProviders, NgModule} from '@angular/core';\n\nimport {InternalFormsSharedModule, NG_MODEL_WITH_FORM_CONTROL_WARNING, REACTIVE_DRIVEN_DIRECTIVES, TEMPLATE_DRIVEN_DIRECTIVES} from './directives';\nimport {CALL_SET_DISABLED_STATE, setDisabledStateDefault, SetDisabledStateOption} from './directives/shared';\n\n/**\n * Exports the required providers and directives for template-driven forms,\n * making them available for import by NgModules that import this module.\n *\n * Providers associated with this module:\n * * `RadioControlRegistry`\n *\n * @see [Forms Overview](/guide/forms-overview)\n * @see [Template-driven Forms Guide](/guide/forms)\n *\n * @publicApi\n */\n@NgModule({\n declarations: TEMPLATE_DRIVEN_DIRECTIVES,\n exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]\n})\nexport class FormsModule {\n /**\n * @description\n * Provides options for configuring the forms module.\n *\n * @param opts An object of configuration options\n * * `callSetDisabledState` Configures whether to `always` call `setDisabledState`, which is more\n * correct, or to only call it `whenDisabled`, which is the legacy behavior.\n */\n static withConfig(opts: {\n callSetDisabledState?: SetDisabledStateOption,\n }): ModuleWithProviders<FormsModule> {\n return {\n ngModule: FormsModule,\n providers: [{\n provide: CALL_SET_DISABLED_STATE,\n useValue: opts.callSetDisabledState ?? setDisabledStateDefault\n }]\n };\n }\n}\n\n/**\n * Exports the required infrastructure and directives for reactive forms,\n * making them available for import by NgModules that import this module.\n *\n * Providers associated with this module:\n * * `FormBuilder`\n * * `RadioControlRegistry`\n *\n * @see [Forms Overview](guide/forms-overview)\n * @see [Reactive Forms Guide](guide/reactive-forms)\n *\n * @publicApi\n */\n@NgModule({\n declarations: [REACTIVE_DRIVEN_DIRECTIVES],\n exports: [InternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES]\n})\nexport class ReactiveFormsModule {\n /**\n * @description\n * Provides options for configuring the reactive forms module.\n *\n * @param opts An object of configuration options\n * * `warnOnNgModelWithFormControl` Configures when to emit a warning when an `ngModel`\n * binding is used with reactive form directives.\n * * `callSetDisabledState` Configures whether to `always` call `setDisabledState`, which is more\n * correct, or to only call it `whenDisabled`, which is the legacy behavior.\n */\n static withConfig(opts: {\n /** @deprecated as of v6 */ warnOnNgModelWithFormControl?: 'never'|'once'|\n 'always',\n callSetDisabledState?: SetDisabledStateOption,\n }): ModuleWithProviders<ReactiveFormsModule> {\n return {\n ngModule: ReactiveFormsModule,\n providers: [\n {\n provide: NG_MODEL_WITH_FORM_CONTROL_WARNING,\n useValue: opts.warnOnNgModelWithFormControl ?? 'always'\n },\n {\n provide: CALL_SET_DISABLED_STATE,\n useValue: opts.callSetDisabledState ?? setDisabledStateDefault\n }\n ]\n };\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {HighContrastModeDetector} from '@angular/cdk/a11y';\nimport {BidiModule} from '@angular/cdk/bidi';\nimport {inject, Inject, InjectionToken, NgModule, Optional} from '@angular/core';\nimport {VERSION as CDK_VERSION} from '@angular/cdk';\nimport {DOCUMENT} from '@angular/common';\nimport {Platform, _isTestEnvironment} from '@angular/cdk/platform';\nimport {VERSION} from '../version';\n\n/** @docs-private */\nexport function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {\n return true;\n}\n\n/** Injection token that configures whether the Material sanity checks are enabled. */\nexport const MATERIAL_SANITY_CHECKS = new InjectionToken<SanityChecks>('mat-sanity-checks', {\n providedIn: 'root',\n factory: MATERIAL_SANITY_CHECKS_FACTORY,\n});\n\n/**\n * Possible sanity checks that can be enabled. If set to\n * true/false, all checks will be enabled/disabled.\n */\nexport type SanityChecks = boolean | GranularSanityChecks;\n\n/** Object that can be used to configure the sanity checks granularly. */\nexport interface GranularSanityChecks {\n doctype: boolean;\n theme: boolean;\n version: boolean;\n}\n\n/**\n * Module that captures anything that should be loaded and/or run for *all* Angular Material\n * components. This includes Bidi, etc.\n *\n * This module should be imported to each top-level component module (e.g., MatTabsModule).\n */\n@NgModule({\n imports: [BidiModule],\n exports: [BidiModule],\n})\nexport class MatCommonModule {\n /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */\n private _hasDoneGlobalChecks = false;\n\n constructor(\n highContrastModeDetector: HighContrastModeDetector,\n @Optional() @Inject(MATERIAL_SANITY_CHECKS) private _sanityChecks: SanityChecks,\n @Inject(DOCUMENT) private _document: Document,\n ) {\n // While A11yModule also does this, we repeat it here to avoid importing A11yModule\n // in MatCommonModule.\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\n\n if (!this._hasDoneGlobalChecks) {\n this._hasDoneGlobalChecks = true;\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n // Inject in here so the reference to `Platform` can be removed in production mode.\n const platform = inject(Platform, {optional: true});\n\n if (this._checkIsEnabled('doctype')) {\n _checkDoctypeIsDefined(this._document);\n }\n\n if (this._checkIsEnabled('theme')) {\n _checkThemeIsPresent(this._document, !!platform?.isBrowser);\n }\n\n if (this._checkIsEnabled('version')) {\n _checkCdkVersionMatch();\n }\n }\n }\n }\n\n /** Gets whether a specific sanity check is enabled. */\n private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {\n if (_isTestEnvironment()) {\n return false;\n }\n\n if (typeof this._sanityChecks === 'boolean') {\n return this._sanityChecks;\n }\n\n return !!this._sanityChecks[name];\n }\n}\n\n/** Checks that the page has a doctype. */\nfunction _checkDoctypeIsDefined(doc: Document): void {\n if (!doc.doctype) {\n console.warn(\n 'Current document does not have a doctype. This may cause ' +\n 'some Angular Material components not to behave as expected.',\n );\n }\n}\n\n/** Checks that a theme has been included. */\nfunction _checkThemeIsPresent(doc: Document, isBrowser: boolean): void {\n // We need to assert that the `body` is defined, because these checks run very early\n // and the `body` won't be defined if the consumer put their scripts in the `head`.\n if (!doc.body || !isBrowser) {\n return;\n }\n\n const testElement = doc.createElement('div');\n testElement.classList.add('mat-theme-loaded-marker');\n doc.body.appendChild(testElement);\n\n const computedStyle = getComputedStyle(testElement);\n\n // In some situations the computed style of the test element can be null. For example in\n // Firefox, the computed style is null if an application is running inside of a hidden iframe.\n // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n if (computedStyle && computedStyle.display !== 'none') {\n console.warn(\n 'Could not find Angular Material core theme. Most Material ' +\n 'components may not work as expected. For more info refer ' +\n 'to the theming guide: https://material.angular.io/guide/theming',\n );\n }\n\n testElement.remove();\n}\n\n/** Checks whether the Material version matches the CDK version. */\nfunction _checkCdkVersionMatch(): void {\n if (VERSION.full !== CDK_VERSION.full) {\n console.warn(\n 'The Angular Material version (' +\n VERSION.full +\n ') does not match ' +\n 'the Angular CDK version (' +\n CDK_VERSION.full +\n ').\\n' +\n 'Please ensure the versions of these two packages exactly match.',\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {AbstractConstructor, Constructor} from './constructor';\n\n/** @docs-private */\nexport interface CanDisable {\n /** Whether the component is disabled. */\n disabled: boolean;\n}\n\ntype CanDisableCtor = Constructor<CanDisable> & AbstractConstructor<CanDisable>;\n\n/** Mixin to augment a directive with a `disabled` property. */\nexport function mixinDisabled<T extends AbstractConstructor<{}>>(base: T): CanDisableCtor & T;\nexport function mixinDisabled<T extends Constructor<{}>>(base: T): CanDisableCtor & T {\n return class extends base {\n private _disabled: boolean = false;\n\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(value: any) {\n this._disabled = coerceBooleanProperty(value);\n }\n\n constructor(...args: any[]) {\n super(...args);\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AbstractConstructor, Constructor} from './constructor';\nimport {ElementRef} from '@angular/core';\n\n/** @docs-private */\nexport interface CanColor {\n /** Theme color palette for the component. */\n color: ThemePalette;\n\n /** Default color to fall back to if no value is set. */\n defaultColor: ThemePalette | undefined;\n}\n\ntype CanColorCtor = Constructor<CanColor> & AbstractConstructor<CanColor>;\n\n/** @docs-private */\nexport interface HasElementRef {\n _elementRef: ElementRef;\n}\n\n/** Possible color palette values. */\nexport type ThemePalette = 'primary' | 'accent' | 'warn' | undefined;\n\n/** Mixin to augment a directive with a `color` property. */\nexport function mixinColor<T extends AbstractConstructor<HasElementRef>>(\n base: T,\n defaultColor?: ThemePalette,\n): CanColorCtor & T;\nexport function mixinColor<T extends Constructor<HasElementRef>>(\n base: T,\n defaultColor?: ThemePalette,\n): CanColorCtor & T {\n return class extends base {\n private _color: ThemePalette;\n defaultColor = defaultColor;\n\n get color(): ThemePalette {\n return this._color;\n }\n set color(value: ThemePalette) {\n const colorPalette = value || this.defaultColor;\n\n if (colorPalette !== this._color) {\n if (this._color) {\n this._elementRef.nativeElement.classList.remove(`mat-${this._color}`);\n }\n if (colorPalette) {\n this._elementRef.nativeElement.classList.add(`mat-${colorPalette}`);\n }\n\n this._color = colorPalette;\n }\n }\n\n constructor(...args: any[]) {\n super(...args);\n\n // Set the default color that can be specified from the mixin.\n this.color = defaultColor;\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {AbstractConstructor, Constructor} from './constructor';\n\n/** @docs-private */\nexport interface CanDisableRipple {\n /** Whether ripples are disabled. */\n disableRipple: boolean;\n}\n\ntype CanDisableRippleCtor = Constructor<CanDisableRipple> & AbstractConstructor<CanDisableRipple>;\n\n/** Mixin to augment a directive with a `disableRipple` property. */\nexport function mixinDisableRipple<T extends AbstractConstructor<{}>>(\n base: T,\n): CanDisableRippleCtor & T;\nexport function mixinDisableRipple<T extends Constructor<{}>>(base: T): CanDisableRippleCtor & T {\n return class extends base {\n private _disableRipple: boolean = false;\n\n /** Whether the ripple effect is disabled or not. */\n get disableRipple(): boolean {\n return this._disableRipple;\n }\n set disableRipple(value: any) {\n this._disableRipple = coerceBooleanProperty(value);\n }\n\n constructor(...args: any[]) {\n super(...args);\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceNumberProperty} from '@angular/cdk/coercion';\nimport {Constructor, AbstractConstructor} from './constructor';\nimport {CanDisable} from './disabled';\n\n/** @docs-private */\nexport interface HasTabIndex {\n /** Tabindex of the component. */\n tabIndex: number;\n\n /** Tabindex to which to fall back to if no value is set. */\n defaultTabIndex: number;\n}\n\ntype HasTabIndexCtor = Constructor<HasTabIndex> & AbstractConstructor<HasTabIndex>;\n\n/** Mixin to augment a directive with a `tabIndex` property. */\nexport function mixinTabIndex<T extends AbstractConstructor<CanDisable>>(\n base: T,\n defaultTabIndex?: number,\n): HasTabIndexCtor & T;\nexport function mixinTabIndex<T extends Constructor<CanDisable>>(\n base: T,\n defaultTabIndex = 0,\n): HasTabIndexCtor & T {\n return class extends base implements HasTabIndex {\n private _tabIndex: number = defaultTabIndex;\n defaultTabIndex = defaultTabIndex;\n\n get tabIndex(): number {\n return this.disabled ? -1 : this._tabIndex;\n }\n set tabIndex(value: number) {\n // If the specified tabIndex value is null or undefined, fall back to the default value.\n this._tabIndex = value != null ? coerceNumberProperty(value) : this.defaultTabIndex;\n }\n\n constructor(...args: any[]) {\n super(...args);\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Possible states for a ripple element. */\nexport const enum RippleState {\n FADING_IN,\n VISIBLE,\n FADING_OUT,\n HIDDEN,\n}\n\nexport type RippleConfig = {\n color?: string;\n centered?: boolean;\n radius?: number;\n persistent?: boolean;\n animation?: RippleAnimationConfig;\n terminateOnPointerUp?: boolean;\n};\n\n/**\n * Interface that describes the configuration for the animation of a ripple.\n * There are two animation phases with different durations for the ripples.\n */\nexport interface RippleAnimationConfig {\n /** Duration in milliseconds for the enter animation (expansion from point of contact). */\n enterDuration?: number;\n /** Duration in milliseconds for the exit animation (fade-out). */\n exitDuration?: number;\n}\n\n/**\n * Reference to a previously launched ripple element.\n */\nexport class RippleRef {\n /** Current state of the ripple. */\n state: RippleState = RippleState.HIDDEN;\n\n constructor(\n private _renderer: {fadeOutRipple(ref: RippleRef): void},\n /** Reference to the ripple HTML element. */\n public element: HTMLElement,\n /** Ripple configuration used for the ripple. */\n public config: RippleConfig,\n /* Whether animations are forcibly disabled for ripples through CSS. */\n public _animationForciblyDisabledThroughCss = false,\n ) {}\n\n /** Fades out the ripple element. */\n fadeOut() {\n this._renderer.fadeOutRipple(this);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {normalizePassiveListenerOptions, _getEventTarget} from '@angular/cdk/platform';\nimport {NgZone} from '@angular/core';\n\n/** Options used to bind a passive capturing event. */\nconst passiveCapturingEventOptions = normalizePassiveListenerOptions({\n passive: true,\n capture: true,\n});\n\n/** Manages events through delegation so that as few event handlers as possible are bound. */\nexport class RippleEventManager {\n private _events = new Map<string, Map<HTMLElement, Set<EventListenerObject>>>();\n\n /** Adds an event handler. */\n addHandler(ngZone: NgZone, name: string, element: HTMLElement, handler: EventListenerObject) {\n const handlersForEvent = this._events.get(name);\n\n if (handlersForEvent) {\n const handlersForElement = handlersForEvent.get(element);\n\n if (handlersForElement) {\n handlersForElement.add(handler);\n } else {\n handlersForEvent.set(element, new Set([handler]));\n }\n } else {\n this._events.set(name, new Map([[element, new Set([handler])]]));\n\n ngZone.runOutsideAngular(() => {\n document.addEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions);\n });\n }\n }\n\n /** Removes an event handler. */\n removeHandler(name: string, element: HTMLElement, handler: EventListenerObject) {\n const handlersForEvent = this._events.get(name);\n\n if (!handlersForEvent) {\n return;\n }\n\n const handlersForElement = handlersForEvent.get(element);\n\n if (!handlersForElement) {\n return;\n }\n\n handlersForElement.delete(handler);\n\n if (handlersForElement.size === 0) {\n handlersForEvent.delete(element);\n }\n\n if (handlersForEvent.size === 0) {\n this._events.delete(name);\n document.removeEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions);\n }\n }\n\n /** Event handler that is bound and which dispatches the events to the different targets. */\n private _delegateEventHandler = (event: Event) => {\n const target = _getEventTarget(event);\n\n if (target) {\n this._events.get(event.type)?.forEach((handlers, element) => {\n if (element === target || element.contains(target as Node)) {\n handlers.forEach(handler => handler.handleEvent(event));\n }\n });\n }\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {ElementRef, NgZone} from '@angular/core';\nimport {Platform, normalizePassiveListenerOptions, _getEventTarget} from '@angular/cdk/platform';\nimport {isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader} from '@angular/cdk/a11y';\nimport {coerceElement} from '@angular/cdk/coercion';\nimport {RippleRef, RippleState, RippleConfig} from './ripple-ref';\nimport {RippleEventManager} from './ripple-event-manager';\n\n/**\n * Interface that describes the target for launching ripples.\n * It defines the ripple configuration and disabled state for interaction ripples.\n * @docs-private\n */\nexport interface RippleTarget {\n /** Configuration for ripples that are launched on pointer down. */\n rippleConfig: RippleConfig;\n /** Whether ripples on pointer down should be disabled. */\n rippleDisabled: boolean;\n}\n\n/** Interfaces the defines ripple element transition event listeners. */\ninterface RippleEventListeners {\n onTransitionEnd: EventListener;\n onTransitionCancel: EventListener;\n}\n\n/**\n * Default ripple animation configuration for ripples without an explicit\n * animation config specified.\n */\nexport const defaultRippleAnimationConfig = {\n enterDuration: 225,\n exitDuration: 150,\n};\n\n/**\n * Timeout for ignoring mouse events. Mouse events will be temporary ignored after touch\n * events to avoid synthetic mouse events.\n */\nconst ignoreMouseEventsTimeout = 800;\n\n/** Options used to bind a passive capturing event. */\nconst passiveCapturingEventOptions = normalizePassiveListenerOptions({\n passive: true,\n capture: true,\n});\n\n/** Events that signal that the pointer is down. */\nconst pointerDownEvents = ['mousedown', 'touchstart'];\n\n/** Events that signal that the pointer is up. */\nconst pointerUpEvents = ['mouseup', 'mouseleave', 'touchend', 'touchcancel'];\n\n/**\n * Helper service that performs DOM manipulations. Not intended to be used outside this module.\n * The constructor takes a reference to the ripple directive's host element and a map of DOM\n * event handlers to be installed on the element that triggers ripple animations.\n * This will eventually become a custom renderer once Angular support exists.\n * @docs-private\n */\nexport class RippleRenderer implements EventListenerObject {\n /** Element where the ripples are being added to. */\n private _containerElement: HTMLElement;\n\n /** Element which triggers the ripple elements on mouse events. */\n private _triggerElement: HTMLElement | null;\n\n /** Whether the pointer is currently down or not. */\n private _isPointerDown = false;\n\n /**\n * Map of currently active ripple references.\n * The ripple reference is mapped to its element event listeners.\n * The reason why `| null` is used is that event listeners are added only\n * when the condition is truthy (see the `_startFadeOutTransition` method).\n */\n private _activeRipples = new Map<RippleRef, RippleEventListeners | null>();\n\n /** Latest non-persistent ripple that was triggered. */\n private _mostRecentTransientRipple: RippleRef | null;\n\n /** Time in milliseconds when the last touchstart event happened. */\n private _lastTouchStartEvent: number;\n\n /** Whether pointer-up event listeners have been registered. */\n private _pointerUpEventsRegistered = false;\n\n /**\n * Cached dimensions of the ripple container. Set when the first\n * ripple is shown and cleared once no more ripples are visible.\n */\n private _containerRect: ClientRect | null;\n\n private static _eventManager = new RippleEventManager();\n\n constructor(\n private _target: RippleTarget,\n private _ngZone: NgZone,\n elementOrElementRef: HTMLElement | ElementRef<HTMLElement>,\n private _platform: Platform,\n ) {\n // Only do anything if we're on the browser.\n if (_platform.isBrowser) {\n this._containerElement = coerceElement(elementOrElementRef);\n }\n }\n\n /**\n * Fades in a ripple at the given coordinates.\n * @param x Coordinate within the element, along the X axis at which to start the ripple.\n * @param y Coordinate within the element, along the Y axis at which to start the ripple.\n * @param config Extra ripple options.\n */\n fadeInRipple(x: number, y: number, config: RippleConfig = {}): RippleRef {\n const containerRect = (this._containerRect =\n this._containerRect || this._containerElement.getBoundingClientRect());\n const animationConfig = {...defaultRippleAnimationConfig, ...config.animation};\n\n if (config.centered) {\n x = containerRect.left + containerRect.width / 2;\n y = containerRect.top + containerRect.height / 2;\n }\n\n const radius = config.radius || distanceToFurthestCorner(x, y, containerRect);\n const offsetX = x - containerRect.left;\n const offsetY = y - containerRect.top;\n const enterDuration = animationConfig.enterDuration;\n\n const ripple = document.createElement('div');\n ripple.classList.add('mat-ripple-element');\n\n ripple.style.left = `${offsetX - radius}px`;\n ripple.style.top = `${offsetY - radius}px`;\n ripple.style.height = `${radius * 2}px`;\n ripple.style.width = `${radius * 2}px`;\n\n // If a custom color has been specified, set it as inline style. If no color is\n // set, the default color will be applied through the ripple theme styles.\n if (config.color != null) {\n ripple.style.backgroundColor = config.color;\n }\n\n ripple.style.transitionDuration = `${enterDuration}ms`;\n\n this._containerElement.appendChild(ripple);\n\n // By default the browser does not recalculate the styles of dynamically created\n // ripple elements. This is critical to ensure that the `scale` animates properly.\n // We enforce a style recalculation by calling `getComputedStyle` and *accessing* a property.\n // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a\n const computedStyles = window.getComputedStyle(ripple);\n const userTransitionProperty = computedStyles.transitionProperty;\n const userTransitionDuration = computedStyles.transitionDuration;\n\n // Note: We detect whether animation is forcibly disabled through CSS (e.g. through\n // `transition: none` or `display: none`). This is technically unexpected since animations are\n // controlled through the animation config, but this exists for backwards compatibility. This\n // logic does not need to be super accurate since it covers some edge cases which can be easily\n // avoided by users.\n const animationForciblyDisabledThroughCss =\n userTransitionProperty === 'none' ||\n // Note: The canonical unit for serialized CSS `<time>` properties is seconds. Additionally\n // some browsers expand the duration for every property (in our case `opacity` and `transform`).\n userTransitionDuration === '0s' ||\n userTransitionDuration === '0s, 0s' ||\n // If the container is 0x0, it's likely `display: none`.\n (containerRect.width === 0 && containerRect.height === 0);\n\n // Exposed reference to the ripple that will be returned.\n const rippleRef = new RippleRef(this, ripple, config, animationForciblyDisabledThroughCss);\n\n // Start the enter animation by setting the transform/scale to 100%. The animation will\n // execute as part of this statement because we forced a style recalculation before.\n // Note: We use a 3d transform here in order to avoid an issue in Safari where\n // the ripples aren't clipped when inside the shadow DOM (see #24028).\n ripple.style.transform = 'scale3d(1, 1, 1)';\n\n rippleRef.state = RippleState.FADING_IN;\n\n if (!config.persistent) {\n this._mostRecentTransientRipple = rippleRef;\n }\n\n let eventListeners: RippleEventListeners | null = null;\n\n // Do not register the `transition` event listener if fade-in and fade-out duration\n // are set to zero. The events won't fire anyway and we can save resources here.\n if (!animationForciblyDisabledThroughCss && (enterDuration || animationConfig.exitDuration)) {\n this._ngZone.runOutsideAngular(() => {\n const onTransitionEnd = () => this._finishRippleTransition(rippleRef);\n const onTransitionCancel = () => this._destroyRipple(rippleRef);\n ripple.addEventListener('transitionend', onTransitionEnd);\n // If the transition is cancelled (e.g. due to DOM removal), we destroy the ripple\n // directly as otherwise we would keep it part of the ripple container forever.\n // https://www.w3.org/TR/css-transitions-1/#:~:text=no%20longer%20in%20the%20document.\n ripple.addEventListener('transitioncancel', onTransitionCancel);\n eventListeners = {onTransitionEnd, onTransitionCancel};\n });\n }\n\n // Add the ripple reference to the list of all active ripples.\n this._activeRipples.set(rippleRef, eventListeners);\n\n // In case there is no fade-in transition duration, we need to manually call the transition\n // end listener because `transitionend` doesn't fire if there is no transition.\n if (animationForciblyDisabledThroughCss || !enterDuration) {\n this._finishRippleTransition(rippleRef);\n }\n\n return rippleRef;\n }\n\n /** Fades out a ripple reference. */\n fadeOutRipple(rippleRef: RippleRef) {\n // For ripples already fading out or hidden, this should be a noop.\n if (rippleRef.state === RippleState.FADING_OUT || rippleRef.state === RippleState.HIDDEN) {\n return;\n }\n\n const rippleEl = rippleRef.element;\n const animationConfig = {...defaultRippleAnimationConfig, ...rippleRef.config.animation};\n\n // This starts the fade-out transition and will fire the transition end listener that\n // removes the ripple element from the DOM.\n rippleEl.style.transitionDuration = `${animationConfig.exitDuration}ms`;\n rippleEl.style.opacity = '0';\n rippleRef.state = RippleState.FADING_OUT;\n\n // In case there is no fade-out transition duration, we need to manually call the\n // transition end listener because `transitionend` doesn't fire if there is no transition.\n if (rippleRef._animationForciblyDisabledThroughCss || !animationConfig.exitDuration) {\n this._finishRippleTransition(rippleRef);\n }\n }\n\n /** Fades out all currently active ripples. */\n fadeOutAll() {\n this._getActiveRipples().forEach(ripple => ripple.fadeOut());\n }\n\n /** Fades out all currently active non-persistent ripples. */\n fadeOutAllNonPersistent() {\n this._getActiveRipples().forEach(ripple => {\n if (!ripple.config.persistent) {\n ripple.fadeOut();\n }\n });\n }\n\n /** Sets up the trigger event listeners */\n setupTriggerEvents(elementOrElementRef: HTMLElement | ElementRef<HTMLElement>) {\n const element = coerceElement(elementOrElementRef);\n\n if (!this._platform.isBrowser || !element || element === this._triggerElement) {\n return;\n }\n\n // Remove all previously registered event listeners from the trigger element.\n this._removeTriggerEvents();\n this._triggerElement = element;\n\n // Use event delegation for the trigger events since they're\n // set up during creation and are performance-sensitive.\n pointerDownEvents.forEach(type => {\n RippleRenderer._eventManager.addHandler(this._ngZone, type, element, this);\n });\n }\n\n /**\n * Handles all registered events.\n * @docs-private\n */\n handleEvent(event: Event) {\n if (event.type === 'mousedown') {\n this._onMousedown(event as MouseEvent);\n } else if (event.type === 'touchstart') {\n this._onTouchStart(event as TouchEvent);\n } else {\n this._onPointerUp();\n }\n\n // If pointer-up events haven't been registered yet, do so now.\n // We do this on-demand in order to reduce the total number of event listeners\n // registered by the ripples, which speeds up the rendering time for large UIs.\n if (!this._pointerUpEventsRegistered) {\n // The events for hiding the ripple are bound directly on the trigger, because:\n // 1. Some of them occur frequently (e.g. `mouseleave`) and any advantage we get from\n // delegation will be diminished by having to look through all the data structures often.\n // 2. They aren't as performance-sensitive, because they're bound only after the user\n // has interacted with an element.\n this._ngZone.runOutsideAngular(() => {\n pointerUpEvents.forEach(type => {\n this._triggerElement!.addEventListener(type, this, passiveCapturingEventOptions);\n });\n });\n\n this._pointerUpEventsRegistered = true;\n }\n }\n\n /** Method that will be called if the fade-in or fade-in transition completed. */\n private _finishRippleTransition(rippleRef: RippleRef) {\n if (rippleRef.state === RippleState.FADING_IN) {\n this._startFadeOutTransition(rippleRef);\n } else if (rippleRef.state === RippleState.FADING_OUT) {\n this._destroyRipple(rippleRef);\n }\n }\n\n /**\n * Starts the fade-out transition of the given ripple if it's not persistent and the pointer\n * is not held down anymore.\n */\n private _startFadeOutTransition(rippleRef: RippleRef) {\n const isMostRecentTransientRipple = rippleRef === this._mostRecentTransientRipple;\n const {persistent} = rippleRef.config;\n\n rippleRef.state = RippleState.VISIBLE;\n\n // When the timer runs out while the user has kept their pointer down, we want to\n // keep only the persistent ripples and the latest transient ripple. We do this,\n // because we don't want stacked transient ripples to appear after their enter\n // animation has finished.\n if (!persistent && (!isMostRecentTransientRipple || !this._isPointerDown)) {\n rippleRef.fadeOut();\n }\n }\n\n /** Destroys the given ripple by removing it from the DOM and updating its state. */\n private _destroyRipple(rippleRef: RippleRef) {\n const eventListeners = this._activeRipples.get(rippleRef) ?? null;\n this._activeRipples.delete(rippleRef);\n\n // Clear out the cached bounding rect if we have no more ripples.\n if (!this._activeRipples.size) {\n this._containerRect = null;\n }\n\n // If the current ref is the most recent transient ripple, unset it\n // avoid memory leaks.\n if (rippleRef === this._mostRecentTransientRipple) {\n this._mostRecentTransientRipple = null;\n }\n\n rippleRef.state = RippleState.HIDDEN;\n if (eventListeners !== null) {\n rippleRef.element.removeEventListener('transitionend', eventListeners.onTransitionEnd);\n rippleRef.element.removeEventListener('transitioncancel', eventListeners.onTransitionCancel);\n }\n rippleRef.element.remove();\n }\n\n /** Function being called whenever the trigger is being pressed using mouse. */\n private _onMousedown(event: MouseEvent) {\n // Screen readers will fire fake mouse events for space/enter. Skip launching a\n // ripple in this case for consistency with the non-screen-reader experience.\n const isFakeMousedown = isFakeMousedownFromScreenReader(event);\n const isSyntheticEvent =\n this._lastTouchStartEvent &&\n Date.now() < this._lastTouchStartEvent + ignoreMouseEventsTimeout;\n\n if (!this._target.rippleDisabled && !isFakeMousedown && !isSyntheticEvent) {\n this._isPointerDown = true;\n this.fadeInRipple(event.clientX, event.clientY, this._target.rippleConfig);\n }\n }\n\n /** Function being called whenever the trigger is being pressed using touch. */\n private _onTouchStart(event: TouchEvent) {\n if (!this._target.rippleDisabled && !isFakeTouchstartFromScreenReader(event)) {\n // Some browsers fire mouse events after a `touchstart` event. Those synthetic mouse\n // events will launch a second ripple if we don't ignore mouse events for a specific\n // time after a touchstart event.\n this._lastTouchStartEvent = Date.now();\n this._isPointerDown = true;\n\n // Use `changedTouches` so we skip any touches where the user put\n // their finger down, but used another finger to tap the element again.\n const touches = event.changedTouches;\n\n for (let i = 0; i < touches.length; i++) {\n this.fadeInRipple(touches[i].clientX, touches[i].clientY, this._target.rippleConfig);\n }\n }\n }\n\n /** Function being called whenever the trigger is being released. */\n private _onPointerUp() {\n if (!this._isPointerDown) {\n return;\n }\n\n this._isPointerDown = false;\n\n // Fade-out all ripples that are visible and not persistent.\n this._getActiveRipples().forEach(ripple => {\n // By default, only ripples that are completely visible will fade out on pointer release.\n // If the `terminateOnPointerUp` option is set, ripples that still fade in will also fade out.\n const isVisible =\n ripple.state === RippleState.VISIBLE ||\n (ripple.config.terminateOnPointerUp && ripple.state === RippleState.FADING_IN);\n\n if (!ripple.config.persistent && isVisible) {\n ripple.fadeOut();\n }\n });\n }\n\n private _getActiveRipples(): RippleRef[] {\n return Array.from(this._activeRipples.keys());\n }\n\n /** Removes previously registered event listeners from the trigger element. */\n _removeTriggerEvents() {\n const trigger = this._triggerElement;\n\n if (trigger) {\n pointerDownEvents.forEach(type =>\n RippleRenderer._eventManager.removeHandler(type, trigger, this),\n );\n\n if (this._pointerUpEventsRegistered) {\n pointerUpEvents.forEach(type =>\n trigger.removeEventListener(type, this, passiveCapturingEventOptions),\n );\n }\n }\n }\n}\n\n/**\n * Returns the distance from the point (x, y) to the furthest corner of a rectangle.\n */\nfunction distanceToFurthestCorner(x: number, y: number, rect: ClientRect) {\n const distX = Math.max(Math.abs(x - rect.left), Math.abs(x - rect.right));\n const distY = Math.max(Math.abs(y - rect.top), Math.abs(y - rect.bottom));\n return Math.sqrt(distX * distX + distY * distY);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Platform} from '@angular/cdk/platform';\nimport {\n Directive,\n ElementRef,\n Inject,\n InjectionToken,\n Input,\n NgZone,\n OnDestroy,\n OnInit,\n Optional,\n} from '@angular/core';\nimport {RippleAnimationConfig, RippleConfig, RippleRef} from './ripple-ref';\nimport {RippleRenderer, RippleTarget} from './ripple-renderer';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\n\n/** Configurable options for `matRipple`. */\nexport interface RippleGlobalOptions {\n /**\n * Whether ripples should be disabled. Ripples can be still launched manually by using\n * the `launch()` method. Therefore focus indicators will still show up.\n */\n disabled?: boolean;\n\n /**\n * Default configuration for the animation duration of the ripples. There are two phases with\n * different durations for the ripples: `enter` and `leave`. The durations will be overwritten\n * by the value of `matRippleAnimation` or if the `NoopAnimationsModule` is included.\n */\n animation?: RippleAnimationConfig;\n\n /**\n * Whether ripples should start fading out immediately after the mouse or touch is released. By\n * default, ripples will wait for the enter animation to complete and for mouse or touch release.\n */\n terminateOnPointerUp?: boolean;\n}\n\n/** Injection token that can be used to specify the global ripple options. */\nexport const MAT_RIPPLE_GLOBAL_OPTIONS = new InjectionToken<RippleGlobalOptions>(\n 'mat-ripple-global-options',\n);\n\n@Directive({\n selector: '[mat-ripple], [matRipple]',\n exportAs: 'matRipple',\n host: {\n 'class': 'mat-ripple',\n '[class.mat-ripple-unbounded]': 'unbounded',\n },\n})\nexport class MatRipple implements OnInit, OnDestroy, RippleTarget {\n /** Custom color for all ripples. */\n @Input('matRippleColor') color: string;\n\n /** Whether the ripples should be visible outside the component's bounds. */\n @Input('matRippleUnbounded') unbounded: boolean;\n\n /**\n * Whether the ripple always originates from the center of the host element's bounds, rather\n * than originating from the location of the click event.\n */\n @Input('matRippleCentered') centered: boolean;\n\n /**\n * If set, the radius in pixels of foreground ripples when fully expanded. If unset, the radius\n * will be the distance from the center of the ripple to the furthest corner of the host element's\n * bounding rectangle.\n */\n @Input('matRippleRadius') radius: number = 0;\n\n /**\n * Configuration for the ripple animation. Allows modifying the enter and exit animation\n * duration of the ripples. The animation durations will be overwritten if the\n * `NoopAnimationsModule` is being used.\n */\n @Input('matRippleAnimation') animation: RippleAnimationConfig;\n\n /**\n * Whether click events will not trigger the ripple. Ripples can be still launched manually\n * by using the `launch()` method.\n */\n @Input('matRippleDisabled')\n get disabled() {\n return this._disabled;\n }\n set disabled(value: boolean) {\n if (value) {\n this.fadeOutAllNonPersistent();\n }\n this._disabled = value;\n this._setupTriggerEventsIfEnabled();\n }\n private _disabled: boolean = false;\n\n /**\n * The element that triggers the ripple when click events are received.\n * Defaults to the directive's host element.\n */\n @Input('matRippleTrigger')\n get trigger() {\n return this._trigger || this._elementRef.nativeElement;\n }\n set trigger(trigger: HTMLElement) {\n this._trigger = trigger;\n this._setupTriggerEventsIfEnabled();\n }\n private _trigger: HTMLElement;\n\n /** Renderer for the ripple DOM manipulations. */\n private _rippleRenderer: RippleRenderer;\n\n /** Options that are set globally for all ripples. */\n private _globalOptions: RippleGlobalOptions;\n\n /** Whether ripple directive is initialized and the input bindings are set. */\n private _isInitialized: boolean = false;\n\n constructor(\n private _elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n platform: Platform,\n @Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalOptions?: RippleGlobalOptions,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) private _animationMode?: string,\n ) {\n this._globalOptions = globalOptions || {};\n this._rippleRenderer = new RippleRenderer(this, ngZone, _elementRef, platform);\n }\n\n ngOnInit() {\n this._isInitialized = true;\n this._setupTriggerEventsIfEnabled();\n }\n\n ngOnDestroy() {\n this._rippleRenderer._removeTriggerEvents();\n }\n\n /** Fades out all currently showing ripple elements. */\n fadeOutAll() {\n this._rippleRenderer.fadeOutAll();\n }\n\n /** Fades out all currently showing non-persistent ripple elements. */\n fadeOutAllNonPersistent() {\n this._rippleRenderer.fadeOutAllNonPersistent();\n }\n\n /**\n * Ripple configuration from the directive's input values.\n * @docs-private Implemented as part of RippleTarget\n */\n get rippleConfig(): RippleConfig {\n return {\n centered: this.centered,\n radius: this.radius,\n color: this.color,\n animation: {\n ...this._globalOptions.animation,\n ...(this._animationMode === 'NoopAnimations' ? {enterDuration: 0, exitDuration: 0} : {}),\n ...this.animation,\n },\n terminateOnPointerUp: this._globalOptions.terminateOnPointerUp,\n };\n }\n\n /**\n * Whether ripples on pointer-down are disabled or not.\n * @docs-private Implemented as part of RippleTarget\n */\n get rippleDisabled(): boolean {\n return this.disabled || !!this._globalOptions.disabled;\n }\n\n /** Sets up the trigger event listeners if ripples are enabled. */\n private _setupTriggerEventsIfEnabled() {\n if (!this.disabled && this._isInitialized) {\n this._rippleRenderer.setupTriggerEvents(this.trigger);\n }\n }\n\n /**\n * Launches a manual ripple using the specified ripple configuration.\n * @param config Configuration for the manual ripple.\n */\n launch(config: RippleConfig): RippleRef;\n\n /**\n * Launches a manual ripple at the specified coordinates relative to the viewport.\n * @param x Coordinate along the X axis at which to fade-in the ripple. Coordinate\n * should be relative to the viewport.\n * @param y Coordinate along the Y axis at which to fade-in the ripple. Coordinate\n * should be relative to the viewport.\n * @param config Optional ripple configuration for the manual ripple.\n */\n launch(x: number, y: number, config?: RippleConfig): RippleRef;\n\n /** Launches a manual ripple at the specified coordinated or just by the ripple config. */\n launch(configOrX: number | RippleConfig, y: number = 0, config?: RippleConfig): RippleRef {\n if (typeof configOrX === 'number') {\n return this._rippleRenderer.fadeInRipple(configOrX, y, {...this.rippleConfig, ...config});\n } else {\n return this._rippleRenderer.fadeInRipple(0, 0, {...this.rippleConfig, ...configOrX});\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '../common-behaviors/common-module';\nimport {MatRipple} from './ripple';\n\nexport * from './ripple';\nexport * from './ripple-ref';\nexport * from './ripple-renderer';\n\n@NgModule({\n imports: [MatCommonModule],\n exports: [MatRipple, MatCommonModule],\n declarations: [MatRipple],\n})\nexport class MatRippleModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {MatPseudoCheckbox} from './pseudo-checkbox';\nimport {MatCommonModule} from '../../common-behaviors/common-module';\n\n@NgModule({\n imports: [MatCommonModule],\n exports: [MatPseudoCheckbox],\n declarations: [MatPseudoCheckbox],\n})\nexport class MatPseudoCheckboxModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ViewContainerRef,\n ComponentFactoryResolver,\n Injector,\n StaticProvider,\n Type,\n} from '@angular/core';\nimport {Direction} from '@angular/cdk/bidi';\nimport {PositionStrategy, ScrollStrategy} from '@angular/cdk/overlay';\nimport {BasePortalOutlet} from '@angular/cdk/portal';\n\n/** Options for where to set focus to automatically on dialog open */\nexport type AutoFocusTarget = 'dialog' | 'first-tabbable' | 'first-heading';\n\n/** Valid ARIA roles for a dialog. */\nexport type DialogRole = 'dialog' | 'alertdialog';\n\n/** Configuration for opening a modal dialog. */\nexport class DialogConfig<D = unknown, R = unknown, C extends BasePortalOutlet = BasePortalOutlet> {\n /**\n * Where the attached component should live in Angular's *logical* component tree.\n * This affects what is available for injection and the change detection order for the\n * component instantiated inside of the dialog. This does not affect where the dialog\n * content will be rendered.\n */\n viewContainerRef?: ViewContainerRef;\n\n /**\n * Injector used for the instantiation of the component to be attached. If provided,\n * takes precedence over the injector indirectly provided by `ViewContainerRef`.\n */\n injector?: Injector;\n\n /** ID for the dialog. If omitted, a unique one will be generated. */\n id?: string;\n\n /** The ARIA role of the dialog element. */\n role?: DialogRole = 'dialog';\n\n /** Optional CSS class or classes applied to the overlay panel. */\n panelClass?: string | string[] = '';\n\n /** Whether the dialog has a backdrop. */\n hasBackdrop?: boolean = true;\n\n /** Optional CSS class or classes applied to the overlay backdrop. */\n backdropClass?: string | string[] = '';\n\n /** Whether the dialog closes with the escape key or pointer events outside the panel element. */\n disableClose?: boolean = false;\n\n /** Width of the dialog. */\n width?: string = '';\n\n /** Height of the dialog. */\n height?: string = '';\n\n /** Min-width of the dialog. If a number is provided, assumes pixel units. */\n minWidth?: number | string;\n\n /** Min-height of the dialog. If a number is provided, assumes pixel units. */\n minHeight?: number | string;\n\n /** Max-width of the dialog. If a number is provided, assumes pixel units. Defaults to 80vw. */\n maxWidth?: number | string;\n\n /** Max-height of the dialog. If a number is provided, assumes pixel units. */\n maxHeight?: number | string;\n\n /** Strategy to use when positioning the dialog. Defaults to centering it on the page. */\n positionStrategy?: PositionStrategy;\n\n /** Data being injected into the child component. */\n data?: D | null = null;\n\n /** Layout direction for the dialog's content. */\n direction?: Direction;\n\n /** ID of the element that describes the dialog. */\n ariaDescribedBy?: string | null = null;\n\n /** ID of the element that labels the dialog. */\n ariaLabelledBy?: string | null = null;\n\n /** Dialog label applied via `aria-label` */\n ariaLabel?: string | null = null;\n\n /** Whether this is a modal dialog. Used to set the `aria-modal` attribute. */\n ariaModal?: boolean = true;\n\n /**\n * Where the dialog should focus on open.\n * @breaking-change 14.0.0 Remove boolean option from autoFocus. Use string or\n * AutoFocusTarget instead.\n */\n autoFocus?: AutoFocusTarget | string | boolean = 'first-tabbable';\n\n /**\n * Whether the dialog should restore focus to the previously-focused element upon closing.\n * Has the following behavior based on the type that is passed in:\n * - `boolean` - when true, will return focus to the element that was focused before the dialog\n * was opened, otherwise won't restore focus at all.\n * - `string` - focus will be restored to the first element that matches the CSS selector.\n * - `HTMLElement` - focus will be restored to the specific element.\n */\n restoreFocus?: boolean | string | HTMLElement = true;\n\n /**\n * Scroll strategy to be used for the dialog. This determines how\n * the dialog responds to scrolling underneath the panel element.\n */\n scrollStrategy?: ScrollStrategy;\n\n /**\n * Whether the dialog should close when the user navigates backwards or forwards through browser\n * history. This does not apply to navigation via anchor element unless using URL-hash based\n * routing (`HashLocationStrategy` in the Angular router).\n */\n closeOnNavigation?: boolean = true;\n\n /**\n * Whether the dialog should close when the dialog service is destroyed. This is useful if\n * another service is wrapping the dialog and is managing the destruction instead.\n */\n closeOnDestroy?: boolean = true;\n\n /**\n * Whether the dialog should close when the underlying overlay is detached. This is useful if\n * another service is wrapping the dialog and is managing the destruction instead. E.g. an\n * external detachment can happen as a result of a scroll strategy triggering it or when the\n * browser location changes.\n */\n closeOnOverlayDetachments?: boolean = true;\n\n /** Alternate `ComponentFactoryResolver` to use when resolving the associated component. */\n componentFactoryResolver?: ComponentFactoryResolver;\n\n /**\n * Providers that will be exposed to the contents of the dialog. Can also\n * be provided as a function in order to generate the providers lazily.\n */\n providers?:\n | StaticProvider[]\n | ((dialogRef: R, config: DialogConfig<D, R, C>, container: C) => StaticProvider[]);\n\n /**\n * Component into which the dialog content will be rendered. Defaults to `CdkDialogContainer`.\n * A configuration object can be passed in to customize the providers that will be exposed\n * to the dialog container.\n */\n container?:\n | Type<C>\n | {\n type: Type<C>;\n providers: (config: DialogConfig<D, R, C>) => StaticProvider[];\n };\n\n /**\n * Context that will be passed to template-based dialogs.\n * A function can be passed in to resolve the context lazily.\n */\n templateContext?: Record<string, any> | (() => Record<string, any>);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n FocusMonitor,\n FocusOrigin,\n FocusTrap,\n FocusTrapFactory,\n InteractivityChecker,\n} from '@angular/cdk/a11y';\nimport {OverlayRef} from '@angular/cdk/overlay';\nimport {_getFocusedElementPierceShadowDom} from '@angular/cdk/platform';\nimport {\n BasePortalOutlet,\n CdkPortalOutlet,\n ComponentPortal,\n DomPortal,\n TemplatePortal,\n} from '@angular/cdk/portal';\nimport {DOCUMENT} from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ComponentRef,\n ElementRef,\n EmbeddedViewRef,\n Inject,\n NgZone,\n OnDestroy,\n Optional,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport {DialogConfig} from './dialog-config';\n\nexport function throwDialogContentAlreadyAttachedError() {\n throw Error('Attempting to attach dialog content after content is already attached');\n}\n\n/**\n * Internal component that wraps user-provided dialog content.\n * @docs-private\n */\n@Component({\n selector: 'cdk-dialog-container',\n templateUrl: './dialog-container.html',\n styleUrls: ['dialog-container.css'],\n encapsulation: ViewEncapsulation.None,\n // Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n host: {\n 'class': 'cdk-dialog-container',\n 'tabindex': '-1',\n '[attr.id]': '_config.id || null',\n '[attr.role]': '_config.role',\n '[attr.aria-modal]': '_config.ariaModal',\n '[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',\n '[attr.aria-label]': '_config.ariaLabel',\n '[attr.aria-describedby]': '_config.ariaDescribedBy || null',\n },\n})\nexport class CdkDialogContainer<C extends DialogConfig = DialogConfig>\n extends BasePortalOutlet\n implements OnDestroy\n{\n protected _document: Document;\n\n /** The portal outlet inside of this container into which the dialog content will be loaded. */\n @ViewChild(CdkPortalOutlet, {static: true}) _portalOutlet: CdkPortalOutlet;\n\n /** The class that traps and manages focus within the dialog. */\n private _focusTrap: FocusTrap;\n\n /** Element that was focused before the dialog was opened. Save this to restore upon close. */\n private _elementFocusedBeforeDialogWasOpened: HTMLElement | null = null;\n\n /**\n * Type of interaction that led to the dialog being closed. This is used to determine\n * whether the focus style will be applied when returning focus to its original location\n * after the dialog is closed.\n */\n _closeInteractionType: FocusOrigin | null = null;\n\n /** ID of the element that should be considered as the dialog's label. */\n _ariaLabelledBy: string | null;\n\n constructor(\n protected _elementRef: ElementRef,\n protected _focusTrapFactory: FocusTrapFactory,\n @Optional() @Inject(DOCUMENT) _document: any,\n @Inject(DialogConfig) readonly _config: C,\n private _interactivityChecker: InteractivityChecker,\n protected _ngZone: NgZone,\n private _overlayRef: OverlayRef,\n private _focusMonitor?: FocusMonitor,\n ) {\n super();\n this._ariaLabelledBy = this._config.ariaLabelledBy || null;\n this._document = _document;\n }\n\n protected _contentAttached() {\n this._initializeFocusTrap();\n this._handleBackdropClicks();\n this._captureInitialFocus();\n }\n\n /**\n * Can be used by child classes to customize the initial focus\n * capturing behavior (e.g. if it's tied to an animation).\n */\n protected _captureInitialFocus() {\n this._trapFocus();\n }\n\n ngOnDestroy() {\n this._restoreFocus();\n }\n\n /**\n * Attach a ComponentPortal as content to this dialog container.\n * @param portal Portal to be attached as the dialog content.\n */\n attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {\n if (this._portalOutlet.hasAttached() && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwDialogContentAlreadyAttachedError();\n }\n\n const result = this._portalOutlet.attachComponentPortal(portal);\n this._contentAttached();\n return result;\n }\n\n /**\n * Attach a TemplatePortal as content to this dialog container.\n * @param portal Portal to be attached as the dialog content.\n */\n attachTemplatePortal<T>(portal: TemplatePortal<T>): EmbeddedViewRef<T> {\n if (this._portalOutlet.hasAttached() && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwDialogContentAlreadyAttachedError();\n }\n\n const result = this._portalOutlet.attachTemplatePortal(portal);\n this._contentAttached();\n return result;\n }\n\n /**\n * Attaches a DOM portal to the dialog container.\n * @param portal Portal to be attached.\n * @deprecated To be turned into a method.\n * @breaking-change 10.0.0\n */\n override attachDomPortal = (portal: DomPortal) => {\n if (this._portalOutlet.hasAttached() && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwDialogContentAlreadyAttachedError();\n }\n\n const result = this._portalOutlet.attachDomPortal(portal);\n this._contentAttached();\n return result;\n };\n\n // TODO(crisbeto): this shouldn't be exposed, but there are internal references to it.\n /** Captures focus if it isn't already inside the dialog. */\n _recaptureFocus() {\n if (!this._containsFocus()) {\n this._trapFocus();\n }\n }\n\n /**\n * Focuses the provided element. If the element is not focusable, it will add a tabIndex\n * attribute to forcefully focus it. The attribute is removed after focus is moved.\n * @param element The element to focus.\n */\n private _forceFocus(element: HTMLElement, options?: FocusOptions) {\n if (!this._interactivityChecker.isFocusable(element)) {\n element.tabIndex = -1;\n // The tabindex attribute should be removed to avoid navigating to that element again\n this._ngZone.runOutsideAngular(() => {\n const callback = () => {\n element.removeEventListener('blur', callback);\n element.removeEventListener('mousedown', callback);\n element.removeAttribute('tabindex');\n };\n\n element.addEventListener('blur', callback);\n element.addEventListener('mousedown', callback);\n });\n }\n element.focus(options);\n }\n\n /**\n * Focuses the first element that matches the given selector within the focus trap.\n * @param selector The CSS selector for the element to set focus to.\n */\n private _focusByCssSelector(selector: string, options?: FocusOptions) {\n let elementToFocus = this._elementRef.nativeElement.querySelector(\n selector,\n ) as HTMLElement | null;\n if (elementToFocus) {\n this._forceFocus(elementToFocus, options);\n }\n }\n\n /**\n * Moves the focus inside the focus trap. When autoFocus is not set to 'dialog', if focus\n * cannot be moved then focus will go to the dialog container.\n */\n protected _trapFocus() {\n const element = this._elementRef.nativeElement;\n // If were to attempt to focus immediately, then the content of the dialog would not yet be\n // ready in instances where change detection has to run first. To deal with this, we simply\n // wait for the microtask queue to be empty when setting focus when autoFocus isn't set to\n // dialog. If the element inside the dialog can't be focused, then the container is focused\n // so the user can't tab into other elements behind it.\n switch (this._config.autoFocus) {\n case false:\n case 'dialog':\n // Ensure that focus is on the dialog container. It's possible that a different\n // component tried to move focus while the open animation was running. See:\n // https://github.com/angular/components/issues/16215. Note that we only want to do this\n // if the focus isn't inside the dialog already, because it's possible that the consumer\n // turned off `autoFocus` in order to move focus themselves.\n if (!this._containsFocus()) {\n element.focus();\n }\n break;\n case true:\n case 'first-tabbable':\n this._focusTrap.focusInitialElementWhenReady().then(focusedSuccessfully => {\n // If we weren't able to find a focusable element in the dialog, then focus the dialog\n // container instead.\n if (!focusedSuccessfully) {\n this._focusDialogContainer();\n }\n });\n break;\n case 'first-heading':\n this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role=\"heading\"]');\n break;\n default:\n this._focusByCssSelector(this._config.autoFocus!);\n break;\n }\n }\n\n /** Restores focus to the element that was focused before the dialog opened. */\n private _restoreFocus() {\n const focusConfig = this._config.restoreFocus;\n let focusTargetElement: HTMLElement | null = null;\n\n if (typeof focusConfig === 'string') {\n focusTargetElement = this._document.querySelector(focusConfig);\n } else if (typeof focusConfig === 'boolean') {\n focusTargetElement = focusConfig ? this._elementFocusedBeforeDialogWasOpened : null;\n } else if (focusConfig) {\n focusTargetElement = focusConfig;\n }\n\n // We need the extra check, because IE can set the `activeElement` to null in some cases.\n if (\n this._config.restoreFocus &&\n focusTargetElement &&\n typeof focusTargetElement.focus === 'function'\n ) {\n const activeElement = _getFocusedElementPierceShadowDom();\n const element = this._elementRef.nativeElement;\n\n // Make sure that focus is still inside the dialog or is on the body (usually because a\n // non-focusable element like the backdrop was clicked) before moving it. It's possible that\n // the consumer moved it themselves before the animation was done, in which case we shouldn't\n // do anything.\n if (\n !activeElement ||\n activeElement === this._document.body ||\n activeElement === element ||\n element.contains(activeElement)\n ) {\n if (this._focusMonitor) {\n this._focusMonitor.focusVia(focusTargetElement, this._closeInteractionType);\n this._closeInteractionType = null;\n } else {\n focusTargetElement.focus();\n }\n }\n }\n\n if (this._focusTrap) {\n this._focusTrap.destroy();\n }\n }\n\n /** Focuses the dialog container. */\n private _focusDialogContainer() {\n // Note that there is no focus method when rendering on the server.\n if (this._elementRef.nativeElement.focus) {\n this._elementRef.nativeElement.focus();\n }\n }\n\n /** Returns whether focus is inside the dialog. */\n private _containsFocus() {\n const element = this._elementRef.nativeElement;\n const activeElement = _getFocusedElementPierceShadowDom();\n return element === activeElement || element.contains(activeElement);\n }\n\n /** Sets up the focus trap. */\n private _initializeFocusTrap() {\n this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);\n\n // Save the previously focused element. This element will be re-focused\n // when the dialog closes.\n if (this._document) {\n this._elementFocusedBeforeDialogWasOpened = _getFocusedElementPierceShadowDom();\n }\n }\n\n /** Sets up the listener that handles clicks on the dialog backdrop. */\n private _handleBackdropClicks() {\n // Clicking on the backdrop will move focus out of dialog.\n // Recapture it if closing via the backdrop is disabled.\n this._overlayRef.backdropClick().subscribe(() => {\n if (this._config.disableClose) {\n this._recaptureFocus();\n }\n });\n }\n}\n","<ng-template cdkPortalOutlet></ng-template>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {OverlayRef} from '@angular/cdk/overlay';\nimport {ESCAPE, hasModifierKey} from '@angular/cdk/keycodes';\nimport {Observable, Subject, Subscription} from 'rxjs';\nimport {DialogConfig} from './dialog-config';\nimport {FocusOrigin} from '@angular/cdk/a11y';\nimport {BasePortalOutlet} from '@angular/cdk/portal';\n\n/** Additional options that can be passed in when closing a dialog. */\nexport interface DialogCloseOptions {\n /** Focus original to use when restoring focus. */\n focusOrigin?: FocusOrigin;\n}\n\n/**\n * Reference to a dialog opened via the Dialog service.\n */\nexport class DialogRef<R = unknown, C = unknown> {\n /**\n * Instance of component opened into the dialog. Will be\n * null when the dialog is opened using a `TemplateRef`.\n */\n readonly componentInstance: C | null;\n\n /** Instance of the container that is rendering out the dialog content. */\n readonly containerInstance: BasePortalOutlet & {_closeInteractionType?: FocusOrigin};\n\n /** Whether the user is allowed to close the dialog. */\n disableClose: boolean | undefined;\n\n /** Emits when the dialog has been closed. */\n readonly closed: Observable<R | undefined> = new Subject<R | undefined>();\n\n /** Emits when the backdrop of the dialog is clicked. */\n readonly backdropClick: Observable<MouseEvent>;\n\n /** Emits when on keyboard events within the dialog. */\n readonly keydownEvents: Observable<KeyboardEvent>;\n\n /** Emits on pointer events that happen outside of the dialog. */\n readonly outsidePointerEvents: Observable<MouseEvent>;\n\n /** Unique ID for the dialog. */\n readonly id: string;\n\n /** Subscription to external detachments of the dialog. */\n private _detachSubscription: Subscription;\n\n constructor(\n readonly overlayRef: OverlayRef,\n readonly config: DialogConfig<any, DialogRef<R, C>, BasePortalOutlet>,\n ) {\n this.disableClose = config.disableClose;\n this.backdropClick = overlayRef.backdropClick();\n this.keydownEvents = overlayRef.keydownEvents();\n this.outsidePointerEvents = overlayRef.outsidePointerEvents();\n this.id = config.id!; // By the time the dialog is created we are guaranteed to have an ID.\n\n this.keydownEvents.subscribe(event => {\n if (event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)) {\n event.preventDefault();\n this.close(undefined, {focusOrigin: 'keyboard'});\n }\n });\n\n this.backdropClick.subscribe(() => {\n if (!this.disableClose) {\n this.close(undefined, {focusOrigin: 'mouse'});\n }\n });\n\n this._detachSubscription = overlayRef.detachments().subscribe(() => {\n // Check specifically for `false`, because we want `undefined` to be treated like `true`.\n if (config.closeOnOverlayDetachments !== false) {\n this.close();\n }\n });\n }\n\n /**\n * Close the dialog.\n * @param result Optional result to return to the dialog opener.\n * @param options Additional options to customize the closing behavior.\n */\n close(result?: R, options?: DialogCloseOptions): void {\n if (this.containerInstance) {\n const closedSubject = this.closed as Subject<R | undefined>;\n this.containerInstance._closeInteractionType = options?.focusOrigin || 'program';\n // Drop the detach subscription first since it can be triggered by the\n // `dispose` call and override the result of this closing sequence.\n this._detachSubscription.unsubscribe();\n this.overlayRef.dispose();\n closedSubject.next(result);\n closedSubject.complete();\n (this as {componentInstance: C}).componentInstance = (\n this as {containerInstance: BasePortalOutlet}\n ).containerInstance = null!;\n }\n }\n\n /** Updates the position of the dialog based on the current position strategy. */\n updatePosition(): this {\n this.overlayRef.updatePosition();\n return this;\n }\n\n /**\n * Updates the dialog's width and height.\n * @param width New width of the dialog.\n * @param height New height of the dialog.\n */\n updateSize(width: string | number = '', height: string | number = ''): this {\n this.overlayRef.updateSize({width, height});\n return this;\n }\n\n /** Add a CSS class or an array of classes to the overlay pane. */\n addPanelClass(classes: string | string[]): this {\n this.overlayRef.addPanelClass(classes);\n return this;\n }\n\n /** Remove a CSS class or an array of classes from the overlay pane. */\n removePanelClass(classes: string | string[]): this {\n this.overlayRef.removePanelClass(classes);\n return this;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\nimport {Overlay, ScrollStrategy} from '@angular/cdk/overlay';\nimport {DialogConfig} from './dialog-config';\n\n/** Injection token for the Dialog's ScrollStrategy. */\nexport const DIALOG_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'DialogScrollStrategy',\n);\n\n/** Injection token for the Dialog's Data. */\nexport const DIALOG_DATA = new InjectionToken<any>('DialogData');\n\n/** Injection token that can be used to provide default options for the dialog module. */\nexport const DEFAULT_DIALOG_CONFIG = new InjectionToken<DialogConfig>('DefaultDialogConfig');\n\n/** @docs-private */\nexport function DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay: Overlay): () => ScrollStrategy {\n return () => overlay.scrollStrategies.block();\n}\n\n/** @docs-private */\nexport const DIALOG_SCROLL_STRATEGY_PROVIDER = {\n provide: DIALOG_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY,\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n TemplateRef,\n Injectable,\n Injector,\n OnDestroy,\n Type,\n StaticProvider,\n Inject,\n Optional,\n SkipSelf,\n} from '@angular/core';\nimport {BasePortalOutlet, ComponentPortal, TemplatePortal} from '@angular/cdk/portal';\nimport {of as observableOf, Observable, Subject, defer} from 'rxjs';\nimport {DialogRef} from './dialog-ref';\nimport {DialogConfig} from './dialog-config';\nimport {Directionality} from '@angular/cdk/bidi';\nimport {\n ComponentType,\n Overlay,\n OverlayRef,\n OverlayConfig,\n ScrollStrategy,\n OverlayContainer,\n} from '@angular/cdk/overlay';\nimport {startWith} from 'rxjs/operators';\n\nimport {DEFAULT_DIALOG_CONFIG, DIALOG_DATA, DIALOG_SCROLL_STRATEGY} from './dialog-injectors';\nimport {CdkDialogContainer} from './dialog-container';\n\n/** Unique id for the created dialog. */\nlet uniqueId = 0;\n\n@Injectable()\nexport class Dialog implements OnDestroy {\n private _openDialogsAtThisLevel: DialogRef<any, any>[] = [];\n private readonly _afterAllClosedAtThisLevel = new Subject<void>();\n private readonly _afterOpenedAtThisLevel = new Subject<DialogRef>();\n private _ariaHiddenElements = new Map<Element, string | null>();\n private _scrollStrategy: () => ScrollStrategy;\n\n /** Keeps track of the currently-open dialogs. */\n get openDialogs(): readonly DialogRef<any, any>[] {\n return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel;\n }\n\n /** Stream that emits when a dialog has been opened. */\n get afterOpened(): Subject<DialogRef<any, any>> {\n return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel;\n }\n\n /**\n * Stream that emits when all open dialog have finished closing.\n * Will emit on subscribe if there are no open dialogs to begin with.\n */\n readonly afterAllClosed: Observable<void> = defer(() =>\n this.openDialogs.length\n ? this._getAfterAllClosed()\n : this._getAfterAllClosed().pipe(startWith(undefined)),\n );\n\n constructor(\n private _overlay: Overlay,\n private _injector: Injector,\n @Optional() @Inject(DEFAULT_DIALOG_CONFIG) private _defaultOptions: DialogConfig,\n @Optional() @SkipSelf() private _parentDialog: Dialog,\n private _overlayContainer: OverlayContainer,\n @Inject(DIALOG_SCROLL_STRATEGY) scrollStrategy: any,\n ) {\n this._scrollStrategy = scrollStrategy;\n }\n\n /**\n * Opens a modal dialog containing the given component.\n * @param component Type of the component to load into the dialog.\n * @param config Extra configuration options.\n * @returns Reference to the newly-opened dialog.\n */\n open<R = unknown, D = unknown, C = unknown>(\n component: ComponentType<C>,\n config?: DialogConfig<D, DialogRef<R, C>>,\n ): DialogRef<R, C>;\n\n /**\n * Opens a modal dialog containing the given template.\n * @param template TemplateRef to instantiate as the dialog content.\n * @param config Extra configuration options.\n * @returns Reference to the newly-opened dialog.\n */\n open<R = unknown, D = unknown, C = unknown>(\n template: TemplateRef<C>,\n config?: DialogConfig<D, DialogRef<R, C>>,\n ): DialogRef<R, C>;\n\n open<R = unknown, D = unknown, C = unknown>(\n componentOrTemplateRef: ComponentType<C> | TemplateRef<C>,\n config?: DialogConfig<D, DialogRef<R, C>>,\n ): DialogRef<R, C>;\n\n open<R = unknown, D = unknown, C = unknown>(\n componentOrTemplateRef: ComponentType<C> | TemplateRef<C>,\n config?: DialogConfig<D, DialogRef<R, C>>,\n ): DialogRef<R, C> {\n const defaults = (this._defaultOptions || new DialogConfig()) as DialogConfig<\n D,\n DialogRef<R, C>\n >;\n config = {...defaults, ...config};\n config.id = config.id || `cdk-dialog-${uniqueId++}`;\n\n if (\n config.id &&\n this.getDialogById(config.id) &&\n (typeof ngDevMode === 'undefined' || ngDevMode)\n ) {\n throw Error(`Dialog with id \"${config.id}\" exists already. The dialog id must be unique.`);\n }\n\n const overlayConfig = this._getOverlayConfig(config);\n const overlayRef = this._overlay.create(overlayConfig);\n const dialogRef = new DialogRef(overlayRef, config);\n const dialogContainer = this._attachContainer(overlayRef, dialogRef, config);\n\n (dialogRef as {containerInstance: BasePortalOutlet}).containerInstance = dialogContainer;\n this._attachDialogContent(componentOrTemplateRef, dialogRef, dialogContainer, config);\n\n // If this is the first dialog that we're opening, hide all the non-overlay content.\n if (!this.openDialogs.length) {\n this._hideNonDialogContentFromAssistiveTechnology();\n }\n\n (this.openDialogs as DialogRef<R, C>[]).push(dialogRef);\n dialogRef.closed.subscribe(() => this._removeOpenDialog(dialogRef, true));\n this.afterOpened.next(dialogRef);\n\n return dialogRef;\n }\n\n /**\n * Closes all of the currently-open dialogs.\n */\n closeAll(): void {\n reverseForEach(this.openDialogs, dialog => dialog.close());\n }\n\n /**\n * Finds an open dialog by its id.\n * @param id ID to use when looking up the dialog.\n */\n getDialogById<R, C>(id: string): DialogRef<R, C> | undefined {\n return this.openDialogs.find(dialog => dialog.id === id);\n }\n\n ngOnDestroy() {\n // Make one pass over all the dialogs that need to be untracked, but should not be closed. We\n // want to stop tracking the open dialog even if it hasn't been closed, because the tracking\n // determines when `aria-hidden` is removed from elements outside the dialog.\n reverseForEach(this._openDialogsAtThisLevel, dialog => {\n // Check for `false` specifically since we want `undefined` to be interpreted as `true`.\n if (dialog.config.closeOnDestroy === false) {\n this._removeOpenDialog(dialog, false);\n }\n });\n\n // Make a second pass and close the remaining dialogs. We do this second pass in order to\n // correctly dispatch the `afterAllClosed` event in case we have a mixed array of dialogs\n // that should be closed and dialogs that should not.\n reverseForEach(this._openDialogsAtThisLevel, dialog => dialog.close());\n\n this._afterAllClosedAtThisLevel.complete();\n this._afterOpenedAtThisLevel.complete();\n this._openDialogsAtThisLevel = [];\n }\n\n /**\n * Creates an overlay config from a dialog config.\n * @param config The dialog configuration.\n * @returns The overlay configuration.\n */\n private _getOverlayConfig<D, R>(config: DialogConfig<D, R>): OverlayConfig {\n const state = new OverlayConfig({\n positionStrategy:\n config.positionStrategy ||\n this._overlay.position().global().centerHorizontally().centerVertically(),\n scrollStrategy: config.scrollStrategy || this._scrollStrategy(),\n panelClass: config.panelClass,\n hasBackdrop: config.hasBackdrop,\n direction: config.direction,\n minWidth: config.minWidth,\n minHeight: config.minHeight,\n maxWidth: config.maxWidth,\n maxHeight: config.maxHeight,\n width: config.width,\n height: config.height,\n disposeOnNavigation: config.closeOnNavigation,\n });\n\n if (config.backdropClass) {\n state.backdropClass = config.backdropClass;\n }\n\n return state;\n }\n\n /**\n * Attaches a dialog container to a dialog's already-created overlay.\n * @param overlay Reference to the dialog's underlying overlay.\n * @param config The dialog configuration.\n * @returns A promise resolving to a ComponentRef for the attached container.\n */\n private _attachContainer<R, D, C>(\n overlay: OverlayRef,\n dialogRef: DialogRef<R, C>,\n config: DialogConfig<D, DialogRef<R, C>>,\n ): BasePortalOutlet {\n const userInjector = config.injector || config.viewContainerRef?.injector;\n const providers: StaticProvider[] = [\n {provide: DialogConfig, useValue: config},\n {provide: DialogRef, useValue: dialogRef},\n {provide: OverlayRef, useValue: overlay},\n ];\n let containerType: Type<BasePortalOutlet>;\n\n if (config.container) {\n if (typeof config.container === 'function') {\n containerType = config.container;\n } else {\n containerType = config.container.type;\n providers.push(...config.container.providers(config));\n }\n } else {\n containerType = CdkDialogContainer;\n }\n\n const containerPortal = new ComponentPortal(\n containerType,\n config.viewContainerRef,\n Injector.create({parent: userInjector || this._injector, providers}),\n config.componentFactoryResolver,\n );\n const containerRef = overlay.attach(containerPortal);\n\n return containerRef.instance;\n }\n\n /**\n * Attaches the user-provided component to the already-created dialog container.\n * @param componentOrTemplateRef The type of component being loaded into the dialog,\n * or a TemplateRef to instantiate as the content.\n * @param dialogRef Reference to the dialog being opened.\n * @param dialogContainer Component that is going to wrap the dialog content.\n * @param config Configuration used to open the dialog.\n */\n private _attachDialogContent<R, D, C>(\n componentOrTemplateRef: ComponentType<C> | TemplateRef<C>,\n dialogRef: DialogRef<R, C>,\n dialogContainer: BasePortalOutlet,\n config: DialogConfig<D, DialogRef<R, C>>,\n ) {\n if (componentOrTemplateRef instanceof TemplateRef) {\n const injector = this._createInjector(config, dialogRef, dialogContainer, undefined);\n let context: any = {$implicit: config.data, dialogRef};\n\n if (config.templateContext) {\n context = {\n ...context,\n ...(typeof config.templateContext === 'function'\n ? config.templateContext()\n : config.templateContext),\n };\n }\n\n dialogContainer.attachTemplatePortal(\n new TemplatePortal<C>(componentOrTemplateRef, null!, context, injector),\n );\n } else {\n const injector = this._createInjector(config, dialogRef, dialogContainer, this._injector);\n const contentRef = dialogContainer.attachComponentPortal<C>(\n new ComponentPortal(\n componentOrTemplateRef,\n config.viewContainerRef,\n injector,\n config.componentFactoryResolver,\n ),\n );\n (dialogRef as {componentInstance: C}).componentInstance = contentRef.instance;\n }\n }\n\n /**\n * Creates a custom injector to be used inside the dialog. This allows a component loaded inside\n * of a dialog to close itself and, optionally, to return a value.\n * @param config Config object that is used to construct the dialog.\n * @param dialogRef Reference to the dialog being opened.\n * @param dialogContainer Component that is going to wrap the dialog content.\n * @param fallbackInjector Injector to use as a fallback when a lookup fails in the custom\n * dialog injector, if the user didn't provide a custom one.\n * @returns The custom injector that can be used inside the dialog.\n */\n private _createInjector<R, D, C>(\n config: DialogConfig<D, DialogRef<R, C>>,\n dialogRef: DialogRef<R, C>,\n dialogContainer: BasePortalOutlet,\n fallbackInjector: Injector | undefined,\n ): Injector {\n const userInjector = config.injector || config.viewContainerRef?.injector;\n const providers: StaticProvider[] = [\n {provide: DIALOG_DATA, useValue: config.data},\n {provide: DialogRef, useValue: dialogRef},\n ];\n\n if (config.providers) {\n if (typeof config.providers === 'function') {\n providers.push(...config.providers(dialogRef, config, dialogContainer));\n } else {\n providers.push(...config.providers);\n }\n }\n\n if (\n config.direction &&\n (!userInjector ||\n !userInjector.get<Directionality | null>(Directionality, null, {optional: true}))\n ) {\n providers.push({\n provide: Directionality,\n useValue: {value: config.direction, change: observableOf()},\n });\n }\n\n return Injector.create({parent: userInjector || fallbackInjector, providers});\n }\n\n /**\n * Removes a dialog from the array of open dialogs.\n * @param dialogRef Dialog to be removed.\n * @param emitEvent Whether to emit an event if this is the last dialog.\n */\n private _removeOpenDialog<R, C>(dialogRef: DialogRef<R, C>, emitEvent: boolean) {\n const index = this.openDialogs.indexOf(dialogRef);\n\n if (index > -1) {\n (this.openDialogs as DialogRef<R, C>[]).splice(index, 1);\n\n // If all the dialogs were closed, remove/restore the `aria-hidden`\n // to a the siblings and emit to the `afterAllClosed` stream.\n if (!this.openDialogs.length) {\n this._ariaHiddenElements.forEach((previousValue, element) => {\n if (previousValue) {\n element.setAttribute('aria-hidden', previousValue);\n } else {\n element.removeAttribute('aria-hidden');\n }\n });\n\n this._ariaHiddenElements.clear();\n\n if (emitEvent) {\n this._getAfterAllClosed().next();\n }\n }\n }\n }\n\n /** Hides all of the content that isn't an overlay from assistive technology. */\n private _hideNonDialogContentFromAssistiveTechnology() {\n const overlayContainer = this._overlayContainer.getContainerElement();\n\n // Ensure that the overlay container is attached to the DOM.\n if (overlayContainer.parentElement) {\n const siblings = overlayContainer.parentElement.children;\n\n for (let i = siblings.length - 1; i > -1; i--) {\n const sibling = siblings[i];\n\n if (\n sibling !== overlayContainer &&\n sibling.nodeName !== 'SCRIPT' &&\n sibling.nodeName !== 'STYLE' &&\n !sibling.hasAttribute('aria-live')\n ) {\n this._ariaHiddenElements.set(sibling, sibling.getAttribute('aria-hidden'));\n sibling.setAttribute('aria-hidden', 'true');\n }\n }\n }\n }\n\n private _getAfterAllClosed(): Subject<void> {\n const parent = this._parentDialog;\n return parent ? parent._getAfterAllClosed() : this._afterAllClosedAtThisLevel;\n }\n}\n\n/**\n * Executes a callback against all elements in an array while iterating in reverse.\n * Useful if the array is being modified as it is being iterated.\n */\nfunction reverseForEach<T>(items: T[] | readonly T[], callback: (current: T) => void) {\n let i = items.length;\n\n while (i--) {\n callback(items[i]);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {OverlayModule} from '@angular/cdk/overlay';\nimport {PortalModule} from '@angular/cdk/portal';\nimport {A11yModule} from '@angular/cdk/a11y';\nimport {Dialog} from './dialog';\nimport {CdkDialogContainer} from './dialog-container';\nimport {DIALOG_SCROLL_STRATEGY_PROVIDER} from './dialog-injectors';\n\n@NgModule({\n imports: [OverlayModule, PortalModule, A11yModule],\n exports: [\n // Re-export the PortalModule so that people extending the `CdkDialogContainer`\n // don't have to remember to import it or be faced with an unhelpful error.\n PortalModule,\n CdkDialogContainer,\n ],\n declarations: [CdkDialogContainer],\n providers: [Dialog, DIALOG_SCROLL_STRATEGY_PROVIDER],\n})\nexport class DialogModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ViewContainerRef, ComponentFactoryResolver, Injector} from '@angular/core';\nimport {Direction} from '@angular/cdk/bidi';\nimport {ScrollStrategy} from '@angular/cdk/overlay';\nimport {_defaultParams} from './dialog-animations';\n\n/** Options for where to set focus to automatically on dialog open */\nexport type AutoFocusTarget = 'dialog' | 'first-tabbable' | 'first-heading';\n\n/** Valid ARIA roles for a dialog element. */\nexport type DialogRole = 'dialog' | 'alertdialog';\n\n/** Possible overrides for a dialog's position. */\nexport interface DialogPosition {\n /** Override for the dialog's top position. */\n top?: string;\n\n /** Override for the dialog's bottom position. */\n bottom?: string;\n\n /** Override for the dialog's left position. */\n left?: string;\n\n /** Override for the dialog's right position. */\n right?: string;\n}\n\n/**\n * Configuration for opening a modal dialog with the MatDialog service.\n */\nexport class MatDialogConfig<D = any> {\n /**\n * Where the attached component should live in Angular's *logical* component tree.\n * This affects what is available for injection and the change detection order for the\n * component instantiated inside of the dialog. This does not affect where the dialog\n * content will be rendered.\n */\n viewContainerRef?: ViewContainerRef;\n\n /**\n * Injector used for the instantiation of the component to be attached. If provided,\n * takes precedence over the injector indirectly provided by `ViewContainerRef`.\n */\n injector?: Injector;\n\n /** ID for the dialog. If omitted, a unique one will be generated. */\n id?: string;\n\n /** The ARIA role of the dialog element. */\n role?: DialogRole = 'dialog';\n\n /** Custom class for the overlay pane. */\n panelClass?: string | string[] = '';\n\n /** Whether the dialog has a backdrop. */\n hasBackdrop?: boolean = true;\n\n /** Custom class for the backdrop. */\n backdropClass?: string | string[] = '';\n\n /** Whether the user can use escape or clicking on the backdrop to close the modal. */\n disableClose?: boolean = false;\n\n /** Width of the dialog. */\n width?: string = '';\n\n /** Height of the dialog. */\n height?: string = '';\n\n /** Min-width of the dialog. If a number is provided, assumes pixel units. */\n minWidth?: number | string;\n\n /** Min-height of the dialog. If a number is provided, assumes pixel units. */\n minHeight?: number | string;\n\n /** Max-width of the dialog. If a number is provided, assumes pixel units. Defaults to 80vw. */\n maxWidth?: number | string = '80vw';\n\n /** Max-height of the dialog. If a number is provided, assumes pixel units. */\n maxHeight?: number | string;\n\n /** Position overrides. */\n position?: DialogPosition;\n\n /** Data being injected into the child component. */\n data?: D | null = null;\n\n /** Layout direction for the dialog's content. */\n direction?: Direction;\n\n /** ID of the element that describes the dialog. */\n ariaDescribedBy?: string | null = null;\n\n /** ID of the element that labels the dialog. */\n ariaLabelledBy?: string | null = null;\n\n /** Aria label to assign to the dialog element. */\n ariaLabel?: string | null = null;\n\n /** Whether this is a modal dialog. Used to set the `aria-modal` attribute. */\n ariaModal?: boolean = true;\n\n /**\n * Where the dialog should focus on open.\n * @breaking-change 14.0.0 Remove boolean option from autoFocus. Use string or\n * AutoFocusTarget instead.\n */\n autoFocus?: AutoFocusTarget | string | boolean = 'first-tabbable';\n\n /**\n * Whether the dialog should restore focus to the\n * previously-focused element, after it's closed.\n */\n restoreFocus?: boolean = true;\n\n /** Whether to wait for the opening animation to finish before trapping focus. */\n delayFocusTrap?: boolean = true;\n\n /** Scroll strategy to be used for the dialog. */\n scrollStrategy?: ScrollStrategy;\n\n /**\n * Whether the dialog should close when the user goes backwards/forwards in history.\n * Note that this usually doesn't include clicking on links (unless the user is using\n * the `HashLocationStrategy`).\n */\n closeOnNavigation?: boolean = true;\n\n /** Alternate `ComponentFactoryResolver` to use when resolving the associated component. */\n componentFactoryResolver?: ComponentFactoryResolver;\n\n /**\n * Duration of the enter animation in ms.\n * Should be a number, string type is deprecated.\n * @breaking-change 17.0.0 Remove string signature.\n */\n enterAnimationDuration?: string | number;\n\n /**\n * Duration of the exit animation in ms.\n * Should be a number, string type is deprecated.\n * @breaking-change 17.0.0 Remove string signature.\n */\n exitAnimationDuration?: string | number;\n\n // TODO(jelbourn): add configuration for lifecycle hooks, ARIA labelling.\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {FocusMonitor, FocusTrapFactory, InteractivityChecker} from '@angular/cdk/a11y';\nimport {OverlayRef} from '@angular/cdk/overlay';\nimport {DOCUMENT} from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Inject,\n NgZone,\n OnDestroy,\n Optional,\n ViewEncapsulation,\n} from '@angular/core';\nimport {MatDialogConfig} from './dialog-config';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\nimport {CdkDialogContainer} from '@angular/cdk/dialog';\nimport {coerceNumberProperty} from '@angular/cdk/coercion';\n\n/** Event that captures the state of dialog container animations. */\ninterface LegacyDialogAnimationEvent {\n state: 'opened' | 'opening' | 'closing' | 'closed';\n totalTime: number;\n}\n\n/** Class added when the dialog is open. */\nconst OPEN_CLASS = 'mdc-dialog--open';\n\n/** Class added while the dialog is opening. */\nconst OPENING_CLASS = 'mdc-dialog--opening';\n\n/** Class added while the dialog is closing. */\nconst CLOSING_CLASS = 'mdc-dialog--closing';\n\n/** Duration of the opening animation in milliseconds. */\nexport const OPEN_ANIMATION_DURATION = 150;\n\n/** Duration of the closing animation in milliseconds. */\nexport const CLOSE_ANIMATION_DURATION = 75;\n\n/**\n * Base class for the `MatDialogContainer`. The base class does not implement\n * animations as these are left to implementers of the dialog container.\n */\n// tslint:disable-next-line:validate-decorators\n@Component({template: ''})\nexport abstract class _MatDialogContainerBase extends CdkDialogContainer<MatDialogConfig> {\n /** Emits when an animation state changes. */\n _animationStateChanged = new EventEmitter<LegacyDialogAnimationEvent>();\n\n constructor(\n elementRef: ElementRef,\n focusTrapFactory: FocusTrapFactory,\n @Optional() @Inject(DOCUMENT) _document: any,\n dialogConfig: MatDialogConfig,\n interactivityChecker: InteractivityChecker,\n ngZone: NgZone,\n overlayRef: OverlayRef,\n focusMonitor?: FocusMonitor,\n ) {\n super(\n elementRef,\n focusTrapFactory,\n _document,\n dialogConfig,\n interactivityChecker,\n ngZone,\n overlayRef,\n focusMonitor,\n );\n }\n\n /** Starts the dialog exit animation. */\n abstract _startExitAnimation(): void;\n\n protected override _captureInitialFocus(): void {\n if (!this._config.delayFocusTrap) {\n this._trapFocus();\n }\n }\n\n /**\n * Callback for when the open dialog animation has finished. Intended to\n * be called by sub-classes that use different animation implementations.\n */\n protected _openAnimationDone(totalTime: number) {\n if (this._config.delayFocusTrap) {\n this._trapFocus();\n }\n\n this._animationStateChanged.next({state: 'opened', totalTime});\n }\n}\n\nconst TRANSITION_DURATION_PROPERTY = '--mat-dialog-transition-duration';\n\n// TODO(mmalerba): Remove this function after animation durations are required\n// to be numbers.\n/**\n * Converts a CSS time string to a number in ms. If the given time is already a\n * number, it is assumed to be in ms.\n */\nfunction parseCssTime(time: string | number | undefined): number | null {\n if (time == null) {\n return null;\n }\n if (typeof time === 'number') {\n return time;\n }\n if (time.endsWith('ms')) {\n return coerceNumberProperty(time.substring(0, time.length - 2));\n }\n if (time.endsWith('s')) {\n return coerceNumberProperty(time.substring(0, time.length - 1)) * 1000;\n }\n if (time === '0') {\n return 0;\n }\n return null; // anything else is invalid.\n}\n\n/**\n * Internal component that wraps user-provided dialog content in a MDC dialog.\n * @docs-private\n */\n@Component({\n selector: 'mat-dialog-container',\n templateUrl: 'dialog-container.html',\n styleUrls: ['dialog.css'],\n encapsulation: ViewEncapsulation.None,\n // Disabled for consistency with the non-MDC dialog container.\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n host: {\n 'class': 'mat-mdc-dialog-container mdc-dialog',\n 'tabindex': '-1',\n '[attr.aria-modal]': '_config.ariaModal',\n '[id]': '_config.id',\n '[attr.role]': '_config.role',\n '[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',\n '[attr.aria-label]': '_config.ariaLabel',\n '[attr.aria-describedby]': '_config.ariaDescribedBy || null',\n '[class._mat-animation-noopable]': '!_animationsEnabled',\n },\n})\nexport class MatDialogContainer extends _MatDialogContainerBase implements OnDestroy {\n /** Whether animations are enabled. */\n _animationsEnabled: boolean = this._animationMode !== 'NoopAnimations';\n\n /** Host element of the dialog container component. */\n private _hostElement: HTMLElement = this._elementRef.nativeElement;\n /** Duration of the dialog open animation. */\n private _openAnimationDuration = this._animationsEnabled\n ? parseCssTime(this._config.enterAnimationDuration) ?? OPEN_ANIMATION_DURATION\n : 0;\n /** Duration of the dialog close animation. */\n private _closeAnimationDuration = this._animationsEnabled\n ? parseCssTime(this._config.exitAnimationDuration) ?? CLOSE_ANIMATION_DURATION\n : 0;\n /** Current timer for dialog animations. */\n private _animationTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n elementRef: ElementRef,\n focusTrapFactory: FocusTrapFactory,\n @Optional() @Inject(DOCUMENT) document: any,\n dialogConfig: MatDialogConfig,\n checker: InteractivityChecker,\n ngZone: NgZone,\n overlayRef: OverlayRef,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) private _animationMode?: string,\n focusMonitor?: FocusMonitor,\n ) {\n super(\n elementRef,\n focusTrapFactory,\n document,\n dialogConfig,\n checker,\n ngZone,\n overlayRef,\n focusMonitor,\n );\n }\n\n protected override _contentAttached(): void {\n // Delegate to the original dialog-container initialization (i.e. saving the\n // previous element, setting up the focus trap and moving focus to the container).\n super._contentAttached();\n\n // Note: Usually we would be able to use the MDC dialog foundation here to handle\n // the dialog animation for us, but there are a few reasons why we just leverage\n // their styles and not use the runtime foundation code:\n // 1. Foundation does not allow us to disable animations.\n // 2. Foundation contains unnecessary features we don't need and aren't\n // tree-shakeable. e.g. background scrim, keyboard event handlers for ESC button.\n // 3. Foundation uses unnecessary timers for animations to work around limitations\n // in React's `setState` mechanism.\n // https://github.com/material-components/material-components-web/pull/3682.\n this._startOpenAnimation();\n }\n\n override ngOnDestroy() {\n super.ngOnDestroy();\n\n if (this._animationTimer !== null) {\n clearTimeout(this._animationTimer);\n }\n }\n\n /** Starts the dialog open animation if enabled. */\n private _startOpenAnimation() {\n this._animationStateChanged.emit({state: 'opening', totalTime: this._openAnimationDuration});\n\n if (this._animationsEnabled) {\n this._hostElement.style.setProperty(\n TRANSITION_DURATION_PROPERTY,\n `${this._openAnimationDuration}ms`,\n );\n\n // We need to give the `setProperty` call from above some time to be applied.\n // One would expect that the open class is added once the animation finished, but MDC\n // uses the open class in combination with the opening class to start the animation.\n this._requestAnimationFrame(() => this._hostElement.classList.add(OPENING_CLASS, OPEN_CLASS));\n this._waitForAnimationToComplete(this._openAnimationDuration, this._finishDialogOpen);\n } else {\n this._hostElement.classList.add(OPEN_CLASS);\n // Note: We could immediately finish the dialog opening here with noop animations,\n // but we defer until next tick so that consumers can subscribe to `afterOpened`.\n // Executing this immediately would mean that `afterOpened` emits synchronously\n // on `dialog.open` before the consumer had a change to subscribe to `afterOpened`.\n Promise.resolve().then(() => this._finishDialogOpen());\n }\n }\n\n /**\n * Starts the exit animation of the dialog if enabled. This method is\n * called by the dialog ref.\n */\n _startExitAnimation(): void {\n this._animationStateChanged.emit({state: 'closing', totalTime: this._closeAnimationDuration});\n this._hostElement.classList.remove(OPEN_CLASS);\n\n if (this._animationsEnabled) {\n this._hostElement.style.setProperty(\n TRANSITION_DURATION_PROPERTY,\n `${this._openAnimationDuration}ms`,\n );\n\n // We need to give the `setProperty` call from above some time to be applied.\n this._requestAnimationFrame(() => this._hostElement.classList.add(CLOSING_CLASS));\n this._waitForAnimationToComplete(this._closeAnimationDuration, this._finishDialogClose);\n } else {\n // This subscription to the `OverlayRef#backdropClick` observable in the `DialogRef` is\n // set up before any user can subscribe to the backdrop click. The subscription triggers\n // the dialog close and this method synchronously. If we'd synchronously emit the `CLOSED`\n // animation state event if animations are disabled, the overlay would be disposed\n // immediately and all other subscriptions to `DialogRef#backdropClick` would be silently\n // skipped. We work around this by waiting with the dialog close until the next tick when\n // all subscriptions have been fired as expected. This is not an ideal solution, but\n // there doesn't seem to be any other good way. Alternatives that have been considered:\n // 1. Deferring `DialogRef.close`. This could be a breaking change due to a new microtask.\n // Also this issue is specific to the MDC implementation where the dialog could\n // technically be closed synchronously. In the non-MDC one, Angular animations are used\n // and closing always takes at least a tick.\n // 2. Ensuring that user subscriptions to `backdropClick`, `keydownEvents` in the dialog\n // ref are first. This would solve the issue, but has the risk of memory leaks and also\n // doesn't solve the case where consumers call `DialogRef.close` in their subscriptions.\n // Based on the fact that this is specific to the MDC-based implementation of the dialog\n // animations, the defer is applied here.\n Promise.resolve().then(() => this._finishDialogClose());\n }\n }\n\n /**\n * Completes the dialog open by clearing potential animation classes, trapping\n * focus and emitting an opened event.\n */\n private _finishDialogOpen = () => {\n this._clearAnimationClasses();\n this._openAnimationDone(this._openAnimationDuration);\n };\n\n /**\n * Completes the dialog close by clearing potential animation classes, restoring\n * focus and emitting a closed event.\n */\n private _finishDialogClose = () => {\n this._clearAnimationClasses();\n this._animationStateChanged.emit({state: 'closed', totalTime: this._closeAnimationDuration});\n };\n\n /** Clears all dialog animation classes. */\n private _clearAnimationClasses() {\n this._hostElement.classList.remove(OPENING_CLASS, CLOSING_CLASS);\n }\n\n private _waitForAnimationToComplete(duration: number, callback: () => void) {\n if (this._animationTimer !== null) {\n clearTimeout(this._animationTimer);\n }\n\n // Note that we want this timer to run inside the NgZone, because we want\n // the related events like `afterClosed` to be inside the zone as well.\n this._animationTimer = setTimeout(callback, duration);\n }\n\n /** Runs a callback in `requestAnimationFrame`, if available. */\n private _requestAnimationFrame(callback: () => void) {\n this._ngZone.runOutsideAngular(() => {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(callback);\n } else {\n callback();\n }\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Possible states of the lifecycle of a dialog. */\nimport {FocusOrigin} from '@angular/cdk/a11y';\nimport {merge, Observable, Subject} from 'rxjs';\nimport {DialogRef} from '@angular/cdk/dialog';\nimport {DialogPosition, MatDialogConfig} from './dialog-config';\nimport {_MatDialogContainerBase} from './dialog-container';\nimport {filter, take} from 'rxjs/operators';\nimport {ESCAPE, hasModifierKey} from '@angular/cdk/keycodes';\nimport {GlobalPositionStrategy} from '@angular/cdk/overlay';\n\nexport const enum MatDialogState {\n OPEN,\n CLOSING,\n CLOSED,\n}\n\n/**\n * Reference to a dialog opened via the MatDialog service.\n */\nexport class MatDialogRef<T, R = any> {\n /** The instance of component opened into the dialog. */\n componentInstance: T;\n\n /** Whether the user is allowed to close the dialog. */\n disableClose: boolean | undefined;\n\n /** Unique ID for the dialog. */\n id: string;\n\n /** Subject for notifying the user that the dialog has finished opening. */\n private readonly _afterOpened = new Subject<void>();\n\n /** Subject for notifying the user that the dialog has started closing. */\n private readonly _beforeClosed = new Subject<R | undefined>();\n\n /** Result to be passed to afterClosed. */\n private _result: R | undefined;\n\n /** Handle to the timeout that's running as a fallback in case the exit animation doesn't fire. */\n private _closeFallbackTimeout: number;\n\n /** Current state of the dialog. */\n private _state = MatDialogState.OPEN;\n\n // TODO(crisbeto): we shouldn't have to declare this property, because `DialogRef.close`\n // already has a second `options` parameter that we can use. The problem is that internal tests\n // have assertions like `expect(MatDialogRef.close).toHaveBeenCalledWith(foo)` which will break,\n // because it'll be called with two arguments by things like `MatDialogClose`.\n /** Interaction that caused the dialog to close. */\n private _closeInteractionType: FocusOrigin | undefined;\n\n constructor(\n private _ref: DialogRef<R, T>,\n config: MatDialogConfig,\n public _containerInstance: _MatDialogContainerBase,\n ) {\n this.disableClose = config.disableClose;\n this.id = _ref.id;\n\n // Emit when opening animation completes\n _containerInstance._animationStateChanged\n .pipe(\n filter(event => event.state === 'opened'),\n take(1),\n )\n .subscribe(() => {\n this._afterOpened.next();\n this._afterOpened.complete();\n });\n\n // Dispose overlay when closing animation is complete\n _containerInstance._animationStateChanged\n .pipe(\n filter(event => event.state === 'closed'),\n take(1),\n )\n .subscribe(() => {\n clearTimeout(this._closeFallbackTimeout);\n this._finishDialogClose();\n });\n\n _ref.overlayRef.detachments().subscribe(() => {\n this._beforeClosed.next(this._result);\n this._beforeClosed.complete();\n this._finishDialogClose();\n });\n\n merge(\n this.backdropClick(),\n this.keydownEvents().pipe(\n filter(event => event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)),\n ),\n ).subscribe(event => {\n if (!this.disableClose) {\n event.preventDefault();\n _closeDialogVia(this, event.type === 'keydown' ? 'keyboard' : 'mouse');\n }\n });\n }\n\n /**\n * Close the dialog.\n * @param dialogResult Optional result to return to the dialog opener.\n */\n close(dialogResult?: R): void {\n this._result = dialogResult;\n\n // Transition the backdrop in parallel to the dialog.\n this._containerInstance._animationStateChanged\n .pipe(\n filter(event => event.state === 'closing'),\n take(1),\n )\n .subscribe(event => {\n this._beforeClosed.next(dialogResult);\n this._beforeClosed.complete();\n this._ref.overlayRef.detachBackdrop();\n\n // The logic that disposes of the overlay depends on the exit animation completing, however\n // it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback\n // timeout which will clean everything up if the animation hasn't fired within the specified\n // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the\n // vast majority of cases the timeout will have been cleared before it has the chance to fire.\n this._closeFallbackTimeout = setTimeout(\n () => this._finishDialogClose(),\n event.totalTime + 100,\n );\n });\n\n this._state = MatDialogState.CLOSING;\n this._containerInstance._startExitAnimation();\n }\n\n /**\n * Gets an observable that is notified when the dialog is finished opening.\n */\n afterOpened(): Observable<void> {\n return this._afterOpened;\n }\n\n /**\n * Gets an observable that is notified when the dialog is finished closing.\n */\n afterClosed(): Observable<R | undefined> {\n return this._ref.closed;\n }\n\n /**\n * Gets an observable that is notified when the dialog has started closing.\n */\n beforeClosed(): Observable<R | undefined> {\n return this._beforeClosed;\n }\n\n /**\n * Gets an observable that emits when the overlay's backdrop has been clicked.\n */\n backdropClick(): Observable<MouseEvent> {\n return this._ref.backdropClick;\n }\n\n /**\n * Gets an observable that emits when keydown events are targeted on the overlay.\n */\n keydownEvents(): Observable<KeyboardEvent> {\n return this._ref.keydownEvents;\n }\n\n /**\n * Updates the dialog's position.\n * @param position New dialog position.\n */\n updatePosition(position?: DialogPosition): this {\n let strategy = this._ref.config.positionStrategy as GlobalPositionStrategy;\n\n if (position && (position.left || position.right)) {\n position.left ? strategy.left(position.left) : strategy.right(position.right);\n } else {\n strategy.centerHorizontally();\n }\n\n if (position && (position.top || position.bottom)) {\n position.top ? strategy.top(position.top) : strategy.bottom(position.bottom);\n } else {\n strategy.centerVertically();\n }\n\n this._ref.updatePosition();\n\n return this;\n }\n\n /**\n * Updates the dialog's width and height.\n * @param width New width of the dialog.\n * @param height New height of the dialog.\n */\n updateSize(width: string = '', height: string = ''): this {\n this._ref.updateSize(width, height);\n return this;\n }\n\n /** Add a CSS class or an array of classes to the overlay pane. */\n addPanelClass(classes: string | string[]): this {\n this._ref.addPanelClass(classes);\n return this;\n }\n\n /** Remove a CSS class or an array of classes from the overlay pane. */\n removePanelClass(classes: string | string[]): this {\n this._ref.removePanelClass(classes);\n return this;\n }\n\n /** Gets the current state of the dialog's lifecycle. */\n getState(): MatDialogState {\n return this._state;\n }\n\n /**\n * Finishes the dialog close by updating the state of the dialog\n * and disposing the overlay.\n */\n private _finishDialogClose() {\n this._state = MatDialogState.CLOSED;\n this._ref.close(this._result, {focusOrigin: this._closeInteractionType});\n this.componentInstance = null!;\n }\n}\n\n/**\n * Closes the dialog with the specified interaction type. This is currently not part of\n * `MatDialogRef` as that would conflict with custom dialog ref mocks provided in tests.\n * More details. See: https://github.com/angular/components/pull/9257#issuecomment-651342226.\n */\n// TODO: Move this back into `MatDialogRef` when we provide an official mock dialog ref.\nexport function _closeDialogVia<R>(ref: MatDialogRef<R>, interactionType: FocusOrigin, result?: R) {\n (ref as unknown as {_closeInteractionType: FocusOrigin})._closeInteractionType = interactionType;\n return ref.close(result);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ComponentType, Overlay, OverlayContainer, ScrollStrategy} from '@angular/cdk/overlay';\nimport {Location} from '@angular/common';\nimport {\n ANIMATION_MODULE_TYPE,\n Inject,\n Injectable,\n InjectionToken,\n Injector,\n OnDestroy,\n Optional,\n SkipSelf,\n TemplateRef,\n Type,\n} from '@angular/core';\nimport {MatDialogConfig} from './dialog-config';\nimport {_MatDialogContainerBase, MatDialogContainer} from './dialog-container';\nimport {MatDialogRef} from './dialog-ref';\nimport {defer, Observable, Subject} from 'rxjs';\nimport {Dialog, DialogConfig} from '@angular/cdk/dialog';\nimport {startWith} from 'rxjs/operators';\n\n/** Injection token that can be used to access the data that was passed in to a dialog. */\nexport const MAT_DIALOG_DATA = new InjectionToken<any>('MatMdcDialogData');\n\n/** Injection token that can be used to specify default dialog options. */\nexport const MAT_DIALOG_DEFAULT_OPTIONS = new InjectionToken<MatDialogConfig>(\n 'mat-mdc-dialog-default-options',\n);\n\n/** Injection token that determines the scroll handling while the dialog is open. */\nexport const MAT_DIALOG_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'mat-mdc-dialog-scroll-strategy',\n);\n\n/** @docs-private */\nexport function MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY(\n overlay: Overlay,\n): () => ScrollStrategy {\n return () => overlay.scrollStrategies.block();\n}\n\n/** @docs-private */\nexport const MAT_DIALOG_SCROLL_STRATEGY_PROVIDER = {\n provide: MAT_DIALOG_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY,\n};\n\n/** @docs-private */\nexport function MAT_DIALOG_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy {\n return () => overlay.scrollStrategies.block();\n}\n\n// Counter for unique dialog ids.\nlet uniqueId = 0;\n\n/**\n * Base class for dialog services. The base dialog service allows\n * for arbitrary dialog refs and dialog container components.\n */\n@Injectable()\nexport abstract class _MatDialogBase<C extends _MatDialogContainerBase> implements OnDestroy {\n private readonly _openDialogsAtThisLevel: MatDialogRef<any>[] = [];\n private readonly _afterAllClosedAtThisLevel = new Subject<void>();\n private readonly _afterOpenedAtThisLevel = new Subject<MatDialogRef<any>>();\n private _scrollStrategy: () => ScrollStrategy;\n protected _idPrefix = 'mat-dialog-';\n private _dialog: Dialog;\n protected dialogConfigClass = MatDialogConfig;\n\n /** Keeps track of the currently-open dialogs. */\n get openDialogs(): MatDialogRef<any>[] {\n return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel;\n }\n\n /** Stream that emits when a dialog has been opened. */\n get afterOpened(): Subject<MatDialogRef<any>> {\n return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel;\n }\n\n private _getAfterAllClosed(): Subject<void> {\n const parent = this._parentDialog;\n return parent ? parent._getAfterAllClosed() : this._afterAllClosedAtThisLevel;\n }\n\n /**\n * Stream that emits when all open dialog have finished closing.\n * Will emit on subscribe if there are no open dialogs to begin with.\n */\n readonly afterAllClosed: Observable<void> = defer(() =>\n this.openDialogs.length\n ? this._getAfterAllClosed()\n : this._getAfterAllClosed().pipe(startWith(undefined)),\n ) as Observable<any>;\n\n constructor(\n private _overlay: Overlay,\n injector: Injector,\n private _defaultOptions: MatDialogConfig | undefined,\n private _parentDialog: _MatDialogBase<C> | undefined,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 15.0.0\n */\n _overlayContainer: OverlayContainer,\n scrollStrategy: any,\n private _dialogRefConstructor: Type<MatDialogRef<any>>,\n private _dialogContainerType: Type<C>,\n private _dialogDataToken: InjectionToken<any>,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 14.0.0\n */\n _animationMode?: 'NoopAnimations' | 'BrowserAnimations',\n ) {\n this._scrollStrategy = scrollStrategy;\n this._dialog = injector.get(Dialog);\n }\n\n /**\n * Opens a modal dialog containing the given component.\n * @param component Type of the component to load into the dialog.\n * @param config Extra configuration options.\n * @returns Reference to the newly-opened dialog.\n */\n open<T, D = any, R = any>(\n component: ComponentType<T>,\n config?: MatDialogConfig<D>,\n ): MatDialogRef<T, R>;\n\n /**\n * Opens a modal dialog containing the given template.\n * @param template TemplateRef to instantiate as the dialog content.\n * @param config Extra configuration options.\n * @returns Reference to the newly-opened dialog.\n */\n open<T, D = any, R = any>(\n template: TemplateRef<T>,\n config?: MatDialogConfig<D>,\n ): MatDialogRef<T, R>;\n\n open<T, D = any, R = any>(\n template: ComponentType<T> | TemplateRef<T>,\n config?: MatDialogConfig<D>,\n ): MatDialogRef<T, R>;\n\n open<T, D = any, R = any>(\n componentOrTemplateRef: ComponentType<T> | TemplateRef<T>,\n config?: MatDialogConfig<D>,\n ): MatDialogRef<T, R> {\n let dialogRef: MatDialogRef<T, R>;\n config = {...(this._defaultOptions || new MatDialogConfig()), ...config};\n config.id = config.id || `${this._idPrefix}${uniqueId++}`;\n config.scrollStrategy = config.scrollStrategy || this._scrollStrategy();\n\n const cdkRef = this._dialog.open<R, D, T>(componentOrTemplateRef, {\n ...config,\n positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),\n // Disable closing since we need to sync it up to the animation ourselves.\n disableClose: true,\n // Disable closing on destroy, because this service cleans up its open dialogs as well.\n // We want to do the cleanup here, rather than the CDK service, because the CDK destroys\n // the dialogs immediately whereas we want it to wait for the animations to finish.\n closeOnDestroy: false,\n // Disable closing on detachments so that we can sync up the animation.\n // The Material dialog ref handles this manually.\n closeOnOverlayDetachments: false,\n container: {\n type: this._dialogContainerType,\n providers: () => [\n // Provide our config as the CDK config as well since it has the same interface as the\n // CDK one, but it contains the actual values passed in by the user for things like\n // `disableClose` which we disable for the CDK dialog since we handle it ourselves.\n {provide: this.dialogConfigClass, useValue: config},\n {provide: DialogConfig, useValue: config},\n ],\n },\n templateContext: () => ({dialogRef}),\n providers: (ref, cdkConfig, dialogContainer) => {\n dialogRef = new this._dialogRefConstructor(ref, config, dialogContainer);\n dialogRef.updatePosition(config?.position);\n return [\n {provide: this._dialogContainerType, useValue: dialogContainer},\n {provide: this._dialogDataToken, useValue: cdkConfig.data},\n {provide: this._dialogRefConstructor, useValue: dialogRef},\n ];\n },\n });\n\n // This can't be assigned in the `providers` callback, because\n // the instance hasn't been assigned to the CDK ref yet.\n dialogRef!.componentInstance = cdkRef.componentInstance!;\n\n this.openDialogs.push(dialogRef!);\n this.afterOpened.next(dialogRef!);\n\n dialogRef!.afterClosed().subscribe(() => {\n const index = this.openDialogs.indexOf(dialogRef);\n\n if (index > -1) {\n this.openDialogs.splice(index, 1);\n\n if (!this.openDialogs.length) {\n this._getAfterAllClosed().next();\n }\n }\n });\n\n return dialogRef!;\n }\n\n /**\n * Closes all of the currently-open dialogs.\n */\n closeAll(): void {\n this._closeDialogs(this.openDialogs);\n }\n\n /**\n * Finds an open dialog by its id.\n * @param id ID to use when looking up the dialog.\n */\n getDialogById(id: string): MatDialogRef<any> | undefined {\n return this.openDialogs.find(dialog => dialog.id === id);\n }\n\n ngOnDestroy() {\n // Only close the dialogs at this level on destroy\n // since the parent service may still be active.\n this._closeDialogs(this._openDialogsAtThisLevel);\n this._afterAllClosedAtThisLevel.complete();\n this._afterOpenedAtThisLevel.complete();\n }\n\n private _closeDialogs(dialogs: MatDialogRef<any>[]) {\n let i = dialogs.length;\n\n while (i--) {\n dialogs[i].close();\n }\n }\n}\n\n/**\n * Service to open Material Design modal dialogs.\n */\n@Injectable()\nexport class MatDialog extends _MatDialogBase<MatDialogContainer> {\n constructor(\n overlay: Overlay,\n injector: Injector,\n /**\n * @deprecated `_location` parameter to be removed.\n * @breaking-change 10.0.0\n */\n @Optional() location: Location,\n @Optional() @Inject(MAT_DIALOG_DEFAULT_OPTIONS) defaultOptions: MatDialogConfig,\n @Inject(MAT_DIALOG_SCROLL_STRATEGY) scrollStrategy: any,\n @Optional() @SkipSelf() parentDialog: MatDialog,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 15.0.0\n */\n overlayContainer: OverlayContainer,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 14.0.0\n */\n @Optional()\n @Inject(ANIMATION_MODULE_TYPE)\n animationMode?: 'NoopAnimations' | 'BrowserAnimations',\n ) {\n super(\n overlay,\n injector,\n defaultOptions,\n parentDialog,\n overlayContainer,\n scrollStrategy,\n MatDialogRef,\n MatDialogContainer,\n MAT_DIALOG_DATA,\n animationMode,\n );\n\n this._idPrefix = 'mat-mdc-dialog-';\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {\n animate,\n state,\n style,\n transition,\n trigger,\n AnimationTriggerMetadata,\n query,\n animateChild,\n group,\n} from '@angular/animations';\n\n/**\n * Default parameters for the animation for backwards compatibility.\n * @docs-private\n */\nexport const _defaultParams = {\n params: {enterAnimationDuration: '150ms', exitAnimationDuration: '75ms'},\n};\n\n/**\n * Animations used by MatDialog.\n * @docs-private\n */\nexport const matDialogAnimations: {\n readonly dialogContainer: AnimationTriggerMetadata;\n} = {\n /** Animation that is applied on the dialog container by default. */\n dialogContainer: trigger('dialogContainer', [\n // Note: The `enter` animation transitions to `transform: none`, because for some reason\n // specifying the transform explicitly, causes IE both to blur the dialog content and\n // decimate the animation performance. Leaving it as `none` solves both issues.\n state('void, exit', style({opacity: 0, transform: 'scale(0.7)'})),\n state('enter', style({transform: 'none'})),\n transition(\n '* => enter',\n group([\n animate(\n '{{enterAnimationDuration}} cubic-bezier(0, 0, 0.2, 1)',\n style({transform: 'none', opacity: 1}),\n ),\n query('@*', animateChild(), {optional: true}),\n ]),\n _defaultParams,\n ),\n transition(\n '* => void, * => exit',\n group([\n animate('{{exitAnimationDuration}} cubic-bezier(0.4, 0.0, 0.2, 1)', style({opacity: 0})),\n query('@*', animateChild(), {optional: true}),\n ]),\n _defaultParams,\n ),\n ]),\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Default parameters for the animation for backwards compatibility.\n * @docs-private\n * @deprecated Use `defaultParams` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const defaultParams = {\n params: {enterAnimationDuration: '150ms', exitAnimationDuration: '75ms'},\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {MatDialogConfig as DialogConfigBase, _defaultParams} from '@angular/material/dialog';\n\n/**\n * @deprecated Use `MatDialogConfig` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport class MatLegacyDialogConfig<D = any> extends DialogConfigBase<D> {\n /** Duration of the enter animation. Has to be a valid CSS value (e.g. 100ms). */\n override enterAnimationDuration?: string = _defaultParams.params.enterAnimationDuration;\n\n /** Duration of the exit animation. Has to be a valid CSS value (e.g. 50ms). */\n override exitAnimationDuration?: string = _defaultParams.params.exitAnimationDuration;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AnimationEvent} from '@angular/animations';\nimport {FocusMonitor, FocusTrapFactory, InteractivityChecker} from '@angular/cdk/a11y';\nimport {OverlayRef} from '@angular/cdk/overlay';\nimport {DOCUMENT} from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n Inject,\n NgZone,\n Optional,\n ViewEncapsulation,\n} from '@angular/core';\nimport {defaultParams} from './dialog-animations';\nimport {MatLegacyDialogConfig} from './dialog-config';\nimport {_MatDialogContainerBase, matDialogAnimations} from '@angular/material/dialog';\n\n/**\n * Internal component that wraps user-provided dialog content.\n * Animation is based on https://material.io/guidelines/motion/choreography.html.\n * @docs-private\n * @deprecated Use `MatDialogContainer` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Component({\n selector: 'mat-dialog-container',\n templateUrl: 'dialog-container.html',\n styleUrls: ['dialog.css'],\n encapsulation: ViewEncapsulation.None,\n // Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.\n // tslint:disable-next-line:validate-decorators\n changeDetection: ChangeDetectionStrategy.Default,\n animations: [matDialogAnimations.dialogContainer],\n host: {\n 'class': 'mat-dialog-container',\n 'tabindex': '-1',\n '[attr.aria-modal]': '_config.ariaModal',\n '[id]': '_config.id',\n '[attr.role]': '_config.role',\n '[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',\n '[attr.aria-label]': '_config.ariaLabel',\n '[attr.aria-describedby]': '_config.ariaDescribedBy || null',\n '[@dialogContainer]': `_getAnimationState()`,\n '(@dialogContainer.start)': '_onAnimationStart($event)',\n '(@dialogContainer.done)': '_onAnimationDone($event)',\n },\n})\nexport class MatLegacyDialogContainer extends _MatDialogContainerBase {\n /** State of the dialog animation. */\n _state: 'void' | 'enter' | 'exit' = 'enter';\n\n /** Callback, invoked whenever an animation on the host completes. */\n _onAnimationDone({toState, totalTime}: AnimationEvent) {\n if (toState === 'enter') {\n this._openAnimationDone(totalTime);\n } else if (toState === 'exit') {\n this._animationStateChanged.next({state: 'closed', totalTime});\n }\n }\n\n /** Callback, invoked when an animation on the host starts. */\n _onAnimationStart({toState, totalTime}: AnimationEvent) {\n if (toState === 'enter') {\n this._animationStateChanged.next({state: 'opening', totalTime});\n } else if (toState === 'exit' || toState === 'void') {\n this._animationStateChanged.next({state: 'closing', totalTime});\n }\n }\n\n /** Starts the dialog exit animation. */\n _startExitAnimation(): void {\n this._state = 'exit';\n\n // Mark the container for check so it can react if the\n // view container is using OnPush change detection.\n this._changeDetectorRef.markForCheck();\n }\n\n constructor(\n elementRef: ElementRef,\n focusTrapFactory: FocusTrapFactory,\n @Optional() @Inject(DOCUMENT) document: any,\n dialogConfig: MatLegacyDialogConfig,\n checker: InteractivityChecker,\n ngZone: NgZone,\n overlayRef: OverlayRef,\n private _changeDetectorRef: ChangeDetectorRef,\n focusMonitor?: FocusMonitor,\n ) {\n super(\n elementRef,\n focusTrapFactory,\n document,\n dialogConfig,\n checker,\n ngZone,\n overlayRef,\n focusMonitor,\n );\n }\n\n _getAnimationState() {\n return {\n value: this._state,\n params: {\n 'enterAnimationDuration':\n this._config.enterAnimationDuration || defaultParams.params.enterAnimationDuration,\n 'exitAnimationDuration':\n this._config.exitAnimationDuration || defaultParams.params.exitAnimationDuration,\n },\n };\n }\n}\n","<ng-template cdkPortalOutlet></ng-template>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {MatDialogRef as NewDialogRef} from '@angular/material/dialog';\n\n/**\n * Reference to a dialog opened via the MatDialog service.\n * @deprecated Use `MatDialogRef` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport class MatLegacyDialogRef<T, R = any> extends NewDialogRef<T, R> {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Overlay, OverlayContainer, ScrollStrategy} from '@angular/cdk/overlay';\nimport {Location} from '@angular/common';\nimport {Inject, Injectable, InjectionToken, Injector, Optional, SkipSelf} from '@angular/core';\nimport {MatLegacyDialogContainer} from './dialog-container';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\nimport {_MatDialogBase} from '@angular/material/dialog';\nimport {MatLegacyDialogRef} from './dialog-ref';\nimport {MatLegacyDialogConfig} from './dialog-config';\n\n/**\n * Injection token that can be used to access the data that was passed in to a dialog.\n * @deprecated Use `MAT_DIALOG_DATA` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const MAT_LEGACY_DIALOG_DATA = new InjectionToken<any>('MatDialogData');\n\n/**\n * Injection token that can be used to specify default dialog options.\n * @deprecated Use `MAT_DIALOG_DEFAULT_OPTIONS` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const MAT_LEGACY_DIALOG_DEFAULT_OPTIONS = new InjectionToken<MatLegacyDialogConfig>(\n 'mat-dialog-default-options',\n);\n\n/**\n * Injection token that determines the scroll handling while the dialog is open.\n * @deprecated Use `MAT_DIALOG_SCROLL_STRATEGY` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const MAT_LEGACY_DIALOG_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'mat-dialog-scroll-strategy',\n);\n\n/**\n * @docs-private\n * @deprecated Use `MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport function MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY(\n overlay: Overlay,\n): () => ScrollStrategy {\n return () => overlay.scrollStrategies.block();\n}\n\n/**\n * @docs-private\n * @deprecated Use `MAT_DIALOG_SCROLL_STRATEGY_PROVIDER` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER = {\n provide: MAT_LEGACY_DIALOG_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY,\n};\n\n/**\n * Service to open Material Design modal dialogs.\n * @deprecated Use `MatDialog` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Injectable()\nexport class MatLegacyDialog extends _MatDialogBase<MatLegacyDialogContainer> {\n protected override dialogConfigClass = MatLegacyDialogConfig;\n\n constructor(\n overlay: Overlay,\n injector: Injector,\n /**\n * @deprecated `_location` parameter to be removed.\n * @breaking-change 10.0.0\n */\n @Optional() _location: Location,\n @Optional() @Inject(MAT_LEGACY_DIALOG_DEFAULT_OPTIONS) defaultOptions: MatLegacyDialogConfig,\n @Inject(MAT_LEGACY_DIALOG_SCROLL_STRATEGY) scrollStrategy: any,\n @Optional() @SkipSelf() parentDialog: MatLegacyDialog,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 15.0.0\n */\n overlayContainer: OverlayContainer,\n /**\n * @deprecated No longer used. To be removed.\n * @breaking-change 14.0.0\n */\n @Optional()\n @Inject(ANIMATION_MODULE_TYPE)\n animationMode?: 'NoopAnimations' | 'BrowserAnimations',\n ) {\n super(\n overlay,\n injector,\n defaultOptions,\n parentDialog,\n overlayContainer,\n scrollStrategy,\n MatLegacyDialogRef,\n MatLegacyDialogContainer,\n MAT_LEGACY_DIALOG_DATA,\n animationMode,\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DialogModule} from '@angular/cdk/dialog';\nimport {OverlayModule} from '@angular/cdk/overlay';\nimport {PortalModule} from '@angular/cdk/portal';\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '@angular/material/core';\nimport {MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER, MatLegacyDialog} from './dialog';\nimport {MatLegacyDialogContainer} from './dialog-container';\nimport {\n MatLegacyDialogActions,\n MatLegacyDialogClose,\n MatLegacyDialogContent,\n MatLegacyDialogTitle,\n} from './dialog-content-directives';\n\n/**\n * @deprecated Use `MatDialogModule` from `@angular/material/dialog` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@NgModule({\n imports: [DialogModule, OverlayModule, PortalModule, MatCommonModule],\n exports: [\n MatLegacyDialogContainer,\n MatLegacyDialogClose,\n MatLegacyDialogTitle,\n MatLegacyDialogContent,\n MatLegacyDialogActions,\n MatCommonModule,\n ],\n declarations: [\n MatLegacyDialogContainer,\n MatLegacyDialogClose,\n MatLegacyDialogTitle,\n MatLegacyDialogActions,\n MatLegacyDialogContent,\n ],\n providers: [MatLegacyDialog, MAT_LEGACY_DIALOG_SCROLL_STRATEGY_PROVIDER],\n})\nexport class MatLegacyDialogModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EventEmitter, TemplateRef, InjectionToken} from '@angular/core';\nimport {MenuPositionX, MenuPositionY} from './menu-positions';\nimport {Direction} from '@angular/cdk/bidi';\nimport {FocusOrigin} from '@angular/cdk/a11y';\nimport {MatMenuContent} from './menu-content';\n\n/**\n * Injection token used to provide the parent menu to menu-specific components.\n * @docs-private\n */\nexport const MAT_MENU_PANEL = new InjectionToken<MatMenuPanel>('MAT_MENU_PANEL');\n\n/**\n * Interface for a custom menu panel that can be used with `matMenuTriggerFor`.\n * @docs-private\n */\nexport interface MatMenuPanel<T = any> {\n xPosition: MenuPositionX;\n yPosition: MenuPositionY;\n overlapTrigger: boolean;\n templateRef: TemplateRef<any>;\n readonly close: EventEmitter<void | 'click' | 'keydown' | 'tab'>;\n parentMenu?: MatMenuPanel | undefined;\n direction?: Direction;\n focusFirstItem: (origin?: FocusOrigin) => void;\n resetActiveItem: () => void;\n setPositionClasses?: (x: MenuPositionX, y: MenuPositionY) => void;\n setElevation?(depth: number): void;\n lazyContent?: MatMenuContent;\n backdropClass?: string;\n overlayPanelClass?: string | string[];\n hasBackdrop?: boolean;\n readonly panelId?: string;\n\n /**\n * @deprecated To be removed.\n * @breaking-change 8.0.0\n */\n addItem?: (item: T) => void;\n\n /**\n * @deprecated To be removed.\n * @breaking-change 8.0.0\n */\n removeItem?: (item: T) => void;\n}\n","<ng-content select=\"mat-icon, [matMenuItemIcon]\"></ng-content>\n<span class=\"mdc-list-item__primary-text\"><ng-content></ng-content></span>\n<div class=\"mat-mdc-menu-ripple\" matRipple\n [matRippleDisabled]=\"disableRipple || disabled\"\n [matRippleTrigger]=\"_getHostElement()\">\n</div>\n<svg\n *ngIf=\"_triggersSubmenu\"\n class=\"mat-mdc-menu-submenu-icon\"\n viewBox=\"0 0 5 10\"\n focusable=\"false\"><polygon points=\"0,0 5,5 0,10\"/></svg>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n OnDestroy,\n ViewEncapsulation,\n Inject,\n Optional,\n Input,\n AfterViewInit,\n ChangeDetectorRef,\n} from '@angular/core';\nimport {\n CanDisable,\n CanDisableRipple,\n mixinDisabled,\n mixinDisableRipple,\n} from '@angular/material/core';\nimport {FocusableOption, FocusMonitor, FocusOrigin} from '@angular/cdk/a11y';\nimport {Subject} from 'rxjs';\nimport {DOCUMENT} from '@angular/common';\nimport {MatMenuPanel, MAT_MENU_PANEL} from './menu-panel';\n\n// Boilerplate for applying mixins to MatMenuItem.\n/** @docs-private */\nconst _MatMenuItemBase = mixinDisableRipple(mixinDisabled(class {}));\n\n/**\n * Single item inside of a `mat-menu`. Provides the menu item styling and accessibility treatment.\n */\n@Component({\n selector: '[mat-menu-item]',\n exportAs: 'matMenuItem',\n inputs: ['disabled', 'disableRipple'],\n host: {\n '[attr.role]': 'role',\n 'class': 'mat-mdc-menu-item mat-mdc-focus-indicator mdc-list-item',\n '[class.mat-mdc-menu-item-highlighted]': '_highlighted',\n '[class.mat-mdc-menu-item-submenu-trigger]': '_triggersSubmenu',\n '[attr.tabindex]': '_getTabIndex()',\n '[attr.aria-disabled]': 'disabled',\n '[attr.disabled]': 'disabled || null',\n '(click)': '_checkDisabled($event)',\n '(mouseenter)': '_handleMouseEnter()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n templateUrl: 'menu-item.html',\n})\nexport class MatMenuItem\n extends _MatMenuItemBase\n implements FocusableOption, CanDisable, CanDisableRipple, AfterViewInit, OnDestroy\n{\n /** ARIA role for the menu item. */\n @Input() role: 'menuitem' | 'menuitemradio' | 'menuitemcheckbox' = 'menuitem';\n\n /** Stream that emits when the menu item is hovered. */\n readonly _hovered: Subject<MatMenuItem> = new Subject<MatMenuItem>();\n\n /** Stream that emits when the menu item is focused. */\n readonly _focused = new Subject<MatMenuItem>();\n\n /** Whether the menu item is highlighted. */\n _highlighted: boolean = false;\n\n /** Whether the menu item acts as a trigger for a sub-menu. */\n _triggersSubmenu: boolean = false;\n\n constructor(\n elementRef: ElementRef<HTMLElement>,\n document: any,\n focusMonitor: FocusMonitor,\n parentMenu: MatMenuPanel<MatMenuItem> | undefined,\n changeDetectorRef: ChangeDetectorRef,\n );\n\n /**\n * @deprecated `document`, `changeDetectorRef` and `focusMonitor` to become required.\n * @breaking-change 12.0.0\n */\n constructor(\n elementRef: ElementRef<HTMLElement>,\n document?: any,\n focusMonitor?: FocusMonitor,\n parentMenu?: MatMenuPanel<MatMenuItem>,\n changeDetectorRef?: ChangeDetectorRef,\n );\n\n constructor(\n private _elementRef: ElementRef<HTMLElement>,\n @Inject(DOCUMENT) private _document?: any,\n private _focusMonitor?: FocusMonitor,\n @Inject(MAT_MENU_PANEL) @Optional() public _parentMenu?: MatMenuPanel<MatMenuItem>,\n private _changeDetectorRef?: ChangeDetectorRef,\n ) {\n super();\n _parentMenu?.addItem?.(this);\n }\n\n /** Focuses the menu item. */\n focus(origin?: FocusOrigin, options?: FocusOptions): void {\n if (this._focusMonitor && origin) {\n this._focusMonitor.focusVia(this._getHostElement(), origin, options);\n } else {\n this._getHostElement().focus(options);\n }\n\n this._focused.next(this);\n }\n\n ngAfterViewInit() {\n if (this._focusMonitor) {\n // Start monitoring the element so it gets the appropriate focused classes. We want\n // to show the focus style for menu items only when the focus was not caused by a\n // mouse or touch interaction.\n this._focusMonitor.monitor(this._elementRef, false);\n }\n }\n\n ngOnDestroy() {\n if (this._focusMonitor) {\n this._focusMonitor.stopMonitoring(this._elementRef);\n }\n\n if (this._parentMenu && this._parentMenu.removeItem) {\n this._parentMenu.removeItem(this);\n }\n\n this._hovered.complete();\n this._focused.complete();\n }\n\n /** Used to set the `tabindex`. */\n _getTabIndex(): string {\n return this.disabled ? '-1' : '0';\n }\n\n /** Returns the host DOM element. */\n _getHostElement(): HTMLElement {\n return this._elementRef.nativeElement;\n }\n\n /** Prevents the default element actions if it is disabled. */\n _checkDisabled(event: Event): void {\n if (this.disabled) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n\n /** Emits to the hover stream. */\n _handleMouseEnter() {\n this._hovered.next(this);\n }\n\n /** Gets the label to be used when determining whether the option should be focused. */\n getLabel(): string {\n const clone = this._elementRef.nativeElement.cloneNode(true) as HTMLElement;\n const icons = clone.querySelectorAll('mat-icon, .material-icons');\n\n // Strip away icons so they don't show up in the text.\n for (let i = 0; i < icons.length; i++) {\n icons[i].remove();\n }\n\n return clone.textContent?.trim() || '';\n }\n\n _setHighlighted(isHighlighted: boolean) {\n // We need to mark this for check for the case where the content is coming from a\n // `matMenuContent` whose change detection tree is at the declaration position,\n // not the insertion position. See #23175.\n // @breaking-change 12.0.0 Remove null check for `_changeDetectorRef`.\n this._highlighted = isHighlighted;\n this._changeDetectorRef?.markForCheck();\n }\n\n _setTriggersSubmenu(triggersSubmenu: boolean) {\n // @breaking-change 12.0.0 Remove null check for `_changeDetectorRef`.\n this._triggersSubmenu = triggersSubmenu;\n this._changeDetectorRef?.markForCheck();\n }\n\n _hasFocus(): boolean {\n return this._document && this._document.activeElement === this._getHostElement();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DomPortalOutlet, TemplatePortal} from '@angular/cdk/portal';\nimport {DOCUMENT} from '@angular/common';\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n ComponentFactoryResolver,\n Directive,\n Inject,\n InjectionToken,\n Injector,\n OnDestroy,\n TemplateRef,\n ViewContainerRef,\n} from '@angular/core';\nimport {Subject} from 'rxjs';\n\n/**\n * Injection token that can be used to reference instances of `MatMenuContent`. It serves\n * as alternative token to the actual `MatMenuContent` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const MAT_MENU_CONTENT = new InjectionToken<MatMenuContent>('MatMenuContent');\n\n@Directive()\nexport abstract class _MatMenuContentBase implements OnDestroy {\n private _portal: TemplatePortal<any>;\n private _outlet: DomPortalOutlet;\n\n /** Emits when the menu content has been attached. */\n readonly _attached = new Subject<void>();\n\n constructor(\n template: TemplateRef<any>,\n componentFactoryResolver: ComponentFactoryResolver,\n appRef: ApplicationRef,\n injector: Injector,\n viewContainerRef: ViewContainerRef,\n document: any,\n changeDetectorRef: ChangeDetectorRef,\n );\n\n /**\n * @deprecated `changeDetectorRef` is now a required parameter.\n * @breaking-change 9.0.0\n */\n constructor(\n template: TemplateRef<any>,\n componentFactoryResolver: ComponentFactoryResolver,\n appRef: ApplicationRef,\n injector: Injector,\n viewContainerRef: ViewContainerRef,\n document: any,\n changeDetectorRef?: ChangeDetectorRef,\n );\n\n constructor(\n private _template: TemplateRef<any>,\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _appRef: ApplicationRef,\n private _injector: Injector,\n private _viewContainerRef: ViewContainerRef,\n @Inject(DOCUMENT) private _document: any,\n private _changeDetectorRef?: ChangeDetectorRef,\n ) {}\n\n /**\n * Attaches the content with a particular context.\n * @docs-private\n */\n attach(context: any = {}) {\n if (!this._portal) {\n this._portal = new TemplatePortal(this._template, this._viewContainerRef);\n }\n\n this.detach();\n\n if (!this._outlet) {\n this._outlet = new DomPortalOutlet(\n this._document.createElement('div'),\n this._componentFactoryResolver,\n this._appRef,\n this._injector,\n );\n }\n\n const element: HTMLElement = this._template.elementRef.nativeElement;\n\n // Because we support opening the same menu from different triggers (which in turn have their\n // own `OverlayRef` panel), we have to re-insert the host element every time, otherwise we\n // risk it staying attached to a pane that's no longer in the DOM.\n element.parentNode!.insertBefore(this._outlet.outletElement, element);\n\n // When `MatMenuContent` is used in an `OnPush` component, the insertion of the menu\n // content via `createEmbeddedView` does not cause the content to be seen as \"dirty\"\n // by Angular. This causes the `@ContentChildren` for menu items within the menu to\n // not be updated by Angular. By explicitly marking for check here, we tell Angular that\n // it needs to check for new menu items and update the `@ContentChild` in `MatMenu`.\n // @breaking-change 9.0.0 Make change detector ref required\n this._changeDetectorRef?.markForCheck();\n this._portal.attach(this._outlet, context);\n this._attached.next();\n }\n\n /**\n * Detaches the content.\n * @docs-private\n */\n detach() {\n if (this._portal.isAttached) {\n this._portal.detach();\n }\n }\n\n ngOnDestroy() {\n if (this._outlet) {\n this._outlet.dispose();\n }\n }\n}\n\n/** Menu content that will be rendered lazily once the menu is opened. */\n@Directive({\n selector: 'ng-template[matMenuContent]',\n providers: [{provide: MAT_MENU_CONTENT, useExisting: MatMenuContent}],\n})\nexport class MatMenuContent extends _MatMenuContentBase {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n trigger,\n state,\n style,\n animate,\n transition,\n AnimationTriggerMetadata,\n} from '@angular/animations';\n\n/**\n * Animations used by the mat-menu component.\n * Animation duration and timing values are based on:\n * https://material.io/guidelines/components/menus.html#menus-usage\n * @docs-private\n */\nexport const matMenuAnimations: {\n readonly transformMenu: AnimationTriggerMetadata;\n readonly fadeInItems: AnimationTriggerMetadata;\n} = {\n /**\n * This animation controls the menu panel's entry and exit from the page.\n *\n * When the menu panel is added to the DOM, it scales in and fades in its border.\n *\n * When the menu panel is removed from the DOM, it simply fades out after a brief\n * delay to display the ripple.\n */\n transformMenu: trigger('transformMenu', [\n state(\n 'void',\n style({\n opacity: 0,\n transform: 'scale(0.8)',\n }),\n ),\n transition(\n 'void => enter',\n animate(\n '120ms cubic-bezier(0, 0, 0.2, 1)',\n style({\n opacity: 1,\n transform: 'scale(1)',\n }),\n ),\n ),\n transition('* => void', animate('100ms 25ms linear', style({opacity: 0}))),\n ]),\n\n /**\n * This animation fades in the background color and content of the menu panel\n * after its containing element is scaled in.\n */\n fadeInItems: trigger('fadeInItems', [\n // TODO(crisbeto): this is inside the `transformMenu`\n // now. Remove next time we do breaking changes.\n state('showing', style({opacity: 1})),\n transition('void => *', [\n style({opacity: 0}),\n animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)'),\n ]),\n ]),\n};\n\n/**\n * @deprecated\n * @breaking-change 8.0.0\n * @docs-private\n */\nexport const fadeInItems = matMenuAnimations.fadeInItems;\n\n/**\n * @deprecated\n * @breaking-change 8.0.0\n * @docs-private\n */\nexport const transformMenu = matMenuAnimations.transformMenu;\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n AfterContentInit,\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Input,\n NgZone,\n OnDestroy,\n Output,\n TemplateRef,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n OnInit,\n ChangeDetectorRef,\n} from '@angular/core';\nimport {AnimationEvent} from '@angular/animations';\nimport {FocusKeyManager, FocusOrigin} from '@angular/cdk/a11y';\nimport {Direction} from '@angular/cdk/bidi';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {\n ESCAPE,\n LEFT_ARROW,\n RIGHT_ARROW,\n DOWN_ARROW,\n UP_ARROW,\n hasModifierKey,\n} from '@angular/cdk/keycodes';\nimport {merge, Observable, Subject, Subscription} from 'rxjs';\nimport {startWith, switchMap, take} from 'rxjs/operators';\nimport {MatMenuItem} from './menu-item';\nimport {MatMenuPanel, MAT_MENU_PANEL} from './menu-panel';\nimport {MenuPositionX, MenuPositionY} from './menu-positions';\nimport {throwMatMenuInvalidPositionX, throwMatMenuInvalidPositionY} from './menu-errors';\nimport {MatMenuContent, MAT_MENU_CONTENT} from './menu-content';\nimport {matMenuAnimations} from './menu-animations';\n\nlet menuPanelUid = 0;\n\n/** Reason why the menu was closed. */\nexport type MenuCloseReason = void | 'click' | 'keydown' | 'tab';\n\n/** Default `mat-menu` options that can be overridden. */\nexport interface MatMenuDefaultOptions {\n /** The x-axis position of the menu. */\n xPosition: MenuPositionX;\n\n /** The y-axis position of the menu. */\n yPosition: MenuPositionY;\n\n /** Whether the menu should overlap the menu trigger. */\n overlapTrigger: boolean;\n\n /** Class to be applied to the menu's backdrop. */\n backdropClass: string;\n\n /** Class or list of classes to be applied to the menu's overlay panel. */\n overlayPanelClass?: string | string[];\n\n /** Whether the menu has a backdrop. */\n hasBackdrop?: boolean;\n}\n\n/** Injection token to be used to override the default options for `mat-menu`. */\nexport const MAT_MENU_DEFAULT_OPTIONS = new InjectionToken<MatMenuDefaultOptions>(\n 'mat-menu-default-options',\n {\n providedIn: 'root',\n factory: MAT_MENU_DEFAULT_OPTIONS_FACTORY,\n },\n);\n\n/** @docs-private */\nexport function MAT_MENU_DEFAULT_OPTIONS_FACTORY(): MatMenuDefaultOptions {\n return {\n overlapTrigger: false,\n xPosition: 'after',\n yPosition: 'below',\n backdropClass: 'cdk-overlay-transparent-backdrop',\n };\n}\n\n/** Base class with all of the `MatMenu` functionality. */\n@Directive()\nexport class _MatMenuBase\n implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnInit, OnDestroy\n{\n private _keyManager: FocusKeyManager<MatMenuItem>;\n private _xPosition: MenuPositionX = this._defaultOptions.xPosition;\n private _yPosition: MenuPositionY = this._defaultOptions.yPosition;\n private _firstItemFocusSubscription?: Subscription;\n private _previousElevation: string;\n protected _elevationPrefix: string;\n protected _baseElevation: number;\n\n /** All items inside the menu. Includes items nested inside another menu. */\n @ContentChildren(MatMenuItem, {descendants: true}) _allItems: QueryList<MatMenuItem>;\n\n /** Only the direct descendant menu items. */\n _directDescendantItems = new QueryList<MatMenuItem>();\n\n /** Config object to be passed into the menu's ngClass */\n _classList: {[key: string]: boolean} = {};\n\n /** Current state of the panel animation. */\n _panelAnimationState: 'void' | 'enter' = 'void';\n\n /** Emits whenever an animation on the menu completes. */\n readonly _animationDone = new Subject<AnimationEvent>();\n\n /** Whether the menu is animating. */\n _isAnimating: boolean;\n\n /** Parent menu of the current menu panel. */\n parentMenu: MatMenuPanel | undefined;\n\n /** Layout direction of the menu. */\n direction: Direction;\n\n /** Class or list of classes to be added to the overlay panel. */\n overlayPanelClass: string | string[] = this._defaultOptions.overlayPanelClass || '';\n\n /** Class to be added to the backdrop element. */\n @Input() backdropClass: string = this._defaultOptions.backdropClass;\n\n /** aria-label for the menu panel. */\n @Input('aria-label') ariaLabel: string;\n\n /** aria-labelledby for the menu panel. */\n @Input('aria-labelledby') ariaLabelledby: string;\n\n /** aria-describedby for the menu panel. */\n @Input('aria-describedby') ariaDescribedby: string;\n\n /** Position of the menu in the X axis. */\n @Input()\n get xPosition(): MenuPositionX {\n return this._xPosition;\n }\n set xPosition(value: MenuPositionX) {\n if (\n value !== 'before' &&\n value !== 'after' &&\n (typeof ngDevMode === 'undefined' || ngDevMode)\n ) {\n throwMatMenuInvalidPositionX();\n }\n this._xPosition = value;\n this.setPositionClasses();\n }\n\n /** Position of the menu in the Y axis. */\n @Input()\n get yPosition(): MenuPositionY {\n return this._yPosition;\n }\n set yPosition(value: MenuPositionY) {\n if (value !== 'above' && value !== 'below' && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwMatMenuInvalidPositionY();\n }\n this._yPosition = value;\n this.setPositionClasses();\n }\n\n /** @docs-private */\n @ViewChild(TemplateRef) templateRef: TemplateRef<any>;\n\n /**\n * List of the items inside of a menu.\n * @deprecated\n * @breaking-change 8.0.0\n */\n @ContentChildren(MatMenuItem, {descendants: false}) items: QueryList<MatMenuItem>;\n\n /**\n * Menu content that will be rendered lazily.\n * @docs-private\n */\n @ContentChild(MAT_MENU_CONTENT) lazyContent: MatMenuContent;\n\n /** Whether the menu should overlap its trigger. */\n @Input()\n get overlapTrigger(): boolean {\n return this._overlapTrigger;\n }\n set overlapTrigger(value: BooleanInput) {\n this._overlapTrigger = coerceBooleanProperty(value);\n }\n private _overlapTrigger: boolean = this._defaultOptions.overlapTrigger;\n\n /** Whether the menu has a backdrop. */\n @Input()\n get hasBackdrop(): boolean | undefined {\n return this._hasBackdrop;\n }\n set hasBackdrop(value: BooleanInput) {\n this._hasBackdrop = coerceBooleanProperty(value);\n }\n private _hasBackdrop: boolean | undefined = this._defaultOptions.hasBackdrop;\n\n /**\n * This method takes classes set on the host mat-menu element and applies them on the\n * menu template that displays in the overlay container. Otherwise, it's difficult\n * to style the containing menu from outside the component.\n * @param classes list of class names\n */\n @Input('class')\n set panelClass(classes: string) {\n const previousPanelClass = this._previousPanelClass;\n\n if (previousPanelClass && previousPanelClass.length) {\n previousPanelClass.split(' ').forEach((className: string) => {\n this._classList[className] = false;\n });\n }\n\n this._previousPanelClass = classes;\n\n if (classes && classes.length) {\n classes.split(' ').forEach((className: string) => {\n this._classList[className] = true;\n });\n\n this._elementRef.nativeElement.className = '';\n }\n }\n private _previousPanelClass: string;\n\n /**\n * This method takes classes set on the host mat-menu element and applies them on the\n * menu template that displays in the overlay container. Otherwise, it's difficult\n * to style the containing menu from outside the component.\n * @deprecated Use `panelClass` instead.\n * @breaking-change 8.0.0\n */\n @Input()\n get classList(): string {\n return this.panelClass;\n }\n set classList(classes: string) {\n this.panelClass = classes;\n }\n\n /** Event emitted when the menu is closed. */\n @Output() readonly closed: EventEmitter<MenuCloseReason> = new EventEmitter<MenuCloseReason>();\n\n /**\n * Event emitted when the menu is closed.\n * @deprecated Switch to `closed` instead\n * @breaking-change 8.0.0\n */\n @Output() readonly close: EventEmitter<MenuCloseReason> = this.closed;\n\n readonly panelId = `mat-menu-panel-${menuPanelUid++}`;\n\n constructor(\n elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n defaultOptions: MatMenuDefaultOptions,\n changeDetectorRef: ChangeDetectorRef,\n );\n\n /**\n * @deprecated `_changeDetectorRef` to become a required parameter.\n * @breaking-change 15.0.0\n */\n constructor(\n elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n defaultOptions: MatMenuDefaultOptions,\n changeDetectorRef?: ChangeDetectorRef,\n );\n\n constructor(\n private _elementRef: ElementRef<HTMLElement>,\n private _ngZone: NgZone,\n @Inject(MAT_MENU_DEFAULT_OPTIONS) private _defaultOptions: MatMenuDefaultOptions,\n // @breaking-change 15.0.0 `_changeDetectorRef` to become a required parameter.\n private _changeDetectorRef?: ChangeDetectorRef,\n ) {}\n\n ngOnInit() {\n this.setPositionClasses();\n }\n\n ngAfterContentInit() {\n this._updateDirectDescendants();\n this._keyManager = new FocusKeyManager(this._directDescendantItems)\n .withWrap()\n .withTypeAhead()\n .withHomeAndEnd();\n this._keyManager.tabOut.subscribe(() => this.closed.emit('tab'));\n\n // If a user manually (programmatically) focuses a menu item, we need to reflect that focus\n // change back to the key manager. Note that we don't need to unsubscribe here because _focused\n // is internal and we know that it gets completed on destroy.\n this._directDescendantItems.changes\n .pipe(\n startWith(this._directDescendantItems),\n switchMap(items => merge(...items.map((item: MatMenuItem) => item._focused))),\n )\n .subscribe(focusedItem => this._keyManager.updateActiveItem(focusedItem as MatMenuItem));\n\n this._directDescendantItems.changes.subscribe((itemsList: QueryList<MatMenuItem>) => {\n // Move focus to another item, if the active item is removed from the list.\n // We need to debounce the callback, because multiple items might be removed\n // in quick succession.\n const manager = this._keyManager;\n\n if (this._panelAnimationState === 'enter' && manager.activeItem?._hasFocus()) {\n const items = itemsList.toArray();\n const index = Math.max(0, Math.min(items.length - 1, manager.activeItemIndex || 0));\n\n if (items[index] && !items[index].disabled) {\n manager.setActiveItem(index);\n } else {\n manager.setNextItemActive();\n }\n }\n });\n }\n\n ngOnDestroy() {\n this._keyManager?.destroy();\n this._directDescendantItems.destroy();\n this.closed.complete();\n this._firstItemFocusSubscription?.unsubscribe();\n }\n\n /** Stream that emits whenever the hovered menu item changes. */\n _hovered(): Observable<MatMenuItem> {\n // Coerce the `changes` property because Angular types it as `Observable<any>`\n const itemChanges = this._directDescendantItems.changes as Observable<QueryList<MatMenuItem>>;\n return itemChanges.pipe(\n startWith(this._directDescendantItems),\n switchMap(items => merge(...items.map((item: MatMenuItem) => item._hovered))),\n ) as Observable<MatMenuItem>;\n }\n\n /*\n * Registers a menu item with the menu.\n * @docs-private\n * @deprecated No longer being used. To be removed.\n * @breaking-change 9.0.0\n */\n addItem(_item: MatMenuItem) {}\n\n /**\n * Removes an item from the menu.\n * @docs-private\n * @deprecated No longer being used. To be removed.\n * @breaking-change 9.0.0\n */\n removeItem(_item: MatMenuItem) {}\n\n /** Handle a keyboard event from the menu, delegating to the appropriate action. */\n _handleKeydown(event: KeyboardEvent) {\n const keyCode = event.keyCode;\n const manager = this._keyManager;\n\n switch (keyCode) {\n case ESCAPE:\n if (!hasModifierKey(event)) {\n event.preventDefault();\n this.closed.emit('keydown');\n }\n break;\n case LEFT_ARROW:\n if (this.parentMenu && this.direction === 'ltr') {\n this.closed.emit('keydown');\n }\n break;\n case RIGHT_ARROW:\n if (this.parentMenu && this.direction === 'rtl') {\n this.closed.emit('keydown');\n }\n break;\n default:\n if (keyCode === UP_ARROW || keyCode === DOWN_ARROW) {\n manager.setFocusOrigin('keyboard');\n }\n\n manager.onKeydown(event);\n return;\n }\n\n // Don't allow the event to propagate if we've already handled it, or it may\n // end up reaching other overlays that were opened earlier (see #22694).\n event.stopPropagation();\n }\n\n /**\n * Focus the first item in the menu.\n * @param origin Action from which the focus originated. Used to set the correct styling.\n */\n focusFirstItem(origin: FocusOrigin = 'program'): void {\n // Wait for `onStable` to ensure iOS VoiceOver screen reader focuses the first item (#24735).\n this._firstItemFocusSubscription?.unsubscribe();\n this._firstItemFocusSubscription = this._ngZone.onStable.pipe(take(1)).subscribe(() => {\n let menuPanel: HTMLElement | null = null;\n\n if (this._directDescendantItems.length) {\n // Because the `mat-menuPanel` is at the DOM insertion point, not inside the overlay, we don't\n // have a nice way of getting a hold of the menuPanel panel. We can't use a `ViewChild` either\n // because the panel is inside an `ng-template`. We work around it by starting from one of\n // the items and walking up the DOM.\n menuPanel = this._directDescendantItems.first!._getHostElement().closest('[role=\"menu\"]');\n }\n\n // If an item in the menuPanel is already focused, avoid overriding the focus.\n if (!menuPanel || !menuPanel.contains(document.activeElement)) {\n const manager = this._keyManager;\n manager.setFocusOrigin(origin).setFirstItemActive();\n\n // If there's no active item at this point, it means that all the items are disabled.\n // Move focus to the menuPanel panel so keyboard events like Escape still work. Also this will\n // give _some_ feedback to screen readers.\n if (!manager.activeItem && menuPanel) {\n menuPanel.focus();\n }\n }\n });\n }\n\n /**\n * Resets the active item in the menu. This is used when the menu is opened, allowing\n * the user to start from the first option when pressing the down arrow.\n */\n resetActiveItem() {\n this._keyManager.setActiveItem(-1);\n }\n\n /**\n * Sets the menu panel elevation.\n * @param depth Number of parent menus that come before the menu.\n */\n setElevation(depth: number): void {\n // The elevation starts at the base and increases by one for each level.\n // Capped at 24 because that's the maximum elevation defined in the Material design spec.\n const elevation = Math.min(this._baseElevation + depth, 24);\n const newElevation = `${this._elevationPrefix}${elevation}`;\n const customElevation = Object.keys(this._classList).find(className => {\n return className.startsWith(this._elevationPrefix);\n });\n\n if (!customElevation || customElevation === this._previousElevation) {\n if (this._previousElevation) {\n this._classList[this._previousElevation] = false;\n }\n\n this._classList[newElevation] = true;\n this._previousElevation = newElevation;\n }\n }\n\n /**\n * Adds classes to the menu panel based on its position. Can be used by\n * consumers to add specific styling based on the position.\n * @param posX Position of the menu along the x axis.\n * @param posY Position of the menu along the y axis.\n * @docs-private\n */\n setPositionClasses(posX: MenuPositionX = this.xPosition, posY: MenuPositionY = this.yPosition) {\n const classes = this._classList;\n classes['mat-menu-before'] = posX === 'before';\n classes['mat-menu-after'] = posX === 'after';\n classes['mat-menu-above'] = posY === 'above';\n classes['mat-menu-below'] = posY === 'below';\n\n // @breaking-change 15.0.0 Remove null check for `_changeDetectorRef`.\n this._changeDetectorRef?.markForCheck();\n }\n\n /** Starts the enter animation. */\n _startAnimation() {\n // @breaking-change 8.0.0 Combine with _resetAnimation.\n this._panelAnimationState = 'enter';\n }\n\n /** Resets the panel animation to its initial state. */\n _resetAnimation() {\n // @breaking-change 8.0.0 Combine with _startAnimation.\n this._panelAnimationState = 'void';\n }\n\n /** Callback that is invoked when the panel animation completes. */\n _onAnimationDone(event: AnimationEvent) {\n this._animationDone.next(event);\n this._isAnimating = false;\n }\n\n _onAnimationStart(event: AnimationEvent) {\n this._isAnimating = true;\n\n // Scroll the content element to the top as soon as the animation starts. This is necessary,\n // because we move focus to the first item while it's still being animated, which can throw\n // the browser off when it determines the scroll position. Alternatively we can move focus\n // when the animation is done, however moving focus asynchronously will interrupt screen\n // readers which are in the process of reading out the menu already. We take the `element`\n // from the `event` since we can't use a `ViewChild` to access the pane.\n if (event.toState === 'enter' && this._keyManager.activeItemIndex === 0) {\n event.element.scrollTop = 0;\n }\n }\n\n /**\n * Sets up a stream that will keep track of any newly-added menu items and will update the list\n * of direct descendants. We collect the descendants this way, because `_allItems` can include\n * items that are part of child menus, and using a custom way of registering items is unreliable\n * when it comes to maintaining the item order.\n */\n private _updateDirectDescendants() {\n this._allItems.changes\n .pipe(startWith(this._allItems))\n .subscribe((items: QueryList<MatMenuItem>) => {\n this._directDescendantItems.reset(items.filter(item => item._parentMenu === this));\n this._directDescendantItems.notifyOnChanges();\n });\n }\n}\n\n@Component({\n selector: 'mat-menu',\n templateUrl: 'menu.html',\n styleUrls: ['menu.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'matMenu',\n host: {\n '[attr.aria-label]': 'null',\n '[attr.aria-labelledby]': 'null',\n '[attr.aria-describedby]': 'null',\n },\n animations: [matMenuAnimations.transformMenu, matMenuAnimations.fadeInItems],\n providers: [{provide: MAT_MENU_PANEL, useExisting: MatMenu}],\n})\nexport class MatMenu extends _MatMenuBase {\n protected override _elevationPrefix = 'mat-elevation-z';\n protected override _baseElevation = 8;\n\n /*\n * @deprecated `changeDetectorRef` parameter will become a required parameter.\n * @breaking-change 15.0.0\n */\n constructor(\n elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n defaultOptions: MatMenuDefaultOptions,\n );\n\n constructor(\n _elementRef: ElementRef<HTMLElement>,\n _ngZone: NgZone,\n @Inject(MAT_MENU_DEFAULT_OPTIONS) _defaultOptions: MatMenuDefaultOptions,\n changeDetectorRef?: ChangeDetectorRef,\n ) {\n super(_elementRef, _ngZone, _defaultOptions, changeDetectorRef);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n FocusMonitor,\n FocusOrigin,\n isFakeMousedownFromScreenReader,\n isFakeTouchstartFromScreenReader,\n} from '@angular/cdk/a11y';\nimport {Direction, Directionality} from '@angular/cdk/bidi';\nimport {ENTER, LEFT_ARROW, RIGHT_ARROW, SPACE} from '@angular/cdk/keycodes';\nimport {\n FlexibleConnectedPositionStrategy,\n HorizontalConnectionPos,\n Overlay,\n OverlayConfig,\n OverlayRef,\n ScrollStrategy,\n VerticalConnectionPos,\n} from '@angular/cdk/overlay';\nimport {TemplatePortal} from '@angular/cdk/portal';\nimport {\n AfterContentInit,\n ChangeDetectorRef,\n Directive,\n ElementRef,\n EventEmitter,\n inject,\n Inject,\n InjectionToken,\n Input,\n NgZone,\n OnDestroy,\n Optional,\n Output,\n Self,\n ViewContainerRef,\n} from '@angular/core';\nimport {normalizePassiveListenerOptions} from '@angular/cdk/platform';\nimport {asapScheduler, merge, Observable, of as observableOf, Subscription} from 'rxjs';\nimport {delay, filter, take, takeUntil} from 'rxjs/operators';\nimport {_MatMenuBase, MenuCloseReason} from './menu';\nimport {throwMatMenuRecursiveError} from './menu-errors';\nimport {MatMenuItem} from './menu-item';\nimport {MAT_MENU_PANEL, MatMenuPanel} from './menu-panel';\nimport {MenuPositionX, MenuPositionY} from './menu-positions';\n\n/** Injection token that determines the scroll handling while the menu is open. */\nexport const MAT_MENU_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'mat-menu-scroll-strategy',\n);\n\n/** @docs-private */\nexport function MAT_MENU_SCROLL_STRATEGY_FACTORY(overlay: Overlay): () => ScrollStrategy {\n return () => overlay.scrollStrategies.reposition();\n}\n\n/** @docs-private */\nexport const MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER = {\n provide: MAT_MENU_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: MAT_MENU_SCROLL_STRATEGY_FACTORY,\n};\n\n/** Options for binding a passive event listener. */\nconst passiveEventListenerOptions = normalizePassiveListenerOptions({passive: true});\n\n/**\n * Default top padding of the menu panel.\n * @deprecated No longer being used. Will be removed.\n * @breaking-change 15.0.0\n */\nexport const MENU_PANEL_TOP_PADDING = 8;\n\n@Directive({\n host: {\n '[attr.aria-haspopup]': 'menu ? \"menu\" : null',\n '[attr.aria-expanded]': 'menuOpen',\n '[attr.aria-controls]': 'menuOpen ? menu.panelId : null',\n '(click)': '_handleClick($event)',\n '(mousedown)': '_handleMousedown($event)',\n '(keydown)': '_handleKeydown($event)',\n },\n})\nexport abstract class _MatMenuTriggerBase implements AfterContentInit, OnDestroy {\n private _portal: TemplatePortal;\n private _overlayRef: OverlayRef | null = null;\n private _menuOpen: boolean = false;\n private _closingActionsSubscription = Subscription.EMPTY;\n private _hoverSubscription = Subscription.EMPTY;\n private _menuCloseSubscription = Subscription.EMPTY;\n private _scrollStrategy: () => ScrollStrategy;\n private _changeDetectorRef = inject(ChangeDetectorRef);\n\n /**\n * We're specifically looking for a `MatMenu` here since the generic `MatMenuPanel`\n * interface lacks some functionality around nested menus and animations.\n */\n private _parentMaterialMenu: _MatMenuBase | undefined;\n\n /**\n * Cached value of the padding of the parent menu panel.\n * Used to offset sub-menus to compensate for the padding.\n */\n private _parentInnerPadding: number | undefined;\n\n /**\n * Handles touch start events on the trigger.\n * Needs to be an arrow function so we can easily use addEventListener and removeEventListener.\n */\n private _handleTouchStart = (event: TouchEvent) => {\n if (!isFakeTouchstartFromScreenReader(event)) {\n this._openedBy = 'touch';\n }\n };\n\n // Tracking input type is necessary so it's possible to only auto-focus\n // the first item of the list when the menu is opened via the keyboard\n _openedBy: Exclude<FocusOrigin, 'program' | null> | undefined = undefined;\n\n /**\n * @deprecated\n * @breaking-change 8.0.0\n */\n @Input('mat-menu-trigger-for')\n get _deprecatedMatMenuTriggerFor(): MatMenuPanel | null {\n return this.menu;\n }\n set _deprecatedMatMenuTriggerFor(v: MatMenuPanel | null) {\n this.menu = v;\n }\n\n /** References the menu instance that the trigger is associated with. */\n @Input('matMenuTriggerFor')\n get menu(): MatMenuPanel | null {\n return this._menu;\n }\n set menu(menu: MatMenuPanel | null) {\n if (menu === this._menu) {\n return;\n }\n\n this._menu = menu;\n this._menuCloseSubscription.unsubscribe();\n\n if (menu) {\n if (menu === this._parentMaterialMenu && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throwMatMenuRecursiveError();\n }\n\n this._menuCloseSubscription = menu.close.subscribe((reason: MenuCloseReason) => {\n this._destroyMenu(reason);\n\n // If a click closed the menu, we should close the entire chain of nested menus.\n if ((reason === 'click' || reason === 'tab') && this._parentMaterialMenu) {\n this._parentMaterialMenu.closed.emit(reason);\n }\n });\n }\n\n this._menuItemInstance?._setTriggersSubmenu(this.triggersSubmenu());\n }\n private _menu: MatMenuPanel | null;\n\n /** Data to be passed along to any lazily-rendered content. */\n @Input('matMenuTriggerData') menuData: any;\n\n /**\n * Whether focus should be restored when the menu is closed.\n * Note that disabling this option can have accessibility implications\n * and it's up to you to manage focus, if you decide to turn it off.\n */\n @Input('matMenuTriggerRestoreFocus') restoreFocus: boolean = true;\n\n /** Event emitted when the associated menu is opened. */\n @Output() readonly menuOpened: EventEmitter<void> = new EventEmitter<void>();\n\n /**\n * Event emitted when the associated menu is opened.\n * @deprecated Switch to `menuOpened` instead\n * @breaking-change 8.0.0\n */\n // tslint:disable-next-line:no-output-on-prefix\n @Output() readonly onMenuOpen: EventEmitter<void> = this.menuOpened;\n\n /** Event emitted when the associated menu is closed. */\n @Output() readonly menuClosed: EventEmitter<void> = new EventEmitter<void>();\n\n /**\n * Event emitted when the associated menu is closed.\n * @deprecated Switch to `menuClosed` instead\n * @breaking-change 8.0.0\n */\n // tslint:disable-next-line:no-output-on-prefix\n @Output() readonly onMenuClose: EventEmitter<void> = this.menuClosed;\n\n constructor(\n overlay: Overlay,\n element: ElementRef<HTMLElement>,\n viewContainerRef: ViewContainerRef,\n scrollStrategy: any,\n parentMenu: MatMenuPanel,\n menuItemInstance: MatMenuItem,\n dir: Directionality,\n focusMonitor: FocusMonitor,\n ngZone: NgZone,\n );\n\n /**\n * @deprecated `focusMonitor` will become a required parameter.\n * @breaking-change 8.0.0\n */\n constructor(\n overlay: Overlay,\n element: ElementRef<HTMLElement>,\n viewContainerRef: ViewContainerRef,\n scrollStrategy: any,\n parentMenu: MatMenuPanel,\n menuItemInstance: MatMenuItem,\n dir: Directionality,\n focusMonitor?: FocusMonitor | null,\n );\n\n /**\n * @deprecated `ngZone` will become a required parameter.\n * @breaking-change 15.0.0\n */\n constructor(\n overlay: Overlay,\n element: ElementRef<HTMLElement>,\n viewContainerRef: ViewContainerRef,\n scrollStrategy: any,\n parentMenu: MatMenuPanel,\n menuItemInstance: MatMenuItem,\n dir: Directionality,\n focusMonitor: FocusMonitor,\n );\n\n constructor(\n private _overlay: Overlay,\n private _element: ElementRef<HTMLElement>,\n private _viewContainerRef: ViewContainerRef,\n @Inject(MAT_MENU_SCROLL_STRATEGY) scrollStrategy: any,\n @Inject(MAT_MENU_PANEL) @Optional() parentMenu: MatMenuPanel,\n // `MatMenuTrigger` is commonly used in combination with a `MatMenuItem`.\n // tslint:disable-next-line: lightweight-tokens\n @Optional() @Self() private _menuItemInstance: MatMenuItem,\n @Optional() private _dir: Directionality,\n private _focusMonitor: FocusMonitor | null,\n private _ngZone?: NgZone,\n ) {\n this._scrollStrategy = scrollStrategy;\n this._parentMaterialMenu = parentMenu instanceof _MatMenuBase ? parentMenu : undefined;\n\n _element.nativeElement.addEventListener(\n 'touchstart',\n this._handleTouchStart,\n passiveEventListenerOptions,\n );\n }\n\n ngAfterContentInit() {\n this._handleHover();\n }\n\n ngOnDestroy() {\n if (this._overlayRef) {\n this._overlayRef.dispose();\n this._overlayRef = null;\n }\n\n this._element.nativeElement.removeEventListener(\n 'touchstart',\n this._handleTouchStart,\n passiveEventListenerOptions,\n );\n\n this._menuCloseSubscription.unsubscribe();\n this._closingActionsSubscription.unsubscribe();\n this._hoverSubscription.unsubscribe();\n }\n\n /** Whether the menu is open. */\n get menuOpen(): boolean {\n return this._menuOpen;\n }\n\n /** The text direction of the containing app. */\n get dir(): Direction {\n return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';\n }\n\n /** Whether the menu triggers a sub-menu or a top-level one. */\n triggersSubmenu(): boolean {\n return !!(this._menuItemInstance && this._parentMaterialMenu && this.menu);\n }\n\n /** Toggles the menu between the open and closed states. */\n toggleMenu(): void {\n return this._menuOpen ? this.closeMenu() : this.openMenu();\n }\n\n /** Opens the menu. */\n openMenu(): void {\n const menu = this.menu;\n\n if (this._menuOpen || !menu) {\n return;\n }\n\n const overlayRef = this._createOverlay(menu);\n const overlayConfig = overlayRef.getConfig();\n const positionStrategy = overlayConfig.positionStrategy as FlexibleConnectedPositionStrategy;\n\n this._setPosition(menu, positionStrategy);\n overlayConfig.hasBackdrop =\n menu.hasBackdrop == null ? !this.triggersSubmenu() : menu.hasBackdrop;\n overlayRef.attach(this._getPortal(menu));\n\n if (menu.lazyContent) {\n menu.lazyContent.attach(this.menuData);\n }\n\n this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());\n this._initMenu(menu);\n\n if (menu instanceof _MatMenuBase) {\n menu._startAnimation();\n menu._directDescendantItems.changes.pipe(takeUntil(menu.close)).subscribe(() => {\n // Re-adjust the position without locking when the amount of items\n // changes so that the overlay is allowed to pick a new optimal position.\n positionStrategy.withLockedPosition(false).reapplyLastPosition();\n positionStrategy.withLockedPosition(true);\n });\n }\n }\n\n /** Closes the menu. */\n closeMenu(): void {\n this.menu?.close.emit();\n }\n\n /**\n * Focuses the menu trigger.\n * @param origin Source of the menu trigger's focus.\n */\n focus(origin?: FocusOrigin, options?: FocusOptions) {\n if (this._focusMonitor && origin) {\n this._focusMonitor.focusVia(this._element, origin, options);\n } else {\n this._element.nativeElement.focus(options);\n }\n }\n\n /**\n * Updates the position of the menu to ensure that it fits all options within the viewport.\n */\n updatePosition(): void {\n this._overlayRef?.updatePosition();\n }\n\n /** Closes the menu and does the necessary cleanup. */\n private _destroyMenu(reason: MenuCloseReason) {\n if (!this._overlayRef || !this.menuOpen) {\n return;\n }\n\n const menu = this.menu;\n this._closingActionsSubscription.unsubscribe();\n this._overlayRef.detach();\n\n // Always restore focus if the user is navigating using the keyboard or the menu was opened\n // programmatically. We don't restore for non-root triggers, because it can prevent focus\n // from making it back to the root trigger when closing a long chain of menus by clicking\n // on the backdrop.\n if (this.restoreFocus && (reason === 'keydown' || !this._openedBy || !this.triggersSubmenu())) {\n this.focus(this._openedBy);\n }\n\n this._openedBy = undefined;\n\n if (menu instanceof _MatMenuBase) {\n menu._resetAnimation();\n\n if (menu.lazyContent) {\n // Wait for the exit animation to finish before detaching the content.\n menu._animationDone\n .pipe(\n filter(event => event.toState === 'void'),\n take(1),\n // Interrupt if the content got re-attached.\n takeUntil(menu.lazyContent._attached),\n )\n .subscribe({\n next: () => menu.lazyContent!.detach(),\n // No matter whether the content got re-attached, reset the menu.\n complete: () => this._setIsMenuOpen(false),\n });\n } else {\n this._setIsMenuOpen(false);\n }\n } else {\n this._setIsMenuOpen(false);\n menu?.lazyContent?.detach();\n }\n }\n\n /**\n * This method sets the menu state to open and focuses the first item if\n * the menu was opened via the keyboard.\n */\n private _initMenu(menu: MatMenuPanel): void {\n menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;\n menu.direction = this.dir;\n this._setMenuElevation(menu);\n menu.focusFirstItem(this._openedBy || 'program');\n this._setIsMenuOpen(true);\n }\n\n /** Updates the menu elevation based on the amount of parent menus that it has. */\n private _setMenuElevation(menu: MatMenuPanel): void {\n if (menu.setElevation) {\n let depth = 0;\n let parentMenu = menu.parentMenu;\n\n while (parentMenu) {\n depth++;\n parentMenu = parentMenu.parentMenu;\n }\n\n menu.setElevation(depth);\n }\n }\n\n // set state rather than toggle to support triggers sharing a menu\n private _setIsMenuOpen(isOpen: boolean): void {\n if (isOpen !== this._menuOpen) {\n this._menuOpen = isOpen;\n this._menuOpen ? this.menuOpened.emit() : this.menuClosed.emit();\n\n if (this.triggersSubmenu()) {\n this._menuItemInstance._setHighlighted(isOpen);\n }\n\n this._changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * This method creates the overlay from the provided menu's template and saves its\n * OverlayRef so that it can be attached to the DOM when openMenu is called.\n */\n private _createOverlay(menu: MatMenuPanel): OverlayRef {\n if (!this._overlayRef) {\n const config = this._getOverlayConfig(menu);\n this._subscribeToPositions(\n menu,\n config.positionStrategy as FlexibleConnectedPositionStrategy,\n );\n this._overlayRef = this._overlay.create(config);\n\n // Consume the `keydownEvents` in order to prevent them from going to another overlay.\n // Ideally we'd also have our keyboard event logic in here, however doing so will\n // break anybody that may have implemented the `MatMenuPanel` themselves.\n this._overlayRef.keydownEvents().subscribe();\n }\n\n return this._overlayRef;\n }\n\n /**\n * This method builds the configuration object needed to create the overlay, the OverlayState.\n * @returns OverlayConfig\n */\n private _getOverlayConfig(menu: MatMenuPanel): OverlayConfig {\n return new OverlayConfig({\n positionStrategy: this._overlay\n .position()\n .flexibleConnectedTo(this._element)\n .withLockedPosition()\n .withGrowAfterOpen()\n .withTransformOriginOn('.mat-menu-panel, .mat-mdc-menu-panel'),\n backdropClass: menu.backdropClass || 'cdk-overlay-transparent-backdrop',\n panelClass: menu.overlayPanelClass,\n scrollStrategy: this._scrollStrategy(),\n direction: this._dir,\n });\n }\n\n /**\n * Listens to changes in the position of the overlay and sets the correct classes\n * on the menu based on the new position. This ensures the animation origin is always\n * correct, even if a fallback position is used for the overlay.\n */\n private _subscribeToPositions(menu: MatMenuPanel, position: FlexibleConnectedPositionStrategy) {\n if (menu.setPositionClasses) {\n position.positionChanges.subscribe(change => {\n const posX: MenuPositionX = change.connectionPair.overlayX === 'start' ? 'after' : 'before';\n const posY: MenuPositionY = change.connectionPair.overlayY === 'top' ? 'below' : 'above';\n\n // @breaking-change 15.0.0 Remove null check for `ngZone`.\n // `positionChanges` fires outside of the `ngZone` and `setPositionClasses` might be\n // updating something in the view so we need to bring it back in.\n if (this._ngZone) {\n this._ngZone.run(() => menu.setPositionClasses!(posX, posY));\n } else {\n menu.setPositionClasses!(posX, posY);\n }\n });\n }\n }\n\n /**\n * Sets the appropriate positions on a position strategy\n * so the overlay connects with the trigger correctly.\n * @param positionStrategy Strategy whose position to update.\n */\n private _setPosition(menu: MatMenuPanel, positionStrategy: FlexibleConnectedPositionStrategy) {\n let [originX, originFallbackX]: HorizontalConnectionPos[] =\n menu.xPosition === 'before' ? ['end', 'start'] : ['start', 'end'];\n\n let [overlayY, overlayFallbackY]: VerticalConnectionPos[] =\n menu.yPosition === 'above' ? ['bottom', 'top'] : ['top', 'bottom'];\n\n let [originY, originFallbackY] = [overlayY, overlayFallbackY];\n let [overlayX, overlayFallbackX] = [originX, originFallbackX];\n let offsetY = 0;\n\n if (this.triggersSubmenu()) {\n // When the menu is a sub-menu, it should always align itself\n // to the edges of the trigger, instead of overlapping it.\n overlayFallbackX = originX = menu.xPosition === 'before' ? 'start' : 'end';\n originFallbackX = overlayX = originX === 'end' ? 'start' : 'end';\n\n if (this._parentMaterialMenu) {\n if (this._parentInnerPadding == null) {\n const firstItem = this._parentMaterialMenu.items.first;\n this._parentInnerPadding = firstItem ? firstItem._getHostElement().offsetTop : 0;\n }\n\n offsetY = overlayY === 'bottom' ? this._parentInnerPadding : -this._parentInnerPadding;\n }\n } else if (!menu.overlapTrigger) {\n originY = overlayY === 'top' ? 'bottom' : 'top';\n originFallbackY = overlayFallbackY === 'top' ? 'bottom' : 'top';\n }\n\n positionStrategy.withPositions([\n {originX, originY, overlayX, overlayY, offsetY},\n {originX: originFallbackX, originY, overlayX: overlayFallbackX, overlayY, offsetY},\n {\n originX,\n originY: originFallbackY,\n overlayX,\n overlayY: overlayFallbackY,\n offsetY: -offsetY,\n },\n {\n originX: originFallbackX,\n originY: originFallbackY,\n overlayX: overlayFallbackX,\n overlayY: overlayFallbackY,\n offsetY: -offsetY,\n },\n ]);\n }\n\n /** Returns a stream that emits whenever an action that should close the menu occurs. */\n private _menuClosingActions() {\n const backdrop = this._overlayRef!.backdropClick();\n const detachments = this._overlayRef!.detachments();\n const parentClose = this._parentMaterialMenu ? this._parentMaterialMenu.closed : observableOf();\n const hover = this._parentMaterialMenu\n ? this._parentMaterialMenu._hovered().pipe(\n filter(active => active !== this._menuItemInstance),\n filter(() => this._menuOpen),\n )\n : observableOf();\n\n return merge(backdrop, parentClose as Observable<MenuCloseReason>, hover, detachments);\n }\n\n /** Handles mouse presses on the trigger. */\n _handleMousedown(event: MouseEvent): void {\n if (!isFakeMousedownFromScreenReader(event)) {\n // Since right or middle button clicks won't trigger the `click` event,\n // we shouldn't consider the menu as opened by mouse in those cases.\n this._openedBy = event.button === 0 ? 'mouse' : undefined;\n\n // Since clicking on the trigger won't close the menu if it opens a sub-menu,\n // we should prevent focus from moving onto it via click to avoid the\n // highlight from lingering on the menu item.\n if (this.triggersSubmenu()) {\n event.preventDefault();\n }\n }\n }\n\n /** Handles key presses on the trigger. */\n _handleKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n\n // Pressing enter on the trigger will trigger the click handler later.\n if (keyCode === ENTER || keyCode === SPACE) {\n this._openedBy = 'keyboard';\n }\n\n if (\n this.triggersSubmenu() &&\n ((keyCode === RIGHT_ARROW && this.dir === 'ltr') ||\n (keyCode === LEFT_ARROW && this.dir === 'rtl'))\n ) {\n this._openedBy = 'keyboard';\n this.openMenu();\n }\n }\n\n /** Handles click events on the trigger. */\n _handleClick(event: MouseEvent): void {\n if (this.triggersSubmenu()) {\n // Stop event propagation to avoid closing the parent menu.\n event.stopPropagation();\n this.openMenu();\n } else {\n this.toggleMenu();\n }\n }\n\n /** Handles the cases where the user hovers over the trigger. */\n private _handleHover() {\n // Subscribe to changes in the hovered item in order to toggle the panel.\n if (!this.triggersSubmenu() || !this._parentMaterialMenu) {\n return;\n }\n\n this._hoverSubscription = this._parentMaterialMenu\n ._hovered()\n // Since we might have multiple competing triggers for the same menu (e.g. a sub-menu\n // with different data and triggers), we have to delay it by a tick to ensure that\n // it won't be closed immediately after it is opened.\n .pipe(\n filter(active => active === this._menuItemInstance && !active.disabled),\n delay(0, asapScheduler),\n )\n .subscribe(() => {\n this._openedBy = 'mouse';\n\n // If the same menu is used between multiple triggers, it might still be animating\n // while the new trigger tries to re-open it. Wait for the animation to finish\n // before doing so. Also interrupt if the user moves to another item.\n if (this.menu instanceof _MatMenuBase && this.menu._isAnimating) {\n // We need the `delay(0)` here in order to avoid\n // 'changed after checked' errors in some cases. See #12194.\n this.menu._animationDone\n .pipe(take(1), delay(0, asapScheduler), takeUntil(this._parentMaterialMenu!._hovered()))\n .subscribe(() => this.openMenu());\n } else {\n this.openMenu();\n }\n });\n }\n\n /** Gets the portal that should be attached to the overlay. */\n private _getPortal(menu: MatMenuPanel): TemplatePortal {\n // Note that we can avoid this check by keeping the portal on the menu panel.\n // While it would be cleaner, we'd have to introduce another required method on\n // `MatMenuPanel`, making it harder to consume.\n if (!this._portal || this._portal.templateRef !== menu.templateRef) {\n this._portal = new TemplatePortal(menu.templateRef, this._viewContainerRef);\n }\n\n return this._portal;\n }\n}\n\n/** Directive applied to an element that should trigger a `mat-menu`. */\n@Directive({\n selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,\n host: {\n 'class': 'mat-mdc-menu-trigger',\n },\n exportAs: 'matMenuTrigger',\n})\nexport class MatMenuTrigger extends _MatMenuTriggerBase {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n Inject,\n NgZone,\n ViewEncapsulation,\n ChangeDetectorRef,\n} from '@angular/core';\nimport {\n MAT_MENU_PANEL,\n matMenuAnimations,\n _MatMenuBase,\n MAT_MENU_DEFAULT_OPTIONS,\n MatMenuDefaultOptions,\n} from '@angular/material/menu';\n\n/**\n * @docs-public MatMenu\n * @deprecated Use `MatMenu` from `@angular/material/menu` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Component({\n selector: 'mat-menu',\n templateUrl: 'menu.html',\n styleUrls: ['menu.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n exportAs: 'matMenu',\n host: {\n '[attr.aria-label]': 'null',\n '[attr.aria-labelledby]': 'null',\n '[attr.aria-describedby]': 'null',\n },\n animations: [matMenuAnimations.transformMenu, matMenuAnimations.fadeInItems],\n providers: [{provide: MAT_MENU_PANEL, useExisting: MatLegacyMenu}],\n})\nexport class MatLegacyMenu extends _MatMenuBase {\n protected override _elevationPrefix = 'mat-elevation-z';\n protected override _baseElevation = 4;\n\n /**\n * @deprecated `changeDetectorRef` parameter will become a required parameter.\n * @breaking-change 15.0.0\n */\n constructor(\n elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n defaultOptions: MatMenuDefaultOptions,\n );\n\n constructor(\n elementRef: ElementRef<HTMLElement>,\n ngZone: NgZone,\n @Inject(MAT_MENU_DEFAULT_OPTIONS) defaultOptions: MatMenuDefaultOptions,\n changeDetectorRef?: ChangeDetectorRef,\n ) {\n super(elementRef, ngZone, defaultOptions, changeDetectorRef);\n }\n}\n","<ng-template>\n <div\n class=\"mat-menu-panel\"\n [id]=\"panelId\"\n [ngClass]=\"_classList\"\n (keydown)=\"_handleKeydown($event)\"\n (click)=\"closed.emit('click')\"\n [@transformMenu]=\"_panelAnimationState\"\n (@transformMenu.start)=\"_onAnimationStart($event)\"\n (@transformMenu.done)=\"_onAnimationDone($event)\"\n tabindex=\"-1\"\n role=\"menu\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"ariaLabelledby || null\"\n [attr.aria-describedby]=\"ariaDescribedby || null\">\n <div class=\"mat-menu-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</ng-template>\n","<ng-content></ng-content>\n<div class=\"mat-menu-ripple\" matRipple\n [matRippleDisabled]=\"disableRipple || disabled\"\n [matRippleTrigger]=\"_getHostElement()\">\n</div>\n\n<svg\n *ngIf=\"_triggersSubmenu\"\n class=\"mat-menu-submenu-icon\"\n viewBox=\"0 0 5 10\"\n focusable=\"false\"><polygon points=\"0,0 5,5 0,10\"/></svg>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive} from '@angular/core';\nimport {_MatMenuTriggerBase} from '@angular/material/menu';\n\n// TODO(andrewseguin): Remove the kebab versions in favor of camelCased attribute selectors\n\n/**\n * Directive applied to an element that should trigger a `mat-menu`.\n * @deprecated Use `MatMenuTrigger` from `@angular/material/menu` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Directive({\n selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,\n host: {\n 'class': 'mat-menu-trigger',\n },\n exportAs: 'matMenuTrigger',\n})\nexport class MatLegacyMenuTrigger extends _MatMenuTriggerBase {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive} from '@angular/core';\nimport {MAT_MENU_CONTENT, _MatMenuContentBase} from '@angular/material/menu';\n\n/**\n * Menu content that will be rendered lazily once the menu is opened.\n * @deprecated Use `MatMenuContent` from `@angular/material/menu` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Directive({\n selector: 'ng-template[matMenuContent]',\n providers: [{provide: MAT_MENU_CONTENT, useExisting: MatLegacyMenuContent}],\n})\nexport class MatLegacyMenuContent extends _MatMenuContentBase {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {OverlayModule} from '@angular/cdk/overlay';\nimport {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule, MatRippleModule} from '@angular/material/core';\nimport {CdkScrollableModule} from '@angular/cdk/scrolling';\nimport {MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER} from '@angular/material/menu';\nimport {MatLegacyMenu} from './menu';\nimport {MatLegacyMenuContent} from './menu-content';\nimport {MatLegacyMenuItem} from './menu-item';\nimport {MatLegacyMenuTrigger} from './menu-trigger';\n\n/**\n * @deprecated Use `MatMenuModule` from `@angular/material/menu` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@NgModule({\n imports: [CommonModule, MatCommonModule, MatRippleModule, OverlayModule],\n exports: [\n CdkScrollableModule,\n MatCommonModule,\n MatLegacyMenu,\n MatLegacyMenuItem,\n MatLegacyMenuTrigger,\n MatLegacyMenuContent,\n ],\n declarations: [MatLegacyMenu, MatLegacyMenuItem, MatLegacyMenuTrigger, MatLegacyMenuContent],\n providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER],\n})\nexport class MatLegacyMenuModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵDomAdapter as DomAdapter} from '@angular/common';\n\n\n\n/**\n * Provides DOM operations in any browser environment.\n *\n * @security Tread carefully! Interacting with the DOM directly is dangerous and\n * can introduce XSS risks.\n */\nexport abstract class GenericBrowserDomAdapter extends DomAdapter {\n override readonly supportsDOMEvents: boolean = true;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵparseCookieValue as parseCookieValue, ɵsetRootDomAdapter as setRootDomAdapter} from '@angular/common';\n\nimport {GenericBrowserDomAdapter} from './generic_browser_adapter';\n\n/**\n * A `DomAdapter` powered by full browser DOM APIs.\n *\n * @security Tread carefully! Interacting with the DOM directly is dangerous and\n * can introduce XSS risks.\n */\n/* tslint:disable:requireParameterType no-console */\nexport class BrowserDomAdapter extends GenericBrowserDomAdapter {\n static makeCurrent() {\n setRootDomAdapter(new BrowserDomAdapter());\n }\n\n override onAndCancel(el: Node, evt: any, listener: any): Function {\n el.addEventListener(evt, listener, false);\n // Needed to follow Dart's subscription semantic, until fix of\n // https://code.google.com/p/dart/issues/detail?id=17406\n return () => {\n el.removeEventListener(evt, listener, false);\n };\n }\n override dispatchEvent(el: Node, evt: any) {\n el.dispatchEvent(evt);\n }\n override remove(node: Node): void {\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n override createElement(tagName: string, doc?: Document): HTMLElement {\n doc = doc || this.getDefaultDocument();\n return doc.createElement(tagName);\n }\n override createHtmlDocument(): Document {\n return document.implementation.createHTMLDocument('fakeTitle');\n }\n override getDefaultDocument(): Document {\n return document;\n }\n\n override isElementNode(node: Node): boolean {\n return node.nodeType === Node.ELEMENT_NODE;\n }\n\n override isShadowRoot(node: any): boolean {\n return node instanceof DocumentFragment;\n }\n\n /** @deprecated No longer being used in Ivy code. To be removed in version 14. */\n override getGlobalEventTarget(doc: Document, target: string): EventTarget|null {\n if (target === 'window') {\n return window;\n }\n if (target === 'document') {\n return doc;\n }\n if (target === 'body') {\n return doc.body;\n }\n return null;\n }\n override getBaseHref(doc: Document): string|null {\n const href = getBaseElementHref();\n return href == null ? null : relativePath(href);\n }\n override resetBaseElement(): void {\n baseElement = null;\n }\n override getUserAgent(): string {\n return window.navigator.userAgent;\n }\n override getCookie(name: string): string|null {\n return parseCookieValue(document.cookie, name);\n }\n}\n\nlet baseElement: HTMLElement|null = null;\nfunction getBaseElementHref(): string|null {\n baseElement = baseElement || document.querySelector('base');\n return baseElement ? baseElement.getAttribute('href') : null;\n}\n\n// based on urlUtils.js in AngularJS 1\nlet urlParsingNode: HTMLAnchorElement|undefined;\nfunction relativePath(url: any): string {\n urlParsingNode = urlParsingNode || document.createElement('a');\n urlParsingNode.setAttribute('href', url);\n const pathName = urlParsingNode.pathname;\n return pathName.charAt(0) === '/' ? pathName : `/${pathName}`;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT, ɵgetDOM as getDOM} from '@angular/common';\nimport {APP_INITIALIZER, ApplicationInitStatus, InjectionToken, Injector, StaticProvider} from '@angular/core';\n\n/**\n * An id that identifies a particular application being bootstrapped, that should\n * match across the client/server boundary.\n */\nexport const TRANSITION_ID = new InjectionToken('TRANSITION_ID');\n\nexport function appInitializerFactory(transitionId: string, document: any, injector: Injector) {\n return () => {\n // Wait for all application initializers to be completed before removing the styles set by\n // the server.\n injector.get(ApplicationInitStatus).donePromise.then(() => {\n const dom = getDOM();\n const styles: HTMLCollectionOf<HTMLStyleElement> =\n document.querySelectorAll(`style[ng-transition=\"${transitionId}\"]`);\n for (let i = 0; i < styles.length; i++) {\n dom.remove(styles[i]);\n }\n });\n };\n}\n\nexport const SERVER_TRANSITION_PROVIDERS: StaticProvider[] = [\n {\n provide: APP_INITIALIZER,\n useFactory: appInitializerFactory,\n deps: [TRANSITION_ID, DOCUMENT, Injector],\n multi: true\n },\n];\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {XhrFactory} from '@angular/common';\nimport {Injectable} from '@angular/core';\n\n/**\n * A factory for `HttpXhrBackend` that uses the `XMLHttpRequest` browser API.\n */\n@Injectable()\nexport class BrowserXhr implements XhrFactory {\n build(): XMLHttpRequest {\n return new XMLHttpRequest();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵgetDOM as getDOM} from '@angular/common';\nimport {Inject, Injectable, InjectionToken, NgZone} from '@angular/core';\n\n/**\n * The injection token for the event-manager plug-in service.\n *\n * @publicApi\n */\nexport const EVENT_MANAGER_PLUGINS =\n new InjectionToken<EventManagerPlugin[]>('EventManagerPlugins');\n\n/**\n * An injectable service that provides event management for Angular\n * through a browser plug-in.\n *\n * @publicApi\n */\n@Injectable()\nexport class EventManager {\n private _plugins: EventManagerPlugin[];\n private _eventNameToPlugin = new Map<string, EventManagerPlugin>();\n\n /**\n * Initializes an instance of the event-manager service.\n */\n constructor(@Inject(EVENT_MANAGER_PLUGINS) plugins: EventManagerPlugin[], private _zone: NgZone) {\n plugins.forEach((plugin) => {\n plugin.manager = this;\n });\n this._plugins = plugins.slice().reverse();\n }\n\n /**\n * Registers a handler for a specific element and event.\n *\n * @param element The HTML element to receive event notifications.\n * @param eventName The name of the event to listen for.\n * @param handler A function to call when the notification occurs. Receives the\n * event object as an argument.\n * @returns A callback function that can be used to remove the handler.\n */\n addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {\n const plugin = this._findPluginFor(eventName);\n return plugin.addEventListener(element, eventName, handler);\n }\n\n /**\n * Registers a global handler for an event in a target view.\n *\n * @param target A target for global event notifications. One of \"window\", \"document\", or \"body\".\n * @param eventName The name of the event to listen for.\n * @param handler A function to call when the notification occurs. Receives the\n * event object as an argument.\n * @returns A callback function that can be used to remove the handler.\n * @deprecated No longer being used in Ivy code. To be removed in version 14.\n */\n addGlobalEventListener(target: string, eventName: string, handler: Function): Function {\n const plugin = this._findPluginFor(eventName);\n return plugin.addGlobalEventListener(target, eventName, handler);\n }\n\n /**\n * Retrieves the compilation zone in which event listeners are registered.\n */\n getZone(): NgZone {\n return this._zone;\n }\n\n /** @internal */\n _findPluginFor(eventName: string): EventManagerPlugin {\n const plugin = this._eventNameToPlugin.get(eventName);\n if (plugin) {\n return plugin;\n }\n\n const plugins = this._plugins;\n for (let i = 0; i < plugins.length; i++) {\n const plugin = plugins[i];\n if (plugin.supports(eventName)) {\n this._eventNameToPlugin.set(eventName, plugin);\n return plugin;\n }\n }\n throw new Error(`No event manager plugin found for event ${eventName}`);\n }\n}\n\nexport abstract class EventManagerPlugin {\n constructor(private _doc: any) {}\n\n // Using non-null assertion because it's set by EventManager's constructor\n manager!: EventManager;\n\n abstract supports(eventName: string): boolean;\n\n abstract addEventListener(element: HTMLElement, eventName: string, handler: Function): Function;\n\n addGlobalEventListener(element: string, eventName: string, handler: Function): Function {\n const target: HTMLElement = getDOM().getGlobalEventTarget(this._doc, element);\n if (!target) {\n throw new Error(`Unsupported event target ${target} for event ${eventName}`);\n }\n return this.addEventListener(target, eventName, handler);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, OnDestroy} from '@angular/core';\n\n@Injectable()\nexport class SharedStylesHost implements OnDestroy {\n private readonly usageCount = new Map<string /** Style string */, number /** Usage count */>();\n\n addStyles(styles: string[]): void {\n for (const style of styles) {\n const usageCount = this.changeUsageCount(style, 1);\n\n if (usageCount === 1) {\n this.onStyleAdded(style);\n }\n }\n }\n\n removeStyles(styles: string[]): void {\n for (const style of styles) {\n const usageCount = this.changeUsageCount(style, -1);\n\n if (usageCount === 0) {\n this.onStyleRemoved(style);\n }\n }\n }\n\n onStyleRemoved(style: string): void {}\n\n onStyleAdded(style: string): void {}\n\n getAllStyles(): IterableIterator<string> {\n return this.usageCount.keys();\n }\n\n private changeUsageCount(style: string, delta: number): number {\n const map = this.usageCount;\n let usage = map.get(style) ?? 0;\n usage += delta;\n\n if (usage > 0) {\n map.set(style, usage);\n } else {\n map.delete(style);\n }\n\n return usage;\n }\n\n ngOnDestroy(): void {\n for (const style of this.getAllStyles()) {\n this.onStyleRemoved(style);\n }\n\n this.usageCount.clear();\n }\n}\n\n@Injectable()\nexport class DomSharedStylesHost extends SharedStylesHost implements OnDestroy {\n // Maps all registered host nodes to a list of style nodes that have been added to the host node.\n private readonly styleRef = new Map<string, HTMLStyleElement[]>();\n private hostNodes = new Set<Node>();\n\n constructor(@Inject(DOCUMENT) private readonly doc: any) {\n super();\n this.resetHostNodes();\n }\n\n override onStyleAdded(style: string): void {\n for (const host of this.hostNodes) {\n this.addStyleToHost(host, style);\n }\n }\n\n override onStyleRemoved(style: string): void {\n const styleRef = this.styleRef;\n const styleElements = styleRef.get(style);\n styleElements?.forEach(e => e.remove());\n styleRef.delete(style);\n }\n\n override ngOnDestroy(): void {\n super.ngOnDestroy();\n this.styleRef.clear();\n this.resetHostNodes();\n }\n\n addHost(hostNode: Node): void {\n this.hostNodes.add(hostNode);\n\n for (const style of this.getAllStyles()) {\n this.addStyleToHost(hostNode, style);\n }\n }\n\n removeHost(hostNode: Node): void {\n this.hostNodes.delete(hostNode);\n }\n\n private addStyleToHost(host: Node, style: string): void {\n const styleEl = this.doc.createElement('style');\n styleEl.textContent = style;\n host.appendChild(styleEl);\n\n const styleElRef = this.styleRef.get(style);\n if (styleElRef) {\n styleElRef.push(styleEl);\n } else {\n this.styleRef.set(style, [styleEl]);\n }\n }\n\n private resetHostNodes(): void {\n const hostNodes = this.hostNodes;\n hostNodes.clear();\n // Re-add the head element back since this is the default host.\n hostNodes.add(this.doc.head);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {APP_ID, Inject, Injectable, InjectionToken, OnDestroy, Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2, ViewEncapsulation} from '@angular/core';\n\nimport {EventManager} from './events/event_manager';\nimport {DomSharedStylesHost} from './shared_styles_host';\n\nexport const NAMESPACE_URIS: {[ns: string]: string} = {\n 'svg': 'http://www.w3.org/2000/svg',\n 'xhtml': 'http://www.w3.org/1999/xhtml',\n 'xlink': 'http://www.w3.org/1999/xlink',\n 'xml': 'http://www.w3.org/XML/1998/namespace',\n 'xmlns': 'http://www.w3.org/2000/xmlns/',\n 'math': 'http://www.w3.org/1998/MathML/',\n};\n\nconst COMPONENT_REGEX = /%COMP%/g;\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\nexport const COMPONENT_VARIABLE = '%COMP%';\nexport const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;\nexport const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;\n\n/**\n * The default value for the `REMOVE_STYLES_ON_COMPONENT_DESTROY` DI token.\n */\nconst REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT = false;\n\n/**\n * A [DI token](guide/glossary#di-token \"DI token definition\") that indicates whether styles\n * of destroyed components should be removed from DOM.\n *\n * By default, the value is set to `false`. This will be changed in the next major version.\n * @publicApi\n */\nexport const REMOVE_STYLES_ON_COMPONENT_DESTROY =\n new InjectionToken<boolean>('RemoveStylesOnCompDestory', {\n providedIn: 'root',\n factory: () => REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT,\n });\n\nexport function shimContentAttribute(componentShortId: string): string {\n return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId);\n}\n\nexport function shimHostAttribute(componentShortId: string): string {\n return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId);\n}\n\nexport function flattenStyles(compId: string, styles: Array<string|string[]>): string[] {\n // Cannot use `Infinity` as depth as `infinity` is not a number literal in TypeScript.\n // See: https://github.com/microsoft/TypeScript/issues/32277\n return styles.flat(100).map(s => s.replace(COMPONENT_REGEX, compId));\n}\n\nfunction decoratePreventDefault(eventHandler: Function): Function {\n // `DebugNode.triggerEventHandler` needs to know if the listener was created with\n // decoratePreventDefault or is a listener added outside the Angular context so it can handle the\n // two differently. In the first case, the special '__ngUnwrap__' token is passed to the unwrap\n // the listener (see below).\n return (event: any) => {\n // Ivy uses '__ngUnwrap__' as a special token that allows us to unwrap the function\n // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. The debug_node\n // can inspect the listener toString contents for the existence of this special token. Because\n // the token is a string literal, it is ensured to not be modified by compiled code.\n if (event === '__ngUnwrap__') {\n return eventHandler;\n }\n\n const allowDefaultBehavior = eventHandler(event);\n if (allowDefaultBehavior === false) {\n // TODO(tbosch): move preventDefault into event plugins...\n event.preventDefault();\n event.returnValue = false;\n }\n\n return undefined;\n };\n}\n\n@Injectable()\nexport class DomRendererFactory2 implements RendererFactory2, OnDestroy {\n private rendererByCompId =\n new Map<string, EmulatedEncapsulationDomRenderer2|NoneEncapsulationDomRenderer>();\n private defaultRenderer: Renderer2;\n\n constructor(\n private eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost,\n @Inject(APP_ID) private appId: string,\n @Inject(REMOVE_STYLES_ON_COMPONENT_DESTROY) private removeStylesOnCompDestory: boolean) {\n this.defaultRenderer = new DefaultDomRenderer2(eventManager);\n }\n\n createRenderer(element: any, type: RendererType2|null): Renderer2 {\n if (!element || !type) {\n return this.defaultRenderer;\n }\n\n const renderer = this.getOrCreateRenderer(element, type);\n\n // Renderers have different logic due to different encapsulation behaviours.\n // Ex: for emulated, an attribute is added to the element.\n if (renderer instanceof EmulatedEncapsulationDomRenderer2) {\n renderer.applyToHost(element);\n } else if (renderer instanceof NoneEncapsulationDomRenderer) {\n renderer.applyStyles();\n }\n\n return renderer;\n }\n\n private getOrCreateRenderer(element: any, type: RendererType2): Renderer2 {\n const rendererByCompId = this.rendererByCompId;\n let renderer = rendererByCompId.get(type.id);\n\n if (!renderer) {\n const eventManager = this.eventManager;\n const sharedStylesHost = this.sharedStylesHost;\n const removeStylesOnCompDestory = this.removeStylesOnCompDestory;\n\n switch (type.encapsulation) {\n case ViewEncapsulation.Emulated:\n renderer = new EmulatedEncapsulationDomRenderer2(\n eventManager, sharedStylesHost, type, this.appId, removeStylesOnCompDestory);\n break;\n case ViewEncapsulation.ShadowDom:\n return new ShadowDomRenderer(eventManager, sharedStylesHost, element, type);\n default:\n renderer = new NoneEncapsulationDomRenderer(\n eventManager, sharedStylesHost, type, removeStylesOnCompDestory);\n break;\n }\n\n renderer.onDestroy = () => rendererByCompId.delete(type.id);\n rendererByCompId.set(type.id, renderer);\n }\n\n return renderer;\n }\n\n ngOnDestroy() {\n this.rendererByCompId.clear();\n }\n\n begin() {}\n end() {}\n}\n\nclass DefaultDomRenderer2 implements Renderer2 {\n data: {[key: string]: any} = Object.create(null);\n\n constructor(private eventManager: EventManager) {}\n\n destroy(): void {}\n\n destroyNode = null;\n\n createElement(name: string, namespace?: string): any {\n if (namespace) {\n // TODO: `|| namespace` was added in\n // https://github.com/angular/angular/commit/2b9cc8503d48173492c29f5a271b61126104fbdb to\n // support how Ivy passed around the namespace URI rather than short name at the time. It did\n // not, however extend the support to other parts of the system (setAttribute, setAttribute,\n // and the ServerRenderer). We should decide what exactly the semantics for dealing with\n // namespaces should be and make it consistent.\n // Related issues:\n // https://github.com/angular/angular/issues/44028\n // https://github.com/angular/angular/issues/44883\n return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);\n }\n\n return document.createElement(name);\n }\n\n createComment(value: string): any {\n return document.createComment(value);\n }\n\n createText(value: string): any {\n return document.createTextNode(value);\n }\n\n appendChild(parent: any, newChild: any): void {\n const targetParent = isTemplateNode(parent) ? parent.content : parent;\n targetParent.appendChild(newChild);\n }\n\n insertBefore(parent: any, newChild: any, refChild: any): void {\n if (parent) {\n const targetParent = isTemplateNode(parent) ? parent.content : parent;\n targetParent.insertBefore(newChild, refChild);\n }\n }\n\n removeChild(parent: any, oldChild: any): void {\n if (parent) {\n parent.removeChild(oldChild);\n }\n }\n\n selectRootElement(selectorOrNode: string|any, preserveContent?: boolean): any {\n let el: any = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) :\n selectorOrNode;\n if (!el) {\n throw new Error(`The selector \"${selectorOrNode}\" did not match any elements`);\n }\n if (!preserveContent) {\n el.textContent = '';\n }\n return el;\n }\n\n parentNode(node: any): any {\n return node.parentNode;\n }\n\n nextSibling(node: any): any {\n return node.nextSibling;\n }\n\n setAttribute(el: any, name: string, value: string, namespace?: string): void {\n if (namespace) {\n name = namespace + ':' + name;\n const namespaceUri = NAMESPACE_URIS[namespace];\n if (namespaceUri) {\n el.setAttributeNS(namespaceUri, name, value);\n } else {\n el.setAttribute(name, value);\n }\n } else {\n el.setAttribute(name, value);\n }\n }\n\n removeAttribute(el: any, name: string, namespace?: string): void {\n if (namespace) {\n const namespaceUri = NAMESPACE_URIS[namespace];\n if (namespaceUri) {\n el.removeAttributeNS(namespaceUri, name);\n } else {\n el.removeAttribute(`${namespace}:${name}`);\n }\n } else {\n el.removeAttribute(name);\n }\n }\n\n addClass(el: any, name: string): void {\n el.classList.add(name);\n }\n\n removeClass(el: any, name: string): void {\n el.classList.remove(name);\n }\n\n setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {\n if (flags & (RendererStyleFlags2.DashCase | RendererStyleFlags2.Important)) {\n el.style.setProperty(style, value, flags & RendererStyleFlags2.Important ? 'important' : '');\n } else {\n el.style[style] = value;\n }\n }\n\n removeStyle(el: any, style: string, flags: RendererStyleFlags2): void {\n if (flags & RendererStyleFlags2.DashCase) {\n // removeProperty has no effect when used on camelCased properties.\n el.style.removeProperty(style);\n } else {\n el.style[style] = '';\n }\n }\n\n setProperty(el: any, name: string, value: any): void {\n NG_DEV_MODE && checkNoSyntheticProp(name, 'property');\n el[name] = value;\n }\n\n setValue(node: any, value: string): void {\n node.nodeValue = value;\n }\n\n listen(target: 'window'|'document'|'body'|any, event: string, callback: (event: any) => boolean):\n () => void {\n NG_DEV_MODE && checkNoSyntheticProp(event, 'listener');\n if (typeof target === 'string') {\n return <() => void>this.eventManager.addGlobalEventListener(\n target, event, decoratePreventDefault(callback));\n }\n return <() => void>this.eventManager.addEventListener(\n target, event, decoratePreventDefault(callback)) as () => void;\n }\n}\n\nconst AT_CHARCODE = (() => '@'.charCodeAt(0))();\nfunction checkNoSyntheticProp(name: string, nameKind: string) {\n if (name.charCodeAt(0) === AT_CHARCODE) {\n throw new Error(`Unexpected synthetic ${nameKind} ${name} found. Please make sure that:\n - Either \\`BrowserAnimationsModule\\` or \\`NoopAnimationsModule\\` are imported in your application.\n - There is corresponding configuration for the animation named \\`${\n name}\\` defined in the \\`animations\\` field of the \\`@Component\\` decorator (see https://angular.io/api/core/Component#animations).`);\n }\n}\n\n\nfunction isTemplateNode(node: any): node is HTMLTemplateElement {\n return node.tagName === 'TEMPLATE' && node.content !== undefined;\n}\n\nclass ShadowDomRenderer extends DefaultDomRenderer2 {\n private shadowRoot: any;\n\n constructor(\n eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost,\n private hostEl: any, component: RendererType2) {\n super(eventManager);\n this.shadowRoot = (hostEl as any).attachShadow({mode: 'open'});\n\n this.sharedStylesHost.addHost(this.shadowRoot);\n const styles = flattenStyles(component.id, component.styles);\n\n for (const style of styles) {\n const styleEl = document.createElement('style');\n styleEl.textContent = style;\n this.shadowRoot.appendChild(styleEl);\n }\n }\n\n private nodeOrShadowRoot(node: any): any {\n return node === this.hostEl ? this.shadowRoot : node;\n }\n\n override appendChild(parent: any, newChild: any): void {\n return super.appendChild(this.nodeOrShadowRoot(parent), newChild);\n }\n override insertBefore(parent: any, newChild: any, refChild: any): void {\n return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild);\n }\n override removeChild(parent: any, oldChild: any): void {\n return super.removeChild(this.nodeOrShadowRoot(parent), oldChild);\n }\n override parentNode(node: any): any {\n return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node)));\n }\n\n override destroy() {\n this.sharedStylesHost.removeHost(this.shadowRoot);\n }\n}\n\nclass NoneEncapsulationDomRenderer extends DefaultDomRenderer2 {\n private readonly styles: string[];\n private rendererUsageCount = 0;\n onDestroy: VoidFunction|undefined;\n\n constructor(\n eventManager: EventManager,\n private readonly sharedStylesHost: DomSharedStylesHost,\n component: RendererType2,\n private removeStylesOnCompDestory: boolean,\n compId = component.id,\n ) {\n super(eventManager);\n this.styles = flattenStyles(compId, component.styles);\n }\n\n applyStyles(): void {\n this.sharedStylesHost.addStyles(this.styles);\n this.rendererUsageCount++;\n }\n\n override destroy(): void {\n if (!this.removeStylesOnCompDestory) {\n return;\n }\n\n this.sharedStylesHost.removeStyles(this.styles);\n this.rendererUsageCount--;\n if (this.rendererUsageCount === 0) {\n this.onDestroy?.();\n }\n }\n}\n\nclass EmulatedEncapsulationDomRenderer2 extends NoneEncapsulationDomRenderer {\n private contentAttr: string;\n private hostAttr: string;\n\n constructor(\n eventManager: EventManager, sharedStylesHost: DomSharedStylesHost, component: RendererType2,\n appId: string, removeStylesOnCompDestory: boolean) {\n const compId = appId + '-' + component.id;\n super(eventManager, sharedStylesHost, component, removeStylesOnCompDestory, compId);\n this.contentAttr = shimContentAttribute(compId);\n this.hostAttr = shimHostAttribute(compId);\n }\n\n applyToHost(element: any): void {\n this.applyStyles();\n this.setAttribute(element, this.hostAttr, '');\n }\n\n override createElement(parent: any, name: string): Element {\n const el = super.createElement(parent, name);\n super.setAttribute(el, this.contentAttr, '');\n return el;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable} from '@angular/core';\n\nimport {EventManagerPlugin} from './event_manager';\n\n@Injectable()\nexport class DomEventsPlugin extends EventManagerPlugin {\n constructor(@Inject(DOCUMENT) doc: any) {\n super(doc);\n }\n\n // This plugin should come last in the list of plugins, because it accepts all\n // events.\n override supports(eventName: string): boolean {\n return true;\n }\n\n override addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {\n element.addEventListener(eventName, handler as EventListener, false);\n return () => this.removeEventListener(element, eventName, handler as EventListener);\n }\n\n removeEventListener(target: any, eventName: string, callback: Function): void {\n return target.removeEventListener(eventName, callback as EventListener);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT, ɵgetDOM as getDOM} from '@angular/common';\nimport {Inject, Injectable, NgZone} from '@angular/core';\n\nimport {EventManagerPlugin} from './event_manager';\n\n/**\n * Defines supported modifiers for key events.\n */\nconst MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift'];\n\n// The following values are here for cross-browser compatibility and to match the W3C standard\n// cf https://www.w3.org/TR/DOM-Level-3-Events-key/\nconst _keyMap: {[k: string]: string} = {\n '\\b': 'Backspace',\n '\\t': 'Tab',\n '\\x7F': 'Delete',\n '\\x1B': 'Escape',\n 'Del': 'Delete',\n 'Esc': 'Escape',\n 'Left': 'ArrowLeft',\n 'Right': 'ArrowRight',\n 'Up': 'ArrowUp',\n 'Down': 'ArrowDown',\n 'Menu': 'ContextMenu',\n 'Scroll': 'ScrollLock',\n 'Win': 'OS'\n};\n\n/**\n * Retrieves modifiers from key-event objects.\n */\nconst MODIFIER_KEY_GETTERS: {[key: string]: (event: KeyboardEvent) => boolean} = {\n 'alt': (event: KeyboardEvent) => event.altKey,\n 'control': (event: KeyboardEvent) => event.ctrlKey,\n 'meta': (event: KeyboardEvent) => event.metaKey,\n 'shift': (event: KeyboardEvent) => event.shiftKey\n};\n\n/**\n * @publicApi\n * A browser plug-in that provides support for handling of key events in Angular.\n */\n@Injectable()\nexport class KeyEventsPlugin extends EventManagerPlugin {\n /**\n * Initializes an instance of the browser plug-in.\n * @param doc The document in which key events will be detected.\n */\n constructor(@Inject(DOCUMENT) doc: any) {\n super(doc);\n }\n\n /**\n * Reports whether a named key event is supported.\n * @param eventName The event name to query.\n * @return True if the named key event is supported.\n */\n override supports(eventName: string): boolean {\n return KeyEventsPlugin.parseEventName(eventName) != null;\n }\n\n /**\n * Registers a handler for a specific element and key event.\n * @param element The HTML element to receive event notifications.\n * @param eventName The name of the key event to listen for.\n * @param handler A function to call when the notification occurs. Receives the\n * event object as an argument.\n * @returns The key event that was registered.\n */\n override addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {\n const parsedEvent = KeyEventsPlugin.parseEventName(eventName)!;\n\n const outsideHandler =\n KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone());\n\n return this.manager.getZone().runOutsideAngular(() => {\n return getDOM().onAndCancel(element, parsedEvent['domEventName'], outsideHandler);\n });\n }\n\n /**\n * Parses the user provided full keyboard event definition and normalizes it for\n * later internal use. It ensures the string is all lowercase, converts special\n * characters to a standard spelling, and orders all the values consistently.\n *\n * @param eventName The name of the key event to listen for.\n * @returns an object with the full, normalized string, and the dom event name\n * or null in the case when the event doesn't match a keyboard event.\n */\n static parseEventName(eventName: string): {fullKey: string, domEventName: string}|null {\n const parts: string[] = eventName.toLowerCase().split('.');\n\n const domEventName = parts.shift();\n if ((parts.length === 0) || !(domEventName === 'keydown' || domEventName === 'keyup')) {\n return null;\n }\n\n const key = KeyEventsPlugin._normalizeKey(parts.pop()!);\n\n let fullKey = '';\n let codeIX = parts.indexOf('code');\n if (codeIX > -1) {\n parts.splice(codeIX, 1);\n fullKey = 'code.';\n }\n MODIFIER_KEYS.forEach(modifierName => {\n const index: number = parts.indexOf(modifierName);\n if (index > -1) {\n parts.splice(index, 1);\n fullKey += modifierName + '.';\n }\n });\n fullKey += key;\n\n if (parts.length != 0 || key.length === 0) {\n // returning null instead of throwing to let another plugin process the event\n return null;\n }\n\n // NOTE: Please don't rewrite this as so, as it will break JSCompiler property renaming.\n // The code must remain in the `result['domEventName']` form.\n // return {domEventName, fullKey};\n const result: {fullKey: string, domEventName: string} = {} as any;\n result['domEventName'] = domEventName;\n result['fullKey'] = fullKey;\n return result;\n }\n\n /**\n * Determines whether the actual keys pressed match the configured key code string.\n * The `fullKeyCode` event is normalized in the `parseEventName` method when the\n * event is attached to the DOM during the `addEventListener` call. This is unseen\n * by the end user and is normalized for internal consistency and parsing.\n *\n * @param event The keyboard event.\n * @param fullKeyCode The normalized user defined expected key event string\n * @returns boolean.\n */\n static matchEventFullKeyCode(event: KeyboardEvent, fullKeyCode: string): boolean {\n let keycode = _keyMap[event.key] || event.key;\n let key = '';\n if (fullKeyCode.indexOf('code.') > -1) {\n keycode = event.code;\n key = 'code.';\n }\n // the keycode could be unidentified so we have to check here\n if (keycode == null || !keycode) return false;\n keycode = keycode.toLowerCase();\n if (keycode === ' ') {\n keycode = 'space'; // for readability\n } else if (keycode === '.') {\n keycode = 'dot'; // because '.' is used as a separator in event names\n }\n MODIFIER_KEYS.forEach(modifierName => {\n if (modifierName !== keycode) {\n const modifierGetter = MODIFIER_KEY_GETTERS[modifierName];\n if (modifierGetter(event)) {\n key += modifierName + '.';\n }\n }\n });\n key += keycode;\n return key === fullKeyCode;\n }\n\n /**\n * Configures a handler callback for a key event.\n * @param fullKey The event name that combines all simultaneous keystrokes.\n * @param handler The function that responds to the key event.\n * @param zone The zone in which the event occurred.\n * @returns A callback function.\n */\n static eventCallback(fullKey: string, handler: Function, zone: NgZone): Function {\n return (event: KeyboardEvent) => {\n if (KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) {\n zone.runGuarded(() => handler(event));\n }\n };\n }\n\n /** @internal */\n static _normalizeKey(keyName: string): string {\n // TODO: switch to a Map if the mapping grows too much\n switch (keyName) {\n case 'esc':\n return 'escape';\n default:\n return keyName;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {CommonModule, DOCUMENT, XhrFactory, ɵPLATFORM_BROWSER_ID as PLATFORM_BROWSER_ID} from '@angular/common';\nimport {APP_ID, ApplicationModule, ApplicationRef, createPlatformFactory, EnvironmentProviders, ErrorHandler, Inject, InjectionToken, ModuleWithProviders, NgModule, NgZone, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, platformCore, PlatformRef, Provider, RendererFactory2, SkipSelf, StaticProvider, Testability, TestabilityRegistry, Type, ɵINJECTOR_SCOPE as INJECTOR_SCOPE, ɵinternalCreateApplication as internalCreateApplication, ɵsetDocument, ɵTESTABILITY as TESTABILITY, ɵTESTABILITY_GETTER as TESTABILITY_GETTER} from '@angular/core';\n\nimport {BrowserDomAdapter} from './browser/browser_adapter';\nimport {SERVER_TRANSITION_PROVIDERS, TRANSITION_ID} from './browser/server-transition';\nimport {BrowserGetTestability} from './browser/testability';\nimport {BrowserXhr} from './browser/xhr';\nimport {DomRendererFactory2, REMOVE_STYLES_ON_COMPONENT_DESTROY} from './dom/dom_renderer';\nimport {DomEventsPlugin} from './dom/events/dom_events';\nimport {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager';\nimport {KeyEventsPlugin} from './dom/events/key_events';\nimport {DomSharedStylesHost, SharedStylesHost} from './dom/shared_styles_host';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * Set of config options available during the application bootstrap operation.\n *\n * @publicApi\n */\nexport interface ApplicationConfig {\n /**\n * List of providers that should be available to the root component and all its children.\n */\n providers: Array<Provider|EnvironmentProviders>;\n}\n\n/**\n * Bootstraps an instance of an Angular application and renders a standalone component as the\n * application's root component. More information about standalone components can be found in [this\n * guide](guide/standalone-components).\n *\n * @usageNotes\n * The root component passed into this function *must* be a standalone one (should have the\n * `standalone: true` flag in the `@Component` decorator config).\n *\n * ```typescript\n * @Component({\n * standalone: true,\n * template: 'Hello world!'\n * })\n * class RootComponent {}\n *\n * const appRef: ApplicationRef = await bootstrapApplication(RootComponent);\n * ```\n *\n * You can add the list of providers that should be available in the application injector by\n * specifying the `providers` field in an object passed as the second argument:\n *\n * ```typescript\n * await bootstrapApplication(RootComponent, {\n * providers: [\n * {provide: BACKEND_URL, useValue: 'https://yourdomain.com/api'}\n * ]\n * });\n * ```\n *\n * The `importProvidersFrom` helper method can be used to collect all providers from any\n * existing NgModule (and transitively from all NgModules that it imports):\n *\n * ```typescript\n * await bootstrapApplication(RootComponent, {\n * providers: [\n * importProvidersFrom(SomeNgModule)\n * ]\n * });\n * ```\n *\n * Note: the `bootstrapApplication` method doesn't include [Testability](api/core/Testability) by\n * default. You can add [Testability](api/core/Testability) by getting the list of necessary\n * providers using `provideProtractorTestingSupport()` function and adding them into the `providers`\n * array, for example:\n *\n * ```typescript\n * import {provideProtractorTestingSupport} from '@angular/platform-browser';\n *\n * await bootstrapApplication(RootComponent, {providers: [provideProtractorTestingSupport()]});\n * ```\n *\n * @param rootComponent A reference to a standalone component that should be rendered.\n * @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for\n * additional info.\n * @returns A promise that returns an `ApplicationRef` instance once resolved.\n *\n * @publicApi\n */\nexport function bootstrapApplication(\n rootComponent: Type<unknown>, options?: ApplicationConfig): Promise<ApplicationRef> {\n return internalCreateApplication({rootComponent, ...createProvidersConfig(options)});\n}\n\n/**\n * Create an instance of an Angular application without bootstrapping any components. This is useful\n * for the situation where one wants to decouple application environment creation (a platform and\n * associated injectors) from rendering components on a screen. Components can be subsequently\n * bootstrapped on the returned `ApplicationRef`.\n *\n * @param options Extra configuration for the application environment, see `ApplicationConfig` for\n * additional info.\n * @returns A promise that returns an `ApplicationRef` instance once resolved.\n *\n * @publicApi\n */\nexport function createApplication(options?: ApplicationConfig) {\n return internalCreateApplication(createProvidersConfig(options));\n}\n\nfunction createProvidersConfig(options?: ApplicationConfig) {\n return {\n appProviders: [\n ...BROWSER_MODULE_PROVIDERS,\n ...(options?.providers ?? []),\n ],\n platformProviders: INTERNAL_BROWSER_PLATFORM_PROVIDERS\n };\n}\n\n/**\n * Returns a set of providers required to setup [Testability](api/core/Testability) for an\n * application bootstrapped using the `bootstrapApplication` function. The set of providers is\n * needed to support testing an application with Protractor (which relies on the Testability APIs\n * to be present).\n *\n * @returns An array of providers required to setup Testability for an application and make it\n * available for testing using Protractor.\n *\n * @publicApi\n */\nexport function provideProtractorTestingSupport(): Provider[] {\n // Return a copy to prevent changes to the original array in case any in-place\n // alterations are performed to the `provideProtractorTestingSupport` call results in app code.\n return [...TESTABILITY_PROVIDERS];\n}\n\nexport function initDomAdapter() {\n BrowserDomAdapter.makeCurrent();\n}\n\nexport function errorHandler(): ErrorHandler {\n return new ErrorHandler();\n}\n\nexport function _document(): any {\n // Tell ivy about the global document\n ɵsetDocument(document);\n return document;\n}\n\nexport const INTERNAL_BROWSER_PLATFORM_PROVIDERS: StaticProvider[] = [\n {provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID},\n {provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true},\n {provide: DOCUMENT, useFactory: _document, deps: []},\n];\n\n/**\n * A factory function that returns a `PlatformRef` instance associated with browser service\n * providers.\n *\n * @publicApi\n */\nexport const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef =\n createPlatformFactory(platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS);\n\n/**\n * Internal marker to signal whether providers from the `BrowserModule` are already present in DI.\n * This is needed to avoid loading `BrowserModule` providers twice. We can't rely on the\n * `BrowserModule` presence itself, since the standalone-based bootstrap just imports\n * `BrowserModule` providers without referencing the module itself.\n */\nconst BROWSER_MODULE_PROVIDERS_MARKER =\n new InjectionToken(NG_DEV_MODE ? 'BrowserModule Providers Marker' : '');\n\nconst TESTABILITY_PROVIDERS = [\n {\n provide: TESTABILITY_GETTER,\n useClass: BrowserGetTestability,\n deps: [],\n },\n {\n provide: TESTABILITY,\n useClass: Testability,\n deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER]\n },\n {\n provide: Testability, // Also provide as `Testability` for backwards-compatibility.\n useClass: Testability,\n deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER]\n }\n];\n\nconst BROWSER_MODULE_PROVIDERS: Provider[] = [\n {provide: INJECTOR_SCOPE, useValue: 'root'},\n {provide: ErrorHandler, useFactory: errorHandler, deps: []}, {\n provide: EVENT_MANAGER_PLUGINS,\n useClass: DomEventsPlugin,\n multi: true,\n deps: [DOCUMENT, NgZone, PLATFORM_ID]\n },\n {provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true, deps: [DOCUMENT]}, {\n provide: DomRendererFactory2,\n useClass: DomRendererFactory2,\n deps: [EventManager, DomSharedStylesHost, APP_ID, REMOVE_STYLES_ON_COMPONENT_DESTROY]\n },\n {provide: RendererFactory2, useExisting: DomRendererFactory2},\n {provide: SharedStylesHost, useExisting: DomSharedStylesHost},\n {provide: DomSharedStylesHost, useClass: DomSharedStylesHost, deps: [DOCUMENT]},\n {provide: EventManager, useClass: EventManager, deps: [EVENT_MANAGER_PLUGINS, NgZone]},\n {provide: XhrFactory, useClass: BrowserXhr, deps: []},\n NG_DEV_MODE ? {provide: BROWSER_MODULE_PROVIDERS_MARKER, useValue: true} : []\n];\n\n/**\n * Exports required infrastructure for all Angular apps.\n * Included by default in all Angular apps created with the CLI\n * `new` command.\n * Re-exports `CommonModule` and `ApplicationModule`, making their\n * exports and providers available to all apps.\n *\n * @publicApi\n */\n@NgModule({\n providers: [\n ...BROWSER_MODULE_PROVIDERS, //\n ...TESTABILITY_PROVIDERS\n ],\n exports: [CommonModule, ApplicationModule],\n})\nexport class BrowserModule {\n constructor(@Optional() @SkipSelf() @Inject(BROWSER_MODULE_PROVIDERS_MARKER)\n providersAlreadyPresent: boolean|null) {\n if (NG_DEV_MODE && providersAlreadyPresent) {\n throw new Error(\n `Providers from the \\`BrowserModule\\` have already been loaded. If you need access ` +\n `to common directives such as NgIf and NgFor, import the \\`CommonModule\\` instead.`);\n }\n }\n\n /**\n * Configures a browser-based app to transition from a server-rendered app, if\n * one is present on the page.\n *\n * @param params An object containing an identifier for the app to transition.\n * The ID must match between the client and server versions of the app.\n * @returns The reconfigured `BrowserModule` to import into the app's root `AppModule`.\n */\n static withServerTransition(params: {appId: string}): ModuleWithProviders<BrowserModule> {\n return {\n ngModule: BrowserModule,\n providers: [\n {provide: APP_ID, useValue: params.appId},\n {provide: TRANSITION_ID, useExisting: APP_ID},\n SERVER_TRANSITION_PROVIDERS,\n ],\n };\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵgetDOM as getDOM} from '@angular/common';\nimport {GetTestability, Testability, TestabilityRegistry, ɵglobal as global} from '@angular/core';\n\nexport class BrowserGetTestability implements GetTestability {\n addToWindow(registry: TestabilityRegistry): void {\n global['getAngularTestability'] = (elem: any, findInAncestors: boolean = true) => {\n const testability = registry.findTestabilityInTree(elem, findInAncestors);\n if (testability == null) {\n throw new Error('Could not find testability for element.');\n }\n return testability;\n };\n\n global['getAllAngularTestabilities'] = () => registry.getAllTestabilities();\n\n global['getAllAngularRootElements'] = () => registry.getAllRootElements();\n\n const whenAllStable = (callback: any /** TODO #9100 */) => {\n const testabilities = global['getAllAngularTestabilities']();\n let count = testabilities.length;\n let didWork = false;\n const decrement = function(didWork_: any /** TODO #9100 */) {\n didWork = didWork || didWork_;\n count--;\n if (count == 0) {\n callback(didWork);\n }\n };\n testabilities.forEach(function(testability: any /** TODO #9100 */) {\n testability.whenStable(decrement);\n });\n };\n\n if (!global['frameworkStabilizers']) {\n global['frameworkStabilizers'] = [];\n }\n global['frameworkStabilizers'].push(whenAllStable);\n }\n\n findTestabilityInTree(registry: TestabilityRegistry, elem: any, findInAncestors: boolean):\n Testability|null {\n if (elem == null) {\n return null;\n }\n const t = registry.getTestability(elem);\n if (t != null) {\n return t;\n } else if (!findInAncestors) {\n return null;\n }\n if (getDOM().isShadowRoot(elem)) {\n return this.findTestabilityInTree(registry, (<any>elem).host, true);\n }\n return this.findTestabilityInTree(registry, elem.parentElement, true);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT, ɵDomAdapter as DomAdapter, ɵgetDOM as getDOM} from '@angular/common';\nimport {Inject, Injectable, ɵɵinject} from '@angular/core';\n\n/**\n * Represents the attributes of an HTML `<meta>` element. The element itself is\n * represented by the internal `HTMLMetaElement`.\n *\n * @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta)\n * @see `Meta`\n *\n * @publicApi\n */\nexport type MetaDefinition = {\n charset?: string;\n content?: string;\n httpEquiv?: string;\n id?: string;\n itemprop?: string;\n name?: string;\n property?: string;\n scheme?: string;\n url?: string;\n}&{\n // TODO(IgorMinar): this type looks wrong\n [prop: string]: string;\n};\n\n/**\n * Factory to create a `Meta` service instance for the current DOM document.\n */\nexport function createMeta() {\n return new Meta(ɵɵinject(DOCUMENT));\n}\n\n/**\n * A service for managing HTML `<meta>` tags.\n *\n * Properties of the `MetaDefinition` object match the attributes of the\n * HTML `<meta>` tag. These tags define document metadata that is important for\n * things like configuring a Content Security Policy, defining browser compatibility\n * and security settings, setting HTTP Headers, defining rich content for social sharing,\n * and Search Engine Optimization (SEO).\n *\n * To identify specific `<meta>` tags in a document, use an attribute selection\n * string in the format `\"tag_attribute='value string'\"`.\n * For example, an `attrSelector` value of `\"name='description'\"` matches a tag\n * whose `name` attribute has the value `\"description\"`.\n * Selectors are used with the `querySelector()` Document method,\n * in the format `meta[{attrSelector}]`.\n *\n * @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta)\n * @see [Document.querySelector()](https://developer.mozilla.org/docs/Web/API/Document/querySelector)\n *\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: createMeta, deps: []})\nexport class Meta {\n private _dom: DomAdapter;\n constructor(@Inject(DOCUMENT) private _doc: any) {\n this._dom = getDOM();\n }\n /**\n * Retrieves or creates a specific `<meta>` tag element in the current HTML document.\n * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute\n * values in the provided tag definition, and verifies that all other attribute values are equal.\n * If an existing element is found, it is returned and is not modified in any way.\n * @param tag The definition of a `<meta>` element to match or create.\n * @param forceCreation True to create a new element without checking whether one already exists.\n * @returns The existing element with the same attributes and values if found,\n * the new element if no match is found, or `null` if the tag parameter is not defined.\n */\n addTag(tag: MetaDefinition, forceCreation: boolean = false): HTMLMetaElement|null {\n if (!tag) return null;\n return this._getOrCreateElement(tag, forceCreation);\n }\n\n /**\n * Retrieves or creates a set of `<meta>` tag elements in the current HTML document.\n * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute\n * values in the provided tag definition, and verifies that all other attribute values are equal.\n * @param tags An array of tag definitions to match or create.\n * @param forceCreation True to create new elements without checking whether they already exist.\n * @returns The matching elements if found, or the new elements.\n */\n addTags(tags: MetaDefinition[], forceCreation: boolean = false): HTMLMetaElement[] {\n if (!tags) return [];\n return tags.reduce((result: HTMLMetaElement[], tag: MetaDefinition) => {\n if (tag) {\n result.push(this._getOrCreateElement(tag, forceCreation));\n }\n return result;\n }, []);\n }\n\n /**\n * Retrieves a `<meta>` tag element in the current HTML document.\n * @param attrSelector The tag attribute and value to match against, in the format\n * `\"tag_attribute='value string'\"`.\n * @returns The matching element, if any.\n */\n getTag(attrSelector: string): HTMLMetaElement|null {\n if (!attrSelector) return null;\n return this._doc.querySelector(`meta[${attrSelector}]`) || null;\n }\n\n /**\n * Retrieves a set of `<meta>` tag elements in the current HTML document.\n * @param attrSelector The tag attribute and value to match against, in the format\n * `\"tag_attribute='value string'\"`.\n * @returns The matching elements, if any.\n */\n getTags(attrSelector: string): HTMLMetaElement[] {\n if (!attrSelector) return [];\n const list /*NodeList*/ = this._doc.querySelectorAll(`meta[${attrSelector}]`);\n return list ? [].slice.call(list) : [];\n }\n\n /**\n * Modifies an existing `<meta>` tag element in the current HTML document.\n * @param tag The tag description with which to replace the existing tag content.\n * @param selector A tag attribute and value to match against, to identify\n * an existing tag. A string in the format `\"tag_attribute=`value string`\"`.\n * If not supplied, matches a tag with the same `name` or `property` attribute value as the\n * replacement tag.\n * @return The modified element.\n */\n updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement|null {\n if (!tag) return null;\n selector = selector || this._parseSelector(tag);\n const meta: HTMLMetaElement = this.getTag(selector)!;\n if (meta) {\n return this._setMetaElementAttributes(tag, meta);\n }\n return this._getOrCreateElement(tag, true);\n }\n\n /**\n * Removes an existing `<meta>` tag element from the current HTML document.\n * @param attrSelector A tag attribute and value to match against, to identify\n * an existing tag. A string in the format `\"tag_attribute=`value string`\"`.\n */\n removeTag(attrSelector: string): void {\n this.removeTagElement(this.getTag(attrSelector)!);\n }\n\n /**\n * Removes an existing `<meta>` tag element from the current HTML document.\n * @param meta The tag definition to match against to identify an existing tag.\n */\n removeTagElement(meta: HTMLMetaElement): void {\n if (meta) {\n this._dom.remove(meta);\n }\n }\n\n private _getOrCreateElement(meta: MetaDefinition, forceCreation: boolean = false):\n HTMLMetaElement {\n if (!forceCreation) {\n const selector: string = this._parseSelector(meta);\n // It's allowed to have multiple elements with the same name so it's not enough to\n // just check that element with the same name already present on the page. We also need to\n // check if element has tag attributes\n const elem = this.getTags(selector).filter(elem => this._containsAttributes(meta, elem))[0];\n if (elem !== undefined) return elem;\n }\n const element: HTMLMetaElement = this._dom.createElement('meta') as HTMLMetaElement;\n this._setMetaElementAttributes(meta, element);\n const head = this._doc.getElementsByTagName('head')[0];\n head.appendChild(element);\n return element;\n }\n\n private _setMetaElementAttributes(tag: MetaDefinition, el: HTMLMetaElement): HTMLMetaElement {\n Object.keys(tag).forEach(\n (prop: string) => el.setAttribute(this._getMetaKeyMap(prop), tag[prop]));\n return el;\n }\n\n private _parseSelector(tag: MetaDefinition): string {\n const attr: string = tag.name ? 'name' : 'property';\n return `${attr}=\"${tag[attr]}\"`;\n }\n\n private _containsAttributes(tag: MetaDefinition, elem: HTMLMetaElement): boolean {\n return Object.keys(tag).every(\n (key: string) => elem.getAttribute(this._getMetaKeyMap(key)) === tag[key]);\n }\n\n private _getMetaKeyMap(prop: string): string {\n return META_KEYS_MAP[prop] || prop;\n }\n}\n\n/**\n * Mapping for MetaDefinition properties with their correct meta attribute names\n */\nconst META_KEYS_MAP: {[prop: string]: string;} = {\n httpEquiv: 'http-equiv'\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT, ɵgetDOM as getDOM} from '@angular/common';\nimport {Inject, Injectable, ɵɵinject} from '@angular/core';\n\n\n/**\n * Factory to create Title service.\n */\nexport function createTitle() {\n return new Title(ɵɵinject(DOCUMENT));\n}\n\n/**\n * A service that can be used to get and set the title of a current HTML document.\n *\n * Since an Angular application can't be bootstrapped on the entire HTML document (`<html>` tag)\n * it is not possible to bind to the `text` property of the `HTMLTitleElement` elements\n * (representing the `<title>` tag). Instead, this service can be used to set and get the current\n * title value.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: createTitle, deps: []})\nexport class Title {\n constructor(@Inject(DOCUMENT) private _doc: any) {}\n /**\n * Get the title of the current HTML document.\n */\n getTitle(): string {\n return this._doc.title;\n }\n\n /**\n * Set the title of the current HTML document.\n * @param newTitle\n */\n setTitle(newTitle: string) {\n this._doc.title = newTitle || '';\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst win = typeof window !== 'undefined' && window || <any>{};\nexport {win as window};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, InjectionToken, NgModule, Optional, Provider, ɵConsole as Console} from '@angular/core';\n\nimport {EVENT_MANAGER_PLUGINS, EventManagerPlugin} from './event_manager';\n\n\n\n/**\n * Supported HammerJS recognizer event names.\n */\nconst EVENT_NAMES = {\n // pan\n 'pan': true,\n 'panstart': true,\n 'panmove': true,\n 'panend': true,\n 'pancancel': true,\n 'panleft': true,\n 'panright': true,\n 'panup': true,\n 'pandown': true,\n // pinch\n 'pinch': true,\n 'pinchstart': true,\n 'pinchmove': true,\n 'pinchend': true,\n 'pinchcancel': true,\n 'pinchin': true,\n 'pinchout': true,\n // press\n 'press': true,\n 'pressup': true,\n // rotate\n 'rotate': true,\n 'rotatestart': true,\n 'rotatemove': true,\n 'rotateend': true,\n 'rotatecancel': true,\n // swipe\n 'swipe': true,\n 'swipeleft': true,\n 'swiperight': true,\n 'swipeup': true,\n 'swipedown': true,\n // tap\n 'tap': true,\n 'doubletap': true\n};\n\n/**\n * DI token for providing [HammerJS](https://hammerjs.github.io/) support to Angular.\n * @see `HammerGestureConfig`\n *\n * @ngModule HammerModule\n * @publicApi\n */\nexport const HAMMER_GESTURE_CONFIG = new InjectionToken<HammerGestureConfig>('HammerGestureConfig');\n\n\n/**\n * Function that loads HammerJS, returning a promise that is resolved once HammerJs is loaded.\n *\n * @publicApi\n */\nexport type HammerLoader = () => Promise<void>;\n\n/**\n * Injection token used to provide a {@link HammerLoader} to Angular.\n *\n * @publicApi\n */\nexport const HAMMER_LOADER = new InjectionToken<HammerLoader>('HammerLoader');\n\nexport interface HammerInstance {\n on(eventName: string, callback?: Function): void;\n off(eventName: string, callback?: Function): void;\n destroy?(): void;\n}\n\n/**\n * An injectable [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)\n * for gesture recognition. Configures specific event recognition.\n * @publicApi\n */\n@Injectable()\nexport class HammerGestureConfig {\n /**\n * A set of supported event names for gestures to be used in Angular.\n * Angular supports all built-in recognizers, as listed in\n * [HammerJS documentation](https://hammerjs.github.io/).\n */\n events: string[] = [];\n\n /**\n * Maps gesture event names to a set of configuration options\n * that specify overrides to the default values for specific properties.\n *\n * The key is a supported event name to be configured,\n * and the options object contains a set of properties, with override values\n * to be applied to the named recognizer event.\n * For example, to disable recognition of the rotate event, specify\n * `{\"rotate\": {\"enable\": false}}`.\n *\n * Properties that are not present take the HammerJS default values.\n * For information about which properties are supported for which events,\n * and their allowed and default values, see\n * [HammerJS documentation](https://hammerjs.github.io/).\n *\n */\n overrides: {[key: string]: Object} = {};\n\n /**\n * Properties whose default values can be overridden for a given event.\n * Different sets of properties apply to different events.\n * For information about which properties are supported for which events,\n * and their allowed and default values, see\n * [HammerJS documentation](https://hammerjs.github.io/).\n */\n options?: {\n cssProps?: any;\n domEvents?: boolean;\n enable?: boolean | ((manager: any) => boolean);\n preset?: any[];\n touchAction?: string;\n recognizers?: any[];\n inputClass?: any;\n inputTarget?: EventTarget;\n };\n\n /**\n * Creates a [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)\n * and attaches it to a given HTML element.\n * @param element The element that will recognize gestures.\n * @returns A HammerJS event-manager object.\n */\n buildHammer(element: HTMLElement): HammerInstance {\n const mc = new Hammer!(element, this.options);\n\n mc.get('pinch').set({enable: true});\n mc.get('rotate').set({enable: true});\n\n for (const eventName in this.overrides) {\n mc.get(eventName).set(this.overrides[eventName]);\n }\n\n return mc;\n }\n}\n\n/**\n * Event plugin that adds Hammer support to an application.\n *\n * @ngModule HammerModule\n */\n@Injectable()\nexport class HammerGesturesPlugin extends EventManagerPlugin {\n private _loaderPromise: Promise<void>|null = null;\n\n constructor(\n @Inject(DOCUMENT) doc: any,\n @Inject(HAMMER_GESTURE_CONFIG) private _config: HammerGestureConfig, private console: Console,\n @Optional() @Inject(HAMMER_LOADER) private loader?: HammerLoader|null) {\n super(doc);\n }\n\n override supports(eventName: string): boolean {\n if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) {\n return false;\n }\n\n if (!(window as any).Hammer && !this.loader) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n this.console.warn(\n `The \"${eventName}\" event cannot be bound because Hammer.JS is not ` +\n `loaded and no custom loader has been specified.`);\n }\n return false;\n }\n\n return true;\n }\n\n override addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {\n const zone = this.manager.getZone();\n eventName = eventName.toLowerCase();\n\n // If Hammer is not present but a loader is specified, we defer adding the event listener\n // until Hammer is loaded.\n if (!(window as any).Hammer && this.loader) {\n this._loaderPromise = this._loaderPromise || zone.runOutsideAngular(() => this.loader!());\n // This `addEventListener` method returns a function to remove the added listener.\n // Until Hammer is loaded, the returned function needs to *cancel* the registration rather\n // than remove anything.\n let cancelRegistration = false;\n let deregister: Function = () => {\n cancelRegistration = true;\n };\n\n zone.runOutsideAngular(\n () => this._loaderPromise!\n .then(() => {\n // If Hammer isn't actually loaded when the custom loader resolves, give up.\n if (!(window as any).Hammer) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n this.console.warn(\n `The custom HAMMER_LOADER completed, but Hammer.JS is not present.`);\n }\n deregister = () => {};\n return;\n }\n\n if (!cancelRegistration) {\n // Now that Hammer is loaded and the listener is being loaded for real,\n // the deregistration function changes from canceling registration to\n // removal.\n deregister = this.addEventListener(element, eventName, handler);\n }\n })\n .catch(() => {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n this.console.warn(\n `The \"${eventName}\" event cannot be bound because the custom ` +\n `Hammer.JS loader failed.`);\n }\n deregister = () => {};\n }));\n\n // Return a function that *executes* `deregister` (and not `deregister` itself) so that we\n // can change the behavior of `deregister` once the listener is added. Using a closure in\n // this way allows us to avoid any additional data structures to track listener removal.\n return () => {\n deregister();\n };\n }\n\n return zone.runOutsideAngular(() => {\n // Creating the manager bind events, must be done outside of angular\n const mc = this._config.buildHammer(element);\n const callback = function(eventObj: HammerInput) {\n zone.runGuarded(function() {\n handler(eventObj);\n });\n };\n mc.on(eventName, callback);\n return () => {\n mc.off(eventName, callback);\n // destroy mc to prevent memory leak\n if (typeof mc.destroy === 'function') {\n mc.destroy();\n }\n };\n });\n }\n\n isCustomEvent(eventName: string): boolean {\n return this._config.events.indexOf(eventName) > -1;\n }\n}\n\n/**\n * Adds support for HammerJS.\n *\n * Import this module at the root of your application so that Angular can work with\n * HammerJS to detect gesture events.\n *\n * Note that applications still need to include the HammerJS script itself. This module\n * simply sets up the coordination layer between HammerJS and Angular's EventManager.\n *\n * @publicApi\n */\n@NgModule({\n providers: [\n {\n provide: EVENT_MANAGER_PLUGINS,\n useClass: HammerGesturesPlugin,\n multi: true,\n deps: [DOCUMENT, HAMMER_GESTURE_CONFIG, Console, [new Optional(), HAMMER_LOADER]]\n },\n {provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig, deps: []},\n ]\n})\nexport class HammerModule {\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {forwardRef, Inject, Injectable, Injector, Sanitizer, SecurityContext, ɵ_sanitizeHtml as _sanitizeHtml, ɵ_sanitizeUrl as _sanitizeUrl, ɵallowSanitizationBypassAndThrow as allowSanitizationBypassOrThrow, ɵbypassSanitizationTrustHtml as bypassSanitizationTrustHtml, ɵbypassSanitizationTrustResourceUrl as bypassSanitizationTrustResourceUrl, ɵbypassSanitizationTrustScript as bypassSanitizationTrustScript, ɵbypassSanitizationTrustStyle as bypassSanitizationTrustStyle, ɵbypassSanitizationTrustUrl as bypassSanitizationTrustUrl, ɵBypassType as BypassType, ɵgetSanitizationBypassType as getSanitizationBypassType, ɵunwrapSafeValue as unwrapSafeValue, ɵXSS_SECURITY_URL as XSS_SECURITY_URL} from '@angular/core';\n\nexport {SecurityContext};\n\n\n\n/**\n * Marker interface for a value that's safe to use in a particular context.\n *\n * @publicApi\n */\nexport interface SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as HTML.\n *\n * @publicApi\n */\nexport interface SafeHtml extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as style (CSS).\n *\n * @publicApi\n */\nexport interface SafeStyle extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as JavaScript.\n *\n * @publicApi\n */\nexport interface SafeScript extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as a URL linking to a document.\n *\n * @publicApi\n */\nexport interface SafeUrl extends SafeValue {}\n\n/**\n * Marker interface for a value that's safe to use as a URL to load executable code from.\n *\n * @publicApi\n */\nexport interface SafeResourceUrl extends SafeValue {}\n\n/**\n * DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing\n * values to be safe to use in the different DOM contexts.\n *\n * For example, when binding a URL in an `<a [href]=\"someValue\">` hyperlink, `someValue` will be\n * sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on\n * the website.\n *\n * In specific situations, it might be necessary to disable sanitization, for example if the\n * application genuinely needs to produce a `javascript:` style link with a dynamic value in it.\n * Users can bypass security by constructing a value with one of the `bypassSecurityTrust...`\n * methods, and then binding to that value from the template.\n *\n * These situations should be very rare, and extraordinary care must be taken to avoid creating a\n * Cross Site Scripting (XSS) security bug!\n *\n * When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as\n * close as possible to the source of the value, to make it easy to verify no security bug is\n * created by its use.\n *\n * It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that\n * does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous\n * code. The sanitizer leaves safe values intact.\n *\n * @security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in\n * sanitization for the value passed in. Carefully check and audit all values and code paths going\n * into this call. Make sure any user data is appropriately escaped for this security context.\n * For more detail, see the [Security Guide](https://g.co/ng/security).\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useExisting: forwardRef(() => DomSanitizerImpl)})\nexport abstract class DomSanitizer implements Sanitizer {\n /**\n * Gets a safe value from either a known safe value or a value with unknown safety.\n *\n * If the given value is already a `SafeValue`, this method returns the unwrapped value.\n * If the security context is HTML and the given value is a plain string, this method\n * sanitizes the string, removing any potentially unsafe content.\n * For any other security context, this method throws an error if provided\n * with a plain string.\n */\n abstract sanitize(context: SecurityContext, value: SafeValue|string|null): string|null;\n\n /**\n * Bypass security and trust the given value to be safe HTML. Only use this when the bound HTML\n * is unsafe (e.g. contains `<script>` tags) and the code should be executed. The sanitizer will\n * leave safe HTML intact, so in most situations this method should not be used.\n *\n * **WARNING:** calling this method with untrusted user data exposes your application to XSS\n * security risks!\n */\n abstract bypassSecurityTrustHtml(value: string): SafeHtml;\n\n /**\n * Bypass security and trust the given value to be safe style value (CSS).\n *\n * **WARNING:** calling this method with untrusted user data exposes your application to XSS\n * security risks!\n */\n abstract bypassSecurityTrustStyle(value: string): SafeStyle;\n\n /**\n * Bypass security and trust the given value to be safe JavaScript.\n *\n * **WARNING:** calling this method with untrusted user data exposes your application to XSS\n * security risks!\n */\n abstract bypassSecurityTrustScript(value: string): SafeScript;\n\n /**\n * Bypass security and trust the given value to be a safe style URL, i.e. a value that can be used\n * in hyperlinks or `<img src>`.\n *\n * **WARNING:** calling this method with untrusted user data exposes your application to XSS\n * security risks!\n */\n abstract bypassSecurityTrustUrl(value: string): SafeUrl;\n\n /**\n * Bypass security and trust the given value to be a safe resource URL, i.e. a location that may\n * be used to load executable code from, like `<script src>`, or `<iframe src>`.\n *\n * **WARNING:** calling this method with untrusted user data exposes your application to XSS\n * security risks!\n */\n abstract bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl;\n}\n\nexport function domSanitizerImplFactory(injector: Injector) {\n return new DomSanitizerImpl(injector.get(DOCUMENT));\n}\n\n@Injectable({providedIn: 'root', useFactory: domSanitizerImplFactory, deps: [Injector]})\nexport class DomSanitizerImpl extends DomSanitizer {\n constructor(@Inject(DOCUMENT) private _doc: any) {\n super();\n }\n\n override sanitize(ctx: SecurityContext, value: SafeValue|string|null): string|null {\n if (value == null) return null;\n switch (ctx) {\n case SecurityContext.NONE:\n return value as string;\n case SecurityContext.HTML:\n if (allowSanitizationBypassOrThrow(value, BypassType.Html)) {\n return unwrapSafeValue(value);\n }\n return _sanitizeHtml(this._doc, String(value)).toString();\n case SecurityContext.STYLE:\n if (allowSanitizationBypassOrThrow(value, BypassType.Style)) {\n return unwrapSafeValue(value);\n }\n return value as string;\n case SecurityContext.SCRIPT:\n if (allowSanitizationBypassOrThrow(value, BypassType.Script)) {\n return unwrapSafeValue(value);\n }\n throw new Error('unsafe value used in a script context');\n case SecurityContext.URL:\n if (allowSanitizationBypassOrThrow(value, BypassType.Url)) {\n return unwrapSafeValue(value);\n }\n return _sanitizeUrl(String(value));\n case SecurityContext.RESOURCE_URL:\n if (allowSanitizationBypassOrThrow(value, BypassType.ResourceUrl)) {\n return unwrapSafeValue(value);\n }\n throw new Error(`unsafe value used in a resource URL context (see ${XSS_SECURITY_URL})`);\n default:\n throw new Error(`Unexpected SecurityContext ${ctx} (see ${XSS_SECURITY_URL})`);\n }\n }\n\n override bypassSecurityTrustHtml(value: string): SafeHtml {\n return bypassSanitizationTrustHtml(value);\n }\n override bypassSecurityTrustStyle(value: string): SafeStyle {\n return bypassSanitizationTrustStyle(value);\n }\n override bypassSecurityTrustScript(value: string): SafeScript {\n return bypassSanitizationTrustScript(value);\n }\n override bypassSecurityTrustUrl(value: string): SafeUrl {\n return bypassSanitizationTrustUrl(value);\n }\n override bypassSecurityTrustResourceUrl(value: string): SafeResourceUrl {\n return bypassSanitizationTrustResourceUrl(value);\n }\n}\n","import { ConnectableObservable } from '../observable/ConnectableObservable';\nimport { Subscription } from '../Subscription';\nimport { MonoTypeOperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Make a {@link ConnectableObservable} behave like a ordinary observable and automates the way\n * you can connect to it.\n *\n * Internally it counts the subscriptions to the observable and subscribes (only once) to the source if\n * the number of subscriptions is larger than 0. If the number of subscriptions is smaller than 1, it\n * unsubscribes from the source. This way you can make sure that everything before the *published*\n * refCount has only a single subscription independently of the number of subscribers to the target\n * observable.\n *\n * Note that using the {@link share} operator is exactly the same as using the `multicast(() => new Subject())` operator\n * (making the observable hot) and the *refCount* operator in a sequence.\n *\n * ![](refCount.png)\n *\n * ## Example\n *\n * In the following example there are two intervals turned into connectable observables\n * by using the *publish* operator. The first one uses the *refCount* operator, the\n * second one does not use it. You will notice that a connectable observable does nothing\n * until you call its connect function.\n *\n * ```ts\n * import { interval, tap, publish, refCount } from 'rxjs';\n *\n * // Turn the interval observable into a ConnectableObservable (hot)\n * const refCountInterval = interval(400).pipe(\n * tap(num => console.log(`refCount ${ num }`)),\n * publish(),\n * refCount()\n * );\n *\n * const publishedInterval = interval(400).pipe(\n * tap(num => console.log(`publish ${ num }`)),\n * publish()\n * );\n *\n * refCountInterval.subscribe();\n * refCountInterval.subscribe();\n * // 'refCount 0' -----> 'refCount 1' -----> etc\n * // All subscriptions will receive the same value and the tap (and\n * // every other operator) before the `publish` operator will be executed\n * // only once per event independently of the number of subscriptions.\n *\n * publishedInterval.subscribe();\n * // Nothing happens until you call .connect() on the observable.\n * ```\n *\n * @return A function that returns an Observable that automates the connection\n * to ConnectableObservable.\n * @see {@link ConnectableObservable}\n * @see {@link share}\n * @see {@link publish}\n * @deprecated Replaced with the {@link share} operator. How `share` is used\n * will depend on the connectable observable you created just prior to the\n * `refCount` operator.\n * Details: https://rxjs.dev/deprecations/multicasting\n */\nexport function refCount<T>(): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n let connection: Subscription | null = null;\n\n (source as any)._refCount++;\n\n const refCounter = createOperatorSubscriber(subscriber, undefined, undefined, undefined, () => {\n if (!source || (source as any)._refCount <= 0 || 0 < --(source as any)._refCount) {\n connection = null;\n return;\n }\n\n ///\n // Compare the local RefCountSubscriber's connection Subscription to the\n // connection Subscription on the shared ConnectableObservable. In cases\n // where the ConnectableObservable source synchronously emits values, and\n // the RefCountSubscriber's downstream Observers synchronously unsubscribe,\n // execution continues to here before the RefCountOperator has a chance to\n // supply the RefCountSubscriber with the shared connection Subscription.\n // For example:\n // ```\n // range(0, 10).pipe(\n // publish(),\n // refCount(),\n // take(5),\n // )\n // .subscribe();\n // ```\n // In order to account for this case, RefCountSubscriber should only dispose\n // the ConnectableObservable's shared connection Subscription if the\n // connection Subscription exists, *and* either:\n // a. RefCountSubscriber doesn't have a reference to the shared connection\n // Subscription yet, or,\n // b. RefCountSubscriber's connection Subscription reference is identical\n // to the shared connection Subscription\n ///\n\n const sharedConnection = (source as any)._connection;\n const conn = connection;\n connection = null;\n\n if (sharedConnection && (!conn || sharedConnection === conn)) {\n sharedConnection.unsubscribe();\n }\n\n subscriber.unsubscribe();\n });\n\n source.subscribe(refCounter);\n\n if (!refCounter.closed) {\n connection = (source as ConnectableObservable<T>).connect();\n }\n });\n}\n","import { Subject } from '../Subject';\nimport { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { Subscription } from '../Subscription';\nimport { refCount as higherOrderRefCount } from '../operators/refCount';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { hasLift } from '../util/lift';\n\n/**\n * @class ConnectableObservable<T>\n * @deprecated Will be removed in v8. Use {@link connectable} to create a connectable observable.\n * If you are using the `refCount` method of `ConnectableObservable`, use the {@link share} operator\n * instead.\n * Details: https://rxjs.dev/deprecations/multicasting\n */\nexport class ConnectableObservable<T> extends Observable<T> {\n protected _subject: Subject<T> | null = null;\n protected _refCount: number = 0;\n protected _connection: Subscription | null = null;\n\n /**\n * @param source The source observable\n * @param subjectFactory The factory that creates the subject used internally.\n * @deprecated Will be removed in v8. Use {@link connectable} to create a connectable observable.\n * `new ConnectableObservable(source, factory)` is equivalent to\n * `connectable(source, { connector: factory })`.\n * When the `refCount()` method is needed, the {@link share} operator should be used instead:\n * `new ConnectableObservable(source, factory).refCount()` is equivalent to\n * `source.pipe(share({ connector: factory }))`.\n * Details: https://rxjs.dev/deprecations/multicasting\n */\n constructor(public source: Observable<T>, protected subjectFactory: () => Subject<T>) {\n super();\n // If we have lift, monkey patch that here. This is done so custom observable\n // types will compose through multicast. Otherwise the resulting observable would\n // simply be an instance of `ConnectableObservable`.\n if (hasLift(source)) {\n this.lift = source.lift;\n }\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber<T>) {\n return this.getSubject().subscribe(subscriber);\n }\n\n protected getSubject(): Subject<T> {\n const subject = this._subject;\n if (!subject || subject.isStopped) {\n this._subject = this.subjectFactory();\n }\n return this._subject!;\n }\n\n protected _teardown() {\n this._refCount = 0;\n const { _connection } = this;\n this._subject = this._connection = null;\n _connection?.unsubscribe();\n }\n\n /**\n * @deprecated {@link ConnectableObservable} will be removed in v8. Use {@link connectable} instead.\n * Details: https://rxjs.dev/deprecations/multicasting\n */\n connect(): Subscription {\n let connection = this._connection;\n if (!connection) {\n connection = this._connection = new Subscription();\n const subject = this.getSubject();\n connection.add(\n this.source.subscribe(\n createOperatorSubscriber(\n subject as any,\n undefined,\n () => {\n this._teardown();\n subject.complete();\n },\n (err) => {\n this._teardown();\n subject.error(err);\n },\n () => this._teardown()\n )\n )\n );\n\n if (connection.closed) {\n this._connection = null;\n connection = Subscription.EMPTY;\n }\n }\n return connection;\n }\n\n /**\n * @deprecated {@link ConnectableObservable} will be removed in v8. Use the {@link share} operator instead.\n * Details: https://rxjs.dev/deprecations/multicasting\n */\n refCount(): Observable<T> {\n return higherOrderRefCount()(this) as Observable<T>;\n }\n}\n","import { EMPTY } from '../observable/empty';\nimport { MonoTypeOperatorFunction } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Waits for the source to complete, then emits the last N values from the source,\n * as specified by the `count` argument.\n *\n * ![](takeLast.png)\n *\n * `takeLast` results in an observable that will hold values up to `count` values in memory,\n * until the source completes. It then pushes all values in memory to the consumer, in the\n * order they were received from the source, then notifies the consumer that it is\n * complete.\n *\n * If for some reason the source completes before the `count` supplied to `takeLast` is reached,\n * all values received until that point are emitted, and then completion is notified.\n *\n * **Warning**: Using `takeLast` with an observable that never completes will result\n * in an observable that never emits a value.\n *\n * ## Example\n *\n * Take the last 3 values of an Observable with many values\n *\n * ```ts\n * import { range, takeLast } from 'rxjs';\n *\n * const many = range(1, 100);\n * const lastThree = many.pipe(takeLast(3));\n * lastThree.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeUntil}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param count The maximum number of values to emit from the end of\n * the sequence of values emitted by the source Observable.\n * @return A function that returns an Observable that emits at most the last\n * `count` values emitted by the source Observable.\n */\nexport function takeLast<T>(count: number): MonoTypeOperatorFunction<T> {\n return count <= 0\n ? () => EMPTY\n : operate((source, subscriber) => {\n // This buffer will hold the values we are going to emit\n // when the source completes. Since we only want to take the\n // last N values, we can't emit until we're sure we're not getting\n // any more values.\n let buffer: T[] = [];\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n // Add the most recent value onto the end of our buffer.\n buffer.push(value);\n // If our buffer is now larger than the number of values we\n // want to take, we remove the oldest value from the buffer.\n count < buffer.length && buffer.shift();\n },\n () => {\n // The source completed, we now know what are last values\n // are, emit them in the order they were received.\n for (const value of buffer) {\n subscriber.next(value);\n }\n subscriber.complete();\n },\n // Errors are passed through to the consumer\n undefined,\n () => {\n // During finalization release the values in our buffer.\n buffer = null!;\n }\n )\n );\n });\n}\n","import { Observable } from '../Observable';\nimport { EmptyError } from '../util/EmptyError';\nimport { OperatorFunction, TruthyTypesOf } from '../types';\nimport { filter } from './filter';\nimport { takeLast } from './takeLast';\nimport { throwIfEmpty } from './throwIfEmpty';\nimport { defaultIfEmpty } from './defaultIfEmpty';\nimport { identity } from '../util/identity';\n\nexport function last<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function last<T, D>(predicate: BooleanConstructor, defaultValue: D): OperatorFunction<T, TruthyTypesOf<T> | D>;\nexport function last<T, D = T>(predicate?: null, defaultValue?: D): OperatorFunction<T, T | D>;\nexport function last<T, S extends T>(\n predicate: (value: T, index: number, source: Observable<T>) => value is S,\n defaultValue?: S\n): OperatorFunction<T, S>;\nexport function last<T, D = T>(\n predicate: (value: T, index: number, source: Observable<T>) => boolean,\n defaultValue?: D\n): OperatorFunction<T, T | D>;\n\n/**\n * Returns an Observable that emits only the last item emitted by the source Observable.\n * It optionally takes a predicate function as a parameter, in which case, rather than emitting\n * the last item from the source Observable, the resulting Observable will emit the last item\n * from the source Observable that satisfies the predicate.\n *\n * ![](last.png)\n *\n * It will throw an error if the source completes without notification or one that matches the predicate. It\n * returns the last value or if a predicate is provided last value that matches the predicate. It returns the\n * given default value if no notification is emitted or matches the predicate.\n *\n * ## Examples\n *\n * Last alphabet from the sequence\n *\n * ```ts\n * import { from, last } from 'rxjs';\n *\n * const source = from(['x', 'y', 'z']);\n * const result = source.pipe(last());\n *\n * result.subscribe(value => console.log(`Last alphabet: ${ value }`));\n *\n * // Outputs\n * // Last alphabet: z\n * ```\n *\n * Default value when the value in the predicate is not matched\n *\n * ```ts\n * import { from, last } from 'rxjs';\n *\n * const source = from(['x', 'y', 'z']);\n * const result = source.pipe(last(char => char === 'a', 'not found'));\n *\n * result.subscribe(value => console.log(`'a' is ${ value }.`));\n *\n * // Outputs\n * // 'a' is not found.\n * ```\n *\n * @see {@link skip}\n * @see {@link skipUntil}\n * @see {@link skipLast}\n * @see {@link skipWhile}\n *\n * @throws {EmptyError} Delivers an EmptyError to the Observer's `error`\n * callback if the Observable completes before any `next` notification was sent.\n * @param {function} [predicate] - The condition any source emitted item has to satisfy.\n * @param {any} [defaultValue] - An optional default value to provide if last\n * predicate isn't met or no values were emitted.\n * @return A function that returns an Observable that emits only the last item\n * satisfying the given condition from the source, or a NoSuchElementException\n * if no such items are emitted.\n * @throws - Throws if no items that match the predicate are emitted by the source Observable.\n */\nexport function last<T, D>(\n predicate?: ((value: T, index: number, source: Observable<T>) => boolean) | null,\n defaultValue?: D\n): OperatorFunction<T, T | D> {\n const hasDefaultValue = arguments.length >= 2;\n return (source: Observable<T>) =>\n source.pipe(\n predicate ? filter((v, i) => predicate(v, i, source)) : identity,\n takeLast(1),\n hasDefaultValue ? defaultIfEmpty(defaultValue!) : throwIfEmpty(() => new EmptyError())\n );\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Route, UrlMatchResult} from './models';\nimport {UrlSegment, UrlSegmentGroup} from './url_tree';\n\n\n/**\n * The primary routing outlet.\n *\n * @publicApi\n */\nexport const PRIMARY_OUTLET = 'primary';\n\n/**\n * A private symbol used to store the value of `Route.title` inside the `Route.data` if it is a\n * static string or `Route.resolve` if anything else. This allows us to reuse the existing route\n * data/resolvers to support the title feature without new instrumentation in the `Router` pipeline.\n */\nexport const RouteTitleKey = Symbol('RouteTitle');\n\n/**\n * A collection of matrix and query URL parameters.\n * @see `convertToParamMap()`\n * @see `ParamMap`\n *\n * @publicApi\n */\nexport type Params = {\n [key: string]: any;\n};\n\n/**\n * A map that provides access to the required and optional parameters\n * specific to a route.\n * The map supports retrieving a single value with `get()`\n * or multiple values with `getAll()`.\n *\n * @see [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)\n *\n * @publicApi\n */\nexport interface ParamMap {\n /**\n * Reports whether the map contains a given parameter.\n * @param name The parameter name.\n * @returns True if the map contains the given parameter, false otherwise.\n */\n has(name: string): boolean;\n /**\n * Retrieves a single value for a parameter.\n * @param name The parameter name.\n * @return The parameter's single value,\n * or the first value if the parameter has multiple values,\n * or `null` when there is no such parameter.\n */\n get(name: string): string|null;\n /**\n * Retrieves multiple values for a parameter.\n * @param name The parameter name.\n * @return An array containing one or more values,\n * or an empty array if there is no such parameter.\n *\n */\n getAll(name: string): string[];\n\n /** Names of the parameters in the map. */\n readonly keys: string[];\n}\n\nclass ParamsAsMap implements ParamMap {\n private params: Params;\n\n constructor(params: Params) {\n this.params = params || {};\n }\n\n has(name: string): boolean {\n return Object.prototype.hasOwnProperty.call(this.params, name);\n }\n\n get(name: string): string|null {\n if (this.has(name)) {\n const v = this.params[name];\n return Array.isArray(v) ? v[0] : v;\n }\n\n return null;\n }\n\n getAll(name: string): string[] {\n if (this.has(name)) {\n const v = this.params[name];\n return Array.isArray(v) ? v : [v];\n }\n\n return [];\n }\n\n get keys(): string[] {\n return Object.keys(this.params);\n }\n}\n\n/**\n * Converts a `Params` instance to a `ParamMap`.\n * @param params The instance to convert.\n * @returns The new map instance.\n *\n * @publicApi\n */\nexport function convertToParamMap(params: Params): ParamMap {\n return new ParamsAsMap(params);\n}\n\n/**\n * Matches the route configuration (`route`) against the actual URL (`segments`).\n *\n * When no matcher is defined on a `Route`, this is the matcher used by the Router by default.\n *\n * @param segments The remaining unmatched segments in the current navigation\n * @param segmentGroup The current segment group being matched\n * @param route The `Route` to match against.\n *\n * @see UrlMatchResult\n * @see Route\n *\n * @returns The resulting match information or `null` if the `route` should not match.\n * @publicApi\n */\nexport function defaultUrlMatcher(\n segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route): UrlMatchResult|null {\n const parts = route.path!.split('/');\n\n if (parts.length > segments.length) {\n // The actual URL is shorter than the config, no match\n return null;\n }\n\n if (route.pathMatch === 'full' &&\n (segmentGroup.hasChildren() || parts.length < segments.length)) {\n // The config is longer than the actual URL but we are looking for a full match, return null\n return null;\n }\n\n const posParams: {[key: string]: UrlSegment} = {};\n\n // Check each config part against the actual URL\n for (let index = 0; index < parts.length; index++) {\n const part = parts[index];\n const segment = segments[index];\n const isParameter = part.startsWith(':');\n if (isParameter) {\n posParams[part.substring(1)] = segment;\n } else if (part !== segment.path) {\n // The actual URL part does not match the config, no match\n return null;\n }\n }\n\n return {consumed: segments.slice(0, parts.length), posParams};\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';\nimport {from, Observable, of} from 'rxjs';\n\nimport {Params} from '../shared';\n\nexport function shallowEqualArrays(a: any[], b: any[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; ++i) {\n if (!shallowEqual(a[i], b[i])) return false;\n }\n return true;\n}\n\nexport function shallowEqual(a: Params, b: Params): boolean {\n // While `undefined` should never be possible, it would sometimes be the case in IE 11\n // and pre-chromium Edge. The check below accounts for this edge case.\n const k1 = a ? Object.keys(a) : undefined;\n const k2 = b ? Object.keys(b) : undefined;\n if (!k1 || !k2 || k1.length != k2.length) {\n return false;\n }\n let key: string;\n for (let i = 0; i < k1.length; i++) {\n key = k1[i];\n if (!equalArraysOrString(a[key], b[key])) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Test equality for arrays of strings or a string.\n */\nexport function equalArraysOrString(a: string|string[], b: string|string[]) {\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n const aSorted = [...a].sort();\n const bSorted = [...b].sort();\n return aSorted.every((val, index) => bSorted[index] === val);\n } else {\n return a === b;\n }\n}\n\n/**\n * Flattens single-level nested arrays.\n */\nexport function flatten<T>(arr: T[][]): T[] {\n return Array.prototype.concat.apply([], arr);\n}\n\n/**\n * Return the last element of an array.\n */\nexport function last<T>(a: T[]): T|null {\n return a.length > 0 ? a[a.length - 1] : null;\n}\n\n/**\n * Verifys all booleans in an array are `true`.\n */\nexport function and(bools: boolean[]): boolean {\n return !bools.some(v => !v);\n}\n\nexport function forEach<K, V>(map: {[key: string]: V}, callback: (v: V, k: string) => void): void {\n for (const prop in map) {\n if (map.hasOwnProperty(prop)) {\n callback(map[prop], prop);\n }\n }\n}\n\nexport function wrapIntoObservable<T>(value: T|Promise<T>|Observable<T>): Observable<T> {\n if (isObservable(value)) {\n return value;\n }\n\n if (isPromise(value)) {\n // Use `Promise.resolve()` to wrap promise-like instances.\n // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the\n // change detection.\n return from(Promise.resolve(value));\n }\n\n return of(value);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from './errors';\nimport {convertToParamMap, ParamMap, Params, PRIMARY_OUTLET} from './shared';\nimport {equalArraysOrString, forEach, shallowEqual} from './utils/collection';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n/**\n * A set of options which specify how to determine if a `UrlTree` is active, given the `UrlTree`\n * for the current router state.\n *\n * @publicApi\n * @see Router.isActive\n */\nexport interface IsActiveMatchOptions {\n /**\n * Defines the strategy for comparing the matrix parameters of two `UrlTree`s.\n *\n * The matrix parameter matching is dependent on the strategy for matching the\n * segments. That is, if the `paths` option is set to `'subset'`, only\n * the matrix parameters of the matching segments will be compared.\n *\n * - `'exact'`: Requires that matching segments also have exact matrix parameter\n * matches.\n * - `'subset'`: The matching segments in the router's active `UrlTree` may contain\n * extra matrix parameters, but those that exist in the `UrlTree` in question must match.\n * - `'ignored'`: When comparing `UrlTree`s, matrix params will be ignored.\n */\n matrixParams: 'exact'|'subset'|'ignored';\n /**\n * Defines the strategy for comparing the query parameters of two `UrlTree`s.\n *\n * - `'exact'`: the query parameters must match exactly.\n * - `'subset'`: the active `UrlTree` may contain extra parameters,\n * but must match the key and value of any that exist in the `UrlTree` in question.\n * - `'ignored'`: When comparing `UrlTree`s, query params will be ignored.\n */\n queryParams: 'exact'|'subset'|'ignored';\n /**\n * Defines the strategy for comparing the `UrlSegment`s of the `UrlTree`s.\n *\n * - `'exact'`: all segments in each `UrlTree` must match.\n * - `'subset'`: a `UrlTree` will be determined to be active if it\n * is a subtree of the active route. That is, the active route may contain extra\n * segments, but must at least have all the segments of the `UrlTree` in question.\n */\n paths: 'exact'|'subset';\n /**\n * - `'exact'`: indicates that the `UrlTree` fragments must be equal.\n * - `'ignored'`: the fragments will not be compared when determining if a\n * `UrlTree` is active.\n */\n fragment: 'exact'|'ignored';\n}\n\ntype ParamMatchOptions = 'exact'|'subset'|'ignored';\n\ntype PathCompareFn =\n (container: UrlSegmentGroup, containee: UrlSegmentGroup, matrixParams: ParamMatchOptions) =>\n boolean;\ntype ParamCompareFn = (container: Params, containee: Params) => boolean;\n\nconst pathCompareMap: Record<IsActiveMatchOptions['paths'], PathCompareFn> = {\n 'exact': equalSegmentGroups,\n 'subset': containsSegmentGroup,\n};\nconst paramCompareMap: Record<ParamMatchOptions, ParamCompareFn> = {\n 'exact': equalParams,\n 'subset': containsParams,\n 'ignored': () => true,\n};\n\nexport function containsTree(\n container: UrlTree, containee: UrlTree, options: IsActiveMatchOptions): boolean {\n return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) &&\n paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) &&\n !(options.fragment === 'exact' && container.fragment !== containee.fragment);\n}\n\nfunction equalParams(container: Params, containee: Params): boolean {\n // TODO: This does not handle array params correctly.\n return shallowEqual(container, containee);\n}\n\nfunction equalSegmentGroups(\n container: UrlSegmentGroup, containee: UrlSegmentGroup,\n matrixParams: ParamMatchOptions): boolean {\n if (!equalPath(container.segments, containee.segments)) return false;\n if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) {\n return false;\n }\n if (container.numberOfChildren !== containee.numberOfChildren) return false;\n for (const c in containee.children) {\n if (!container.children[c]) return false;\n if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams))\n return false;\n }\n return true;\n}\n\nfunction containsParams(container: Params, containee: Params): boolean {\n return Object.keys(containee).length <= Object.keys(container).length &&\n Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key]));\n}\n\nfunction containsSegmentGroup(\n container: UrlSegmentGroup, containee: UrlSegmentGroup,\n matrixParams: ParamMatchOptions): boolean {\n return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams);\n}\n\nfunction containsSegmentGroupHelper(\n container: UrlSegmentGroup, containee: UrlSegmentGroup, containeePaths: UrlSegment[],\n matrixParams: ParamMatchOptions): boolean {\n if (container.segments.length > containeePaths.length) {\n const current = container.segments.slice(0, containeePaths.length);\n if (!equalPath(current, containeePaths)) return false;\n if (containee.hasChildren()) return false;\n if (!matrixParamsMatch(current, containeePaths, matrixParams)) return false;\n return true;\n\n } else if (container.segments.length === containeePaths.length) {\n if (!equalPath(container.segments, containeePaths)) return false;\n if (!matrixParamsMatch(container.segments, containeePaths, matrixParams)) return false;\n for (const c in containee.children) {\n if (!container.children[c]) return false;\n if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) {\n return false;\n }\n }\n return true;\n\n } else {\n const current = containeePaths.slice(0, container.segments.length);\n const next = containeePaths.slice(container.segments.length);\n if (!equalPath(container.segments, current)) return false;\n if (!matrixParamsMatch(container.segments, current, matrixParams)) return false;\n if (!container.children[PRIMARY_OUTLET]) return false;\n return containsSegmentGroupHelper(\n container.children[PRIMARY_OUTLET], containee, next, matrixParams);\n }\n}\n\nfunction matrixParamsMatch(\n containerPaths: UrlSegment[], containeePaths: UrlSegment[], options: ParamMatchOptions) {\n return containeePaths.every((containeeSegment, i) => {\n return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters);\n });\n}\n\n/**\n * @description\n *\n * Represents the parsed URL.\n *\n * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a\n * serialized tree.\n * UrlTree is a data structure that provides a lot of affordances in dealing with URLs\n *\n * @usageNotes\n * ### Example\n *\n * ```\n * @Component({templateUrl:'template.html'})\n * class MyComponent {\n * constructor(router: Router) {\n * const tree: UrlTree =\n * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment');\n * const f = tree.fragment; // return 'fragment'\n * const q = tree.queryParams; // returns {debug: 'true'}\n * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];\n * const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33'\n * g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor'\n * g.children['support'].segments; // return 1 segment 'help'\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport class UrlTree {\n /** @internal */\n _queryParamMap?: ParamMap;\n /** @internal */\n _warnIfUsedForNavigation?: string;\n\n constructor(\n /** The root segment group of the URL tree */\n public root: UrlSegmentGroup = new UrlSegmentGroup([], {}),\n /** The query params of the URL */\n public queryParams: Params = {},\n /** The fragment of the URL */\n public fragment: string|null = null) {\n if (NG_DEV_MODE) {\n if (root.segments.length > 0) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT,\n 'The root `UrlSegmentGroup` should not contain `segments`. ' +\n 'Instead, these segments belong in the `children` so they can be associated with a named outlet.');\n }\n }\n }\n\n get queryParamMap(): ParamMap {\n if (!this._queryParamMap) {\n this._queryParamMap = convertToParamMap(this.queryParams);\n }\n return this._queryParamMap;\n }\n\n /** @docsNotRequired */\n toString(): string {\n return DEFAULT_SERIALIZER.serialize(this);\n }\n}\n\n/**\n * @description\n *\n * Represents the parsed URL segment group.\n *\n * See `UrlTree` for more information.\n *\n * @publicApi\n */\nexport class UrlSegmentGroup {\n /** @internal */\n _sourceSegment?: UrlSegmentGroup;\n /** @internal */\n _segmentIndexShift?: number;\n /**\n * @internal\n *\n * Used only in dev mode to detect if application relies on `relativeLinkResolution: 'legacy'`\n * Should be removed in when `relativeLinkResolution` is removed.\n */\n _segmentIndexShiftCorrected?: number;\n /** The parent node in the url tree */\n parent: UrlSegmentGroup|null = null;\n\n constructor(\n /** The URL segments of this group. See `UrlSegment` for more information */\n public segments: UrlSegment[],\n /** The list of children of this group */\n public children: {[key: string]: UrlSegmentGroup}) {\n forEach(children, (v: any, k: any) => v.parent = this);\n }\n\n /** Whether the segment has child segments */\n hasChildren(): boolean {\n return this.numberOfChildren > 0;\n }\n\n /** Number of child segments */\n get numberOfChildren(): number {\n return Object.keys(this.children).length;\n }\n\n /** @docsNotRequired */\n toString(): string {\n return serializePaths(this);\n }\n}\n\n\n/**\n * @description\n *\n * Represents a single URL segment.\n *\n * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix\n * parameters associated with the segment.\n *\n * @usageNotes\n * ### Example\n *\n * ```\n * @Component({templateUrl:'template.html'})\n * class MyComponent {\n * constructor(router: Router) {\n * const tree: UrlTree = router.parseUrl('/team;id=33');\n * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET];\n * const s: UrlSegment[] = g.segments;\n * s[0].path; // returns 'team'\n * s[0].parameters; // returns {id: 33}\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport class UrlSegment {\n /** @internal */\n _parameterMap?: ParamMap;\n\n constructor(\n /** The path part of a URL segment */\n public path: string,\n\n /** The matrix parameters associated with a segment */\n public parameters: {[name: string]: string}) {}\n\n get parameterMap(): ParamMap {\n if (!this._parameterMap) {\n this._parameterMap = convertToParamMap(this.parameters);\n }\n return this._parameterMap;\n }\n\n /** @docsNotRequired */\n toString(): string {\n return serializePath(this);\n }\n}\n\nexport function equalSegments(as: UrlSegment[], bs: UrlSegment[]): boolean {\n return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));\n}\n\nexport function equalPath(as: UrlSegment[], bs: UrlSegment[]): boolean {\n if (as.length !== bs.length) return false;\n return as.every((a, i) => a.path === bs[i].path);\n}\n\nexport function mapChildrenIntoArray<T>(\n segment: UrlSegmentGroup, fn: (v: UrlSegmentGroup, k: string) => T[]): T[] {\n let res: T[] = [];\n forEach(segment.children, (child: UrlSegmentGroup, childOutlet: string) => {\n if (childOutlet === PRIMARY_OUTLET) {\n res = res.concat(fn(child, childOutlet));\n }\n });\n forEach(segment.children, (child: UrlSegmentGroup, childOutlet: string) => {\n if (childOutlet !== PRIMARY_OUTLET) {\n res = res.concat(fn(child, childOutlet));\n }\n });\n return res;\n}\n\n\n/**\n * @description\n *\n * Serializes and deserializes a URL string into a URL tree.\n *\n * The url serialization strategy is customizable. You can\n * make all URLs case insensitive by providing a custom UrlSerializer.\n *\n * See `DefaultUrlSerializer` for an example of a URL serializer.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: () => new DefaultUrlSerializer()})\nexport abstract class UrlSerializer {\n /** Parse a url into a `UrlTree` */\n abstract parse(url: string): UrlTree;\n\n /** Converts a `UrlTree` into a url */\n abstract serialize(tree: UrlTree): string;\n}\n\n/**\n * @description\n *\n * A default implementation of the `UrlSerializer`.\n *\n * Example URLs:\n *\n * ```\n * /inbox/33(popup:compose)\n * /inbox/33;open=true/messages/44\n * ```\n *\n * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the\n * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to\n * specify route specific parameters.\n *\n * @publicApi\n */\nexport class DefaultUrlSerializer implements UrlSerializer {\n /** Parses a url into a `UrlTree` */\n parse(url: string): UrlTree {\n const p = new UrlParser(url);\n return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());\n }\n\n /** Converts a `UrlTree` into a url */\n serialize(tree: UrlTree): string {\n const segment = `/${serializeSegment(tree.root, true)}`;\n const query = serializeQueryParams(tree.queryParams);\n const fragment =\n typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment)}` : '';\n\n return `${segment}${query}${fragment}`;\n }\n}\n\nconst DEFAULT_SERIALIZER = new DefaultUrlSerializer();\n\nexport function serializePaths(segment: UrlSegmentGroup): string {\n return segment.segments.map(p => serializePath(p)).join('/');\n}\n\nfunction serializeSegment(segment: UrlSegmentGroup, root: boolean): string {\n if (!segment.hasChildren()) {\n return serializePaths(segment);\n }\n\n if (root) {\n const primary = segment.children[PRIMARY_OUTLET] ?\n serializeSegment(segment.children[PRIMARY_OUTLET], false) :\n '';\n const children: string[] = [];\n\n forEach(segment.children, (v: UrlSegmentGroup, k: string) => {\n if (k !== PRIMARY_OUTLET) {\n children.push(`${k}:${serializeSegment(v, false)}`);\n }\n });\n\n return children.length > 0 ? `${primary}(${children.join('//')})` : primary;\n\n } else {\n const children = mapChildrenIntoArray(segment, (v: UrlSegmentGroup, k: string) => {\n if (k === PRIMARY_OUTLET) {\n return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];\n }\n\n return [`${k}:${serializeSegment(v, false)}`];\n });\n\n // use no parenthesis if the only child is a primary outlet route\n if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) {\n return `${serializePaths(segment)}/${children[0]}`;\n }\n\n return `${serializePaths(segment)}/(${children.join('//')})`;\n }\n}\n\n/**\n * Encodes a URI string with the default encoding. This function will only ever be called from\n * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need\n * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't\n * have to be encoded per https://url.spec.whatwg.org.\n */\nfunction encodeUriString(s: string): string {\n return encodeURIComponent(s)\n .replace(/%40/g, '@')\n .replace(/%3A/gi, ':')\n .replace(/%24/g, '$')\n .replace(/%2C/gi, ',');\n}\n\n/**\n * This function should be used to encode both keys and values in a query string key/value. In\n * the following URL, you need to call encodeUriQuery on \"k\" and \"v\":\n *\n * http://www.site.org/html;mk=mv?k=v#f\n */\nexport function encodeUriQuery(s: string): string {\n return encodeUriString(s).replace(/%3B/gi, ';');\n}\n\n/**\n * This function should be used to encode a URL fragment. In the following URL, you need to call\n * encodeUriFragment on \"f\":\n *\n * http://www.site.org/html;mk=mv?k=v#f\n */\nexport function encodeUriFragment(s: string): string {\n return encodeURI(s);\n}\n\n/**\n * This function should be run on any URI segment as well as the key and value in a key/value\n * pair for matrix params. In the following URL, you need to call encodeUriSegment on \"html\",\n * \"mk\", and \"mv\":\n *\n * http://www.site.org/html;mk=mv?k=v#f\n */\nexport function encodeUriSegment(s: string): string {\n return encodeUriString(s).replace(/\\(/g, '%28').replace(/\\)/g, '%29').replace(/%26/gi, '&');\n}\n\nexport function decode(s: string): string {\n return decodeURIComponent(s);\n}\n\n// Query keys/values should have the \"+\" replaced first, as \"+\" in a query string is \" \".\n// decodeURIComponent function will not decode \"+\" as a space.\nexport function decodeQuery(s: string): string {\n return decode(s.replace(/\\+/g, '%20'));\n}\n\nexport function serializePath(path: UrlSegment): string {\n return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;\n}\n\nfunction serializeMatrixParams(params: {[key: string]: string}): string {\n return Object.keys(params)\n .map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`)\n .join('');\n}\n\nfunction serializeQueryParams(params: {[key: string]: any}): string {\n const strParams: string[] =\n Object.keys(params)\n .map((name) => {\n const value = params[name];\n return Array.isArray(value) ?\n value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') :\n `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;\n })\n .filter(s => !!s);\n\n return strParams.length ? `?${strParams.join('&')}` : '';\n}\n\nconst SEGMENT_RE = /^[^\\/()?;=#]+/;\nfunction matchSegments(str: string): string {\n const match = str.match(SEGMENT_RE);\n return match ? match[0] : '';\n}\n\nconst QUERY_PARAM_RE = /^[^=?&#]+/;\n// Return the name of the query param at the start of the string or an empty string\nfunction matchQueryParams(str: string): string {\n const match = str.match(QUERY_PARAM_RE);\n return match ? match[0] : '';\n}\n\nconst QUERY_PARAM_VALUE_RE = /^[^&#]+/;\n// Return the value of the query param at the start of the string or an empty string\nfunction matchUrlQueryParamValue(str: string): string {\n const match = str.match(QUERY_PARAM_VALUE_RE);\n return match ? match[0] : '';\n}\n\nclass UrlParser {\n private remaining: string;\n\n constructor(private url: string) {\n this.remaining = url;\n }\n\n parseRootSegment(): UrlSegmentGroup {\n this.consumeOptional('/');\n\n if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {\n return new UrlSegmentGroup([], {});\n }\n\n // The root segment group never has segments\n return new UrlSegmentGroup([], this.parseChildren());\n }\n\n parseQueryParams(): Params {\n const params: Params = {};\n if (this.consumeOptional('?')) {\n do {\n this.parseQueryParam(params);\n } while (this.consumeOptional('&'));\n }\n return params;\n }\n\n parseFragment(): string|null {\n return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;\n }\n\n private parseChildren(): {[outlet: string]: UrlSegmentGroup} {\n if (this.remaining === '') {\n return {};\n }\n\n this.consumeOptional('/');\n\n const segments: UrlSegment[] = [];\n if (!this.peekStartsWith('(')) {\n segments.push(this.parseSegment());\n }\n\n while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {\n this.capture('/');\n segments.push(this.parseSegment());\n }\n\n let children: {[outlet: string]: UrlSegmentGroup} = {};\n if (this.peekStartsWith('/(')) {\n this.capture('/');\n children = this.parseParens(true);\n }\n\n let res: {[outlet: string]: UrlSegmentGroup} = {};\n if (this.peekStartsWith('(')) {\n res = this.parseParens(false);\n }\n\n if (segments.length > 0 || Object.keys(children).length > 0) {\n res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);\n }\n\n return res;\n }\n\n // parse a segment with its matrix parameters\n // ie `name;k1=v1;k2`\n private parseSegment(): UrlSegment {\n const path = matchSegments(this.remaining);\n if (path === '' && this.peekStartsWith(';')) {\n throw new RuntimeError(\n RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS,\n NG_DEV_MODE && `Empty path url segment cannot have parameters: '${this.remaining}'.`);\n }\n\n this.capture(path);\n return new UrlSegment(decode(path), this.parseMatrixParams());\n }\n\n private parseMatrixParams(): {[key: string]: string} {\n const params: {[key: string]: string} = {};\n while (this.consumeOptional(';')) {\n this.parseParam(params);\n }\n return params;\n }\n\n private parseParam(params: {[key: string]: string}): void {\n const key = matchSegments(this.remaining);\n if (!key) {\n return;\n }\n this.capture(key);\n let value: any = '';\n if (this.consumeOptional('=')) {\n const valueMatch = matchSegments(this.remaining);\n if (valueMatch) {\n value = valueMatch;\n this.capture(value);\n }\n }\n\n params[decode(key)] = decode(value);\n }\n\n // Parse a single query parameter `name[=value]`\n private parseQueryParam(params: Params): void {\n const key = matchQueryParams(this.remaining);\n if (!key) {\n return;\n }\n this.capture(key);\n let value: any = '';\n if (this.consumeOptional('=')) {\n const valueMatch = matchUrlQueryParamValue(this.remaining);\n if (valueMatch) {\n value = valueMatch;\n this.capture(value);\n }\n }\n\n const decodedKey = decodeQuery(key);\n const decodedVal = decodeQuery(value);\n\n if (params.hasOwnProperty(decodedKey)) {\n // Append to existing values\n let currentVal = params[decodedKey];\n if (!Array.isArray(currentVal)) {\n currentVal = [currentVal];\n params[decodedKey] = currentVal;\n }\n currentVal.push(decodedVal);\n } else {\n // Create a new value\n params[decodedKey] = decodedVal;\n }\n }\n\n // parse `(a/b//outlet_name:c/d)`\n private parseParens(allowPrimary: boolean): {[outlet: string]: UrlSegmentGroup} {\n const segments: {[key: string]: UrlSegmentGroup} = {};\n this.capture('(');\n\n while (!this.consumeOptional(')') && this.remaining.length > 0) {\n const path = matchSegments(this.remaining);\n\n const next = this.remaining[path.length];\n\n // if is is not one of these characters, then the segment was unescaped\n // or the group was not closed\n if (next !== '/' && next !== ')' && next !== ';') {\n throw new RuntimeError(\n RuntimeErrorCode.UNPARSABLE_URL, NG_DEV_MODE && `Cannot parse url '${this.url}'`);\n }\n\n let outletName: string = undefined!;\n if (path.indexOf(':') > -1) {\n outletName = path.slice(0, path.indexOf(':'));\n this.capture(outletName);\n this.capture(':');\n } else if (allowPrimary) {\n outletName = PRIMARY_OUTLET;\n }\n\n const children = this.parseChildren();\n segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] :\n new UrlSegmentGroup([], children);\n this.consumeOptional('//');\n }\n\n return segments;\n }\n\n private peekStartsWith(str: string): boolean {\n return this.remaining.startsWith(str);\n }\n\n // Consumes the prefix when it is present and returns whether it has been consumed\n private consumeOptional(str: string): boolean {\n if (this.peekStartsWith(str)) {\n this.remaining = this.remaining.substring(str.length);\n return true;\n }\n return false;\n }\n\n private capture(str: string): void {\n if (!this.consumeOptional(str)) {\n throw new RuntimeError(\n RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL, NG_DEV_MODE && `Expected \"${str}\".`);\n }\n }\n}\n\nexport function createRoot(rootCandidate: UrlSegmentGroup) {\n return rootCandidate.segments.length > 0 ?\n new UrlSegmentGroup([], {[PRIMARY_OUTLET]: rootCandidate}) :\n rootCandidate;\n}\n\n/**\n * Recursively merges primary segment children into their parents and also drops empty children\n * (those which have no segments and no children themselves). The latter prevents serializing a\n * group into something like `/a(aux:)`, where `aux` is an empty child segment.\n */\nexport function squashSegmentGroup(segmentGroup: UrlSegmentGroup): UrlSegmentGroup {\n const newChildren: Record<string, UrlSegmentGroup> = {};\n for (const childOutlet of Object.keys(segmentGroup.children)) {\n const child = segmentGroup.children[childOutlet];\n const childCandidate = squashSegmentGroup(child);\n // don't add empty children\n if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {\n newChildren[childOutlet] = childCandidate;\n }\n }\n const s = new UrlSegmentGroup(segmentGroup.segments, newChildren);\n return mergeTrivialChildren(s);\n}\n\n/**\n * When possible, merges the primary outlet child into the parent `UrlSegmentGroup`.\n *\n * When a segment group has only one child which is a primary outlet, merges that child into the\n * parent. That is, the child segment group's segments are merged into the `s` and the child's\n * children become the children of `s`. Think of this like a 'squash', merging the child segment\n * group into the parent.\n */\nfunction mergeTrivialChildren(s: UrlSegmentGroup): UrlSegmentGroup {\n if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {\n const c = s.children[PRIMARY_OUTLET];\n return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);\n }\n\n return s;\n}\n\nexport function isUrlTree(v: any): v is UrlTree {\n return v instanceof UrlTree;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {RuntimeErrorCode} from './errors';\nimport {ActivatedRoute, ActivatedRouteSnapshot} from './router_state';\nimport {Params, PRIMARY_OUTLET} from './shared';\nimport {createRoot, squashSegmentGroup, UrlSegment, UrlSegmentGroup, UrlTree} from './url_tree';\nimport {forEach, last, shallowEqual} from './utils/collection';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n/**\n * Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`.\n *\n * @publicApi\n *\n *\n * @param relativeTo The `ActivatedRouteSnapshot` to apply the commands to\n * @param commands An array of URL fragments with which to construct the new URL tree.\n * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path\n * segments, followed by the parameters for each segment.\n * The fragments are applied to the one provided in the `relativeTo` parameter.\n * @param queryParams The query parameters for the `UrlTree`. `null` if the `UrlTree` does not have\n * any query parameters.\n * @param fragment The fragment for the `UrlTree`. `null` if the `UrlTree` does not have a fragment.\n *\n * @usageNotes\n *\n * ```\n * // create /team/33/user/11\n * createUrlTreeFromSnapshot(snapshot, ['/team', 33, 'user', 11]);\n *\n * // create /team/33;expand=true/user/11\n * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {expand: true}, 'user', 11]);\n *\n * // you can collapse static segments like this (this works only with the first passed-in value):\n * createUrlTreeFromSnapshot(snapshot, ['/team/33/user', userId]);\n *\n * // If the first segment can contain slashes, and you do not want the router to split it,\n * // you can do the following:\n * createUrlTreeFromSnapshot(snapshot, [{segmentPath: '/one/two'}]);\n *\n * // create /team/33/(user/11//right:chat)\n * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right:\n * 'chat'}}], null, null);\n *\n * // remove the right secondary node\n * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right: null}}]);\n *\n * // For the examples below, assume the current URL is for the `/team/33/user/11` and the\n * `ActivatedRouteSnapshot` points to `user/11`:\n *\n * // navigate to /team/33/user/11/details\n * createUrlTreeFromSnapshot(snapshot, ['details']);\n *\n * // navigate to /team/33/user/22\n * createUrlTreeFromSnapshot(snapshot, ['../22']);\n *\n * // navigate to /team/44/user/22\n * createUrlTreeFromSnapshot(snapshot, ['../../team/44/user/22']);\n * ```\n */\nexport function createUrlTreeFromSnapshot(\n relativeTo: ActivatedRouteSnapshot, commands: any[], queryParams: Params|null = null,\n fragment: string|null = null): UrlTree {\n const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo);\n return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment);\n}\n\nexport function createSegmentGroupFromRoute(route: ActivatedRouteSnapshot): UrlSegmentGroup {\n let targetGroup: UrlSegmentGroup|undefined;\n\n function createSegmentGroupFromRouteRecursive(currentRoute: ActivatedRouteSnapshot):\n UrlSegmentGroup {\n const childOutlets: {[outlet: string]: UrlSegmentGroup} = {};\n for (const childSnapshot of currentRoute.children) {\n const root = createSegmentGroupFromRouteRecursive(childSnapshot);\n childOutlets[childSnapshot.outlet] = root;\n }\n const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets);\n if (currentRoute === route) {\n targetGroup = segmentGroup;\n }\n return segmentGroup;\n }\n const rootCandidate = createSegmentGroupFromRouteRecursive(route.root);\n const rootSegmentGroup = createRoot(rootCandidate);\n\n return targetGroup ?? rootSegmentGroup;\n}\n\nexport function createUrlTreeFromSegmentGroup(\n relativeTo: UrlSegmentGroup, commands: any[], queryParams: Params|null,\n fragment: string|null): UrlTree {\n let root = relativeTo;\n while (root.parent) {\n root = root.parent;\n }\n // There are no commands so the `UrlTree` goes to the same path as the one created from the\n // `UrlSegmentGroup`. All we need to do is update the `queryParams` and `fragment` without\n // applying any other logic.\n if (commands.length === 0) {\n return tree(root, root, root, queryParams, fragment);\n }\n\n const nav = computeNavigation(commands);\n\n if (nav.toRoot()) {\n return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment);\n }\n\n const position = findStartingPositionForTargetGroup(nav, root, relativeTo);\n const newSegmentGroup = position.processChildren ?\n updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) :\n updateSegmentGroup(position.segmentGroup, position.index, nav.commands);\n return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment);\n}\n\nexport function createUrlTree(\n route: ActivatedRoute, urlTree: UrlTree, commands: any[], queryParams: Params|null,\n fragment: string|null): UrlTree {\n if (commands.length === 0) {\n return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment);\n }\n\n const nav = computeNavigation(commands);\n\n if (nav.toRoot()) {\n return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment);\n }\n\n function createTreeUsingPathIndex(lastPathIndex: number) {\n const startingPosition =\n findStartingPosition(nav, urlTree, route.snapshot?._urlSegment, lastPathIndex);\n\n const segmentGroup = startingPosition.processChildren ?\n updateSegmentGroupChildren(\n startingPosition.segmentGroup, startingPosition.index, nav.commands) :\n updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands);\n return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment);\n }\n // Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this\n // may be the case. Since we try to access it at an earlier point before the refactor to add the\n // warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it\n // didn't before.\n const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex);\n\n return result;\n}\n\nfunction isMatrixParams(command: any): boolean {\n return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;\n}\n\n/**\n * Determines if a given command has an `outlets` map. When we encounter a command\n * with an outlets k/v map, we need to apply each outlet individually to the existing segment.\n */\nfunction isCommandWithOutlets(command: any): command is {outlets: {[key: string]: any}} {\n return typeof command === 'object' && command != null && command.outlets;\n}\n\nfunction tree(\n oldRoot: UrlSegmentGroup, oldSegmentGroup: UrlSegmentGroup, newSegmentGroup: UrlSegmentGroup,\n queryParams: Params|null, fragment: string|null): UrlTree {\n let qp: any = {};\n if (queryParams) {\n forEach(queryParams, (value: any, name: any) => {\n qp[name] = Array.isArray(value) ? value.map((v: any) => `${v}`) : `${value}`;\n });\n }\n\n let rootCandidate: UrlSegmentGroup;\n if (oldRoot === oldSegmentGroup) {\n rootCandidate = newSegmentGroup;\n } else {\n rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup);\n }\n\n const newRoot = createRoot(squashSegmentGroup(rootCandidate));\n return new UrlTree(newRoot, qp, fragment);\n}\n\n/**\n * Replaces the `oldSegment` which is located in some child of the `current` with the `newSegment`.\n * This also has the effect of creating new `UrlSegmentGroup` copies to update references. This\n * shouldn't be necessary but the fallback logic for an invalid ActivatedRoute in the creation uses\n * the Router's current url tree. If we don't create new segment groups, we end up modifying that\n * value.\n */\nfunction replaceSegment(\n current: UrlSegmentGroup, oldSegment: UrlSegmentGroup,\n newSegment: UrlSegmentGroup): UrlSegmentGroup {\n const children: {[key: string]: UrlSegmentGroup} = {};\n forEach(current.children, (c: UrlSegmentGroup, outletName: string) => {\n if (c === oldSegment) {\n children[outletName] = newSegment;\n } else {\n children[outletName] = replaceSegment(c, oldSegment, newSegment);\n }\n });\n return new UrlSegmentGroup(current.segments, children);\n}\n\nclass Navigation {\n constructor(\n public isAbsolute: boolean, public numberOfDoubleDots: number, public commands: any[]) {\n if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {\n throw new RuntimeError(\n RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS,\n NG_DEV_MODE && 'Root segment cannot have matrix parameters');\n }\n\n const cmdWithOutlet = commands.find(isCommandWithOutlets);\n if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {\n throw new RuntimeError(\n RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND,\n NG_DEV_MODE && '{outlets:{}} has to be the last command');\n }\n }\n\n public toRoot(): boolean {\n return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';\n }\n}\n\n/** Transforms commands to a normalized `Navigation` */\nfunction computeNavigation(commands: any[]): Navigation {\n if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') {\n return new Navigation(true, 0, commands);\n }\n\n let numberOfDoubleDots = 0;\n let isAbsolute = false;\n\n const res: any[] = commands.reduce((res, cmd, cmdIdx) => {\n if (typeof cmd === 'object' && cmd != null) {\n if (cmd.outlets) {\n const outlets: {[k: string]: any} = {};\n forEach(cmd.outlets, (commands: any, name: string) => {\n outlets[name] = typeof commands === 'string' ? commands.split('/') : commands;\n });\n return [...res, {outlets}];\n }\n\n if (cmd.segmentPath) {\n return [...res, cmd.segmentPath];\n }\n }\n\n if (!(typeof cmd === 'string')) {\n return [...res, cmd];\n }\n\n if (cmdIdx === 0) {\n cmd.split('/').forEach((urlPart, partIndex) => {\n if (partIndex == 0 && urlPart === '.') {\n // skip './a'\n } else if (partIndex == 0 && urlPart === '') { // '/a'\n isAbsolute = true;\n } else if (urlPart === '..') { // '../a'\n numberOfDoubleDots++;\n } else if (urlPart != '') {\n res.push(urlPart);\n }\n });\n\n return res;\n }\n\n return [...res, cmd];\n }, []);\n\n return new Navigation(isAbsolute, numberOfDoubleDots, res);\n}\n\nclass Position {\n constructor(\n public segmentGroup: UrlSegmentGroup, public processChildren: boolean, public index: number) {\n }\n}\n\nfunction findStartingPositionForTargetGroup(\n nav: Navigation, root: UrlSegmentGroup, target: UrlSegmentGroup): Position {\n if (nav.isAbsolute) {\n return new Position(root, true, 0);\n }\n\n if (!target) {\n // `NaN` is used only to maintain backwards compatibility with incorrectly mocked\n // `ActivatedRouteSnapshot` in tests. In prior versions of this code, the position here was\n // determined based on an internal property that was rarely mocked, resulting in `NaN`. In\n // reality, this code path should _never_ be touched since `target` is not allowed to be falsey.\n return new Position(root, false, NaN);\n }\n if (target.parent === null) {\n return new Position(target, true, 0);\n }\n\n const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;\n const index = target.segments.length - 1 + modifier;\n return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots);\n}\n\nfunction findStartingPosition(\n nav: Navigation, tree: UrlTree, segmentGroup: UrlSegmentGroup,\n lastPathIndex: number): Position {\n if (nav.isAbsolute) {\n return new Position(tree.root, true, 0);\n }\n\n if (lastPathIndex === -1) {\n // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children\n // see issue #26224, #13011, #35687\n // However, if the ActivatedRoute is the root we should process children like above.\n const processChildren = segmentGroup === tree.root;\n return new Position(segmentGroup, processChildren, 0);\n }\n\n const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;\n const index = lastPathIndex + modifier;\n return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots);\n}\n\nfunction createPositionApplyingDoubleDots(\n group: UrlSegmentGroup, index: number, numberOfDoubleDots: number): Position {\n let g = group;\n let ci = index;\n let dd = numberOfDoubleDots;\n while (dd > ci) {\n dd -= ci;\n g = g.parent!;\n if (!g) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_DOUBLE_DOTS, NG_DEV_MODE && 'Invalid number of \\'../\\'');\n }\n ci = g.segments.length;\n }\n return new Position(g, false, ci - dd);\n}\n\nfunction getOutlets(commands: unknown[]): {[k: string]: unknown[]|string} {\n if (isCommandWithOutlets(commands[0])) {\n return commands[0].outlets;\n }\n\n return {[PRIMARY_OUTLET]: commands};\n}\n\nfunction updateSegmentGroup(\n segmentGroup: UrlSegmentGroup, startIndex: number, commands: any[]): UrlSegmentGroup {\n if (!segmentGroup) {\n segmentGroup = new UrlSegmentGroup([], {});\n }\n if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {\n return updateSegmentGroupChildren(segmentGroup, startIndex, commands);\n }\n\n const m = prefixedWith(segmentGroup, startIndex, commands);\n const slicedCommands = commands.slice(m.commandIndex);\n if (m.match && m.pathIndex < segmentGroup.segments.length) {\n const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});\n g.children[PRIMARY_OUTLET] =\n new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);\n return updateSegmentGroupChildren(g, 0, slicedCommands);\n } else if (m.match && slicedCommands.length === 0) {\n return new UrlSegmentGroup(segmentGroup.segments, {});\n } else if (m.match && !segmentGroup.hasChildren()) {\n return createNewSegmentGroup(segmentGroup, startIndex, commands);\n } else if (m.match) {\n return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);\n } else {\n return createNewSegmentGroup(segmentGroup, startIndex, commands);\n }\n}\n\nfunction updateSegmentGroupChildren(\n segmentGroup: UrlSegmentGroup, startIndex: number, commands: any[]): UrlSegmentGroup {\n if (commands.length === 0) {\n return new UrlSegmentGroup(segmentGroup.segments, {});\n } else {\n const outlets = getOutlets(commands);\n const children: {[key: string]: UrlSegmentGroup} = {};\n // If the set of commands does not apply anything to the primary outlet and the child segment is\n // an empty path primary segment on its own, we want to apply the commands to the empty child\n // path rather than here. The outcome is that the empty primary child is effectively removed\n // from the final output UrlTree. Imagine the following config:\n //\n // {path: '', children: [{path: '**', outlet: 'popup'}]}.\n //\n // Navigation to /(popup:a) will activate the child outlet correctly Given a follow-up\n // navigation with commands\n // ['/', {outlets: {'popup': 'b'}}], we _would not_ want to apply the outlet commands to the\n // root segment because that would result in\n // //(popup:a)(popup:b) since the outlet command got applied one level above where it appears in\n // the `ActivatedRoute` rather than updating the existing one.\n //\n // Because empty paths do not appear in the URL segments and the fact that the segments used in\n // the output `UrlTree` are squashed to eliminate these empty paths where possible\n // https://github.com/angular/angular/blob/13f10de40e25c6900ca55bd83b36bd533dacfa9e/packages/router/src/url_tree.ts#L755\n // it can be hard to determine what is the right thing to do when applying commands to a\n // `UrlSegmentGroup` that is created from an \"unsquashed\"/expanded `ActivatedRoute` tree.\n // This code effectively \"squashes\" empty path primary routes when they have no siblings on\n // the same level of the tree.\n if (!outlets[PRIMARY_OUTLET] && segmentGroup.children[PRIMARY_OUTLET] &&\n segmentGroup.numberOfChildren === 1 &&\n segmentGroup.children[PRIMARY_OUTLET].segments.length === 0) {\n const childrenOfEmptyChild =\n updateSegmentGroupChildren(segmentGroup.children[PRIMARY_OUTLET], startIndex, commands);\n return new UrlSegmentGroup(segmentGroup.segments, childrenOfEmptyChild.children);\n }\n\n forEach(outlets, (commands, outlet) => {\n if (typeof commands === 'string') {\n commands = [commands];\n }\n if (commands !== null) {\n children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);\n }\n });\n\n forEach(segmentGroup.children, (child: UrlSegmentGroup, childOutlet: string) => {\n if (outlets[childOutlet] === undefined) {\n children[childOutlet] = child;\n }\n });\n return new UrlSegmentGroup(segmentGroup.segments, children);\n }\n}\n\nfunction prefixedWith(segmentGroup: UrlSegmentGroup, startIndex: number, commands: any[]) {\n let currentCommandIndex = 0;\n let currentPathIndex = startIndex;\n\n const noMatch = {match: false, pathIndex: 0, commandIndex: 0};\n while (currentPathIndex < segmentGroup.segments.length) {\n if (currentCommandIndex >= commands.length) return noMatch;\n const path = segmentGroup.segments[currentPathIndex];\n const command = commands[currentCommandIndex];\n // Do not try to consume command as part of the prefixing if it has outlets because it can\n // contain outlets other than the one being processed. Consuming the outlets command would\n // result in other outlets being ignored.\n if (isCommandWithOutlets(command)) {\n break;\n }\n const curr = `${command}`;\n const next =\n currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;\n\n if (currentPathIndex > 0 && curr === undefined) break;\n\n if (curr && next && (typeof next === 'object') && next.outlets === undefined) {\n if (!compare(curr, next, path)) return noMatch;\n currentCommandIndex += 2;\n } else {\n if (!compare(curr, {}, path)) return noMatch;\n currentCommandIndex++;\n }\n currentPathIndex++;\n }\n\n return {match: true, pathIndex: currentPathIndex, commandIndex: currentCommandIndex};\n}\n\nfunction createNewSegmentGroup(\n segmentGroup: UrlSegmentGroup, startIndex: number, commands: any[]): UrlSegmentGroup {\n const paths = segmentGroup.segments.slice(0, startIndex);\n\n let i = 0;\n while (i < commands.length) {\n const command = commands[i];\n if (isCommandWithOutlets(command)) {\n const children = createNewSegmentChildren(command.outlets);\n return new UrlSegmentGroup(paths, children);\n }\n\n // if we start with an object literal, we need to reuse the path part from the segment\n if (i === 0 && isMatrixParams(commands[0])) {\n const p = segmentGroup.segments[startIndex];\n paths.push(new UrlSegment(p.path, stringify(commands[0])));\n i++;\n continue;\n }\n\n const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`;\n const next = (i < commands.length - 1) ? commands[i + 1] : null;\n if (curr && next && isMatrixParams(next)) {\n paths.push(new UrlSegment(curr, stringify(next)));\n i += 2;\n } else {\n paths.push(new UrlSegment(curr, {}));\n i++;\n }\n }\n return new UrlSegmentGroup(paths, {});\n}\n\nfunction createNewSegmentChildren(outlets: {[name: string]: unknown[]|string}):\n {[outlet: string]: UrlSegmentGroup} {\n const children: {[outlet: string]: UrlSegmentGroup} = {};\n forEach(outlets, (commands, outlet) => {\n if (typeof commands === 'string') {\n commands = [commands];\n }\n if (commands !== null) {\n children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);\n }\n });\n return children;\n}\n\nfunction stringify(params: {[key: string]: any}): {[key: string]: string} {\n const res: {[key: string]: string} = {};\n forEach(params, (v: any, k: string) => res[k] = `${v}`);\n return res;\n}\n\nfunction compare(path: string, params: {[key: string]: any}, segment: UrlSegment): boolean {\n return path == segment.path && shallowEqual(params, segment.parameters);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Route} from './models';\nimport {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state';\n\n/**\n * Identifies the call or event that triggered a navigation.\n *\n * * 'imperative': Triggered by `router.navigateByUrl()` or `router.navigate()`.\n * * 'popstate' : Triggered by a `popstate` event.\n * * 'hashchange'-: Triggered by a `hashchange` event.\n *\n * @publicApi\n */\nexport type NavigationTrigger = 'imperative'|'popstate'|'hashchange';\nexport const IMPERATIVE_NAVIGATION = 'imperative';\n\n/**\n * Identifies the type of a router event.\n *\n * @publicApi\n */\nexport const enum EventType {\n NavigationStart,\n NavigationEnd,\n NavigationCancel,\n NavigationError,\n RoutesRecognized,\n ResolveStart,\n ResolveEnd,\n GuardsCheckStart,\n GuardsCheckEnd,\n RouteConfigLoadStart,\n RouteConfigLoadEnd,\n ChildActivationStart,\n ChildActivationEnd,\n ActivationStart,\n ActivationEnd,\n Scroll,\n NavigationSkipped,\n}\n\n/**\n * Base for events the router goes through, as opposed to events tied to a specific\n * route. Fired one time for any given navigation.\n *\n * The following code shows how a class subscribes to router events.\n *\n * ```ts\n * import {Event, RouterEvent, Router} from '@angular/router';\n *\n * class MyService {\n * constructor(public router: Router) {\n * router.events.pipe(\n * filter((e: Event): e is RouterEvent => e instanceof RouterEvent)\n * ).subscribe((e: RouterEvent) => {\n * // Do something\n * });\n * }\n * }\n * ```\n *\n * @see `Event`\n * @see [Router events summary](guide/router-reference#router-events)\n * @publicApi\n */\nexport class RouterEvent {\n constructor(\n /** A unique ID that the router assigns to every router navigation. */\n public id: number,\n /** The URL that is the destination for this navigation. */\n public url: string) {}\n}\n\n/**\n * An event triggered when a navigation starts.\n *\n * @publicApi\n */\nexport class NavigationStart extends RouterEvent {\n readonly type = EventType.NavigationStart;\n\n /**\n * Identifies the call or event that triggered the navigation.\n * An `imperative` trigger is a call to `router.navigateByUrl()` or `router.navigate()`.\n *\n * @see `NavigationEnd`\n * @see `NavigationCancel`\n * @see `NavigationError`\n */\n navigationTrigger?: NavigationTrigger;\n\n /**\n * The navigation state that was previously supplied to the `pushState` call,\n * when the navigation is triggered by a `popstate` event. Otherwise null.\n *\n * The state object is defined by `NavigationExtras`, and contains any\n * developer-defined state value, as well as a unique ID that\n * the router assigns to every router transition/navigation.\n *\n * From the perspective of the router, the router never \"goes back\".\n * When the user clicks on the back button in the browser,\n * a new navigation ID is created.\n *\n * Use the ID in this previous-state object to differentiate between a newly created\n * state and one returned to by a `popstate` event, so that you can restore some\n * remembered state, such as scroll position.\n *\n */\n restoredState?: {[k: string]: any, navigationId: number}|null;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n navigationTrigger: NavigationTrigger = 'imperative',\n /** @docsNotRequired */\n restoredState: {[k: string]: any, navigationId: number}|null = null) {\n super(id, url);\n this.navigationTrigger = navigationTrigger;\n this.restoredState = restoredState;\n }\n\n /** @docsNotRequired */\n override toString(): string {\n return `NavigationStart(id: ${this.id}, url: '${this.url}')`;\n }\n}\n\n/**\n * An event triggered when a navigation ends successfully.\n *\n * @see `NavigationStart`\n * @see `NavigationCancel`\n * @see `NavigationError`\n *\n * @publicApi\n */\nexport class NavigationEnd extends RouterEvent {\n readonly type = EventType.NavigationEnd;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string) {\n super(id, url);\n }\n\n /** @docsNotRequired */\n override toString(): string {\n return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}')`;\n }\n}\n\n/**\n * A code for the `NavigationCancel` event of the `Router` to indicate the\n * reason a navigation failed.\n *\n * @publicApi\n */\nexport const enum NavigationCancellationCode {\n /**\n * A navigation failed because a guard returned a `UrlTree` to redirect.\n */\n Redirect,\n /**\n * A navigation failed because a more recent navigation started.\n */\n SupersededByNewNavigation,\n /**\n * A navigation failed because one of the resolvers completed without emiting a value.\n */\n NoDataFromResolver,\n /**\n * A navigation failed because a guard returned `false`.\n */\n GuardRejected,\n}\n\n/**\n * A code for the `NavigationSkipped` event of the `Router` to indicate the\n * reason a navigation was skipped.\n *\n * @publicApi\n */\nexport const enum NavigationSkippedCode {\n /**\n * A navigation was skipped because the navigation URL was the same as the current Router URL.\n */\n IgnoredSameUrlNavigation,\n /**\n * A navigation was skipped because the configured `UrlHandlingStrategy` return `false` for both\n * the current Router URL and the target of the navigation.\n *\n * @see UrlHandlingStrategy\n */\n IgnoredByUrlHandlingStrategy,\n}\n\n/**\n * An event triggered when a navigation is canceled, directly or indirectly.\n * This can happen for several reasons including when a route guard\n * returns `false` or initiates a redirect by returning a `UrlTree`.\n *\n * @see `NavigationStart`\n * @see `NavigationEnd`\n * @see `NavigationError`\n *\n * @publicApi\n */\nexport class NavigationCancel extends RouterEvent {\n readonly type = EventType.NavigationCancel;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /**\n * A description of why the navigation was cancelled. For debug purposes only. Use `code`\n * instead for a stable cancellation reason that can be used in production.\n */\n public reason: string,\n /**\n * A code to indicate why the navigation was canceled. This cancellation code is stable for\n * the reason and can be relied on whereas the `reason` string could change and should not be\n * used in production.\n */\n readonly code?: NavigationCancellationCode) {\n super(id, url);\n }\n\n /** @docsNotRequired */\n override toString(): string {\n return `NavigationCancel(id: ${this.id}, url: '${this.url}')`;\n }\n}\n\n/**\n * An event triggered when a navigation is skipped.\n * This can happen for a couple reasons including onSameUrlHandling\n * is set to `ignore` and the navigation URL is not different than the\n * current state.\n *\n * @publicApi\n */\nexport class NavigationSkipped extends RouterEvent {\n readonly type = EventType.NavigationSkipped;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /**\n * A description of why the navigation was skipped. For debug purposes only. Use `code`\n * instead for a stable skipped reason that can be used in production.\n */\n public reason: string,\n /**\n * A code to indicate why the navigation was skipped. This code is stable for\n * the reason and can be relied on whereas the `reason` string could change and should not be\n * used in production.\n */\n readonly code?: NavigationSkippedCode) {\n super(id, url);\n }\n}\n\n/**\n * An event triggered when a navigation fails due to an unexpected error.\n *\n * @see `NavigationStart`\n * @see `NavigationEnd`\n * @see `NavigationCancel`\n *\n * @publicApi\n */\nexport class NavigationError extends RouterEvent {\n readonly type = EventType.NavigationError;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public error: any,\n /**\n * The target of the navigation when the error occurred.\n *\n * Note that this can be `undefined` because an error could have occurred before the\n * `RouterStateSnapshot` was created for the navigation.\n */\n readonly target?: RouterStateSnapshot) {\n super(id, url);\n }\n\n /** @docsNotRequired */\n override toString(): string {\n return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;\n }\n}\n\n/**\n * An event triggered when routes are recognized.\n *\n * @publicApi\n */\nexport class RoutesRecognized extends RouterEvent {\n readonly type = EventType.RoutesRecognized;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string,\n /** @docsNotRequired */\n public state: RouterStateSnapshot) {\n super(id, url);\n }\n\n /** @docsNotRequired */\n override toString(): string {\n return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}', state: ${this.state})`;\n }\n}\n\n/**\n * An event triggered at the start of the Guard phase of routing.\n *\n * @see `GuardsCheckEnd`\n *\n * @publicApi\n */\nexport class GuardsCheckStart extends RouterEvent {\n readonly type = EventType.GuardsCheckStart;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string,\n /** @docsNotRequired */\n public state: RouterStateSnapshot) {\n super(id, url);\n }\n\n override toString(): string {\n return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}', state: ${this.state})`;\n }\n}\n\n/**\n * An event triggered at the end of the Guard phase of routing.\n *\n * @see `GuardsCheckStart`\n *\n * @publicApi\n */\nexport class GuardsCheckEnd extends RouterEvent {\n readonly type = EventType.GuardsCheckEnd;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string,\n /** @docsNotRequired */\n public state: RouterStateSnapshot,\n /** @docsNotRequired */\n public shouldActivate: boolean) {\n super(id, url);\n }\n\n override toString(): string {\n return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;\n }\n}\n\n/**\n * An event triggered at the start of the Resolve phase of routing.\n *\n * Runs in the \"resolve\" phase whether or not there is anything to resolve.\n * In future, may change to only run when there are things to be resolved.\n *\n * @see `ResolveEnd`\n *\n * @publicApi\n */\nexport class ResolveStart extends RouterEvent {\n readonly type = EventType.ResolveStart;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string,\n /** @docsNotRequired */\n public state: RouterStateSnapshot) {\n super(id, url);\n }\n\n override toString(): string {\n return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}', state: ${this.state})`;\n }\n}\n\n/**\n * An event triggered at the end of the Resolve phase of routing.\n * @see `ResolveStart`.\n *\n * @publicApi\n */\nexport class ResolveEnd extends RouterEvent {\n readonly type = EventType.ResolveEnd;\n\n constructor(\n /** @docsNotRequired */\n id: number,\n /** @docsNotRequired */\n url: string,\n /** @docsNotRequired */\n public urlAfterRedirects: string,\n /** @docsNotRequired */\n public state: RouterStateSnapshot) {\n super(id, url);\n }\n\n override toString(): string {\n return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${\n this.urlAfterRedirects}', state: ${this.state})`;\n }\n}\n\n/**\n * An event triggered before lazy loading a route configuration.\n *\n * @see `RouteConfigLoadEnd`\n *\n * @publicApi\n */\nexport class RouteConfigLoadStart {\n readonly type = EventType.RouteConfigLoadStart;\n\n constructor(\n /** @docsNotRequired */\n public route: Route) {}\n toString(): string {\n return `RouteConfigLoadStart(path: ${this.route.path})`;\n }\n}\n\n/**\n * An event triggered when a route has been lazy loaded.\n *\n * @see `RouteConfigLoadStart`\n *\n * @publicApi\n */\nexport class RouteConfigLoadEnd {\n readonly type = EventType.RouteConfigLoadEnd;\n\n constructor(\n /** @docsNotRequired */\n public route: Route) {}\n toString(): string {\n return `RouteConfigLoadEnd(path: ${this.route.path})`;\n }\n}\n\n/**\n * An event triggered at the start of the child-activation\n * part of the Resolve phase of routing.\n * @see `ChildActivationEnd`\n * @see `ResolveStart`\n *\n * @publicApi\n */\nexport class ChildActivationStart {\n readonly type = EventType.ChildActivationStart;\n\n constructor(\n /** @docsNotRequired */\n public snapshot: ActivatedRouteSnapshot) {}\n toString(): string {\n const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';\n return `ChildActivationStart(path: '${path}')`;\n }\n}\n\n/**\n * An event triggered at the end of the child-activation part\n * of the Resolve phase of routing.\n * @see `ChildActivationStart`\n * @see `ResolveStart`\n * @publicApi\n */\nexport class ChildActivationEnd {\n readonly type = EventType.ChildActivationEnd;\n\n constructor(\n /** @docsNotRequired */\n public snapshot: ActivatedRouteSnapshot) {}\n toString(): string {\n const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';\n return `ChildActivationEnd(path: '${path}')`;\n }\n}\n\n/**\n * An event triggered at the start of the activation part\n * of the Resolve phase of routing.\n * @see `ActivationEnd`\n * @see `ResolveStart`\n *\n * @publicApi\n */\nexport class ActivationStart {\n readonly type = EventType.ActivationStart;\n\n constructor(\n /** @docsNotRequired */\n public snapshot: ActivatedRouteSnapshot) {}\n toString(): string {\n const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';\n return `ActivationStart(path: '${path}')`;\n }\n}\n\n/**\n * An event triggered at the end of the activation part\n * of the Resolve phase of routing.\n * @see `ActivationStart`\n * @see `ResolveStart`\n *\n * @publicApi\n */\nexport class ActivationEnd {\n readonly type = EventType.ActivationEnd;\n\n constructor(\n /** @docsNotRequired */\n public snapshot: ActivatedRouteSnapshot) {}\n toString(): string {\n const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';\n return `ActivationEnd(path: '${path}')`;\n }\n}\n\n/**\n * An event triggered by scrolling.\n *\n * @publicApi\n */\nexport class Scroll {\n readonly type = EventType.Scroll;\n\n constructor(\n /** @docsNotRequired */\n readonly routerEvent: NavigationEnd,\n\n /** @docsNotRequired */\n readonly position: [number, number]|null,\n\n /** @docsNotRequired */\n readonly anchor: string|null) {}\n\n toString(): string {\n const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;\n return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;\n }\n}\n\n/**\n * Router events that allow you to track the lifecycle of the router.\n *\n * The events occur in the following sequence:\n *\n * * [NavigationStart](api/router/NavigationStart): Navigation starts.\n * * [RouteConfigLoadStart](api/router/RouteConfigLoadStart): Before\n * the router [lazy loads](/guide/router#lazy-loading) a route configuration.\n * * [RouteConfigLoadEnd](api/router/RouteConfigLoadEnd): After a route has been lazy loaded.\n * * [RoutesRecognized](api/router/RoutesRecognized): When the router parses the URL\n * and the routes are recognized.\n * * [GuardsCheckStart](api/router/GuardsCheckStart): When the router begins the *guards*\n * phase of routing.\n * * [ChildActivationStart](api/router/ChildActivationStart): When the router\n * begins activating a route's children.\n * * [ActivationStart](api/router/ActivationStart): When the router begins activating a route.\n * * [GuardsCheckEnd](api/router/GuardsCheckEnd): When the router finishes the *guards*\n * phase of routing successfully.\n * * [ResolveStart](api/router/ResolveStart): When the router begins the *resolve*\n * phase of routing.\n * * [ResolveEnd](api/router/ResolveEnd): When the router finishes the *resolve*\n * phase of routing successfully.\n * * [ChildActivationEnd](api/router/ChildActivationEnd): When the router finishes\n * activating a route's children.\n * * [ActivationEnd](api/router/ActivationEnd): When the router finishes activating a route.\n * * [NavigationEnd](api/router/NavigationEnd): When navigation ends successfully.\n * * [NavigationCancel](api/router/NavigationCancel): When navigation is canceled.\n * * [NavigationError](api/router/NavigationError): When navigation fails\n * due to an unexpected error.\n * * [Scroll](api/router/Scroll): When the user scrolls.\n *\n * @publicApi\n */\nexport type Event = RouterEvent|NavigationStart|NavigationEnd|NavigationCancel|NavigationError|\n RoutesRecognized|GuardsCheckStart|GuardsCheckEnd|RouteConfigLoadStart|RouteConfigLoadEnd|\n ChildActivationStart|ChildActivationEnd|ActivationStart|ActivationEnd|Scroll|ResolveStart|\n ResolveEnd|NavigationSkipped;\n\n\nexport function stringifyEvent(routerEvent: Event): string {\n if (!('type' in routerEvent)) {\n return `Unknown Router Event: ${routerEvent.constructor.name}`;\n }\n switch (routerEvent.type) {\n case EventType.ActivationEnd:\n return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;\n case EventType.ActivationStart:\n return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;\n case EventType.ChildActivationEnd:\n return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;\n case EventType.ChildActivationStart:\n return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;\n case EventType.GuardsCheckEnd:\n return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${\n routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${\n routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;\n case EventType.GuardsCheckStart:\n return `GuardsCheckStart(id: ${routerEvent.id}, url: '${\n routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${\n routerEvent.state})`;\n case EventType.NavigationCancel:\n return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;\n case EventType.NavigationSkipped:\n return `NavigationSkipped(id: ${routerEvent.id}, url: '${routerEvent.url}')`;\n case EventType.NavigationEnd:\n return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${\n routerEvent.urlAfterRedirects}')`;\n case EventType.NavigationError:\n return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${\n routerEvent.error})`;\n case EventType.NavigationStart:\n return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;\n case EventType.ResolveEnd:\n return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${\n routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;\n case EventType.ResolveStart:\n return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${\n routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;\n case EventType.RouteConfigLoadEnd:\n return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;\n case EventType.RouteConfigLoadStart:\n return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;\n case EventType.RoutesRecognized:\n return `RoutesRecognized(id: ${routerEvent.id}, url: '${\n routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${\n routerEvent.state})`;\n case EventType.Scroll:\n const pos =\n routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;\n return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable} from '@angular/core';\n\nimport {createSegmentGroupFromRoute, createUrlTree, createUrlTreeFromSegmentGroup} from './create_url_tree';\nimport {ActivatedRoute, RouterState} from './router_state';\nimport {Params} from './shared';\nimport {UrlSegmentGroup, UrlTree} from './url_tree';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n@Injectable()\nexport class LegacyCreateUrlTree implements CreateUrlTreeStrategy {\n createUrlTree(\n relativeTo: ActivatedRoute|null|undefined, currentState: RouterState, currentUrlTree: UrlTree,\n commands: any[], queryParams: Params|null, fragment: string|null): UrlTree {\n const a = relativeTo || currentState.root;\n const tree = createUrlTree(a, currentUrlTree, commands, queryParams, fragment);\n if (NG_DEV_MODE) {\n const treeFromSnapshotStrategy = new CreateUrlTreeUsingSnapshot().createUrlTree(\n relativeTo, currentState, currentUrlTree, commands, queryParams, fragment);\n if (treeFromSnapshotStrategy.toString() !== tree.toString()) {\n let warningString = `The navigation to ${tree.toString()} will instead go to ${\n treeFromSnapshotStrategy.toString()} in an upcoming version of Angular.`;\n if (!!relativeTo) {\n warningString += ' `relativeTo` might need to be removed from the `UrlCreationOptions`.';\n }\n tree._warnIfUsedForNavigation = warningString;\n }\n }\n return tree;\n }\n}\n\n@Injectable()\nexport class CreateUrlTreeUsingSnapshot implements CreateUrlTreeStrategy {\n createUrlTree(\n relativeTo: ActivatedRoute|null|undefined, currentState: RouterState, currentUrlTree: UrlTree,\n commands: any[], queryParams: Params|null, fragment: string|null): UrlTree {\n let relativeToUrlSegmentGroup: UrlSegmentGroup|undefined;\n try {\n const relativeToSnapshot = relativeTo ? relativeTo.snapshot : currentState.snapshot.root;\n relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeToSnapshot);\n } catch (e: unknown) {\n // This is strictly for backwards compatibility with tests that create\n // invalid `ActivatedRoute` mocks.\n // Note: the difference between having this fallback for invalid `ActivatedRoute` setups and\n // just throwing is ~500 test failures. Fixing all of those tests by hand is not feasible at\n // the moment.\n if (typeof commands[0] !== 'string' || !commands[0].startsWith('/')) {\n // Navigations that were absolute in the old way of creating UrlTrees\n // would still work because they wouldn't attempt to match the\n // segments in the `ActivatedRoute` to the `currentUrlTree` but\n // instead just replace the root segment with the navigation result.\n // Non-absolute navigations would fail to apply the commands because\n // the logic could not find the segment to replace (so they'd act like there were no\n // commands).\n commands = [];\n }\n relativeToUrlSegmentGroup = currentUrlTree.root;\n }\n return createUrlTreeFromSegmentGroup(\n relativeToUrlSegmentGroup, commands, queryParams, fragment);\n }\n}\n\n@Injectable({providedIn: 'root', useClass: LegacyCreateUrlTree})\nexport abstract class CreateUrlTreeStrategy {\n abstract createUrlTree(\n relativeTo: ActivatedRoute|null|undefined, currentState: RouterState, currentUrlTree: UrlTree,\n commands: any[], queryParams: Params|null, fragment: string|null): UrlTree;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport class Tree<T> {\n /** @internal */\n _root: TreeNode<T>;\n\n constructor(root: TreeNode<T>) {\n this._root = root;\n }\n\n get root(): T {\n return this._root.value;\n }\n\n /**\n * @internal\n */\n parent(t: T): T|null {\n const p = this.pathFromRoot(t);\n return p.length > 1 ? p[p.length - 2] : null;\n }\n\n /**\n * @internal\n */\n children(t: T): T[] {\n const n = findNode(t, this._root);\n return n ? n.children.map(t => t.value) : [];\n }\n\n /**\n * @internal\n */\n firstChild(t: T): T|null {\n const n = findNode(t, this._root);\n return n && n.children.length > 0 ? n.children[0].value : null;\n }\n\n /**\n * @internal\n */\n siblings(t: T): T[] {\n const p = findPath(t, this._root);\n if (p.length < 2) return [];\n\n const c = p[p.length - 2].children.map(c => c.value);\n return c.filter(cc => cc !== t);\n }\n\n /**\n * @internal\n */\n pathFromRoot(t: T): T[] {\n return findPath(t, this._root).map(s => s.value);\n }\n}\n\n\n// DFS for the node matching the value\nfunction findNode<T>(value: T, node: TreeNode<T>): TreeNode<T>|null {\n if (value === node.value) return node;\n\n for (const child of node.children) {\n const node = findNode(value, child);\n if (node) return node;\n }\n\n return null;\n}\n\n// Return the path to the node with the given value using DFS\nfunction findPath<T>(value: T, node: TreeNode<T>): TreeNode<T>[] {\n if (value === node.value) return [node];\n\n for (const child of node.children) {\n const path = findPath(value, child);\n if (path.length) {\n path.unshift(node);\n return path;\n }\n }\n\n return [];\n}\n\nexport class TreeNode<T> {\n constructor(public value: T, public children: TreeNode<T>[]) {}\n\n toString(): string {\n return `TreeNode(${this.value})`;\n }\n}\n\n// Return the list of T indexed by outlet name\nexport function nodeChildrenAsMap<T extends {outlet: string}>(node: TreeNode<T>|null) {\n const map: {[outlet: string]: TreeNode<T>} = {};\n\n if (node) {\n node.children.forEach(child => map[child.value.outlet] = child);\n }\n\n return map;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Type} from '@angular/core';\nimport {BehaviorSubject, Observable, of} from 'rxjs';\nimport {map} from 'rxjs/operators';\n\nimport {Data, ResolveData, Route} from './models';\nimport {convertToParamMap, ParamMap, Params, PRIMARY_OUTLET, RouteTitleKey} from './shared';\nimport {equalSegments, UrlSegment, UrlSegmentGroup, UrlTree} from './url_tree';\nimport {shallowEqual, shallowEqualArrays} from './utils/collection';\nimport {Tree, TreeNode} from './utils/tree';\n\n/**\n * Represents the state of the router as a tree of activated routes.\n *\n * @usageNotes\n *\n * Every node in the route tree is an `ActivatedRoute` instance\n * that knows about the \"consumed\" URL segments, the extracted parameters,\n * and the resolved data.\n * Use the `ActivatedRoute` properties to traverse the tree from any node.\n *\n * The following fragment shows how a component gets the root node\n * of the current state to establish its own route tree:\n *\n * ```\n * @Component({templateUrl:'template.html'})\n * class MyComponent {\n * constructor(router: Router) {\n * const state: RouterState = router.routerState;\n * const root: ActivatedRoute = state.root;\n * const child = root.firstChild;\n * const id: Observable<string> = child.params.map(p => p.id);\n * //...\n * }\n * }\n * ```\n *\n * @see `ActivatedRoute`\n * @see [Getting route information](guide/router#getting-route-information)\n *\n * @publicApi\n */\nexport class RouterState extends Tree<ActivatedRoute> {\n /** @internal */\n constructor(\n root: TreeNode<ActivatedRoute>,\n /** The current snapshot of the router state */\n public snapshot: RouterStateSnapshot) {\n super(root);\n setRouterState(<RouterState>this, root);\n }\n\n override toString(): string {\n return this.snapshot.toString();\n }\n}\n\nexport function createEmptyState(urlTree: UrlTree, rootComponent: Type<any>|null): RouterState {\n const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);\n const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]);\n const emptyParams = new BehaviorSubject({});\n const emptyData = new BehaviorSubject({});\n const emptyQueryParams = new BehaviorSubject({});\n const fragment = new BehaviorSubject('');\n const activated = new ActivatedRoute(\n emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent,\n snapshot.root);\n activated.snapshot = snapshot.root;\n return new RouterState(new TreeNode<ActivatedRoute>(activated, []), snapshot);\n}\n\nexport function createEmptyStateSnapshot(\n urlTree: UrlTree, rootComponent: Type<any>|null): RouterStateSnapshot {\n const emptyParams = {};\n const emptyData = {};\n const emptyQueryParams = {};\n const fragment = '';\n const activated = new ActivatedRouteSnapshot(\n [], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null,\n urlTree.root, -1, {});\n return new RouterStateSnapshot('', new TreeNode<ActivatedRouteSnapshot>(activated, []));\n}\n\n/**\n * Provides access to information about a route associated with a component\n * that is loaded in an outlet.\n * Use to traverse the `RouterState` tree and extract information from nodes.\n *\n * The following example shows how to construct a component using information from a\n * currently activated route.\n *\n * Note: the observables in this class only emit when the current and previous values differ based\n * on shallow equality. For example, changing deeply nested properties in resolved `data` will not\n * cause the `ActivatedRoute.data` `Observable` to emit a new value.\n *\n * {@example router/activated-route/module.ts region=\"activated-route\"\n * header=\"activated-route.component.ts\"}\n *\n * @see [Getting route information](guide/router#getting-route-information)\n *\n * @publicApi\n */\nexport class ActivatedRoute {\n /** The current snapshot of this route */\n snapshot!: ActivatedRouteSnapshot;\n /** @internal */\n _futureSnapshot: ActivatedRouteSnapshot;\n /** @internal */\n _routerState!: RouterState;\n /** @internal */\n _paramMap?: Observable<ParamMap>;\n /** @internal */\n _queryParamMap?: Observable<ParamMap>;\n\n /** An Observable of the resolved route title */\n readonly title: Observable<string|undefined> =\n this.data?.pipe(map((d: Data) => d[RouteTitleKey])) ?? of(undefined);\n\n /** @internal */\n constructor(\n /** An observable of the URL segments matched by this route. */\n public url: Observable<UrlSegment[]>,\n /** An observable of the matrix parameters scoped to this route. */\n public params: Observable<Params>,\n /** An observable of the query parameters shared by all the routes. */\n public queryParams: Observable<Params>,\n /** An observable of the URL fragment shared by all the routes. */\n public fragment: Observable<string|null>,\n /** An observable of the static and resolved data of this route. */\n public data: Observable<Data>,\n /** The outlet name of the route, a constant. */\n public outlet: string,\n /** The component of the route, a constant. */\n public component: Type<any>|null, futureSnapshot: ActivatedRouteSnapshot) {\n this._futureSnapshot = futureSnapshot;\n }\n\n /** The configuration used to match this route. */\n get routeConfig(): Route|null {\n return this._futureSnapshot.routeConfig;\n }\n\n /** The root of the router state. */\n get root(): ActivatedRoute {\n return this._routerState.root;\n }\n\n /** The parent of this route in the router state tree. */\n get parent(): ActivatedRoute|null {\n return this._routerState.parent(this);\n }\n\n /** The first child of this route in the router state tree. */\n get firstChild(): ActivatedRoute|null {\n return this._routerState.firstChild(this);\n }\n\n /** The children of this route in the router state tree. */\n get children(): ActivatedRoute[] {\n return this._routerState.children(this);\n }\n\n /** The path from the root of the router state tree to this route. */\n get pathFromRoot(): ActivatedRoute[] {\n return this._routerState.pathFromRoot(this);\n }\n\n /**\n * An Observable that contains a map of the required and optional parameters\n * specific to the route.\n * The map supports retrieving single and multiple values from the same parameter.\n */\n get paramMap(): Observable<ParamMap> {\n if (!this._paramMap) {\n this._paramMap = this.params.pipe(map((p: Params): ParamMap => convertToParamMap(p)));\n }\n return this._paramMap;\n }\n\n /**\n * An Observable that contains a map of the query parameters available to all routes.\n * The map supports retrieving single and multiple values from the query parameter.\n */\n get queryParamMap(): Observable<ParamMap> {\n if (!this._queryParamMap) {\n this._queryParamMap =\n this.queryParams.pipe(map((p: Params): ParamMap => convertToParamMap(p)));\n }\n return this._queryParamMap;\n }\n\n toString(): string {\n return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;\n }\n}\n\nexport type ParamsInheritanceStrategy = 'emptyOnly'|'always';\n\n/** @internal */\nexport type Inherited = {\n params: Params,\n data: Data,\n resolve: Data,\n};\n\n/**\n * Returns the inherited params, data, and resolve for a given route.\n * By default, this only inherits values up to the nearest path-less or component-less route.\n * @internal\n */\nexport function inheritedParamsDataResolve(\n route: ActivatedRouteSnapshot,\n paramsInheritanceStrategy: ParamsInheritanceStrategy = 'emptyOnly'): Inherited {\n const pathFromRoot = route.pathFromRoot;\n\n let inheritingStartingFrom = 0;\n if (paramsInheritanceStrategy !== 'always') {\n inheritingStartingFrom = pathFromRoot.length - 1;\n\n while (inheritingStartingFrom >= 1) {\n const current = pathFromRoot[inheritingStartingFrom];\n const parent = pathFromRoot[inheritingStartingFrom - 1];\n // current route is an empty path => inherits its parent's params and data\n if (current.routeConfig && current.routeConfig.path === '') {\n inheritingStartingFrom--;\n\n // parent is componentless => current route should inherit its params and data\n } else if (!parent.component) {\n inheritingStartingFrom--;\n\n } else {\n break;\n }\n }\n }\n\n return flattenInherited(pathFromRoot.slice(inheritingStartingFrom));\n}\n\n/** @internal */\nfunction flattenInherited(pathFromRoot: ActivatedRouteSnapshot[]): Inherited {\n return pathFromRoot.reduce((res, curr) => {\n const params = {...res.params, ...curr.params};\n const data = {...res.data, ...curr.data};\n const resolve =\n {...curr.data, ...res.resolve, ...curr.routeConfig?.data, ...curr._resolvedData};\n return {params, data, resolve};\n }, {params: {}, data: {}, resolve: {}});\n}\n\n/**\n * @description\n *\n * Contains the information about a route associated with a component loaded in an\n * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to\n * traverse the router state tree.\n *\n * The following example initializes a component with route information extracted\n * from the snapshot of the root node at the time of creation.\n *\n * ```\n * @Component({templateUrl:'./my-component.html'})\n * class MyComponent {\n * constructor(route: ActivatedRoute) {\n * const id: string = route.snapshot.params.id;\n * const url: string = route.snapshot.url.join('');\n * const user = route.snapshot.data.user;\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport class ActivatedRouteSnapshot {\n /** The configuration used to match this route **/\n public readonly routeConfig: Route|null;\n /** @internal **/\n _urlSegment: UrlSegmentGroup;\n /** @internal */\n _lastPathIndex: number;\n /** @internal */\n _resolve: ResolveData;\n /** @internal */\n _resolvedData?: Data;\n /** @internal */\n _routerState!: RouterStateSnapshot;\n /** @internal */\n _paramMap?: ParamMap;\n /** @internal */\n _queryParamMap?: ParamMap;\n\n /** The resolved route title */\n get title(): string|undefined {\n // Note: This _must_ be a getter because the data is mutated in the resolvers. Title will not be\n // available at the time of class instantiation.\n return this.data?.[RouteTitleKey];\n }\n\n /** @internal */\n constructor(\n /** The URL segments matched by this route */\n public url: UrlSegment[],\n /**\n * The matrix parameters scoped to this route.\n *\n * You can compute all params (or data) in the router state or to get params outside\n * of an activated component by traversing the `RouterState` tree as in the following\n * example:\n * ```\n * collectRouteParams(router: Router) {\n * let params = {};\n * let stack: ActivatedRouteSnapshot[] = [router.routerState.snapshot.root];\n * while (stack.length > 0) {\n * const route = stack.pop()!;\n * params = {...params, ...route.params};\n * stack.push(...route.children);\n * }\n * return params;\n * }\n * ```\n */\n public params: Params,\n /** The query parameters shared by all the routes */\n public queryParams: Params,\n /** The URL fragment shared by all the routes */\n public fragment: string|null,\n /** The static and resolved data of this route */\n public data: Data,\n /** The outlet name of the route */\n public outlet: string,\n /** The component of the route */\n public component: Type<any>|null, routeConfig: Route|null, urlSegment: UrlSegmentGroup,\n lastPathIndex: number, resolve: ResolveData) {\n this.routeConfig = routeConfig;\n this._urlSegment = urlSegment;\n this._lastPathIndex = lastPathIndex;\n this._resolve = resolve;\n }\n\n /** The root of the router state */\n get root(): ActivatedRouteSnapshot {\n return this._routerState.root;\n }\n\n /** The parent of this route in the router state tree */\n get parent(): ActivatedRouteSnapshot|null {\n return this._routerState.parent(this);\n }\n\n /** The first child of this route in the router state tree */\n get firstChild(): ActivatedRouteSnapshot|null {\n return this._routerState.firstChild(this);\n }\n\n /** The children of this route in the router state tree */\n get children(): ActivatedRouteSnapshot[] {\n return this._routerState.children(this);\n }\n\n /** The path from the root of the router state tree to this route */\n get pathFromRoot(): ActivatedRouteSnapshot[] {\n return this._routerState.pathFromRoot(this);\n }\n\n get paramMap(): ParamMap {\n if (!this._paramMap) {\n this._paramMap = convertToParamMap(this.params);\n }\n return this._paramMap;\n }\n\n get queryParamMap(): ParamMap {\n if (!this._queryParamMap) {\n this._queryParamMap = convertToParamMap(this.queryParams);\n }\n return this._queryParamMap;\n }\n\n toString(): string {\n const url = this.url.map(segment => segment.toString()).join('/');\n const matched = this.routeConfig ? this.routeConfig.path : '';\n return `Route(url:'${url}', path:'${matched}')`;\n }\n}\n\n/**\n * @description\n *\n * Represents the state of the router at a moment in time.\n *\n * This is a tree of activated route snapshots. Every node in this tree knows about\n * the \"consumed\" URL segments, the extracted parameters, and the resolved data.\n *\n * The following example shows how a component is initialized with information\n * from the snapshot of the root node's state at the time of creation.\n *\n * ```\n * @Component({templateUrl:'template.html'})\n * class MyComponent {\n * constructor(router: Router) {\n * const state: RouterState = router.routerState;\n * const snapshot: RouterStateSnapshot = state.snapshot;\n * const root: ActivatedRouteSnapshot = snapshot.root;\n * const child = root.firstChild;\n * const id: Observable<string> = child.params.map(p => p.id);\n * //...\n * }\n * }\n * ```\n *\n * @publicApi\n */\nexport class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> {\n /** @internal */\n constructor(\n /** The url from which this snapshot was created */\n public url: string, root: TreeNode<ActivatedRouteSnapshot>) {\n super(root);\n setRouterState(<RouterStateSnapshot>this, root);\n }\n\n override toString(): string {\n return serializeNode(this._root);\n }\n}\n\nfunction setRouterState<U, T extends {_routerState: U}>(state: U, node: TreeNode<T>): void {\n node.value._routerState = state;\n node.children.forEach(c => setRouterState(state, c));\n}\n\nfunction serializeNode(node: TreeNode<ActivatedRouteSnapshot>): string {\n const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : '';\n return `${node.value}${c}`;\n}\n\n/**\n * The expectation is that the activate route is created with the right set of parameters.\n * So we push new values into the observables only when they are not the initial values.\n * And we detect that by checking if the snapshot field is set.\n */\nexport function advanceActivatedRoute(route: ActivatedRoute): void {\n if (route.snapshot) {\n const currentSnapshot = route.snapshot;\n const nextSnapshot = route._futureSnapshot;\n route.snapshot = nextSnapshot;\n if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {\n (<any>route.queryParams).next(nextSnapshot.queryParams);\n }\n if (currentSnapshot.fragment !== nextSnapshot.fragment) {\n (<any>route.fragment).next(nextSnapshot.fragment);\n }\n if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {\n (<any>route.params).next(nextSnapshot.params);\n }\n if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {\n (<any>route.url).next(nextSnapshot.url);\n }\n if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {\n (<any>route.data).next(nextSnapshot.data);\n }\n } else {\n route.snapshot = route._futureSnapshot;\n\n // this is for resolved data\n (<any>route.data).next(route._futureSnapshot.data);\n }\n}\n\n\nexport function equalParamsAndUrlSegments(\n a: ActivatedRouteSnapshot, b: ActivatedRouteSnapshot): boolean {\n const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);\n const parentsMismatch = !a.parent !== !b.parent;\n\n return equalUrlParams && !parentsMismatch &&\n (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent!));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BehaviorSubject} from 'rxjs';\n\nimport {DetachedRouteHandleInternal, RouteReuseStrategy} from './route_reuse_strategy';\nimport {ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot} from './router_state';\nimport {TreeNode} from './utils/tree';\n\nexport function createRouterState(\n routeReuseStrategy: RouteReuseStrategy, curr: RouterStateSnapshot,\n prevState: RouterState): RouterState {\n const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);\n return new RouterState(root, curr);\n}\n\nfunction createNode(\n routeReuseStrategy: RouteReuseStrategy, curr: TreeNode<ActivatedRouteSnapshot>,\n prevState?: TreeNode<ActivatedRoute>): TreeNode<ActivatedRoute> {\n // reuse an activated route that is currently displayed on the screen\n if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {\n const value = prevState.value;\n value._futureSnapshot = curr.value;\n const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);\n return new TreeNode<ActivatedRoute>(value, children);\n } else {\n if (routeReuseStrategy.shouldAttach(curr.value)) {\n // retrieve an activated route that is used to be displayed, but is not currently displayed\n const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);\n if (detachedRouteHandle !== null) {\n const tree = (detachedRouteHandle as DetachedRouteHandleInternal).route;\n tree.value._futureSnapshot = curr.value;\n tree.children = curr.children.map(c => createNode(routeReuseStrategy, c));\n return tree;\n }\n }\n\n const value = createActivatedRoute(curr.value);\n const children = curr.children.map(c => createNode(routeReuseStrategy, c));\n return new TreeNode<ActivatedRoute>(value, children);\n }\n}\n\nfunction createOrReuseChildren(\n routeReuseStrategy: RouteReuseStrategy, curr: TreeNode<ActivatedRouteSnapshot>,\n prevState: TreeNode<ActivatedRoute>) {\n return curr.children.map(child => {\n for (const p of prevState.children) {\n if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {\n return createNode(routeReuseStrategy, child, p);\n }\n }\n return createNode(routeReuseStrategy, child);\n });\n}\n\nfunction createActivatedRoute(c: ActivatedRouteSnapshot) {\n return new ActivatedRoute(\n new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams),\n new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NavigationCancellationCode} from './events';\nimport {NavigationBehaviorOptions} from './models';\nimport {isUrlTree, UrlSerializer, UrlTree} from './url_tree';\n\nexport const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';\n\nexport type NavigationCancelingError =\n Error&{[NAVIGATION_CANCELING_ERROR]: true, cancellationCode: NavigationCancellationCode};\nexport type RedirectingNavigationCancelingError = NavigationCancelingError&{\n url: UrlTree;\n navigationBehaviorOptions?: NavigationBehaviorOptions;\n cancellationCode: NavigationCancellationCode.Redirect;\n};\n\nexport function redirectingNavigationError(\n urlSerializer: UrlSerializer, redirect: UrlTree): RedirectingNavigationCancelingError {\n const {redirectTo, navigationBehaviorOptions} =\n isUrlTree(redirect) ? {redirectTo: redirect, navigationBehaviorOptions: undefined} : redirect;\n const error =\n navigationCancelingError(\n ngDevMode && `Redirecting to \"${urlSerializer.serialize(redirectTo)}\"`,\n NavigationCancellationCode.Redirect, redirect) as RedirectingNavigationCancelingError;\n error.url = redirectTo;\n error.navigationBehaviorOptions = navigationBehaviorOptions;\n return error;\n}\n\nexport function navigationCancelingError(\n message: string|null|false, code: NavigationCancellationCode, redirectUrl?: UrlTree) {\n const error =\n new Error('NavigationCancelingError: ' + (message || '')) as NavigationCancelingError;\n error[NAVIGATION_CANCELING_ERROR] = true;\n error.cancellationCode = code;\n if (redirectUrl) {\n (error as RedirectingNavigationCancelingError).url = redirectUrl;\n }\n return error;\n}\n\nexport function isRedirectingNavigationCancelingError(\n error: unknown|\n RedirectingNavigationCancelingError): error is RedirectingNavigationCancelingError {\n return isNavigationCancelingError(error) && isUrlTree((error as any).url);\n}\nexport function isNavigationCancelingError(error: unknown): error is NavigationCancelingError {\n return error && (error as any)[NAVIGATION_CANCELING_ERROR];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ComponentFactoryResolver, ComponentRef, EnvironmentInjector, Injectable} from '@angular/core';\n\nimport {RouterOutletContract} from './directives/router_outlet';\nimport {ActivatedRoute} from './router_state';\n\n\n/**\n * Store contextual information about a `RouterOutlet`\n *\n * @publicApi\n */\nexport class OutletContext {\n outlet: RouterOutletContract|null = null;\n route: ActivatedRoute|null = null;\n /**\n * @deprecated Passing a resolver to retrieve a component factory is not required and is\n * deprecated since v14.\n */\n resolver: ComponentFactoryResolver|null = null;\n injector: EnvironmentInjector|null = null;\n children = new ChildrenOutletContexts();\n attachRef: ComponentRef<any>|null = null;\n}\n\n/**\n * Store contextual information about the children (= nested) `RouterOutlet`\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class ChildrenOutletContexts {\n // contexts for child outlets, by name.\n private contexts = new Map<string, OutletContext>();\n\n /** Called when a `RouterOutlet` directive is instantiated */\n onChildOutletCreated(childName: string, outlet: RouterOutletContract): void {\n const context = this.getOrCreateContext(childName);\n context.outlet = outlet;\n this.contexts.set(childName, context);\n }\n\n /**\n * Called when a `RouterOutlet` directive is destroyed.\n * We need to keep the context as the outlet could be destroyed inside a NgIf and might be\n * re-created later.\n */\n onChildOutletDestroyed(childName: string): void {\n const context = this.getContext(childName);\n if (context) {\n context.outlet = null;\n context.attachRef = null;\n }\n }\n\n /**\n * Called when the corresponding route is deactivated during navigation.\n * Because the component get destroyed, all children outlet are destroyed.\n */\n onOutletDeactivated(): Map<string, OutletContext> {\n const contexts = this.contexts;\n this.contexts = new Map();\n return contexts;\n }\n\n onOutletReAttached(contexts: Map<string, OutletContext>) {\n this.contexts = contexts;\n }\n\n getOrCreateContext(childName: string): OutletContext {\n let context = this.getContext(childName);\n\n if (!context) {\n context = new OutletContext();\n this.contexts.set(childName, context);\n }\n\n return context;\n }\n\n getContext(childName: string): OutletContext|null {\n return this.contexts.get(childName) || null;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, EnvironmentInjector, EventEmitter, inject, Injector, Input, OnDestroy, OnInit, Output, SimpleChanges, ViewContainerRef, ɵRuntimeError as RuntimeError,} from '@angular/core';\n\nimport {RuntimeErrorCode} from '../errors';\nimport {Data} from '../models';\nimport {ChildrenOutletContexts} from '../router_outlet_context';\nimport {ActivatedRoute} from '../router_state';\nimport {PRIMARY_OUTLET} from '../shared';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n/**\n * An interface that defines the contract for developing a component outlet for the `Router`.\n *\n * An outlet acts as a placeholder that Angular dynamically fills based on the current router state.\n *\n * A router outlet should register itself with the `Router` via\n * `ChildrenOutletContexts#onChildOutletCreated` and unregister with\n * `ChildrenOutletContexts#onChildOutletDestroyed`. When the `Router` identifies a matched `Route`,\n * it looks for a registered outlet in the `ChildrenOutletContexts` and activates it.\n *\n * @see `ChildrenOutletContexts`\n * @publicApi\n */\nexport interface RouterOutletContract {\n /**\n * Whether the given outlet is activated.\n *\n * An outlet is considered \"activated\" if it has an active component.\n */\n isActivated: boolean;\n\n /** The instance of the activated component or `null` if the outlet is not activated. */\n component: Object|null;\n\n /**\n * The `Data` of the `ActivatedRoute` snapshot.\n */\n activatedRouteData: Data;\n\n /**\n * The `ActivatedRoute` for the outlet or `null` if the outlet is not activated.\n */\n activatedRoute: ActivatedRoute|null;\n\n /**\n * Called by the `Router` when the outlet should activate (create a component).\n */\n activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector|null): void;\n /**\n * Called by the `Router` when the outlet should activate (create a component).\n *\n * @deprecated Passing a resolver to retrieve a component factory is not required and is\n * deprecated since v14.\n */\n activateWith(activatedRoute: ActivatedRoute, resolver: ComponentFactoryResolver|null): void;\n\n /**\n * A request to destroy the currently activated component.\n *\n * When a `RouteReuseStrategy` indicates that an `ActivatedRoute` should be removed but stored for\n * later re-use rather than destroyed, the `Router` will call `detach` instead.\n */\n deactivate(): void;\n\n /**\n * Called when the `RouteReuseStrategy` instructs to detach the subtree.\n *\n * This is similar to `deactivate`, but the activated component should _not_ be destroyed.\n * Instead, it is returned so that it can be reattached later via the `attach` method.\n */\n detach(): ComponentRef<unknown>;\n\n /**\n * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree.\n */\n attach(ref: ComponentRef<unknown>, activatedRoute: ActivatedRoute): void;\n\n /**\n * Emits an activate event when a new component is instantiated\n **/\n activateEvents?: EventEmitter<unknown>;\n\n /**\n * Emits a deactivate event when a component is destroyed.\n */\n deactivateEvents?: EventEmitter<unknown>;\n\n /**\n * Emits an attached component instance when the `RouteReuseStrategy` instructs to re-attach a\n * previously detached subtree.\n **/\n attachEvents?: EventEmitter<unknown>;\n\n /**\n * Emits a detached component instance when the `RouteReuseStrategy` instructs to detach the\n * subtree.\n */\n detachEvents?: EventEmitter<unknown>;\n}\n\n/**\n * @description\n *\n * Acts as a placeholder that Angular dynamically fills based on the current router state.\n *\n * Each outlet can have a unique name, determined by the optional `name` attribute.\n * The name cannot be set or changed dynamically. If not set, default value is \"primary\".\n *\n * ```\n * <router-outlet></router-outlet>\n * <router-outlet name='left'></router-outlet>\n * <router-outlet name='right'></router-outlet>\n * ```\n *\n * Named outlets can be the targets of secondary routes.\n * The `Route` object for a secondary route has an `outlet` property to identify the target outlet:\n *\n * `{path: <base-path>, component: <component>, outlet: <target_outlet_name>}`\n *\n * Using named outlets and secondary routes, you can target multiple outlets in\n * the same `RouterLink` directive.\n *\n * The router keeps track of separate branches in a navigation tree for each named outlet and\n * generates a representation of that tree in the URL.\n * The URL for a secondary route uses the following syntax to specify both the primary and secondary\n * routes at the same time:\n *\n * `http://base-path/primary-route-path(outlet-name:route-path)`\n *\n * A router outlet emits an activate event when a new component is instantiated,\n * deactivate event when a component is destroyed.\n * An attached event emits when the `RouteReuseStrategy` instructs the outlet to reattach the\n * subtree, and the detached event emits when the `RouteReuseStrategy` instructs the outlet to\n * detach the subtree.\n *\n * ```\n * <router-outlet\n * (activate)='onActivate($event)'\n * (deactivate)='onDeactivate($event)'\n * (attach)='onAttach($event)'\n * (detach)='onDetach($event)'></router-outlet>\n * ```\n *\n * @see [Routing tutorial](guide/router-tutorial-toh#named-outlets \"Example of a named\n * outlet and secondary route configuration\").\n * @see `RouterLink`\n * @see `Route`\n * @ngModule RouterModule\n *\n * @publicApi\n */\n@Directive({\n selector: 'router-outlet',\n exportAs: 'outlet',\n standalone: true,\n})\nexport class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract {\n private activated: ComponentRef<any>|null = null;\n private _activatedRoute: ActivatedRoute|null = null;\n /**\n * The name of the outlet\n *\n * @see [named outlets](guide/router-tutorial-toh#displaying-multiple-routes-in-named-outlets)\n */\n @Input() name = PRIMARY_OUTLET;\n\n @Output('activate') activateEvents = new EventEmitter<any>();\n @Output('deactivate') deactivateEvents = new EventEmitter<any>();\n /**\n * Emits an attached component instance when the `RouteReuseStrategy` instructs to re-attach a\n * previously detached subtree.\n **/\n @Output('attach') attachEvents = new EventEmitter<unknown>();\n /**\n * Emits a detached component instance when the `RouteReuseStrategy` instructs to detach the\n * subtree.\n */\n @Output('detach') detachEvents = new EventEmitter<unknown>();\n\n private parentContexts = inject(ChildrenOutletContexts);\n private location = inject(ViewContainerRef);\n private changeDetector = inject(ChangeDetectorRef);\n private environmentInjector = inject(EnvironmentInjector);\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges) {\n if (changes['name']) {\n const {firstChange, previousValue} = changes['name'];\n if (firstChange) {\n // The first change is handled by ngOnInit. Because ngOnChanges doesn't get called when no\n // input is set at all, we need to centrally handle the first change there.\n return;\n }\n\n // unregister with the old name\n if (this.isTrackedInParentContexts(previousValue)) {\n this.deactivate();\n this.parentContexts.onChildOutletDestroyed(previousValue);\n }\n // register the new name\n this.initializeOutletWithName();\n }\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n // Ensure that the registered outlet is this one before removing it on the context.\n if (this.isTrackedInParentContexts(this.name)) {\n this.parentContexts.onChildOutletDestroyed(this.name);\n }\n }\n\n private isTrackedInParentContexts(outletName: string) {\n return this.parentContexts.getContext(outletName)?.outlet === this;\n }\n\n /** @nodoc */\n ngOnInit(): void {\n this.initializeOutletWithName();\n }\n\n private initializeOutletWithName() {\n this.parentContexts.onChildOutletCreated(this.name, this);\n if (this.activated) {\n return;\n }\n\n // If the outlet was not instantiated at the time the route got activated we need to populate\n // the outlet when it is initialized (ie inside a NgIf)\n const context = this.parentContexts.getContext(this.name);\n if (context?.route) {\n if (context.attachRef) {\n // `attachRef` is populated when there is an existing component to mount\n this.attach(context.attachRef, context.route);\n } else {\n // otherwise the component defined in the configuration is created\n this.activateWith(context.route, context.injector);\n }\n }\n }\n\n get isActivated(): boolean {\n return !!this.activated;\n }\n\n /**\n * @returns The currently activated component instance.\n * @throws An error if the outlet is not activated.\n */\n get component(): Object {\n if (!this.activated)\n throw new RuntimeError(\n RuntimeErrorCode.OUTLET_NOT_ACTIVATED, NG_DEV_MODE && 'Outlet is not activated');\n return this.activated.instance;\n }\n\n get activatedRoute(): ActivatedRoute {\n if (!this.activated)\n throw new RuntimeError(\n RuntimeErrorCode.OUTLET_NOT_ACTIVATED, NG_DEV_MODE && 'Outlet is not activated');\n return this._activatedRoute as ActivatedRoute;\n }\n\n get activatedRouteData(): Data {\n if (this._activatedRoute) {\n return this._activatedRoute.snapshot.data;\n }\n return {};\n }\n\n /**\n * Called when the `RouteReuseStrategy` instructs to detach the subtree\n */\n detach(): ComponentRef<any> {\n if (!this.activated)\n throw new RuntimeError(\n RuntimeErrorCode.OUTLET_NOT_ACTIVATED, NG_DEV_MODE && 'Outlet is not activated');\n this.location.detach();\n const cmp = this.activated;\n this.activated = null;\n this._activatedRoute = null;\n this.detachEvents.emit(cmp.instance);\n return cmp;\n }\n\n /**\n * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree\n */\n attach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute) {\n this.activated = ref;\n this._activatedRoute = activatedRoute;\n this.location.insert(ref.hostView);\n this.attachEvents.emit(ref.instance);\n }\n\n deactivate(): void {\n if (this.activated) {\n const c = this.component;\n this.activated.destroy();\n this.activated = null;\n this._activatedRoute = null;\n this.deactivateEvents.emit(c);\n }\n }\n\n activateWith(\n activatedRoute: ActivatedRoute,\n resolverOrInjector?: ComponentFactoryResolver|EnvironmentInjector|null) {\n if (this.isActivated) {\n throw new RuntimeError(\n RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED,\n NG_DEV_MODE && 'Cannot activate an already activated outlet');\n }\n this._activatedRoute = activatedRoute;\n const location = this.location;\n const snapshot = activatedRoute.snapshot;\n const component = snapshot.component!;\n const childContexts = this.parentContexts.getOrCreateContext(this.name).children;\n const injector = new OutletInjector(activatedRoute, childContexts, location.injector);\n\n if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {\n const factory = resolverOrInjector.resolveComponentFactory(component);\n this.activated = location.createComponent(factory, location.length, injector);\n } else {\n const environmentInjector = resolverOrInjector ?? this.environmentInjector;\n this.activated = location.createComponent(\n component, {index: location.length, injector, environmentInjector});\n }\n // Calling `markForCheck` to make sure we will run the change detection when the\n // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.\n this.changeDetector.markForCheck();\n this.activateEvents.emit(this.activated.instance);\n }\n}\n\nclass OutletInjector implements Injector {\n constructor(\n private route: ActivatedRoute, private childContexts: ChildrenOutletContexts,\n private parent: Injector) {}\n\n get(token: any, notFoundValue?: any): any {\n if (token === ActivatedRoute) {\n return this.route;\n }\n\n if (token === ChildrenOutletContexts) {\n return this.childContexts;\n }\n\n return this.parent.get(token, notFoundValue);\n }\n}\n\nfunction isComponentFactoryResolver(item: any): item is ComponentFactoryResolver {\n return !!item.resolveComponentFactory;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Component} from '@angular/core';\n\nimport {RouterOutlet} from '../directives/router_outlet';\n\n/**\n * This component is used internally within the router to be a placeholder when an empty\n * router-outlet is needed. For example, with a config such as:\n *\n * `{path: 'parent', outlet: 'nav', children: [...]}`\n *\n * In order to render, there needs to be a component on this config, which will default\n * to this `EmptyOutletComponent`.\n */\n@Component({\n template: `<router-outlet></router-outlet>`,\n imports: [RouterOutlet],\n standalone: true,\n})\nexport class ɵEmptyOutletComponent {\n}\n\nexport {ɵEmptyOutletComponent as EmptyOutletComponent};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {createEnvironmentInjector, EnvironmentInjector, isStandalone, Type, ɵisNgModule as isNgModule, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {EmptyOutletComponent} from '../components/empty_outlet';\nimport {RuntimeErrorCode} from '../errors';\nimport {Route, Routes} from '../models';\nimport {ActivatedRouteSnapshot} from '../router_state';\nimport {PRIMARY_OUTLET} from '../shared';\n\n/**\n * Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist\n * and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the\n * `currentInjector`.\n *\n * @param route The route that might have providers\n * @param currentInjector The parent injector of the `Route`\n */\nexport function getOrCreateRouteInjectorIfNeeded(\n route: Route, currentInjector: EnvironmentInjector) {\n if (route.providers && !route._injector) {\n route._injector =\n createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);\n }\n return route._injector ?? currentInjector;\n}\n\nexport function getLoadedRoutes(route: Route): Route[]|undefined {\n return route._loadedRoutes;\n}\n\nexport function getLoadedInjector(route: Route): EnvironmentInjector|undefined {\n return route._loadedInjector;\n}\nexport function getLoadedComponent(route: Route): Type<unknown>|undefined {\n return route._loadedComponent;\n}\n\nexport function getProvidersInjector(route: Route): EnvironmentInjector|undefined {\n return route._injector;\n}\n\nexport function validateConfig(\n config: Routes, parentPath: string = '', requireStandaloneComponents = false): void {\n // forEach doesn't iterate undefined values\n for (let i = 0; i < config.length; i++) {\n const route: Route = config[i];\n const fullPath: string = getFullPath(parentPath, route);\n validateNode(route, fullPath, requireStandaloneComponents);\n }\n}\n\nexport function assertStandalone(fullPath: string, component: Type<unknown>|undefined) {\n if (component && isNgModule(component)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}'. You are using 'loadComponent' with a module, ` +\n `but it must be used with standalone components. Use 'loadChildren' instead.`);\n } else if (component && !isStandalone(component)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${fullPath}'. The component must be standalone.`);\n }\n}\n\nfunction validateNode(route: Route, fullPath: string, requireStandaloneComponents: boolean): void {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n if (!route) {\n throw new RuntimeError(RuntimeErrorCode.INVALID_ROUTE_CONFIG, `\n Invalid configuration of route '${fullPath}': Encountered undefined route.\n The reason might be an extra comma.\n\n Example:\n const routes: Routes = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },, << two commas\n { path: 'detail/:id', component: HeroDetailComponent }\n ];\n `);\n }\n if (Array.isArray(route)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${fullPath}': Array cannot be specified`);\n }\n if (!route.redirectTo && !route.component && !route.loadComponent && !route.children &&\n !route.loadChildren && (route.outlet && route.outlet !== PRIMARY_OUTLET)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);\n }\n if (route.redirectTo && route.children) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': redirectTo and children cannot be used together`);\n }\n if (route.redirectTo && route.loadChildren) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': redirectTo and loadChildren cannot be used together`);\n }\n if (route.children && route.loadChildren) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': children and loadChildren cannot be used together`);\n }\n if (route.redirectTo && (route.component || route.loadComponent)) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': redirectTo and component/loadComponent cannot be used together`);\n }\n if (route.component && route.loadComponent) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': component and loadComponent cannot be used together`);\n }\n if (route.redirectTo && route.canActivate) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` +\n `so canActivate will never be executed.`);\n }\n if (route.path && route.matcher) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);\n }\n if (route.redirectTo === void 0 && !route.component && !route.loadComponent &&\n !route.children && !route.loadChildren) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);\n }\n if (route.path === void 0 && route.matcher === void 0) {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${\n fullPath}': routes must have either a path or a matcher specified`);\n }\n if (typeof route.path === 'string' && route.path.charAt(0) === '/') {\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '${fullPath}': path cannot start with a slash`);\n }\n if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {\n const exp =\n `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;\n throw new RuntimeError(\n RuntimeErrorCode.INVALID_ROUTE_CONFIG,\n `Invalid configuration of route '{path: \"${fullPath}\", redirectTo: \"${\n route.redirectTo}\"}': please provide 'pathMatch'. ${exp}`);\n }\n if (requireStandaloneComponents) {\n assertStandalone(fullPath, route.component);\n }\n }\n if (route.children) {\n validateConfig(route.children, fullPath, requireStandaloneComponents);\n }\n}\n\nfunction getFullPath(parentPath: string, currentRoute: Route): string {\n if (!currentRoute) {\n return parentPath;\n }\n if (!parentPath && !currentRoute.path) {\n return '';\n } else if (parentPath && !currentRoute.path) {\n return `${parentPath}/`;\n } else if (!parentPath && currentRoute.path) {\n return currentRoute.path;\n } else {\n return `${parentPath}/${currentRoute.path}`;\n }\n}\n\n/**\n * Makes a copy of the config and adds any default required properties.\n */\nexport function standardizeConfig(r: Route): Route {\n const children = r.children && r.children.map(standardizeConfig);\n const c = children ? {...r, children} : {...r};\n if ((!c.component && !c.loadComponent) && (children || c.loadChildren) &&\n (c.outlet && c.outlet !== PRIMARY_OUTLET)) {\n c.component = EmptyOutletComponent;\n }\n return c;\n}\n\n/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */\nexport function getOutlet(route: Route): string {\n return route.outlet || PRIMARY_OUTLET;\n}\n\n/**\n * Sorts the `routes` such that the ones with an outlet matching `outletName` come first.\n * The order of the configs is otherwise preserved.\n */\nexport function sortByMatchingOutlets(routes: Routes, outletName: string): Routes {\n const sortedConfig = routes.filter(r => getOutlet(r) === outletName);\n sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));\n return sortedConfig;\n}\n\n/**\n * Gets the first injector in the snapshot's parent tree.\n *\n * If the `Route` has a static list of providers, the returned injector will be the one created from\n * those. If it does not exist, the returned injector may come from the parents, which may be from a\n * loaded config or their static providers.\n *\n * Returns `null` if there is neither this nor any parents have a stored injector.\n *\n * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and\n * also used for getting the correct injector to use for creating components.\n */\nexport function getClosestRouteInjector(snapshot: ActivatedRouteSnapshot): EnvironmentInjector|\n null {\n if (!snapshot) return null;\n\n // If the current route has its own injector, which is created from the static providers on the\n // route itself, we should use that. Otherwise, we start at the parent since we do not want to\n // include the lazy loaded injector from this route.\n if (snapshot.routeConfig?._injector) {\n return snapshot.routeConfig._injector;\n }\n\n for (let s = snapshot.parent; s; s = s.parent) {\n const route = s.routeConfig;\n // Note that the order here is important. `_loadedInjector` stored on the route with\n // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector`\n // is created from the static providers on that parent route, so it applies to the children as\n // well, but only if there is no lazy loaded NgModuleRef injector.\n if (route?._loadedInjector) return route._loadedInjector;\n if (route?._injector) return route._injector;\n }\n\n return null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ComponentFactoryResolver, EnvironmentInjector, NgModuleRef} from '@angular/core';\nimport {MonoTypeOperatorFunction} from 'rxjs';\nimport {map} from 'rxjs/operators';\n\nimport {ActivationEnd, ChildActivationEnd, Event} from '../events';\nimport {NavigationTransition} from '../navigation_transition';\nimport {DetachedRouteHandleInternal, RouteReuseStrategy} from '../route_reuse_strategy';\nimport {ChildrenOutletContexts} from '../router_outlet_context';\nimport {ActivatedRoute, advanceActivatedRoute, RouterState} from '../router_state';\nimport {forEach} from '../utils/collection';\nimport {getClosestRouteInjector} from '../utils/config';\nimport {nodeChildrenAsMap, TreeNode} from '../utils/tree';\n\nexport const activateRoutes =\n (rootContexts: ChildrenOutletContexts, routeReuseStrategy: RouteReuseStrategy,\n forwardEvent: (evt: Event) => void): MonoTypeOperatorFunction<NavigationTransition> =>\n map(t => {\n new ActivateRoutes(\n routeReuseStrategy, t.targetRouterState!, t.currentRouterState, forwardEvent)\n .activate(rootContexts);\n return t;\n });\n\nexport class ActivateRoutes {\n constructor(\n private routeReuseStrategy: RouteReuseStrategy, private futureState: RouterState,\n private currState: RouterState, private forwardEvent: (evt: Event) => void) {}\n\n activate(parentContexts: ChildrenOutletContexts): void {\n const futureRoot = this.futureState._root;\n const currRoot = this.currState ? this.currState._root : null;\n\n this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);\n advanceActivatedRoute(this.futureState.root);\n this.activateChildRoutes(futureRoot, currRoot, parentContexts);\n }\n\n // De-activate the child route that are not re-used for the future state\n private deactivateChildRoutes(\n futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,\n contexts: ChildrenOutletContexts): void {\n const children: {[outletName: string]: TreeNode<ActivatedRoute>} = nodeChildrenAsMap(currNode);\n\n // Recurse on the routes active in the future state to de-activate deeper children\n futureNode.children.forEach(futureChild => {\n const childOutletName = futureChild.value.outlet;\n this.deactivateRoutes(futureChild, children[childOutletName], contexts);\n delete children[childOutletName];\n });\n\n // De-activate the routes that will not be re-used\n forEach(children, (v: TreeNode<ActivatedRoute>, childName: string) => {\n this.deactivateRouteAndItsChildren(v, contexts);\n });\n }\n\n private deactivateRoutes(\n futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>,\n parentContext: ChildrenOutletContexts): void {\n const future = futureNode.value;\n const curr = currNode ? currNode.value : null;\n\n if (future === curr) {\n // Reusing the node, check to see if the children need to be de-activated\n if (future.component) {\n // If we have a normal route, we need to go through an outlet.\n const context = parentContext.getContext(future.outlet);\n if (context) {\n this.deactivateChildRoutes(futureNode, currNode, context.children);\n }\n } else {\n // if we have a componentless route, we recurse but keep the same outlet map.\n this.deactivateChildRoutes(futureNode, currNode, parentContext);\n }\n } else {\n if (curr) {\n // Deactivate the current route which will not be re-used\n this.deactivateRouteAndItsChildren(currNode, parentContext);\n }\n }\n }\n\n private deactivateRouteAndItsChildren(\n route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): void {\n // If there is no component, the Route is never attached to an outlet (because there is no\n // component to attach).\n if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {\n this.detachAndStoreRouteSubtree(route, parentContexts);\n } else {\n this.deactivateRouteAndOutlet(route, parentContexts);\n }\n }\n\n private detachAndStoreRouteSubtree(\n route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): void {\n const context = parentContexts.getContext(route.value.outlet);\n const contexts = context && route.value.component ? context.children : parentContexts;\n const children: {[outletName: string]: TreeNode<ActivatedRoute>} = nodeChildrenAsMap(route);\n\n for (const childOutlet of Object.keys(children)) {\n this.deactivateRouteAndItsChildren(children[childOutlet], contexts);\n }\n\n if (context && context.outlet) {\n const componentRef = context.outlet.detach();\n const contexts = context.children.onOutletDeactivated();\n this.routeReuseStrategy.store(route.value.snapshot, {componentRef, route, contexts});\n }\n }\n\n private deactivateRouteAndOutlet(\n route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): void {\n const context = parentContexts.getContext(route.value.outlet);\n // The context could be `null` if we are on a componentless route but there may still be\n // children that need deactivating.\n const contexts = context && route.value.component ? context.children : parentContexts;\n const children: {[outletName: string]: TreeNode<ActivatedRoute>} = nodeChildrenAsMap(route);\n\n for (const childOutlet of Object.keys(children)) {\n this.deactivateRouteAndItsChildren(children[childOutlet], contexts);\n }\n\n if (context) {\n if (context.outlet) {\n // Destroy the component\n context.outlet.deactivate();\n // Destroy the contexts for all the outlets that were in the component\n context.children.onOutletDeactivated();\n }\n // Clear the information about the attached component on the context but keep the reference to\n // the outlet. Clear even if outlet was not yet activated to avoid activating later with old\n // info\n context.attachRef = null;\n context.resolver = null;\n context.route = null;\n }\n }\n\n private activateChildRoutes(\n futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,\n contexts: ChildrenOutletContexts): void {\n const children: {[outlet: string]: TreeNode<ActivatedRoute>} = nodeChildrenAsMap(currNode);\n futureNode.children.forEach(c => {\n this.activateRoutes(c, children[c.value.outlet], contexts);\n this.forwardEvent(new ActivationEnd(c.value.snapshot));\n });\n if (futureNode.children.length) {\n this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));\n }\n }\n\n private activateRoutes(\n futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>,\n parentContexts: ChildrenOutletContexts): void {\n const future = futureNode.value;\n const curr = currNode ? currNode.value : null;\n\n advanceActivatedRoute(future);\n\n // reusing the node\n if (future === curr) {\n if (future.component) {\n // If we have a normal route, we need to go through an outlet.\n const context = parentContexts.getOrCreateContext(future.outlet);\n this.activateChildRoutes(futureNode, currNode, context.children);\n } else {\n // if we have a componentless route, we recurse but keep the same outlet map.\n this.activateChildRoutes(futureNode, currNode, parentContexts);\n }\n } else {\n if (future.component) {\n // if we have a normal route, we need to place the component into the outlet and recurse.\n const context = parentContexts.getOrCreateContext(future.outlet);\n\n if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {\n const stored =\n (<DetachedRouteHandleInternal>this.routeReuseStrategy.retrieve(future.snapshot));\n this.routeReuseStrategy.store(future.snapshot, null);\n context.children.onOutletReAttached(stored.contexts);\n context.attachRef = stored.componentRef;\n context.route = stored.route.value;\n if (context.outlet) {\n // Attach right away when the outlet has already been instantiated\n // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated\n context.outlet.attach(stored.componentRef, stored.route.value);\n }\n\n advanceActivatedRoute(stored.route.value);\n this.activateChildRoutes(futureNode, null, context.children);\n } else {\n const injector = getClosestRouteInjector(future.snapshot);\n const cmpFactoryResolver = injector?.get(ComponentFactoryResolver) ?? null;\n context.attachRef = null;\n context.route = future;\n context.resolver = cmpFactoryResolver;\n context.injector = injector;\n if (context.outlet) {\n // Activate the outlet when it has already been instantiated\n // Otherwise it will get activated from its `ngOnInit` when instantiated\n context.outlet.activateWith(future, context.injector);\n }\n\n this.activateChildRoutes(futureNode, null, context.children);\n }\n } else {\n // if we have a componentless route, we recurse but keep the same outlet map.\n this.activateChildRoutes(futureNode, null, parentContexts);\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injector, ProviderToken, ɵisInjectable as isInjectable} from '@angular/core';\n\nimport {RunGuardsAndResolvers} from '../models';\nimport {ChildrenOutletContexts, OutletContext} from '../router_outlet_context';\nimport {ActivatedRouteSnapshot, equalParamsAndUrlSegments, RouterStateSnapshot} from '../router_state';\nimport {equalPath} from '../url_tree';\nimport {forEach, shallowEqual} from '../utils/collection';\nimport {nodeChildrenAsMap, TreeNode} from '../utils/tree';\n\nexport class CanActivate {\n readonly route: ActivatedRouteSnapshot;\n constructor(public path: ActivatedRouteSnapshot[]) {\n this.route = this.path[this.path.length - 1];\n }\n}\n\nexport class CanDeactivate {\n constructor(public component: Object|null, public route: ActivatedRouteSnapshot) {}\n}\n\nexport declare type Checks = {\n canDeactivateChecks: CanDeactivate[],\n canActivateChecks: CanActivate[],\n};\n\nexport function getAllRouteGuards(\n future: RouterStateSnapshot, curr: RouterStateSnapshot,\n parentContexts: ChildrenOutletContexts) {\n const futureRoot = future._root;\n const currRoot = curr ? curr._root : null;\n\n return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);\n}\n\nexport function getCanActivateChild(p: ActivatedRouteSnapshot):\n {node: ActivatedRouteSnapshot, guards: any[]}|null {\n const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;\n if (!canActivateChild || canActivateChild.length === 0) return null;\n return {node: p, guards: canActivateChild};\n}\n\nexport function getTokenOrFunctionIdentity<T>(\n tokenOrFunction: Function|ProviderToken<T>, injector: Injector): Function|T {\n const NOT_FOUND = Symbol();\n const result = injector.get<T|Symbol>(tokenOrFunction, NOT_FOUND);\n if (result === NOT_FOUND) {\n if (typeof tokenOrFunction === 'function' && !isInjectable(tokenOrFunction)) {\n // We think the token is just a function so return it as-is\n return tokenOrFunction;\n } else {\n // This will throw the not found error\n return injector.get<T>(tokenOrFunction);\n }\n }\n return result as T;\n}\n\nfunction getChildRouteGuards(\n futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>|null,\n contexts: ChildrenOutletContexts|null, futurePath: ActivatedRouteSnapshot[], checks: Checks = {\n canDeactivateChecks: [],\n canActivateChecks: []\n }): Checks {\n const prevChildren = nodeChildrenAsMap(currNode);\n\n // Process the children of the future route\n futureNode.children.forEach(c => {\n getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);\n delete prevChildren[c.value.outlet];\n });\n\n // Process any children left from the current route (not active for the future route)\n forEach(\n prevChildren,\n (v: TreeNode<ActivatedRouteSnapshot>, k: string) =>\n deactivateRouteAndItsChildren(v, contexts!.getContext(k), checks));\n\n return checks;\n}\n\nfunction getRouteGuards(\n futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>,\n parentContexts: ChildrenOutletContexts|null, futurePath: ActivatedRouteSnapshot[],\n checks: Checks = {\n canDeactivateChecks: [],\n canActivateChecks: []\n }): Checks {\n const future = futureNode.value;\n const curr = currNode ? currNode.value : null;\n const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;\n\n // reusing the node\n if (curr && future.routeConfig === curr.routeConfig) {\n const shouldRun =\n shouldRunGuardsAndResolvers(curr, future, future.routeConfig!.runGuardsAndResolvers);\n if (shouldRun) {\n checks.canActivateChecks.push(new CanActivate(futurePath));\n } else {\n // we need to set the data\n future.data = curr.data;\n future._resolvedData = curr._resolvedData;\n }\n\n // If we have a component, we need to go through an outlet.\n if (future.component) {\n getChildRouteGuards(\n futureNode, currNode, context ? context.children : null, futurePath, checks);\n\n // if we have a componentless route, we recurse but keep the same outlet map.\n } else {\n getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);\n }\n\n if (shouldRun && context && context.outlet && context.outlet.isActivated) {\n checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));\n }\n } else {\n if (curr) {\n deactivateRouteAndItsChildren(currNode, context, checks);\n }\n\n checks.canActivateChecks.push(new CanActivate(futurePath));\n // If we have a component, we need to go through an outlet.\n if (future.component) {\n getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);\n\n // if we have a componentless route, we recurse but keep the same outlet map.\n } else {\n getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);\n }\n }\n\n return checks;\n}\n\nfunction shouldRunGuardsAndResolvers(\n curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot,\n mode: RunGuardsAndResolvers|undefined): boolean {\n if (typeof mode === 'function') {\n return mode(curr, future);\n }\n switch (mode) {\n case 'pathParamsChange':\n return !equalPath(curr.url, future.url);\n\n case 'pathParamsOrQueryParamsChange':\n return !equalPath(curr.url, future.url) ||\n !shallowEqual(curr.queryParams, future.queryParams);\n\n case 'always':\n return true;\n\n case 'paramsOrQueryParamsChange':\n return !equalParamsAndUrlSegments(curr, future) ||\n !shallowEqual(curr.queryParams, future.queryParams);\n\n case 'paramsChange':\n default:\n return !equalParamsAndUrlSegments(curr, future);\n }\n}\n\nfunction deactivateRouteAndItsChildren(\n route: TreeNode<ActivatedRouteSnapshot>, context: OutletContext|null, checks: Checks): void {\n const children = nodeChildrenAsMap(route);\n const r = route.value;\n\n forEach(children, (node: TreeNode<ActivatedRouteSnapshot>, childName: string) => {\n if (!r.component) {\n deactivateRouteAndItsChildren(node, context, checks);\n } else if (context) {\n deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);\n } else {\n deactivateRouteAndItsChildren(node, null, checks);\n }\n });\n\n if (!r.component) {\n checks.canDeactivateChecks.push(new CanDeactivate(null, r));\n } else if (context && context.outlet && context.outlet.isActivated) {\n checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));\n } else {\n checks.canDeactivateChecks.push(new CanDeactivate(null, r));\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EmptyError} from 'rxjs';\n\nimport {CanActivate, CanActivateChild, CanDeactivate, CanLoad, CanMatch} from '../models';\nimport {NAVIGATION_CANCELING_ERROR, NavigationCancelingError, RedirectingNavigationCancelingError} from '../navigation_canceling_error';\nimport {isUrlTree} from '../url_tree';\n\n/**\n * Simple function check, but generic so type inference will flow. Example:\n *\n * function product(a: number, b: number) {\n * return a * b;\n * }\n *\n * if (isFunction<product>(fn)) {\n * return fn(1, 2);\n * } else {\n * throw \"Must provide the `product` function\";\n * }\n */\nexport function isFunction<T>(v: any): v is T {\n return typeof v === 'function';\n}\n\nexport function isBoolean(v: any): v is boolean {\n return typeof v === 'boolean';\n}\n\nexport function isCanLoad(guard: any): guard is CanLoad {\n return guard && isFunction<CanLoad>(guard.canLoad);\n}\n\nexport function isCanActivate(guard: any): guard is CanActivate {\n return guard && isFunction<CanActivate>(guard.canActivate);\n}\n\nexport function isCanActivateChild(guard: any): guard is CanActivateChild {\n return guard && isFunction<CanActivateChild>(guard.canActivateChild);\n}\n\nexport function isCanDeactivate<T>(guard: any): guard is CanDeactivate<T> {\n return guard && isFunction<CanDeactivate<T>>(guard.canDeactivate);\n}\nexport function isCanMatch(guard: any): guard is CanMatch {\n return guard && isFunction<CanMatch>(guard.canMatch);\n}\n\nexport function isRedirectingNavigationCancelingError(\n error: unknown|\n RedirectingNavigationCancelingError): error is RedirectingNavigationCancelingError {\n return isNavigationCancelingError(error) && isUrlTree((error as any).url);\n}\n\nexport function isNavigationCancelingError(error: unknown): error is NavigationCancelingError {\n return error && (error as any)[NAVIGATION_CANCELING_ERROR];\n}\n\nexport function isEmptyError(e: Error): e is EmptyError {\n return e instanceof EmptyError || e?.name === 'EmptyError';\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {combineLatest, Observable, OperatorFunction} from 'rxjs';\nimport {filter, map, scan, startWith, switchMap, take} from 'rxjs/operators';\n\nimport {isUrlTree, UrlTree} from '../url_tree';\n\nconst INITIAL_VALUE = Symbol('INITIAL_VALUE');\ndeclare type INTERIM_VALUES = typeof INITIAL_VALUE | boolean | UrlTree;\n\nexport function prioritizedGuardValue():\n OperatorFunction<Observable<boolean|UrlTree>[], boolean|UrlTree> {\n return switchMap(obs => {\n return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE as INTERIM_VALUES))))\n .pipe(\n map((results: INTERIM_VALUES[]) => {\n for (const result of results) {\n if (result === true) {\n // If result is true, check the next one\n continue;\n } else if (result === INITIAL_VALUE) {\n // If guard has not finished, we need to stop processing.\n return INITIAL_VALUE;\n } else if (result === false || result instanceof UrlTree) {\n // Result finished and was not true. Return the result.\n // Note that we only allow false/UrlTree. Other values are considered invalid and\n // ignored.\n return result;\n }\n }\n // Everything resolved to true. Return true.\n return true;\n }),\n filter((item): item is boolean|UrlTree => item !== INITIAL_VALUE),\n take(1),\n );\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, ProviderToken} from '@angular/core';\nimport {concat, defer, from, MonoTypeOperatorFunction, Observable, of, OperatorFunction, pipe} from 'rxjs';\nimport {concatMap, first, map, mergeMap, tap} from 'rxjs/operators';\n\nimport {ActivationStart, ChildActivationStart, Event} from '../events';\nimport {CanActivateChild, CanActivateChildFn, CanActivateFn, CanDeactivateFn, CanLoadFn, CanMatchFn, Route} from '../models';\nimport {redirectingNavigationError} from '../navigation_canceling_error';\nimport {NavigationTransition} from '../navigation_transition';\nimport {ActivatedRouteSnapshot, RouterStateSnapshot} from '../router_state';\nimport {isUrlTree, UrlSegment, UrlSerializer, UrlTree} from '../url_tree';\nimport {wrapIntoObservable} from '../utils/collection';\nimport {getClosestRouteInjector} from '../utils/config';\nimport {CanActivate, CanDeactivate, getCanActivateChild, getTokenOrFunctionIdentity} from '../utils/preactivation';\nimport {isBoolean, isCanActivate, isCanActivateChild, isCanDeactivate, isCanLoad, isCanMatch} from '../utils/type_guards';\n\nimport {prioritizedGuardValue} from './prioritized_guard_value';\n\nexport function checkGuards(injector: EnvironmentInjector, forwardEvent?: (evt: Event) => void):\n MonoTypeOperatorFunction<NavigationTransition> {\n return mergeMap(t => {\n const {targetSnapshot, currentSnapshot, guards: {canActivateChecks, canDeactivateChecks}} = t;\n if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {\n return of({...t, guardsResult: true});\n }\n\n return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot!, currentSnapshot, injector)\n .pipe(\n mergeMap(canDeactivate => {\n return canDeactivate && isBoolean(canDeactivate) ?\n runCanActivateChecks(targetSnapshot!, canActivateChecks, injector, forwardEvent) :\n of(canDeactivate);\n }),\n map(guardsResult => ({...t, guardsResult})));\n });\n}\n\nfunction runCanDeactivateChecks(\n checks: CanDeactivate[], futureRSS: RouterStateSnapshot, currRSS: RouterStateSnapshot,\n injector: EnvironmentInjector) {\n return from(checks).pipe(\n mergeMap(\n check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, injector)),\n first(result => {\n return result !== true;\n }, true as boolean | UrlTree));\n}\n\nfunction runCanActivateChecks(\n futureSnapshot: RouterStateSnapshot, checks: CanActivate[], injector: EnvironmentInjector,\n forwardEvent?: (evt: Event) => void) {\n return from(checks).pipe(\n concatMap((check: CanActivate) => {\n return concat(\n fireChildActivationStart(check.route.parent, forwardEvent),\n fireActivationStart(check.route, forwardEvent),\n runCanActivateChild(futureSnapshot, check.path, injector),\n runCanActivate(futureSnapshot, check.route, injector));\n }),\n first(result => {\n return result !== true;\n }, true as boolean | UrlTree));\n}\n\n/**\n * This should fire off `ActivationStart` events for each route being activated at this\n * level.\n * In other words, if you're activating `a` and `b` below, `path` will contain the\n * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always\n * return\n * `true` so checks continue to run.\n */\nfunction fireActivationStart(\n snapshot: ActivatedRouteSnapshot|null,\n forwardEvent?: (evt: Event) => void): Observable<boolean> {\n if (snapshot !== null && forwardEvent) {\n forwardEvent(new ActivationStart(snapshot));\n }\n return of(true);\n}\n\n/**\n * This should fire off `ChildActivationStart` events for each route being activated at this\n * level.\n * In other words, if you're activating `a` and `b` below, `path` will contain the\n * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always\n * return\n * `true` so checks continue to run.\n */\nfunction fireChildActivationStart(\n snapshot: ActivatedRouteSnapshot|null,\n forwardEvent?: (evt: Event) => void): Observable<boolean> {\n if (snapshot !== null && forwardEvent) {\n forwardEvent(new ChildActivationStart(snapshot));\n }\n return of(true);\n}\n\nfunction runCanActivate(\n futureRSS: RouterStateSnapshot, futureARS: ActivatedRouteSnapshot,\n injector: EnvironmentInjector): Observable<boolean|UrlTree> {\n const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;\n if (!canActivate || canActivate.length === 0) return of(true);\n\n const canActivateObservables =\n canActivate.map((canActivate: CanActivateFn|ProviderToken<unknown>) => {\n return defer(() => {\n const closestInjector = getClosestRouteInjector(futureARS) ?? injector;\n const guard = getTokenOrFunctionIdentity<CanActivate>(canActivate, closestInjector);\n const guardVal = isCanActivate(guard) ?\n guard.canActivate(futureARS, futureRSS) :\n closestInjector.runInContext(() => (guard as CanActivateFn)(futureARS, futureRSS));\n return wrapIntoObservable(guardVal).pipe(first());\n });\n });\n return of(canActivateObservables).pipe(prioritizedGuardValue());\n}\n\nfunction runCanActivateChild(\n futureRSS: RouterStateSnapshot, path: ActivatedRouteSnapshot[],\n injector: EnvironmentInjector): Observable<boolean|UrlTree> {\n const futureARS = path[path.length - 1];\n\n const canActivateChildGuards = path.slice(0, path.length - 1)\n .reverse()\n .map(p => getCanActivateChild(p))\n .filter(_ => _ !== null);\n\n const canActivateChildGuardsMapped = canActivateChildGuards.map((d: any) => {\n return defer(() => {\n const guardsMapped =\n d.guards.map((canActivateChild: CanActivateChildFn|ProviderToken<unknown>) => {\n const closestInjector = getClosestRouteInjector(d.node) ?? injector;\n const guard =\n getTokenOrFunctionIdentity<CanActivateChild>(canActivateChild, closestInjector);\n const guardVal = isCanActivateChild(guard) ?\n guard.canActivateChild(futureARS, futureRSS) :\n closestInjector.runInContext(\n () => (guard as CanActivateChildFn)(futureARS, futureRSS));\n return wrapIntoObservable(guardVal).pipe(first());\n });\n return of(guardsMapped).pipe(prioritizedGuardValue());\n });\n });\n return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());\n}\n\nfunction runCanDeactivate(\n component: Object|null, currARS: ActivatedRouteSnapshot, currRSS: RouterStateSnapshot,\n futureRSS: RouterStateSnapshot, injector: EnvironmentInjector): Observable<boolean|UrlTree> {\n const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;\n if (!canDeactivate || canDeactivate.length === 0) return of(true);\n const canDeactivateObservables = canDeactivate.map((c: any) => {\n const closestInjector = getClosestRouteInjector(currARS) ?? injector;\n const guard = getTokenOrFunctionIdentity<any>(c, closestInjector);\n const guardVal = isCanDeactivate(guard) ?\n guard.canDeactivate(component, currARS, currRSS, futureRSS) :\n closestInjector.runInContext(\n () => (guard as CanDeactivateFn<any>)(component, currARS, currRSS, futureRSS));\n return wrapIntoObservable(guardVal).pipe(first());\n });\n return of(canDeactivateObservables).pipe(prioritizedGuardValue());\n}\n\nexport function runCanLoadGuards(\n injector: EnvironmentInjector, route: Route, segments: UrlSegment[],\n urlSerializer: UrlSerializer): Observable<boolean> {\n const canLoad = route.canLoad;\n if (canLoad === undefined || canLoad.length === 0) {\n return of(true);\n }\n\n const canLoadObservables = canLoad.map((injectionToken: any) => {\n const guard = getTokenOrFunctionIdentity<any>(injectionToken, injector);\n const guardVal = isCanLoad(guard) ?\n guard.canLoad(route, segments) :\n injector.runInContext(() => (guard as CanLoadFn)(route, segments));\n return wrapIntoObservable(guardVal);\n });\n\n return of(canLoadObservables)\n .pipe(\n prioritizedGuardValue(),\n redirectIfUrlTree(urlSerializer),\n );\n}\n\nfunction redirectIfUrlTree(urlSerializer: UrlSerializer):\n OperatorFunction<UrlTree|boolean, boolean> {\n return pipe(\n tap((result: UrlTree|boolean) => {\n if (!isUrlTree(result)) return;\n\n throw redirectingNavigationError(urlSerializer, result);\n }),\n map(result => result === true),\n );\n}\n\nexport function runCanMatchGuards(\n injector: EnvironmentInjector, route: Route, segments: UrlSegment[],\n urlSerializer: UrlSerializer): Observable<boolean> {\n const canMatch = route.canMatch;\n if (!canMatch || canMatch.length === 0) return of(true);\n\n const canMatchObservables = canMatch.map(injectionToken => {\n const guard = getTokenOrFunctionIdentity(injectionToken, injector);\n const guardVal = isCanMatch(guard) ?\n guard.canMatch(route, segments) :\n injector.runInContext(() => (guard as CanMatchFn)(route, segments));\n return wrapIntoObservable(guardVal);\n });\n\n return of(canMatchObservables)\n .pipe(\n prioritizedGuardValue(),\n redirectIfUrlTree(urlSerializer),\n );\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, Injector} from '@angular/core';\nimport {Observable, of} from 'rxjs';\nimport {map} from 'rxjs/operators';\n\nimport {Route} from '../models';\nimport {runCanMatchGuards} from '../operators/check_guards';\nimport {defaultUrlMatcher, PRIMARY_OUTLET} from '../shared';\nimport {UrlSegment, UrlSegmentGroup, UrlSerializer} from '../url_tree';\n\nimport {forEach} from './collection';\nimport {getOrCreateRouteInjectorIfNeeded, getOutlet} from './config';\n\nexport interface MatchResult {\n matched: boolean;\n consumedSegments: UrlSegment[];\n remainingSegments: UrlSegment[];\n parameters: {[k: string]: string};\n positionalParamSegments: {[k: string]: UrlSegment};\n}\n\nconst noMatch: MatchResult = {\n matched: false,\n consumedSegments: [],\n remainingSegments: [],\n parameters: {},\n positionalParamSegments: {}\n};\n\nexport function matchWithChecks(\n segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment[],\n injector: EnvironmentInjector, urlSerializer: UrlSerializer): Observable<MatchResult> {\n const result = match(segmentGroup, route, segments);\n if (!result.matched) {\n return of(result);\n }\n\n // Only create the Route's `EnvironmentInjector` if it matches the attempted\n // navigation\n injector = getOrCreateRouteInjectorIfNeeded(route, injector);\n return runCanMatchGuards(injector, route, segments, urlSerializer)\n .pipe(\n map((v) => v === true ? result : {...noMatch}),\n );\n}\n\nexport function match(\n segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment[]): MatchResult {\n if (route.path === '') {\n if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {\n return {...noMatch};\n }\n\n return {\n matched: true,\n consumedSegments: [],\n remainingSegments: segments,\n parameters: {},\n positionalParamSegments: {}\n };\n }\n\n const matcher = route.matcher || defaultUrlMatcher;\n const res = matcher(segments, segmentGroup, route);\n if (!res) return {...noMatch};\n\n const posParams: {[n: string]: string} = {};\n forEach(res.posParams!, (v: UrlSegment, k: string) => {\n posParams[k] = v.path;\n });\n const parameters = res.consumed.length > 0 ?\n {...posParams, ...res.consumed[res.consumed.length - 1].parameters} :\n posParams;\n\n return {\n matched: true,\n consumedSegments: res.consumed,\n remainingSegments: segments.slice(res.consumed.length),\n // TODO(atscott): investigate combining parameters and positionalParamSegments\n parameters,\n positionalParamSegments: res.posParams ?? {}\n };\n}\n\nexport function split(\n segmentGroup: UrlSegmentGroup, consumedSegments: UrlSegment[], slicedSegments: UrlSegment[],\n config: Route[]) {\n if (slicedSegments.length > 0 &&\n containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {\n const s = new UrlSegmentGroup(\n consumedSegments,\n createChildrenForEmptyPaths(\n segmentGroup, consumedSegments, config,\n new UrlSegmentGroup(slicedSegments, segmentGroup.children)));\n s._sourceSegment = segmentGroup;\n s._segmentIndexShift = consumedSegments.length;\n return {segmentGroup: s, slicedSegments: []};\n }\n\n if (slicedSegments.length === 0 &&\n containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {\n const s = new UrlSegmentGroup(\n segmentGroup.segments,\n addEmptyPathsToChildrenIfNeeded(\n segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children));\n s._sourceSegment = segmentGroup;\n s._segmentIndexShift = consumedSegments.length;\n return {segmentGroup: s, slicedSegments};\n }\n\n const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);\n s._sourceSegment = segmentGroup;\n s._segmentIndexShift = consumedSegments.length;\n return {segmentGroup: s, slicedSegments};\n}\n\nfunction addEmptyPathsToChildrenIfNeeded(\n segmentGroup: UrlSegmentGroup, consumedSegments: UrlSegment[], slicedSegments: UrlSegment[],\n routes: Route[],\n children: {[name: string]: UrlSegmentGroup}): {[name: string]: UrlSegmentGroup} {\n const res: {[name: string]: UrlSegmentGroup} = {};\n for (const r of routes) {\n if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {\n const s = new UrlSegmentGroup([], {});\n s._sourceSegment = segmentGroup;\n s._segmentIndexShift = consumedSegments.length;\n res[getOutlet(r)] = s;\n }\n }\n return {...children, ...res};\n}\n\nfunction createChildrenForEmptyPaths(\n segmentGroup: UrlSegmentGroup, consumedSegments: UrlSegment[], routes: Route[],\n primarySegment: UrlSegmentGroup): {[name: string]: UrlSegmentGroup} {\n const res: {[name: string]: UrlSegmentGroup} = {};\n res[PRIMARY_OUTLET] = primarySegment;\n primarySegment._sourceSegment = segmentGroup;\n primarySegment._segmentIndexShift = consumedSegments.length;\n\n for (const r of routes) {\n if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {\n const s = new UrlSegmentGroup([], {});\n s._sourceSegment = segmentGroup;\n s._segmentIndexShift = consumedSegments.length;\n res[getOutlet(r)] = s;\n }\n }\n return res;\n}\n\nfunction containsEmptyPathMatchesWithNamedOutlets(\n segmentGroup: UrlSegmentGroup, slicedSegments: UrlSegment[], routes: Route[]): boolean {\n return routes.some(\n r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);\n}\n\nfunction containsEmptyPathMatches(\n segmentGroup: UrlSegmentGroup, slicedSegments: UrlSegment[], routes: Route[]): boolean {\n return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));\n}\n\nfunction emptyPathMatch(\n segmentGroup: UrlSegmentGroup, slicedSegments: UrlSegment[], r: Route): boolean {\n if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {\n return false;\n }\n\n return r.path === '';\n}\n\n/**\n * Determines if `route` is a path match for the `rawSegment`, `segments`, and `outlet` without\n * verifying that its children are a full match for the remainder of the `rawSegment` children as\n * well.\n */\nexport function isImmediateMatch(\n route: Route, rawSegment: UrlSegmentGroup, segments: UrlSegment[], outlet: string): boolean {\n // We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to\n // a config like\n // * `{path: '', children: [{path: 'b', outlet: 'b'}]}`\n // or even\n // * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]`\n //\n // The exception here is when the segment outlet is for the primary outlet. This would\n // result in a match inside the named outlet because all children there are written as primary\n // outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like\n // * `{path: '', outlet: 'x' children: [{path: 'b'}]}`\n // This should only match if the url is `/(x:b)`.\n if (getOutlet(route) !== outlet &&\n (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {\n return false;\n }\n if (route.path === '**') {\n return true;\n }\n return match(rawSegment, route, segments).matched;\n}\n\nexport function noLeftoversInUrl(\n segmentGroup: UrlSegmentGroup, segments: UrlSegment[], outlet: string): boolean {\n return segments.length === 0 && !segmentGroup.children[outlet];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, ɵRuntimeError as RuntimeError} from '@angular/core';\nimport {from, Observable, of, throwError} from 'rxjs';\nimport {catchError, concatMap, first, last, map, mergeMap, scan, switchMap, tap} from 'rxjs/operators';\n\nimport {RuntimeErrorCode} from './errors';\nimport {NavigationCancellationCode} from './events';\nimport {LoadedRouterConfig, Route, Routes} from './models';\nimport {navigationCancelingError} from './navigation_canceling_error';\nimport {runCanLoadGuards} from './operators/check_guards';\nimport {RouterConfigLoader} from './router_config_loader';\nimport {Params, PRIMARY_OUTLET} from './shared';\nimport {createRoot, squashSegmentGroup, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree} from './url_tree';\nimport {forEach} from './utils/collection';\nimport {getOrCreateRouteInjectorIfNeeded, getOutlet, sortByMatchingOutlets} from './utils/config';\nimport {isImmediateMatch, match, matchWithChecks, noLeftoversInUrl, split} from './utils/config_matching';\nimport {isEmptyError} from './utils/type_guards';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\nclass NoMatch {\n public segmentGroup: UrlSegmentGroup|null;\n\n constructor(segmentGroup?: UrlSegmentGroup) {\n this.segmentGroup = segmentGroup || null;\n }\n}\n\nclass AbsoluteRedirect {\n constructor(public urlTree: UrlTree) {}\n}\n\nfunction noMatch(segmentGroup: UrlSegmentGroup): Observable<UrlSegmentGroup> {\n return throwError(new NoMatch(segmentGroup));\n}\n\nfunction absoluteRedirect(newTree: UrlTree): Observable<any> {\n return throwError(new AbsoluteRedirect(newTree));\n}\n\nfunction namedOutletsRedirect(redirectTo: string): Observable<any> {\n return throwError(new RuntimeError(\n RuntimeErrorCode.NAMED_OUTLET_REDIRECT,\n NG_DEV_MODE &&\n `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));\n}\n\nfunction canLoadFails(route: Route): Observable<LoadedRouterConfig> {\n return throwError(navigationCancelingError(\n NG_DEV_MODE &&\n `Cannot load children because the guard of the route \"path: '${\n route.path}'\" returned false`,\n NavigationCancellationCode.GuardRejected));\n}\n\n/**\n * Returns the `UrlTree` with the redirection applied.\n *\n * Lazy modules are loaded along the way.\n */\nexport function applyRedirects(\n injector: EnvironmentInjector, configLoader: RouterConfigLoader, urlSerializer: UrlSerializer,\n urlTree: UrlTree, config: Routes): Observable<UrlTree> {\n return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply();\n}\n\nclass ApplyRedirects {\n private allowRedirects: boolean = true;\n\n constructor(\n private injector: EnvironmentInjector, private configLoader: RouterConfigLoader,\n private urlSerializer: UrlSerializer, private urlTree: UrlTree, private config: Routes) {}\n\n apply(): Observable<UrlTree> {\n const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;\n // TODO(atscott): creating a new segment removes the _sourceSegment _segmentIndexShift, which is\n // only necessary to prevent failures in tests which assert exact object matches. The `split` is\n // now shared between `applyRedirects` and `recognize` but only the `recognize` step needs these\n // properties. Before the implementations were merged, the `applyRedirects` would not assign\n // them. We should be able to remove this logic as a \"breaking change\" but should do some more\n // investigation into the failures first.\n const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children);\n\n const expanded$ =\n this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);\n const urlTrees$ = expanded$.pipe(map((rootSegmentGroup: UrlSegmentGroup) => {\n return this.createUrlTree(\n squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment);\n }));\n return urlTrees$.pipe(catchError((e: any) => {\n if (e instanceof AbsoluteRedirect) {\n // After an absolute redirect we do not apply any more redirects!\n // If this implementation changes, update the documentation note in `redirectTo`.\n this.allowRedirects = false;\n // we need to run matching, so we can fetch all lazy-loaded modules\n return this.match(e.urlTree);\n }\n\n if (e instanceof NoMatch) {\n throw this.noMatchError(e);\n }\n\n throw e;\n }));\n }\n\n private match(tree: UrlTree): Observable<UrlTree> {\n const expanded$ =\n this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET);\n const mapped$ = expanded$.pipe(map((rootSegmentGroup: UrlSegmentGroup) => {\n return this.createUrlTree(\n squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment);\n }));\n return mapped$.pipe(catchError((e: any): Observable<UrlTree> => {\n if (e instanceof NoMatch) {\n throw this.noMatchError(e);\n }\n\n throw e;\n }));\n }\n\n private noMatchError(e: NoMatch): any {\n return new RuntimeError(\n RuntimeErrorCode.NO_MATCH,\n NG_DEV_MODE && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`);\n }\n\n private createUrlTree(rootCandidate: UrlSegmentGroup, queryParams: Params, fragment: string|null):\n UrlTree {\n const root = createRoot(rootCandidate);\n return new UrlTree(root, queryParams, fragment);\n }\n\n private expandSegmentGroup(\n injector: EnvironmentInjector, routes: Route[], segmentGroup: UrlSegmentGroup,\n outlet: string): Observable<UrlSegmentGroup> {\n if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {\n return this.expandChildren(injector, routes, segmentGroup)\n .pipe(map((children: any) => new UrlSegmentGroup([], children)));\n }\n\n return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true);\n }\n\n // Recursively expand segment groups for all the child outlets\n private expandChildren(\n injector: EnvironmentInjector, routes: Route[],\n segmentGroup: UrlSegmentGroup): Observable<{[name: string]: UrlSegmentGroup}> {\n // Expand outlets one at a time, starting with the primary outlet. We need to do it this way\n // because an absolute redirect from the primary outlet takes precedence.\n const childOutlets: string[] = [];\n for (const child of Object.keys(segmentGroup.children)) {\n if (child === 'primary') {\n childOutlets.unshift(child);\n } else {\n childOutlets.push(child);\n }\n }\n\n return from(childOutlets)\n .pipe(\n concatMap(childOutlet => {\n const child = segmentGroup.children[childOutlet];\n // Sort the routes so routes with outlets that match the segment appear\n // first, followed by routes for other outlets, which might match if they have an\n // empty path.\n const sortedRoutes = sortByMatchingOutlets(routes, childOutlet);\n return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet)\n .pipe(map(s => ({segment: s, outlet: childOutlet})));\n }),\n scan(\n (children, expandedChild) => {\n children[expandedChild.outlet] = expandedChild.segment;\n return children;\n },\n {} as {[outlet: string]: UrlSegmentGroup}),\n last(),\n );\n }\n\n private expandSegment(\n injector: EnvironmentInjector, segmentGroup: UrlSegmentGroup, routes: Route[],\n segments: UrlSegment[], outlet: string,\n allowRedirects: boolean): Observable<UrlSegmentGroup> {\n return from(routes).pipe(\n concatMap(r => {\n const expanded$ = this.expandSegmentAgainstRoute(\n injector, segmentGroup, routes, r, segments, outlet, allowRedirects);\n return expanded$.pipe(catchError((e: any) => {\n if (e instanceof NoMatch) {\n return of(null);\n }\n throw e;\n }));\n }),\n first((s): s is UrlSegmentGroup => !!s), catchError((e: any, _: any) => {\n if (isEmptyError(e)) {\n if (noLeftoversInUrl(segmentGroup, segments, outlet)) {\n return of(new UrlSegmentGroup([], {}));\n }\n return noMatch(segmentGroup);\n }\n throw e;\n }));\n }\n\n private expandSegmentAgainstRoute(\n injector: EnvironmentInjector, segmentGroup: UrlSegmentGroup, routes: Route[], route: Route,\n paths: UrlSegment[], outlet: string, allowRedirects: boolean): Observable<UrlSegmentGroup> {\n if (!isImmediateMatch(route, segmentGroup, paths, outlet)) {\n return noMatch(segmentGroup);\n }\n\n if (route.redirectTo === undefined) {\n return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet);\n }\n\n if (allowRedirects && this.allowRedirects) {\n return this.expandSegmentAgainstRouteUsingRedirect(\n injector, segmentGroup, routes, route, paths, outlet);\n }\n\n return noMatch(segmentGroup);\n }\n\n private expandSegmentAgainstRouteUsingRedirect(\n injector: EnvironmentInjector, segmentGroup: UrlSegmentGroup, routes: Route[], route: Route,\n segments: UrlSegment[], outlet: string): Observable<UrlSegmentGroup> {\n if (route.path === '**') {\n return this.expandWildCardWithParamsAgainstRouteUsingRedirect(\n injector, routes, route, outlet);\n }\n\n return this.expandRegularSegmentAgainstRouteUsingRedirect(\n injector, segmentGroup, routes, route, segments, outlet);\n }\n\n private expandWildCardWithParamsAgainstRouteUsingRedirect(\n injector: EnvironmentInjector, routes: Route[], route: Route,\n outlet: string): Observable<UrlSegmentGroup> {\n const newTree = this.applyRedirectCommands([], route.redirectTo!, {});\n if (route.redirectTo!.startsWith('/')) {\n return absoluteRedirect(newTree);\n }\n\n return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments: UrlSegment[]) => {\n const group = new UrlSegmentGroup(newSegments, {});\n return this.expandSegment(injector, group, routes, newSegments, outlet, false);\n }));\n }\n\n private expandRegularSegmentAgainstRouteUsingRedirect(\n injector: EnvironmentInjector, segmentGroup: UrlSegmentGroup, routes: Route[], route: Route,\n segments: UrlSegment[], outlet: string): Observable<UrlSegmentGroup> {\n const {matched, consumedSegments, remainingSegments, positionalParamSegments} =\n match(segmentGroup, route, segments);\n if (!matched) return noMatch(segmentGroup);\n\n const newTree =\n this.applyRedirectCommands(consumedSegments, route.redirectTo!, positionalParamSegments);\n if (route.redirectTo!.startsWith('/')) {\n return absoluteRedirect(newTree);\n }\n\n return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments: UrlSegment[]) => {\n return this.expandSegment(\n injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false);\n }));\n }\n\n private matchSegmentAgainstRoute(\n injector: EnvironmentInjector, rawSegmentGroup: UrlSegmentGroup, route: Route,\n segments: UrlSegment[], outlet: string): Observable<UrlSegmentGroup> {\n if (route.path === '**') {\n // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation\n injector = getOrCreateRouteInjectorIfNeeded(route, injector);\n if (route.loadChildren) {\n const loaded$ = route._loadedRoutes ?\n of({routes: route._loadedRoutes, injector: route._loadedInjector}) :\n this.configLoader.loadChildren(injector, route);\n return loaded$.pipe(map((cfg: LoadedRouterConfig) => {\n route._loadedRoutes = cfg.routes;\n route._loadedInjector = cfg.injector;\n return new UrlSegmentGroup(segments, {});\n }));\n }\n\n return of(new UrlSegmentGroup(segments, {}));\n }\n\n return matchWithChecks(rawSegmentGroup, route, segments, injector, this.urlSerializer)\n .pipe(\n switchMap(({matched, consumedSegments, remainingSegments}) => {\n if (!matched) return noMatch(rawSegmentGroup);\n\n // If the route has an injector created from providers, we should start using that.\n injector = route._injector ?? injector;\n const childConfig$ = this.getChildConfig(injector, route, segments);\n\n return childConfig$.pipe(mergeMap((routerConfig: LoadedRouterConfig) => {\n const childInjector = routerConfig.injector ?? injector;\n const childConfig = routerConfig.routes;\n\n const {segmentGroup: splitSegmentGroup, slicedSegments} =\n split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig);\n // See comment on the other call to `split` about why this is necessary.\n const segmentGroup =\n new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children);\n\n if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {\n const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup);\n return expanded$.pipe(\n map((children: any) => new UrlSegmentGroup(consumedSegments, children)));\n }\n\n if (childConfig.length === 0 && slicedSegments.length === 0) {\n return of(new UrlSegmentGroup(consumedSegments, {}));\n }\n\n const matchedOnOutlet = getOutlet(route) === outlet;\n const expanded$ = this.expandSegment(\n childInjector, segmentGroup, childConfig, slicedSegments,\n matchedOnOutlet ? PRIMARY_OUTLET : outlet, true);\n return expanded$.pipe(\n map((cs: UrlSegmentGroup) => new UrlSegmentGroup(\n consumedSegments.concat(cs.segments), cs.children)));\n }));\n }),\n );\n }\n\n private getChildConfig(injector: EnvironmentInjector, route: Route, segments: UrlSegment[]):\n Observable<LoadedRouterConfig> {\n if (route.children) {\n // The children belong to the same module\n return of({routes: route.children, injector});\n }\n\n if (route.loadChildren) {\n // lazy children belong to the loaded module\n if (route._loadedRoutes !== undefined) {\n return of({routes: route._loadedRoutes, injector: route._loadedInjector});\n }\n\n return runCanLoadGuards(injector, route, segments, this.urlSerializer)\n .pipe(mergeMap((shouldLoadResult: boolean) => {\n if (shouldLoadResult) {\n return this.configLoader.loadChildren(injector, route)\n .pipe(tap((cfg: LoadedRouterConfig) => {\n route._loadedRoutes = cfg.routes;\n route._loadedInjector = cfg.injector;\n }));\n }\n return canLoadFails(route);\n }));\n }\n\n return of({routes: [], injector});\n }\n\n private lineralizeSegments(route: Route, urlTree: UrlTree): Observable<UrlSegment[]> {\n let res: UrlSegment[] = [];\n let c = urlTree.root;\n while (true) {\n res = res.concat(c.segments);\n if (c.numberOfChildren === 0) {\n return of(res);\n }\n\n if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {\n return namedOutletsRedirect(route.redirectTo!);\n }\n\n c = c.children[PRIMARY_OUTLET];\n }\n }\n\n private applyRedirectCommands(\n segments: UrlSegment[], redirectTo: string, posParams: {[k: string]: UrlSegment}): UrlTree {\n return this.applyRedirectCreateUrlTree(\n redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);\n }\n\n private applyRedirectCreateUrlTree(\n redirectTo: string, urlTree: UrlTree, segments: UrlSegment[],\n posParams: {[k: string]: UrlSegment}): UrlTree {\n const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);\n return new UrlTree(\n newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams),\n urlTree.fragment);\n }\n\n private createQueryParams(redirectToParams: Params, actualParams: Params): Params {\n const res: Params = {};\n forEach(redirectToParams, (v: any, k: string) => {\n const copySourceValue = typeof v === 'string' && v.startsWith(':');\n if (copySourceValue) {\n const sourceName = v.substring(1);\n res[k] = actualParams[sourceName];\n } else {\n res[k] = v;\n }\n });\n return res;\n }\n\n private createSegmentGroup(\n redirectTo: string, group: UrlSegmentGroup, segments: UrlSegment[],\n posParams: {[k: string]: UrlSegment}): UrlSegmentGroup {\n const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);\n\n let children: {[n: string]: UrlSegmentGroup} = {};\n forEach(group.children, (child: UrlSegmentGroup, name: string) => {\n children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);\n });\n\n return new UrlSegmentGroup(updatedSegments, children);\n }\n\n private createSegments(\n redirectTo: string, redirectToSegments: UrlSegment[], actualSegments: UrlSegment[],\n posParams: {[k: string]: UrlSegment}): UrlSegment[] {\n return redirectToSegments.map(\n s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) :\n this.findOrReturn(s, actualSegments));\n }\n\n private findPosParam(\n redirectTo: string, redirectToUrlSegment: UrlSegment,\n posParams: {[k: string]: UrlSegment}): UrlSegment {\n const pos = posParams[redirectToUrlSegment.path.substring(1)];\n if (!pos)\n throw new RuntimeError(\n RuntimeErrorCode.MISSING_REDIRECT,\n NG_DEV_MODE &&\n `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);\n return pos;\n }\n\n private findOrReturn(redirectToUrlSegment: UrlSegment, actualSegments: UrlSegment[]): UrlSegment {\n let idx = 0;\n for (const s of actualSegments) {\n if (s.path === redirectToUrlSegment.path) {\n actualSegments.splice(idx);\n return s;\n }\n idx++;\n }\n return redirectToUrlSegment;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, Type, ɵRuntimeError as RuntimeError} from '@angular/core';\nimport {EmptyError, from, Observable, Observer, of} from 'rxjs';\nimport {catchError, concatMap, defaultIfEmpty, first, last as rxjsLast, map, scan, switchMap, takeWhile} from 'rxjs/operators';\n\nimport {RuntimeErrorCode} from './errors';\nimport {Data, ResolveData, Route, Routes} from './models';\nimport {ActivatedRouteSnapshot, inheritedParamsDataResolve, ParamsInheritanceStrategy, RouterStateSnapshot} from './router_state';\nimport {PRIMARY_OUTLET} from './shared';\nimport {UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree} from './url_tree';\nimport {last} from './utils/collection';\nimport {getOutlet, sortByMatchingOutlets} from './utils/config';\nimport {isImmediateMatch, matchWithChecks, noLeftoversInUrl, split} from './utils/config_matching';\nimport {TreeNode} from './utils/tree';\nimport {isEmptyError} from './utils/type_guards';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\nclass NoMatch {}\n\nfunction newObservableError(e: unknown): Observable<RouterStateSnapshot> {\n // TODO(atscott): This pattern is used throughout the router code and can be `throwError` instead.\n return new Observable<RouterStateSnapshot>((obs: Observer<RouterStateSnapshot>) => obs.error(e));\n}\n\nexport function recognize(\n injector: EnvironmentInjector, rootComponentType: Type<any>|null, config: Routes,\n urlTree: UrlTree, url: string, urlSerializer: UrlSerializer,\n paramsInheritanceStrategy: ParamsInheritanceStrategy =\n 'emptyOnly'): Observable<RouterStateSnapshot> {\n return new Recognizer(\n injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy,\n urlSerializer)\n .recognize()\n .pipe(switchMap(result => {\n if (result === null) {\n return newObservableError(new NoMatch());\n } else {\n return of(result);\n }\n }));\n}\n\nexport class Recognizer {\n constructor(\n private injector: EnvironmentInjector, private rootComponentType: Type<any>|null,\n private config: Routes, private urlTree: UrlTree, private url: string,\n private paramsInheritanceStrategy: ParamsInheritanceStrategy,\n private readonly urlSerializer: UrlSerializer) {}\n\n recognize(): Observable<RouterStateSnapshot|null> {\n const rootSegmentGroup =\n split(this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined))\n .segmentGroup;\n\n return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET)\n .pipe(map(children => {\n if (children === null) {\n return null;\n }\n\n // Use Object.freeze to prevent readers of the Router state from modifying it outside of a\n // navigation, resulting in the router being out of sync with the browser.\n const root = new ActivatedRouteSnapshot(\n [], Object.freeze({}), Object.freeze({...this.urlTree.queryParams}),\n this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null,\n this.urlTree.root, -1, {});\n\n const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children);\n const routeState = new RouterStateSnapshot(this.url, rootNode);\n this.inheritParamsAndData(routeState._root);\n return routeState;\n }));\n }\n\n inheritParamsAndData(routeNode: TreeNode<ActivatedRouteSnapshot>): void {\n const route = routeNode.value;\n\n const i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy);\n route.params = Object.freeze(i.params);\n route.data = Object.freeze(i.data);\n\n routeNode.children.forEach(n => this.inheritParamsAndData(n));\n }\n\n processSegmentGroup(\n injector: EnvironmentInjector, config: Route[], segmentGroup: UrlSegmentGroup,\n outlet: string): Observable<TreeNode<ActivatedRouteSnapshot>[]|null> {\n if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {\n return this.processChildren(injector, config, segmentGroup);\n }\n\n return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet);\n }\n\n /**\n * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if\n * we cannot find a match for _any_ of the children.\n *\n * @param config - The `Routes` to match against\n * @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the\n * config.\n */\n processChildren(injector: EnvironmentInjector, config: Route[], segmentGroup: UrlSegmentGroup):\n Observable<TreeNode<ActivatedRouteSnapshot>[]|null> {\n return from(Object.keys(segmentGroup.children))\n .pipe(\n concatMap(childOutlet => {\n const child = segmentGroup.children[childOutlet];\n // Sort the config so that routes with outlets that match the one being activated\n // appear first, followed by routes for other outlets, which might match if they have\n // an empty path.\n const sortedConfig = sortByMatchingOutlets(config, childOutlet);\n return this.processSegmentGroup(injector, sortedConfig, child, childOutlet);\n }),\n scan((children, outletChildren) => {\n if (!children || !outletChildren) return null;\n children.push(...outletChildren);\n return children;\n }),\n takeWhile(children => children !== null),\n defaultIfEmpty(null as TreeNode<ActivatedRouteSnapshot>[] | null),\n rxjsLast(),\n map(children => {\n if (children === null) return null;\n // Because we may have matched two outlets to the same empty path segment, we can have\n // multiple activated results for the same outlet. We should merge the children of\n // these results so the final return value is only one `TreeNode` per outlet.\n const mergedChildren = mergeEmptyPathMatches(children);\n if (NG_DEV_MODE) {\n // This should really never happen - we are only taking the first match for each\n // outlet and merge the empty path matches.\n checkOutletNameUniqueness(mergedChildren);\n }\n sortActivatedRouteSnapshots(mergedChildren);\n return mergedChildren;\n }),\n );\n }\n\n processSegment(\n injector: EnvironmentInjector, routes: Route[], segmentGroup: UrlSegmentGroup,\n segments: UrlSegment[], outlet: string): Observable<TreeNode<ActivatedRouteSnapshot>[]|null> {\n return from(routes).pipe(\n concatMap(r => {\n return this.processSegmentAgainstRoute(\n r._injector ?? injector, r, segmentGroup, segments, outlet);\n }),\n first((x): x is TreeNode<ActivatedRouteSnapshot>[] => !!x), catchError(e => {\n if (isEmptyError(e)) {\n if (noLeftoversInUrl(segmentGroup, segments, outlet)) {\n return of([]);\n }\n return of(null);\n }\n throw e;\n }));\n }\n\n processSegmentAgainstRoute(\n injector: EnvironmentInjector, route: Route, rawSegment: UrlSegmentGroup,\n segments: UrlSegment[], outlet: string): Observable<TreeNode<ActivatedRouteSnapshot>[]|null> {\n if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet)) return of(null);\n\n let matchResult: Observable<{\n snapshot: ActivatedRouteSnapshot,\n consumedSegments: UrlSegment[],\n remainingSegments: UrlSegment[],\n }|null>;\n\n if (route.path === '**') {\n const params = segments.length > 0 ? last(segments)!.parameters : {};\n const pathIndexShift = getPathIndexShift(rawSegment) + segments.length;\n const snapshot = new ActivatedRouteSnapshot(\n segments, params, Object.freeze({...this.urlTree.queryParams}), this.urlTree.fragment,\n getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null,\n route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route));\n matchResult = of({\n snapshot,\n consumedSegments: [],\n remainingSegments: [],\n });\n } else {\n matchResult =\n matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer)\n .pipe(map(({matched, consumedSegments, remainingSegments, parameters}) => {\n if (!matched) {\n return null;\n }\n const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length;\n\n const snapshot = new ActivatedRouteSnapshot(\n consumedSegments, parameters, Object.freeze({...this.urlTree.queryParams}),\n this.urlTree.fragment, getData(route), getOutlet(route),\n route.component ?? route._loadedComponent ?? null, route,\n getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route));\n return {snapshot, consumedSegments, remainingSegments};\n }));\n }\n\n return matchResult.pipe(switchMap((result) => {\n if (result === null) {\n return of(null);\n }\n const {snapshot, consumedSegments, remainingSegments} = result;\n // If the route has an injector created from providers, we should start using that.\n injector = route._injector ?? injector;\n const childInjector = route._loadedInjector ?? injector;\n const childConfig: Route[] = getChildConfig(route);\n\n const {segmentGroup, slicedSegments} = split(\n rawSegment, consumedSegments, remainingSegments,\n // Filter out routes with redirectTo because we are trying to create activated route\n // snapshots and don't handle redirects here. That should have been done in\n // `applyRedirects`.\n childConfig.filter(c => c.redirectTo === undefined));\n\n if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {\n return this.processChildren(childInjector, childConfig, segmentGroup).pipe(map(children => {\n if (children === null) {\n return null;\n }\n return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];\n }));\n }\n\n if (childConfig.length === 0 && slicedSegments.length === 0) {\n return of([new TreeNode<ActivatedRouteSnapshot>(snapshot, [])]);\n }\n\n const matchedOnOutlet = getOutlet(route) === outlet;\n // If we matched a config due to empty path match on a different outlet, we need to\n // continue passing the current outlet for the segment rather than switch to PRIMARY.\n // Note that we switch to primary when we have a match because outlet configs look like\n // this: {path: 'a', outlet: 'a', children: [\n // {path: 'b', component: B},\n // {path: 'c', component: C},\n // ]}\n // Notice that the children of the named outlet are configured with the primary outlet\n return this\n .processSegment(\n childInjector, childConfig, segmentGroup, slicedSegments,\n matchedOnOutlet ? PRIMARY_OUTLET : outlet)\n .pipe(map(children => {\n if (children === null) {\n return null;\n }\n return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];\n }));\n }));\n }\n}\n\nfunction sortActivatedRouteSnapshots(nodes: TreeNode<ActivatedRouteSnapshot>[]): void {\n nodes.sort((a, b) => {\n if (a.value.outlet === PRIMARY_OUTLET) return -1;\n if (b.value.outlet === PRIMARY_OUTLET) return 1;\n return a.value.outlet.localeCompare(b.value.outlet);\n });\n}\n\nfunction getChildConfig(route: Route): Route[] {\n if (route.children) {\n return route.children;\n }\n\n if (route.loadChildren) {\n return route._loadedRoutes!;\n }\n\n return [];\n}\n\nfunction hasEmptyPathConfig(node: TreeNode<ActivatedRouteSnapshot>) {\n const config = node.value.routeConfig;\n return config && config.path === '' && config.redirectTo === undefined;\n}\n\n/**\n * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with\n * the children from each duplicate. This is necessary because different outlets can match a\n * single empty path route config and the results need to then be merged.\n */\nfunction mergeEmptyPathMatches(nodes: Array<TreeNode<ActivatedRouteSnapshot>>):\n Array<TreeNode<ActivatedRouteSnapshot>> {\n const result: Array<TreeNode<ActivatedRouteSnapshot>> = [];\n // The set of nodes which contain children that were merged from two duplicate empty path nodes.\n const mergedNodes: Set<TreeNode<ActivatedRouteSnapshot>> = new Set();\n\n for (const node of nodes) {\n if (!hasEmptyPathConfig(node)) {\n result.push(node);\n continue;\n }\n\n const duplicateEmptyPathNode =\n result.find(resultNode => node.value.routeConfig === resultNode.value.routeConfig);\n if (duplicateEmptyPathNode !== undefined) {\n duplicateEmptyPathNode.children.push(...node.children);\n mergedNodes.add(duplicateEmptyPathNode);\n } else {\n result.push(node);\n }\n }\n // For each node which has children from multiple sources, we need to recompute a new `TreeNode`\n // by also merging those children. This is necessary when there are multiple empty path configs\n // in a row. Put another way: whenever we combine children of two nodes, we need to also check\n // if any of those children can be combined into a single node as well.\n for (const mergedNode of mergedNodes) {\n const mergedChildren = mergeEmptyPathMatches(mergedNode.children);\n result.push(new TreeNode(mergedNode.value, mergedChildren));\n }\n return result.filter(n => !mergedNodes.has(n));\n}\n\nfunction checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): void {\n const names: {[k: string]: ActivatedRouteSnapshot} = {};\n nodes.forEach(n => {\n const routeWithSameOutletName = names[n.value.outlet];\n if (routeWithSameOutletName) {\n const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');\n const c = n.value.url.map(s => s.toString()).join('/');\n throw new RuntimeError(\n RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET,\n NG_DEV_MODE && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);\n }\n names[n.value.outlet] = n.value;\n });\n}\n\nfunction getSourceSegmentGroup(segmentGroup: UrlSegmentGroup): UrlSegmentGroup {\n let s = segmentGroup;\n while (s._sourceSegment) {\n s = s._sourceSegment;\n }\n return s;\n}\n\nfunction getPathIndexShift(segmentGroup: UrlSegmentGroup): number {\n let s = segmentGroup;\n let res = s._segmentIndexShift ?? 0;\n while (s._sourceSegment) {\n s = s._sourceSegment;\n res += s._segmentIndexShift ?? 0;\n }\n return res - 1;\n}\n\nfunction getCorrectedPathIndexShift(segmentGroup: UrlSegmentGroup): number {\n let s = segmentGroup;\n let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;\n while (s._sourceSegment) {\n s = s._sourceSegment;\n res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0;\n }\n return res - 1;\n}\n\nfunction getData(route: Route): Data {\n return route.data || {};\n}\n\nfunction getResolve(route: Route): ResolveData {\n return route.resolve || {};\n}\n","import { OperatorFunction, MonoTypeOperatorFunction, TruthyTypesOf } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\nexport function takeWhile<T>(predicate: BooleanConstructor, inclusive: true): MonoTypeOperatorFunction<T>;\nexport function takeWhile<T>(predicate: BooleanConstructor, inclusive: false): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function takeWhile<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function takeWhile<T, S extends T>(predicate: (value: T, index: number) => value is S): OperatorFunction<T, S>;\nexport function takeWhile<T, S extends T>(predicate: (value: T, index: number) => value is S, inclusive: false): OperatorFunction<T, S>;\nexport function takeWhile<T>(predicate: (value: T, index: number) => boolean, inclusive?: boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Emits values emitted by the source Observable so long as each value satisfies\n * the given `predicate`, and then completes as soon as this `predicate` is not\n * satisfied.\n *\n * <span class=\"informal\">Takes values from the source only while they pass the\n * condition given. When the first value does not satisfy, it completes.</span>\n *\n * ![](takeWhile.png)\n *\n * `takeWhile` subscribes and begins mirroring the source Observable. Each value\n * emitted on the source is given to the `predicate` function which returns a\n * boolean, representing a condition to be satisfied by the source values. The\n * output Observable emits the source values until such time as the `predicate`\n * returns false, at which point `takeWhile` stops mirroring the source\n * Observable and completes the output Observable.\n *\n * ## Example\n *\n * Emit click events only while the clientX property is greater than 200\n *\n * ```ts\n * import { fromEvent, takeWhile } from 'rxjs';\n *\n * const clicks = fromEvent<PointerEvent>(document, 'click');\n * const result = clicks.pipe(takeWhile(ev => ev.clientX > 200));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeLast}\n * @see {@link takeUntil}\n * @see {@link skip}\n *\n * @param {function(value: T, index: number): boolean} predicate A function that\n * evaluates a value emitted by the source Observable and returns a boolean.\n * Also takes the (zero-based) index as the second argument.\n * @param {boolean} inclusive When set to `true` the value that caused\n * `predicate` to return `false` will also be emitted.\n * @return A function that returns an Observable that emits values from the\n * source Observable so long as each value satisfies the condition defined by\n * the `predicate`, then completes.\n */\nexport function takeWhile<T>(predicate: (value: T, index: number) => boolean, inclusive = false): MonoTypeOperatorFunction<T> {\n return operate((source, subscriber) => {\n let index = 0;\n source.subscribe(\n createOperatorSubscriber(subscriber, (value) => {\n const result = predicate(value, index++);\n (result || inclusive) && subscriber.next(value);\n !result && subscriber.complete();\n })\n );\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, ProviderToken} from '@angular/core';\nimport {EMPTY, from, MonoTypeOperatorFunction, Observable, of, throwError} from 'rxjs';\nimport {catchError, concatMap, first, map, mapTo, mergeMap, takeLast, tap} from 'rxjs/operators';\n\nimport {ResolveData, Route} from '../models';\nimport {NavigationTransition} from '../navigation_transition';\nimport {ActivatedRouteSnapshot, inheritedParamsDataResolve, RouterStateSnapshot} from '../router_state';\nimport {RouteTitleKey} from '../shared';\nimport {wrapIntoObservable} from '../utils/collection';\nimport {getClosestRouteInjector} from '../utils/config';\nimport {getTokenOrFunctionIdentity} from '../utils/preactivation';\nimport {isEmptyError} from '../utils/type_guards';\n\nexport function resolveData(\n paramsInheritanceStrategy: 'emptyOnly'|'always',\n injector: EnvironmentInjector): MonoTypeOperatorFunction<NavigationTransition> {\n return mergeMap(t => {\n const {targetSnapshot, guards: {canActivateChecks}} = t;\n\n if (!canActivateChecks.length) {\n return of(t);\n }\n let canActivateChecksResolved = 0;\n return from(canActivateChecks)\n .pipe(\n concatMap(\n check =>\n runResolve(check.route, targetSnapshot!, paramsInheritanceStrategy, injector)),\n tap(() => canActivateChecksResolved++),\n takeLast(1),\n mergeMap(_ => canActivateChecksResolved === canActivateChecks.length ? of(t) : EMPTY),\n );\n });\n}\n\nfunction runResolve(\n futureARS: ActivatedRouteSnapshot, futureRSS: RouterStateSnapshot,\n paramsInheritanceStrategy: 'emptyOnly'|'always', injector: EnvironmentInjector) {\n const config = futureARS.routeConfig;\n const resolve = futureARS._resolve;\n if (config?.title !== undefined && !hasStaticTitle(config)) {\n resolve[RouteTitleKey] = config.title;\n }\n return resolveNode(resolve, futureARS, futureRSS, injector).pipe(map((resolvedData: any) => {\n futureARS._resolvedData = resolvedData;\n futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve;\n if (config && hasStaticTitle(config)) {\n futureARS.data[RouteTitleKey] = config.title;\n }\n return null;\n }));\n}\n\nfunction resolveNode(\n resolve: ResolveData, futureARS: ActivatedRouteSnapshot, futureRSS: RouterStateSnapshot,\n injector: EnvironmentInjector): Observable<any> {\n const keys = getDataKeys(resolve);\n if (keys.length === 0) {\n return of({});\n }\n const data: {[k: string|symbol]: any} = {};\n return from(keys).pipe(\n mergeMap(\n key => getResolver(resolve[key], futureARS, futureRSS, injector)\n .pipe(first(), tap((value: any) => {\n data[key] = value;\n }))),\n takeLast(1),\n mapTo(data),\n catchError((e: unknown) => isEmptyError(e as Error) ? EMPTY : throwError(e)),\n );\n}\n\nfunction getDataKeys(obj: Object): Array<string|symbol> {\n return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];\n}\n\nfunction getResolver(\n injectionToken: ProviderToken<any>|Function, futureARS: ActivatedRouteSnapshot,\n futureRSS: RouterStateSnapshot, injector: EnvironmentInjector): Observable<any> {\n const closestInjector = getClosestRouteInjector(futureARS) ?? injector;\n const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);\n const resolverValue = resolver.resolve ?\n resolver.resolve(futureARS, futureRSS) :\n closestInjector.runInContext(() => resolver(futureARS, futureRSS));\n return wrapIntoObservable(resolverValue);\n}\n\nfunction hasStaticTitle(config: Route) {\n return typeof config.title === 'string' || config.title === null;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {from, MonoTypeOperatorFunction, ObservableInput, of} from 'rxjs';\nimport {map, switchMap} from 'rxjs/operators';\n\n/**\n * Perform a side effect through a switchMap for every emission on the source Observable,\n * but return an Observable that is identical to the source. It's essentially the same as\n * the `tap` operator, but if the side effectful `next` function returns an ObservableInput,\n * it will wait before continuing with the original value.\n */\nexport function switchTap<T>(next: (x: T) => void|ObservableInput<any>):\n MonoTypeOperatorFunction<T> {\n return switchMap(v => {\n const nextResult = next(v);\n if (nextResult) {\n return from(nextResult).pipe(map(() => v));\n }\n return of(v);\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Compiler, EnvironmentInjector, inject, Injectable, InjectFlags, InjectionToken, Injector, NgModuleFactory, Type} from '@angular/core';\nimport {ConnectableObservable, from, Observable, of, Subject} from 'rxjs';\nimport {catchError, finalize, map, mergeMap, refCount, tap} from 'rxjs/operators';\n\nimport {DefaultExport, LoadChildren, LoadChildrenCallback, LoadedRouterConfig, Route, Routes} from './models';\nimport {flatten, wrapIntoObservable} from './utils/collection';\nimport {assertStandalone, standardizeConfig, validateConfig} from './utils/config';\n\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * The [DI token](guide/glossary/#di-token) for a router configuration.\n *\n * `ROUTES` is a low level API for router configuration via dependency injection.\n *\n * We recommend that in almost all cases to use higher level APIs such as `RouterModule.forRoot()`,\n * `provideRouter`, or `Router.resetConfig()`.\n *\n * @publicApi\n */\nexport const ROUTES = new InjectionToken<Route[][]>('ROUTES');\n\ntype ComponentLoader = Observable<Type<unknown>>;\n\n@Injectable({providedIn: 'root'})\nexport class RouterConfigLoader {\n private componentLoaders = new WeakMap<Route, ComponentLoader>();\n private childrenLoaders = new WeakMap<Route, Observable<LoadedRouterConfig>>();\n onLoadStartListener?: (r: Route) => void;\n onLoadEndListener?: (r: Route) => void;\n private readonly compiler = inject(Compiler);\n\n loadComponent(route: Route): Observable<Type<unknown>> {\n if (this.componentLoaders.get(route)) {\n return this.componentLoaders.get(route)!;\n } else if (route._loadedComponent) {\n return of(route._loadedComponent);\n }\n\n if (this.onLoadStartListener) {\n this.onLoadStartListener(route);\n }\n const loadRunner = wrapIntoObservable(route.loadComponent!())\n .pipe(\n map(maybeUnwrapDefaultExport),\n tap(component => {\n if (this.onLoadEndListener) {\n this.onLoadEndListener(route);\n }\n NG_DEV_MODE && assertStandalone(route.path ?? '', component);\n route._loadedComponent = component;\n }),\n finalize(() => {\n this.componentLoaders.delete(route);\n }),\n );\n // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much\n const loader =\n new ConnectableObservable(loadRunner, () => new Subject<Type<unknown>>()).pipe(refCount());\n this.componentLoaders.set(route, loader);\n return loader;\n }\n\n loadChildren(parentInjector: Injector, route: Route): Observable<LoadedRouterConfig> {\n if (this.childrenLoaders.get(route)) {\n return this.childrenLoaders.get(route)!;\n } else if (route._loadedRoutes) {\n return of({routes: route._loadedRoutes, injector: route._loadedInjector});\n }\n\n if (this.onLoadStartListener) {\n this.onLoadStartListener(route);\n }\n const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren!);\n const loadRunner = moduleFactoryOrRoutes$.pipe(\n map((factoryOrRoutes: NgModuleFactory<any>|Routes) => {\n if (this.onLoadEndListener) {\n this.onLoadEndListener(route);\n }\n // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no\n // injector associated with lazy loading a `Route` array.\n let injector: EnvironmentInjector|undefined;\n let rawRoutes: Route[];\n let requireStandaloneComponents = false;\n if (Array.isArray(factoryOrRoutes)) {\n rawRoutes = factoryOrRoutes;\n requireStandaloneComponents = true;\n } else {\n injector = factoryOrRoutes.create(parentInjector).injector;\n // When loading a module that doesn't provide `RouterModule.forChild()` preloader\n // will get stuck in an infinite loop. The child module's Injector will look to\n // its parent `Injector` when it doesn't find any ROUTES so it will return routes\n // for it's parent module instead.\n rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));\n }\n const routes = rawRoutes.map(standardizeConfig);\n NG_DEV_MODE && validateConfig(routes, route.path, requireStandaloneComponents);\n return {routes, injector};\n }),\n finalize(() => {\n this.childrenLoaders.delete(route);\n }),\n );\n // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much\n const loader = new ConnectableObservable(loadRunner, () => new Subject<LoadedRouterConfig>())\n .pipe(refCount());\n this.childrenLoaders.set(route, loader);\n return loader;\n }\n\n private loadModuleFactoryOrRoutes(loadChildren: LoadChildren):\n Observable<NgModuleFactory<any>|Routes> {\n return wrapIntoObservable((loadChildren as LoadChildrenCallback)())\n .pipe(\n map(maybeUnwrapDefaultExport),\n mergeMap((t) => {\n if (t instanceof NgModuleFactory || Array.isArray(t)) {\n return of(t);\n } else {\n return from(this.compiler.compileModuleAsync(t));\n }\n }),\n );\n }\n}\n\nfunction isWrappedDefaultExport<T>(value: T|DefaultExport<T>): value is DefaultExport<T> {\n // We use `in` here with a string key `'default'`, because we expect `DefaultExport` objects to be\n // dynamically imported ES modules with a spec-mandated `default` key. Thus we don't expect that\n // `default` will be a renamed property.\n return value && typeof value === 'object' && 'default' in value;\n}\n\nfunction maybeUnwrapDefaultExport<T>(input: T|DefaultExport<T>): T {\n // As per `isWrappedDefaultExport`, the `default` key here is generated by the browser and not\n // subject to property renaming, so we reference it with bracket access.\n return isWrappedDefaultExport(input) ? input['default'] : input;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, inject, Injectable, Type} from '@angular/core';\nimport {BehaviorSubject, combineLatest, EMPTY, Observable, of, Subject} from 'rxjs';\nimport {catchError, defaultIfEmpty, filter, finalize, map, switchMap, take, tap} from 'rxjs/operators';\n\nimport {createRouterState} from './create_router_state';\nimport {Event, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTrigger, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized} from './events';\nimport {NavigationBehaviorOptions, QueryParamsHandling, Route, Routes} from './models';\nimport {isNavigationCancelingError, isRedirectingNavigationCancelingError, redirectingNavigationError} from './navigation_canceling_error';\nimport {activateRoutes} from './operators/activate_routes';\nimport {applyRedirects} from './operators/apply_redirects';\nimport {checkGuards} from './operators/check_guards';\nimport {recognize} from './operators/recognize';\nimport {resolveData} from './operators/resolve_data';\nimport {switchTap} from './operators/switch_tap';\nimport {TitleStrategy} from './page_title_strategy';\nimport {RouteReuseStrategy} from './route_reuse_strategy';\nimport {ErrorHandler} from './router_config';\nimport {RouterConfigLoader} from './router_config_loader';\nimport {ChildrenOutletContexts} from './router_outlet_context';\nimport {ActivatedRoute, ActivatedRouteSnapshot, createEmptyState, RouterState, RouterStateSnapshot} from './router_state';\nimport {Params} from './shared';\nimport {UrlHandlingStrategy} from './url_handling_strategy';\nimport {isUrlTree, UrlSerializer, UrlTree} from './url_tree';\nimport {Checks, getAllRouteGuards} from './utils/preactivation';\n\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * @description\n *\n * Options that modify the `Router` URL.\n * Supply an object containing any of these properties to a `Router` navigation function to\n * control how the target URL should be constructed.\n *\n * @see [Router.navigate() method](api/router/Router#navigate)\n * @see [Router.createUrlTree() method](api/router/Router#createurltree)\n * @see [Routing and Navigation guide](guide/router)\n *\n * @publicApi\n */\nexport interface UrlCreationOptions {\n /**\n * Specifies a root URI to use for relative navigation.\n *\n * For example, consider the following route configuration where the parent route\n * has two children.\n *\n * ```\n * [{\n * path: 'parent',\n * component: ParentComponent,\n * children: [{\n * path: 'list',\n * component: ListComponent\n * },{\n * path: 'child',\n * component: ChildComponent\n * }]\n * }]\n * ```\n *\n * The following `go()` function navigates to the `list` route by\n * interpreting the destination URI as relative to the activated `child` route\n *\n * ```\n * @Component({...})\n * class ChildComponent {\n * constructor(private router: Router, private route: ActivatedRoute) {}\n *\n * go() {\n * router.navigate(['../list'], { relativeTo: this.route });\n * }\n * }\n * ```\n *\n * A value of `null` or `undefined` indicates that the navigation commands should be applied\n * relative to the root.\n */\n relativeTo?: ActivatedRoute|null;\n\n /**\n * Sets query parameters to the URL.\n *\n * ```\n * // Navigate to /results?page=1\n * router.navigate(['/results'], { queryParams: { page: 1 } });\n * ```\n */\n queryParams?: Params|null;\n\n /**\n * Sets the hash fragment for the URL.\n *\n * ```\n * // Navigate to /results#top\n * router.navigate(['/results'], { fragment: 'top' });\n * ```\n */\n fragment?: string;\n\n /**\n * How to handle query parameters in the router link for the next navigation.\n * One of:\n * * `preserve` : Preserve current parameters.\n * * `merge` : Merge new with current parameters.\n *\n * The \"preserve\" option discards any new query params:\n * ```\n * // from /view1?page=1 to/view2?page=1\n * router.navigate(['/view2'], { queryParams: { page: 2 }, queryParamsHandling: \"preserve\"\n * });\n * ```\n * The \"merge\" option appends new query params to the params from the current URL:\n * ```\n * // from /view1?page=1 to/view2?page=1&otherKey=2\n * router.navigate(['/view2'], { queryParams: { otherKey: 2 }, queryParamsHandling: \"merge\"\n * });\n * ```\n * In case of a key collision between current parameters and those in the `queryParams` object,\n * the new value is used.\n *\n */\n queryParamsHandling?: QueryParamsHandling|null;\n\n /**\n * When true, preserves the URL fragment for the next navigation\n *\n * ```\n * // Preserve fragment from /results#top to /view#top\n * router.navigate(['/view'], { preserveFragment: true });\n * ```\n */\n preserveFragment?: boolean;\n}\n\n/**\n * @description\n *\n * Options that modify the `Router` navigation strategy.\n * Supply an object containing any of these properties to a `Router` navigation function to\n * control how the target URL should be constructed or interpreted.\n *\n * @see [Router.navigate() method](api/router/Router#navigate)\n * @see [Router.navigateByUrl() method](api/router/Router#navigatebyurl)\n * @see [Router.createUrlTree() method](api/router/Router#createurltree)\n * @see [Routing and Navigation guide](guide/router)\n * @see UrlCreationOptions\n * @see NavigationBehaviorOptions\n *\n * @publicApi\n */\nexport interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {}\n\nexport type RestoredState = {\n [k: string]: any,\n // TODO(#27607): Remove `navigationId` and `ɵrouterPageId` and move to `ng` or `ɵ` namespace.\n navigationId: number,\n // The `ɵ` prefix is there to reduce the chance of colliding with any existing user properties on\n // the history state.\n ɵrouterPageId?: number,\n};\n\n/**\n * Information about a navigation operation.\n * Retrieve the most recent navigation object with the\n * [Router.getCurrentNavigation() method](api/router/Router#getcurrentnavigation) .\n *\n * * *id* : The unique identifier of the current navigation.\n * * *initialUrl* : The target URL passed into the `Router#navigateByUrl()` call before navigation.\n * This is the value before the router has parsed or applied redirects to it.\n * * *extractedUrl* : The initial target URL after being parsed with `UrlSerializer.extract()`.\n * * *finalUrl* : The extracted URL after redirects have been applied.\n * This URL may not be available immediately, therefore this property can be `undefined`.\n * It is guaranteed to be set after the `RoutesRecognized` event fires.\n * * *trigger* : Identifies how this navigation was triggered.\n * -- 'imperative'--Triggered by `router.navigateByUrl` or `router.navigate`.\n * -- 'popstate'--Triggered by a popstate event.\n * -- 'hashchange'--Triggered by a hashchange event.\n * * *extras* : A `NavigationExtras` options object that controlled the strategy used for this\n * navigation.\n * * *previousNavigation* : The previously successful `Navigation` object. Only one previous\n * navigation is available, therefore this previous `Navigation` object has a `null` value for its\n * own `previousNavigation`.\n *\n * @publicApi\n */\nexport interface Navigation {\n /**\n * The unique identifier of the current navigation.\n */\n id: number;\n /**\n * The target URL passed into the `Router#navigateByUrl()` call before navigation. This is\n * the value before the router has parsed or applied redirects to it.\n */\n initialUrl: UrlTree;\n /**\n * The initial target URL after being parsed with `UrlHandlingStrategy.extract()`.\n */\n extractedUrl: UrlTree;\n /**\n * The extracted URL after redirects have been applied.\n * This URL may not be available immediately, therefore this property can be `undefined`.\n * It is guaranteed to be set after the `RoutesRecognized` event fires.\n */\n finalUrl?: UrlTree;\n /**\n * Identifies how this navigation was triggered.\n *\n * * 'imperative'--Triggered by `router.navigateByUrl` or `router.navigate`.\n * * 'popstate'--Triggered by a popstate event.\n * * 'hashchange'--Triggered by a hashchange event.\n */\n trigger: 'imperative'|'popstate'|'hashchange';\n /**\n * Options that controlled the strategy used for this navigation.\n * See `NavigationExtras`.\n */\n extras: NavigationExtras;\n /**\n * The previously successful `Navigation` object. Only one previous navigation\n * is available, therefore this previous `Navigation` object has a `null` value\n * for its own `previousNavigation`.\n */\n previousNavigation: Navigation|null;\n}\n\nexport interface NavigationTransition {\n id: number;\n targetPageId: number;\n currentUrlTree: UrlTree;\n extractedUrl: UrlTree;\n currentRawUrl: UrlTree;\n urlAfterRedirects?: UrlTree;\n rawUrl: UrlTree;\n extras: NavigationExtras;\n resolve: any;\n reject: any;\n promise: Promise<boolean>;\n source: NavigationTrigger;\n restoredState: RestoredState|null;\n currentSnapshot: RouterStateSnapshot;\n targetSnapshot: RouterStateSnapshot|null;\n currentRouterState: RouterState;\n targetRouterState: RouterState|null;\n guards: Checks;\n guardsResult: boolean|UrlTree|null;\n}\n\n/**\n * The interface from the Router needed by the transitions. Used to avoid a circular dependency on\n * Router. This interface should be whittled down with future refactors. For example, we do not need\n * to get `UrlSerializer` from the Router. We can instead inject it in `NavigationTransitions`\n * directly.\n */\ninterface InternalRouterInterface {\n browserUrlTree: UrlTree;\n currentUrlTree: UrlTree;\n rawUrlTree: UrlTree;\n readonly routerState: RouterState;\n errorHandler: ErrorHandler;\n titleStrategy?: TitleStrategy;\n navigated: boolean;\n urlHandlingStrategy: UrlHandlingStrategy;\n routeReuseStrategy: RouteReuseStrategy;\n onSameUrlNavigation: 'reload'|'ignore';\n paramsInheritanceStrategy: 'emptyOnly'|'always';\n urlUpdateStrategy: 'deferred'|'eager';\n serializeUrl(url: UrlTree): string;\n config: Routes;\n setBrowserUrl(url: UrlTree, t: NavigationTransition): void;\n restoreHistory(t: NavigationTransition, restoringFromCaughtError?: boolean): void;\n scheduleNavigation(\n rawUrl: UrlTree, source: NavigationTrigger, restoredState: RestoredState|null,\n extras: NavigationExtras,\n priorPromise?: {resolve: any, reject: any, promise: Promise<boolean>}): Promise<boolean>;\n}\n\n@Injectable({providedIn: 'root'})\nexport class NavigationTransitions {\n currentNavigation: Navigation|null = null;\n lastSuccessfulNavigation: Navigation|null = null;\n readonly events = new Subject<Event>();\n private readonly configLoader = inject(RouterConfigLoader);\n private readonly environmentInjector = inject(EnvironmentInjector);\n private readonly urlSerializer = inject(UrlSerializer);\n private readonly rootContexts = inject(ChildrenOutletContexts);\n navigationId = 0;\n get hasRequestedNavigation() {\n return this.navigationId !== 0;\n }\n private transitions?: BehaviorSubject<NavigationTransition>;\n /**\n * Hook that enables you to pause navigation after the preactivation phase.\n * Used by `RouterModule`.\n *\n * @internal\n */\n afterPreactivation: () => Observable<void> = () => of(void 0);\n /** @internal */\n rootComponentType: Type<any>|null = null;\n\n constructor() {\n const onLoadStart = (r: Route) => this.events.next(new RouteConfigLoadStart(r));\n const onLoadEnd = (r: Route) => this.events.next(new RouteConfigLoadEnd(r));\n this.configLoader.onLoadEndListener = onLoadEnd;\n this.configLoader.onLoadStartListener = onLoadStart;\n }\n\n complete() {\n this.transitions?.complete();\n }\n\n handleNavigationRequest(\n request: Pick<\n NavigationTransition,\n 'targetPageId'|'source'|'restoredState'|'currentUrlTree'|'currentRawUrl'|'rawUrl'|\n 'extras'|'resolve'|'reject'|'promise'|'currentSnapshot'|'currentRouterState'>) {\n const id = ++this.navigationId;\n this.transitions?.next({...this.transitions.value, ...request, id});\n }\n\n setupNavigations(router: InternalRouterInterface): Observable<NavigationTransition> {\n this.transitions = new BehaviorSubject<NavigationTransition>({\n id: 0,\n targetPageId: 0,\n currentUrlTree: router.currentUrlTree,\n currentRawUrl: router.currentUrlTree,\n extractedUrl: router.urlHandlingStrategy.extract(router.currentUrlTree),\n urlAfterRedirects: router.urlHandlingStrategy.extract(router.currentUrlTree),\n rawUrl: router.currentUrlTree,\n extras: {},\n resolve: null,\n reject: null,\n promise: Promise.resolve(true),\n source: IMPERATIVE_NAVIGATION,\n restoredState: null,\n currentSnapshot: router.routerState.snapshot,\n targetSnapshot: null,\n currentRouterState: router.routerState,\n targetRouterState: null,\n guards: {canActivateChecks: [], canDeactivateChecks: []},\n guardsResult: null,\n });\n return this.transitions.pipe(\n filter(t => t.id !== 0),\n\n // Extract URL\n map(t =>\n ({...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl)} as\n NavigationTransition)),\n\n // Using switchMap so we cancel executing navigations when a new one comes in\n switchMap(overallTransitionState => {\n let completed = false;\n let errored = false;\n return of(overallTransitionState)\n .pipe(\n // Store the Navigation object\n tap(t => {\n this.currentNavigation = {\n id: t.id,\n initialUrl: t.rawUrl,\n extractedUrl: t.extractedUrl,\n trigger: t.source,\n extras: t.extras,\n previousNavigation: !this.lastSuccessfulNavigation ? null : {\n ...this.lastSuccessfulNavigation,\n previousNavigation: null,\n },\n };\n }),\n switchMap(t => {\n const browserUrlTree = router.browserUrlTree.toString();\n const urlTransition = !router.navigated ||\n t.extractedUrl.toString() !== browserUrlTree ||\n // Navigations which succeed or ones which fail and are cleaned up\n // correctly should result in `browserUrlTree` and `currentUrlTree`\n // matching. If this is not the case, assume something went wrong and\n // try processing the URL again.\n browserUrlTree !== router.currentUrlTree.toString();\n\n\n const onSameUrlNavigation =\n t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;\n if (!urlTransition && onSameUrlNavigation !== 'reload') {\n const reason = NG_DEV_MODE ?\n `Navigation to ${\n t.rawUrl} was ignored because it is the same as the current Router URL.` :\n '';\n this.events.next(new NavigationSkipped(\n t.id, router.serializeUrl(overallTransitionState.rawUrl), reason,\n NavigationSkippedCode.IgnoredSameUrlNavigation));\n router.rawUrlTree = t.rawUrl;\n t.resolve(null);\n return EMPTY;\n }\n\n if (router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {\n // If the source of the navigation is from a browser event, the URL is\n // already updated. We already need to sync the internal state.\n if (isBrowserTriggeredNavigation(t.source)) {\n router.browserUrlTree = t.extractedUrl;\n }\n return of(t).pipe(\n // Fire NavigationStart event\n switchMap(t => {\n const transition = this.transitions?.getValue();\n this.events.next(new NavigationStart(\n t.id, this.urlSerializer.serialize(t.extractedUrl), t.source,\n t.restoredState));\n if (transition !== this.transitions?.getValue()) {\n return EMPTY;\n }\n\n // This delay is required to match old behavior that forced\n // navigation to always be async\n return Promise.resolve(t);\n }),\n\n // ApplyRedirects\n applyRedirects(\n this.environmentInjector, this.configLoader,\n this.urlSerializer, router.config),\n\n // Update the currentNavigation\n // `urlAfterRedirects` is guaranteed to be set after this point\n tap(t => {\n this.currentNavigation = {\n ...this.currentNavigation!,\n finalUrl: t.urlAfterRedirects\n };\n overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;\n }),\n\n // Recognize\n recognize(\n this.environmentInjector, this.rootComponentType,\n router.config, this.urlSerializer,\n router.paramsInheritanceStrategy),\n\n // Update URL if in `eager` update mode\n tap(t => {\n overallTransitionState.targetSnapshot = t.targetSnapshot;\n if (router.urlUpdateStrategy === 'eager') {\n if (!t.extras.skipLocationChange) {\n const rawUrl = router.urlHandlingStrategy.merge(\n t.urlAfterRedirects!, t.rawUrl);\n router.setBrowserUrl(rawUrl, t);\n }\n router.browserUrlTree = t.urlAfterRedirects!;\n }\n\n // Fire RoutesRecognized\n const routesRecognized = new RoutesRecognized(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(t.urlAfterRedirects!),\n t.targetSnapshot!);\n this.events.next(routesRecognized);\n }));\n } else if (\n urlTransition &&\n router.urlHandlingStrategy.shouldProcessUrl(router.rawUrlTree)) {\n /* When the current URL shouldn't be processed, but the previous one\n * was, we handle this \"error condition\" by navigating to the\n * previously successful URL, but leaving the URL intact.*/\n const {id, extractedUrl, source, restoredState, extras} = t;\n const navStart = new NavigationStart(\n id, this.urlSerializer.serialize(extractedUrl), source,\n restoredState);\n this.events.next(navStart);\n const targetSnapshot =\n createEmptyState(extractedUrl, this.rootComponentType).snapshot;\n\n overallTransitionState = {\n ...t,\n targetSnapshot,\n urlAfterRedirects: extractedUrl,\n extras: {...extras, skipLocationChange: false, replaceUrl: false},\n };\n return of(overallTransitionState);\n } else {\n /* When neither the current or previous URL can be processed, do\n * nothing other than update router's internal reference to the\n * current \"settled\" URL. This way the next navigation will be coming\n * from the current URL in the browser.\n */\n const reason = NG_DEV_MODE ?\n `Navigation was ignored because the UrlHandlingStrategy` +\n ` indicated neither the current URL ${\n router.rawUrlTree} nor target URL ${\n t.rawUrl} should be processed.` :\n '';\n this.events.next(new NavigationSkipped(\n t.id, router.serializeUrl(overallTransitionState.extractedUrl),\n reason, NavigationSkippedCode.IgnoredByUrlHandlingStrategy));\n router.rawUrlTree = t.rawUrl;\n t.resolve(null);\n return EMPTY;\n }\n }),\n\n // --- GUARDS ---\n tap(t => {\n const guardsStart = new GuardsCheckStart(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(t.urlAfterRedirects!),\n t.targetSnapshot!);\n this.events.next(guardsStart);\n }),\n\n map(t => {\n overallTransitionState = {\n ...t,\n guards: getAllRouteGuards(\n t.targetSnapshot!, t.currentSnapshot, this.rootContexts)\n };\n return overallTransitionState;\n }),\n\n checkGuards(\n this.environmentInjector, (evt: Event) => this.events.next(evt)),\n tap(t => {\n overallTransitionState.guardsResult = t.guardsResult;\n if (isUrlTree(t.guardsResult)) {\n throw redirectingNavigationError(this.urlSerializer, t.guardsResult);\n }\n\n const guardsEnd = new GuardsCheckEnd(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(t.urlAfterRedirects!),\n t.targetSnapshot!, !!t.guardsResult);\n this.events.next(guardsEnd);\n }),\n\n filter(t => {\n if (!t.guardsResult) {\n router.restoreHistory(t);\n this.cancelNavigationTransition(\n t, '', NavigationCancellationCode.GuardRejected);\n return false;\n }\n return true;\n }),\n\n // --- RESOLVE ---\n switchTap(t => {\n if (t.guards.canActivateChecks.length) {\n return of(t).pipe(\n tap(t => {\n const resolveStart = new ResolveStart(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(t.urlAfterRedirects!),\n t.targetSnapshot!);\n this.events.next(resolveStart);\n }),\n switchMap(t => {\n let dataResolved = false;\n return of(t).pipe(\n resolveData(\n router.paramsInheritanceStrategy,\n this.environmentInjector),\n tap({\n next: () => dataResolved = true,\n complete: () => {\n if (!dataResolved) {\n router.restoreHistory(t);\n this.cancelNavigationTransition(\n t,\n NG_DEV_MODE ?\n `At least one route resolver didn't emit any value.` :\n '',\n NavigationCancellationCode.NoDataFromResolver);\n }\n }\n }),\n );\n }),\n tap(t => {\n const resolveEnd = new ResolveEnd(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(t.urlAfterRedirects!),\n t.targetSnapshot!);\n this.events.next(resolveEnd);\n }));\n }\n return undefined;\n }),\n\n // --- LOAD COMPONENTS ---\n switchTap((t: NavigationTransition) => {\n const loadComponents =\n (route: ActivatedRouteSnapshot): Array<Observable<void>> => {\n const loaders: Array<Observable<void>> = [];\n if (route.routeConfig?.loadComponent &&\n !route.routeConfig._loadedComponent) {\n loaders.push(this.configLoader.loadComponent(route.routeConfig)\n .pipe(\n tap(loadedComponent => {\n route.component = loadedComponent;\n }),\n map(() => void 0),\n ));\n }\n for (const child of route.children) {\n loaders.push(...loadComponents(child));\n }\n return loaders;\n };\n return combineLatest(loadComponents(t.targetSnapshot!.root))\n .pipe(defaultIfEmpty(), take(1));\n }),\n\n switchTap(() => this.afterPreactivation()),\n\n map((t: NavigationTransition) => {\n const targetRouterState = createRouterState(\n router.routeReuseStrategy, t.targetSnapshot!, t.currentRouterState);\n overallTransitionState = {...t, targetRouterState};\n return (overallTransitionState);\n }),\n\n /* Once here, we are about to activate synchronously. The assumption is\n this will succeed, and user code may read from the Router service.\n Therefore before activation, we need to update router properties storing\n the current URL and the RouterState, as well as updated the browser URL.\n All this should happen *before* activating. */\n tap((t: NavigationTransition) => {\n router.currentUrlTree = t.urlAfterRedirects!;\n router.rawUrlTree =\n router.urlHandlingStrategy.merge(t.urlAfterRedirects!, t.rawUrl);\n\n (router as {routerState: RouterState}).routerState =\n t.targetRouterState!;\n\n if (router.urlUpdateStrategy === 'deferred') {\n if (!t.extras.skipLocationChange) {\n router.setBrowserUrl(router.rawUrlTree, t);\n }\n router.browserUrlTree = t.urlAfterRedirects!;\n }\n }),\n\n activateRoutes(\n this.rootContexts, router.routeReuseStrategy,\n (evt: Event) => this.events.next(evt)),\n\n // Ensure that if some observable used to drive the transition doesn't\n // complete, the navigation still finalizes This should never happen, but\n // this is done as a safety measure to avoid surfacing this error (#49567).\n take(1),\n\n tap({\n next: (t: NavigationTransition) => {\n completed = true;\n this.lastSuccessfulNavigation = this.currentNavigation;\n router.navigated = true;\n this.events.next(new NavigationEnd(\n t.id, this.urlSerializer.serialize(t.extractedUrl),\n this.urlSerializer.serialize(router.currentUrlTree)));\n router.titleStrategy?.updateTitle(t.targetRouterState!.snapshot);\n t.resolve(true);\n },\n complete: () => {\n completed = true;\n }\n }),\n finalize(() => {\n /* When the navigation stream finishes either through error or success,\n * we set the `completed` or `errored` flag. However, there are some\n * situations where we could get here without either of those being set.\n * For instance, a redirect during NavigationStart. Therefore, this is a\n * catch-all to make sure the NavigationCancel event is fired when a\n * navigation gets cancelled but not caught by other means. */\n if (!completed && !errored) {\n const cancelationReason = NG_DEV_MODE ?\n `Navigation ID ${\n overallTransitionState\n .id} is not equal to the current navigation id ${\n this.navigationId}` :\n '';\n this.cancelNavigationTransition(\n overallTransitionState, cancelationReason,\n NavigationCancellationCode.SupersededByNewNavigation);\n }\n // Only clear current navigation if it is still set to the one that\n // finalized.\n if (this.currentNavigation?.id === overallTransitionState.id) {\n this.currentNavigation = null;\n }\n }),\n catchError((e) => {\n errored = true;\n /* This error type is issued during Redirect, and is handled as a\n * cancellation rather than an error. */\n if (isNavigationCancelingError(e)) {\n if (!isRedirectingNavigationCancelingError(e)) {\n // Set property only if we're not redirecting. If we landed on a page\n // and redirect to `/` route, the new navigation is going to see the\n // `/` isn't a change from the default currentUrlTree and won't\n // navigate. This is only applicable with initial navigation, so\n // setting `navigated` only when not redirecting resolves this\n // scenario.\n router.navigated = true;\n router.restoreHistory(overallTransitionState, true);\n }\n const navCancel = new NavigationCancel(\n overallTransitionState.id,\n this.urlSerializer.serialize(overallTransitionState.extractedUrl),\n e.message, e.cancellationCode);\n this.events.next(navCancel);\n\n // When redirecting, we need to delay resolving the navigation\n // promise and push it to the redirect navigation\n if (!isRedirectingNavigationCancelingError(e)) {\n overallTransitionState.resolve(false);\n } else {\n const mergedTree =\n router.urlHandlingStrategy.merge(e.url, router.rawUrlTree);\n const extras = {\n skipLocationChange:\n overallTransitionState.extras.skipLocationChange,\n // The URL is already updated at this point if we have 'eager' URL\n // updates or if the navigation was triggered by the browser (back\n // button, URL bar, etc). We want to replace that item in history\n // if the navigation is rejected.\n replaceUrl: router.urlUpdateStrategy === 'eager' ||\n isBrowserTriggeredNavigation(overallTransitionState.source)\n };\n\n router.scheduleNavigation(\n mergedTree, IMPERATIVE_NAVIGATION, null, extras, {\n resolve: overallTransitionState.resolve,\n reject: overallTransitionState.reject,\n promise: overallTransitionState.promise\n });\n }\n\n /* All other errors should reset to the router's internal URL reference\n * to the pre-error state. */\n } else {\n router.restoreHistory(overallTransitionState, true);\n const navError = new NavigationError(\n overallTransitionState.id,\n this.urlSerializer.serialize(overallTransitionState.extractedUrl),\n e, overallTransitionState.targetSnapshot ?? undefined);\n this.events.next(navError);\n try {\n overallTransitionState.resolve(router.errorHandler(e));\n } catch (ee) {\n overallTransitionState.reject(ee);\n }\n }\n return EMPTY;\n }));\n // casting because `pipe` returns observable({}) when called with 8+ arguments\n })) as Observable<NavigationTransition>;\n }\n\n private cancelNavigationTransition(\n t: NavigationTransition, reason: string, code: NavigationCancellationCode) {\n const navCancel =\n new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);\n this.events.next(navCancel);\n t.resolve(false);\n }\n}\n\nexport function isBrowserTriggeredNavigation(source: NavigationTrigger) {\n return source !== IMPERATIVE_NAVIGATION;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector} from '@angular/core';\nimport {MonoTypeOperatorFunction} from 'rxjs';\nimport {map, switchMap} from 'rxjs/operators';\n\nimport {applyRedirects as applyRedirectsFn} from '../apply_redirects';\nimport {Routes} from '../models';\nimport {NavigationTransition} from '../navigation_transition';\nimport {RouterConfigLoader} from '../router_config_loader';\nimport {UrlSerializer} from '../url_tree';\n\nexport function applyRedirects(\n environmentInjector: EnvironmentInjector, configLoader: RouterConfigLoader,\n urlSerializer: UrlSerializer, config: Routes): MonoTypeOperatorFunction<NavigationTransition> {\n return switchMap(\n t =>\n applyRedirectsFn(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config)\n .pipe(map(urlAfterRedirects => ({...t, urlAfterRedirects}))));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {EnvironmentInjector, Type} from '@angular/core';\nimport {MonoTypeOperatorFunction} from 'rxjs';\nimport {map, mergeMap} from 'rxjs/operators';\n\nimport {Route} from '../models';\nimport {NavigationTransition} from '../navigation_transition';\nimport {recognize as recognizeFn} from '../recognize';\nimport {UrlSerializer} from '../url_tree';\n\nexport function recognize(\n injector: EnvironmentInjector, rootComponentType: Type<any>|null, config: Route[],\n serializer: UrlSerializer, paramsInheritanceStrategy: 'emptyOnly'|'always'):\n MonoTypeOperatorFunction<NavigationTransition> {\n return mergeMap(\n t => recognizeFn(\n injector, rootComponentType, config, t.urlAfterRedirects!,\n serializer.serialize(t.urlAfterRedirects!), serializer, paramsInheritanceStrategy)\n .pipe(map(targetSnapshot => ({...t, targetSnapshot}))));\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {inject, Injectable} from '@angular/core';\nimport {Title} from '@angular/platform-browser';\n\nimport {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state';\nimport {PRIMARY_OUTLET, RouteTitleKey} from './shared';\n\n/**\n * Provides a strategy for setting the page title after a router navigation.\n *\n * The built-in implementation traverses the router state snapshot and finds the deepest primary\n * outlet with `title` property. Given the `Routes` below, navigating to\n * `/base/child(popup:aux)` would result in the document title being set to \"child\".\n * ```\n * [\n * {path: 'base', title: 'base', children: [\n * {path: 'child', title: 'child'},\n * ],\n * {path: 'aux', outlet: 'popup', title: 'popupTitle'}\n * ]\n * ```\n *\n * This class can be used as a base class for custom title strategies. That is, you can create your\n * own class that extends the `TitleStrategy`. Note that in the above example, the `title`\n * from the named outlet is never used. However, a custom strategy might be implemented to\n * incorporate titles in named outlets.\n *\n * @publicApi\n * @see [Page title guide](guide/router#setting-the-page-title)\n */\n@Injectable({providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy)})\nexport abstract class TitleStrategy {\n /** Performs the application title update. */\n abstract updateTitle(snapshot: RouterStateSnapshot): void;\n\n /**\n * @returns The `title` of the deepest primary route.\n */\n buildTitle(snapshot: RouterStateSnapshot): string|undefined {\n let pageTitle: string|undefined;\n let route: ActivatedRouteSnapshot|undefined = snapshot.root;\n while (route !== undefined) {\n pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;\n route = route.children.find(child => child.outlet === PRIMARY_OUTLET);\n }\n return pageTitle;\n }\n\n /**\n * Given an `ActivatedRouteSnapshot`, returns the final value of the\n * `Route.title` property, which can either be a static string or a resolved value.\n */\n getResolvedTitleForRoute(snapshot: ActivatedRouteSnapshot) {\n return snapshot.data[RouteTitleKey];\n }\n}\n\n/**\n * The default `TitleStrategy` used by the router that updates the title using the `Title` service.\n */\n@Injectable({providedIn: 'root'})\nexport class DefaultTitleStrategy extends TitleStrategy {\n constructor(readonly title: Title) {\n super();\n }\n\n /**\n * Sets the title of the browser to the given value.\n *\n * @param title The `pageTitle` from the deepest primary route.\n */\n override updateTitle(snapshot: RouterStateSnapshot): void {\n const title = this.buildTitle(snapshot);\n if (title !== undefined) {\n this.title.setTitle(title);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ComponentRef, inject, Injectable} from '@angular/core';\n\nimport {OutletContext} from './router_outlet_context';\nimport {ActivatedRoute, ActivatedRouteSnapshot} from './router_state';\nimport {TreeNode} from './utils/tree';\n\n/**\n * @description\n *\n * Represents the detached route tree.\n *\n * This is an opaque value the router will give to a custom route reuse strategy\n * to store and retrieve later on.\n *\n * @publicApi\n */\nexport type DetachedRouteHandle = {};\n\n/** @internal */\nexport type DetachedRouteHandleInternal = {\n contexts: Map<string, OutletContext>,\n componentRef: ComponentRef<any>,\n route: TreeNode<ActivatedRoute>,\n};\n\n/**\n * @description\n *\n * Provides a way to customize when activated routes get reused.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy)})\nexport abstract class RouteReuseStrategy {\n /** Determines if this route (and its subtree) should be detached to be reused later */\n abstract shouldDetach(route: ActivatedRouteSnapshot): boolean;\n\n /**\n * Stores the detached route.\n *\n * Storing a `null` value should erase the previously stored value.\n */\n abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle|null): void;\n\n /** Determines if this route (and its subtree) should be reattached */\n abstract shouldAttach(route: ActivatedRouteSnapshot): boolean;\n\n /** Retrieves the previously stored route */\n abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null;\n\n /** Determines if a route should be reused */\n abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean;\n}\n\n/**\n * @description\n *\n * This base route reuse strategy only reuses routes when the matched router configs are\n * identical. This prevents components from being destroyed and recreated\n * when just the route parameters, query parameters or fragment change\n * (that is, the existing component is _reused_).\n *\n * This strategy does not store any routes for later reuse.\n *\n * Angular uses this strategy by default.\n *\n *\n * It can be used as a base class for custom route reuse strategies, i.e. you can create your own\n * class that extends the `BaseRouteReuseStrategy` one.\n * @publicApi\n */\nexport abstract class BaseRouteReuseStrategy implements RouteReuseStrategy {\n /**\n * Whether the given route should detach for later reuse.\n * Always returns false for `BaseRouteReuseStrategy`.\n * */\n shouldDetach(route: ActivatedRouteSnapshot): boolean {\n return false;\n }\n\n /**\n * A no-op; the route is never stored since this strategy never detaches routes for later re-use.\n */\n store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}\n\n /** Returns `false`, meaning the route (and its subtree) is never reattached */\n shouldAttach(route: ActivatedRouteSnapshot): boolean {\n return false;\n }\n\n /** Returns `null` because this strategy does not store routes for later re-use. */\n retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null {\n return null;\n }\n\n /**\n * Determines if a route should be reused.\n * This strategy returns `true` when the future route config and current route config are\n * identical.\n */\n shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {\n return future.routeConfig === curr.routeConfig;\n }\n}\n\n@Injectable({providedIn: 'root'})\nexport class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\n\nimport {OnSameUrlNavigation} from './models';\nimport {UrlSerializer, UrlTree} from './url_tree';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\n/**\n * Error handler that is invoked when a navigation error occurs.\n *\n * If the handler returns a value, the navigation Promise is resolved with this value.\n * If the handler throws an exception, the navigation Promise is rejected with\n * the exception.\n *\n * @publicApi\n * @deprecated Subscribe to the `Router` events and watch for `NavigationError` instead.\n */\nexport type ErrorHandler = (error: any) => any;\n\n/**\n * Allowed values in an `ExtraOptions` object that configure\n * when the router performs the initial navigation operation.\n *\n * * 'enabledNonBlocking' - (default) The initial navigation starts after the\n * root component has been created. The bootstrap is not blocked on the completion of the initial\n * navigation.\n * * 'enabledBlocking' - The initial navigation starts before the root component is created.\n * The bootstrap is blocked until the initial navigation is complete. This value is required\n * for [server-side rendering](guide/universal) to work.\n * * 'disabled' - The initial navigation is not performed. The location listener is set up before\n * the root component gets created. Use if there is a reason to have\n * more control over when the router starts its initial navigation due to some complex\n * initialization logic.\n *\n * @see `forRoot()`\n *\n * @publicApi\n */\nexport type InitialNavigation = 'disabled'|'enabledBlocking'|'enabledNonBlocking';\n\n/**\n * Extra configuration options that can be used with the `withRouterConfig` function.\n *\n * @publicApi\n */\nexport interface RouterConfigOptions {\n /**\n * Configures how the Router attempts to restore state when a navigation is cancelled.\n *\n * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the\n * router before the navigation started. This means that if the URL of the browser is updated\n * _before_ the navigation is canceled, the Router will simply replace the item in history rather\n * than trying to restore to the previous location in the session history. This happens most\n * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward\n * buttons.\n *\n * 'computed' - Will attempt to return to the same index in the session history that corresponds\n * to the Angular route when the navigation gets cancelled. For example, if the browser back\n * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation\n * and vice versa.\n *\n * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only\n * handles a portion of the URL because the history restoration navigates to the previous place in\n * the browser history rather than simply resetting a portion of the URL.\n *\n * The default value is `replace` when not set.\n */\n canceledNavigationResolution?: 'replace'|'computed';\n\n /**\n * Configures the default for handling a navigation request to the current URL.\n *\n * If unset, the `Router` will use `'ignore'`.\n *\n * @see `OnSameUrlNavigation`\n */\n onSameUrlNavigation?: OnSameUrlNavigation;\n\n /**\n * Defines how the router merges parameters, data, and resolved data from parent to child\n * routes. By default ('emptyOnly'), inherits parent parameters only for\n * path-less or component-less routes.\n *\n * Set to 'always' to enable unconditional inheritance of parent parameters.\n *\n * Note that when dealing with matrix parameters, \"parent\" refers to the parent `Route`\n * config which does not necessarily mean the \"URL segment to the left\". When the `Route` `path`\n * contains multiple segments, the matrix parameters must appear on the last segment. For example,\n * matrix parameters for `{path: 'a/b', component: MyComp}` should appear as `a/b;foo=bar` and not\n * `a;foo=bar/b`.\n *\n */\n paramsInheritanceStrategy?: 'emptyOnly'|'always';\n\n /**\n * Defines when the router updates the browser URL. By default ('deferred'),\n * update after successful navigation.\n * Set to 'eager' if prefer to update the URL at the beginning of navigation.\n * Updating the URL early allows you to handle a failure of navigation by\n * showing an error message with the URL that failed.\n */\n urlUpdateStrategy?: 'deferred'|'eager';\n}\n\n/**\n * Configuration options for the scrolling feature which can be used with `withInMemoryScrolling`\n * function.\n *\n * @publicApi\n */\nexport interface InMemoryScrollingOptions {\n /**\n * When set to 'enabled', scrolls to the anchor element when the URL has a fragment.\n * Anchor scrolling is disabled by default.\n *\n * Anchor scrolling does not happen on 'popstate'. Instead, we restore the position\n * that we stored or scroll to the top.\n */\n anchorScrolling?: 'disabled'|'enabled';\n\n /**\n * Configures if the scroll position needs to be restored when navigating back.\n *\n * * 'disabled'- (Default) Does nothing. Scroll position is maintained on navigation.\n * * 'top'- Sets the scroll position to x = 0, y = 0 on all navigation.\n * * 'enabled'- Restores the previous scroll position on backward navigation, else sets the\n * position to the anchor if one is provided, or sets the scroll position to [0, 0] (forward\n * navigation). This option will be the default in the future.\n *\n * You can implement custom scroll restoration behavior by adapting the enabled behavior as\n * in the following example.\n *\n * ```typescript\n * class AppComponent {\n * movieData: any;\n *\n * constructor(private router: Router, private viewportScroller: ViewportScroller,\n * changeDetectorRef: ChangeDetectorRef) {\n * router.events.pipe(filter((event: Event): event is Scroll => event instanceof Scroll)\n * ).subscribe(e => {\n * fetch('http://example.com/movies.json').then(response => {\n * this.movieData = response.json();\n * // update the template with the data before restoring scroll\n * changeDetectorRef.detectChanges();\n *\n * if (e.position) {\n * viewportScroller.scrollToPosition(e.position);\n * }\n * });\n * });\n * }\n * }\n * ```\n */\n scrollPositionRestoration?: 'disabled'|'enabled'|'top';\n}\n\n/**\n * A set of configuration options for a router module, provided in the\n * `forRoot()` method.\n *\n * @see `forRoot()`\n *\n *\n * @publicApi\n */\nexport interface ExtraOptions extends InMemoryScrollingOptions, RouterConfigOptions {\n /**\n * When true, log all internal navigation events to the console.\n * Use for debugging.\n */\n enableTracing?: boolean;\n\n /**\n * When true, enable the location strategy that uses the URL fragment\n * instead of the history API.\n */\n useHash?: boolean;\n\n /**\n * One of `enabled`, `enabledBlocking`, `enabledNonBlocking` or `disabled`.\n * When set to `enabled` or `enabledBlocking`, the initial navigation starts before the root\n * component is created. The bootstrap is blocked until the initial navigation is complete. This\n * value is required for [server-side rendering](guide/universal) to work. When set to\n * `enabledNonBlocking`, the initial navigation starts after the root component has been created.\n * The bootstrap is not blocked on the completion of the initial navigation. When set to\n * `disabled`, the initial navigation is not performed. The location listener is set up before the\n * root component gets created. Use if there is a reason to have more control over when the router\n * starts its initial navigation due to some complex initialization logic.\n */\n initialNavigation?: InitialNavigation;\n\n /**\n * A custom error handler for failed navigations.\n * If the handler returns a value, the navigation Promise is resolved with this value.\n * If the handler throws an exception, the navigation Promise is rejected with the exception.\n *\n * @deprecated Subscribe to the `Router` events and watch for `NavigationError` instead.\n */\n errorHandler?: (error: any) => any;\n\n /**\n * Configures a preloading strategy.\n * One of `PreloadAllModules` or `NoPreloading` (the default).\n */\n preloadingStrategy?: any;\n\n /**\n * Configures the scroll offset the router will use when scrolling to an element.\n *\n * When given a tuple with x and y position value,\n * the router uses that offset each time it scrolls.\n * When given a function, the router invokes the function every time\n * it restores scroll position.\n */\n scrollOffset?: [number, number]|(() => [number, number]);\n\n /**\n * A custom handler for malformed URI errors. The handler is invoked when `encodedURI` contains\n * invalid character sequences.\n * The default implementation is to redirect to the root URL, dropping\n * any path or parameter information. The function takes three parameters:\n *\n * - `'URIError'` - Error thrown when parsing a bad URL.\n * - `'UrlSerializer'` - UrlSerializer that’s configured with the router.\n * - `'url'` - The malformed URL that caused the URIError\n *\n * @deprecated URI parsing errors should be handled in the `UrlSerializer` instead.\n * */\n malformedUriErrorHandler?:\n (error: URIError, urlSerializer: UrlSerializer, url: string) => UrlTree;\n}\n\n/**\n * A [DI token](guide/glossary/#di-token) for the router service.\n *\n * @publicApi\n */\nexport const ROUTER_CONFIGURATION =\n new InjectionToken<ExtraOptions>(NG_DEV_MODE ? 'router config' : '', {\n providedIn: 'root',\n factory: () => ({}),\n });\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {inject, Injectable} from '@angular/core';\n\nimport {UrlTree} from './url_tree';\n\n/**\n * @description\n *\n * Provides a way to migrate AngularJS applications to Angular.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy)})\nexport abstract class UrlHandlingStrategy {\n /**\n * Tells the router if this URL should be processed.\n *\n * When it returns true, the router will execute the regular navigation.\n * When it returns false, the router will set the router state to an empty state.\n * As a result, all the active components will be destroyed.\n *\n */\n abstract shouldProcessUrl(url: UrlTree): boolean;\n\n /**\n * Extracts the part of the URL that should be handled by the router.\n * The rest of the URL will remain untouched.\n */\n abstract extract(url: UrlTree): UrlTree;\n\n /**\n * Merges the URL fragment with the rest of the URL.\n */\n abstract merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree;\n}\n\n/**\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class DefaultUrlHandlingStrategy implements UrlHandlingStrategy {\n shouldProcessUrl(url: UrlTree): boolean {\n return true;\n }\n extract(url: UrlTree): UrlTree {\n return url;\n }\n merge(newUrlPart: UrlTree, wholeUrl: UrlTree): UrlTree {\n return newUrlPart;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Location} from '@angular/common';\nimport {inject, Injectable, NgZone, Type, ɵConsole as Console, ɵRuntimeError as RuntimeError} from '@angular/core';\nimport {Observable, of, SubscriptionLike} from 'rxjs';\n\nimport {CreateUrlTreeStrategy} from './create_url_tree_strategy';\nimport {RuntimeErrorCode} from './errors';\nimport {Event, IMPERATIVE_NAVIGATION, NavigationTrigger} from './events';\nimport {NavigationBehaviorOptions, OnSameUrlNavigation, Routes} from './models';\nimport {Navigation, NavigationExtras, NavigationTransition, NavigationTransitions, RestoredState, UrlCreationOptions} from './navigation_transition';\nimport {TitleStrategy} from './page_title_strategy';\nimport {RouteReuseStrategy} from './route_reuse_strategy';\nimport {ROUTER_CONFIGURATION} from './router_config';\nimport {ROUTES} from './router_config_loader';\nimport {createEmptyState, RouterState} from './router_state';\nimport {Params} from './shared';\nimport {UrlHandlingStrategy} from './url_handling_strategy';\nimport {containsTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree';\nimport {flatten} from './utils/collection';\nimport {standardizeConfig, validateConfig} from './utils/config';\n\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;\n\nfunction defaultErrorHandler(error: any): any {\n throw error;\n}\n\nfunction defaultMalformedUriErrorHandler(\n error: URIError, urlSerializer: UrlSerializer, url: string): UrlTree {\n return urlSerializer.parse('/');\n}\n\n/**\n * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`\n * (exact = true).\n */\nexport const exactMatchOptions: IsActiveMatchOptions = {\n paths: 'exact',\n fragment: 'ignored',\n matrixParams: 'ignored',\n queryParams: 'exact'\n};\n\n/**\n * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`\n * (exact = false).\n */\nexport const subsetMatchOptions: IsActiveMatchOptions = {\n paths: 'subset',\n fragment: 'ignored',\n matrixParams: 'ignored',\n queryParams: 'subset'\n};\n\n/**\n * @description\n *\n * A service that provides navigation among views and URL manipulation capabilities.\n *\n * @see `Route`.\n * @see [Routing and Navigation Guide](guide/router).\n *\n * @ngModule RouterModule\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class Router {\n /**\n * Represents the activated `UrlTree` that the `Router` is configured to handle (through\n * `UrlHandlingStrategy`). That is, after we find the route config tree that we're going to\n * activate, run guards, and are just about to activate the route, we set the currentUrlTree.\n *\n * This should match the `browserUrlTree` when a navigation succeeds. If the\n * `UrlHandlingStrategy.shouldProcessUrl` is `false`, only the `browserUrlTree` is updated.\n * @internal\n */\n currentUrlTree: UrlTree;\n /**\n * Meant to represent the entire browser url after a successful navigation. In the life of a\n * navigation transition:\n * 1. The rawUrl represents the full URL that's being navigated to\n * 2. We apply redirects, which might only apply to _part_ of the URL (due to\n * `UrlHandlingStrategy`).\n * 3. Right before activation (because we assume activation will succeed), we update the\n * rawUrlTree to be a combination of the urlAfterRedirects (again, this might only apply to part\n * of the initial url) and the rawUrl of the transition (which was the original navigation url in\n * its full form).\n * @internal\n *\n * Note that this is _only_ here to support `UrlHandlingStrategy.extract` and\n * `UrlHandlingStrategy.shouldProcessUrl`. If those didn't exist, we could get by with\n * `currentUrlTree` alone. If a new Router were to be provided (i.e. one that works with the\n * browser navigation API), we should think about whether this complexity should be carried over.\n *\n * - extract: `rawUrlTree` is needed because `extract` may only return part\n * of the navigation URL. Thus, `currentUrlTree` may only represent _part_ of the browser URL.\n * When a navigation gets cancelled and we need to reset the URL or a new navigation occurs, we\n * need to know the _whole_ browser URL, not just the part handled by UrlHandlingStrategy.\n * - shouldProcessUrl: When this returns `false`, the router just ignores the navigation but still\n * updates the `rawUrlTree` with the assumption that the navigation was caused by the location\n * change listener due to a URL update by the AngularJS router. In this case, we still need to\n * know what the browser's URL is for future navigations.\n *\n */\n rawUrlTree: UrlTree;\n /**\n * Meant to represent the part of the browser url that the `Router` is set up to handle (via the\n * `UrlHandlingStrategy`). This value is updated immediately after the browser url is updated (or\n * the browser url update is skipped via `skipLocationChange`). With that, note that\n * `browserUrlTree` _may not_ reflect the actual browser URL for two reasons:\n *\n * 1. `UrlHandlingStrategy` only handles part of the URL\n * 2. `skipLocationChange` does not update the browser url.\n *\n * So to reiterate, `browserUrlTree` only represents the Router's internal understanding of the\n * current route, either before guards with `urlUpdateStrategy === 'eager'` or right before\n * activation with `'deferred'`.\n *\n * This should match the `currentUrlTree` when the navigation succeeds.\n * @internal\n */\n browserUrlTree: UrlTree;\n private disposed = false;\n\n private locationSubscription?: SubscriptionLike;\n // TODO(b/260747083): This should not exist and navigationId should be private in\n // `NavigationTransitions`\n private get navigationId() {\n return this.navigationTransitions.navigationId;\n }\n\n /**\n * The id of the currently active page in the router.\n * Updated to the transition's target id on a successful navigation.\n *\n * This is used to track what page the router last activated. When an attempted navigation fails,\n * the router can then use this to compute how to restore the state back to the previously active\n * page.\n */\n private currentPageId: number = 0;\n /**\n * The ɵrouterPageId of whatever page is currently active in the browser history. This is\n * important for computing the target page id for new navigations because we need to ensure each\n * page id in the browser history is 1 more than the previous entry.\n */\n private get browserPageId(): number|undefined {\n if (this.canceledNavigationResolution !== 'computed') {\n return undefined;\n }\n return (this.location.getState() as RestoredState | null)?.ɵrouterPageId;\n }\n private console = inject(Console);\n private isNgZoneEnabled: boolean = false;\n\n /**\n * An event stream for routing events.\n */\n public get events(): Observable<Event> {\n // TODO(atscott): This _should_ be events.asObservable(). However, this change requires internal\n // cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't\n // allowed/supported but we still have to fix these or file bugs against the teams before making\n // the change.\n return this.navigationTransitions.events;\n }\n /**\n * The current state of routing in this NgModule.\n */\n public readonly routerState: RouterState;\n\n private options = inject(ROUTER_CONFIGURATION, {optional: true}) || {};\n\n /**\n * A handler for navigation errors in this NgModule.\n *\n * @deprecated Subscribe to the `Router` events and watch for `NavigationError` instead.\n * `provideRouter` has the `withNavigationErrorHandler` feature to make this easier.\n * @see `withNavigationErrorHandler`\n */\n errorHandler = this.options.errorHandler || defaultErrorHandler;\n\n /**\n * A handler for errors thrown by `Router.parseUrl(url)`\n * when `url` contains an invalid character.\n * The most common case is a `%` sign\n * that's not encoded and is not part of a percent encoded sequence.\n *\n * @deprecated URI parsing errors should be handled in the `UrlSerializer`.\n *\n * @see `RouterModule`\n */\n malformedUriErrorHandler =\n this.options.malformedUriErrorHandler || defaultMalformedUriErrorHandler;\n\n /**\n * True if at least one navigation event has occurred,\n * false otherwise.\n */\n navigated: boolean = false;\n private lastSuccessfulId: number = -1;\n\n /**\n * A strategy for extracting and merging URLs.\n * Used for AngularJS to Angular migrations.\n *\n * @deprecated Configure using `providers` instead:\n * `{provide: UrlHandlingStrategy, useClass: MyStrategy}`.\n */\n urlHandlingStrategy = inject(UrlHandlingStrategy);\n\n /**\n * A strategy for re-using routes.\n *\n * @deprecated Configure using `providers` instead:\n * `{provide: RouteReuseStrategy, useClass: MyStrategy}`.\n */\n routeReuseStrategy = inject(RouteReuseStrategy);\n\n /** Strategy used to create a UrlTree. */\n private readonly urlCreationStrategy = inject(CreateUrlTreeStrategy);\n\n /**\n * A strategy for setting the title based on the `routerState`.\n *\n * @deprecated Configure using `providers` instead:\n * `{provide: TitleStrategy, useClass: MyStrategy}`.\n */\n titleStrategy?: TitleStrategy = inject(TitleStrategy);\n\n /**\n * How to handle a navigation request to the current URL.\n *\n *\n * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.\n * @see `withRouterConfig`\n * @see `provideRouter`\n * @see `RouterModule`\n */\n onSameUrlNavigation: OnSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';\n\n /**\n * How to merge parameters, data, resolved data, and title from parent to child\n * routes. One of:\n *\n * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data\n * for path-less or component-less routes.\n * - `'always'` : Inherit parent parameters, data, and resolved data\n * for all child routes.\n *\n * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.\n * @see `withRouterConfig`\n * @see `provideRouter`\n * @see `RouterModule`\n */\n paramsInheritanceStrategy: 'emptyOnly'|'always' =\n this.options.paramsInheritanceStrategy || 'emptyOnly';\n\n /**\n * Determines when the router updates the browser URL.\n * By default (`\"deferred\"`), updates the browser URL after navigation has finished.\n * Set to `'eager'` to update the browser URL at the beginning of navigation.\n * You can choose to update early so that, if navigation fails,\n * you can show an error message with the URL that failed.\n *\n * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.\n * @see `withRouterConfig`\n * @see `provideRouter`\n * @see `RouterModule`\n */\n urlUpdateStrategy: 'deferred'|'eager' = this.options.urlUpdateStrategy || 'deferred';\n\n /**\n * Configures how the Router attempts to restore state when a navigation is cancelled.\n *\n * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the\n * router before the navigation started. This means that if the URL of the browser is updated\n * _before_ the navigation is canceled, the Router will simply replace the item in history rather\n * than trying to restore to the previous location in the session history. This happens most\n * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward\n * buttons.\n *\n * 'computed' - Will attempt to return to the same index in the session history that corresponds\n * to the Angular route when the navigation gets cancelled. For example, if the browser back\n * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation\n * and vice versa.\n *\n * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only\n * handles a portion of the URL because the history restoration navigates to the previous place in\n * the browser history rather than simply resetting a portion of the URL.\n *\n * The default value is `replace`.\n *\n * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.\n * @see `withRouterConfig`\n * @see `provideRouter`\n * @see `RouterModule`\n */\n canceledNavigationResolution: 'replace'|'computed' =\n this.options.canceledNavigationResolution || 'replace';\n\n config: Routes = flatten(inject(ROUTES, {optional: true}) ?? []);\n\n private readonly navigationTransitions = inject(NavigationTransitions);\n private readonly urlSerializer = inject(UrlSerializer);\n private readonly location = inject(Location);\n\n constructor() {\n this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();\n\n this.resetConfig(this.config);\n this.currentUrlTree = new UrlTree();\n this.rawUrlTree = this.currentUrlTree;\n this.browserUrlTree = this.currentUrlTree;\n\n this.routerState = createEmptyState(this.currentUrlTree, null);\n\n this.navigationTransitions.setupNavigations(this).subscribe(\n t => {\n this.lastSuccessfulId = t.id;\n this.currentPageId = this.browserPageId ?? 0;\n },\n e => {\n this.console.warn(`Unhandled Navigation Error: ${e}`);\n });\n }\n\n /** @internal */\n resetRootComponentType(rootComponentType: Type<any>): void {\n // TODO: vsavkin router 4.0 should make the root component set to null\n // this will simplify the lifecycle of the router.\n this.routerState.root.component = rootComponentType;\n this.navigationTransitions.rootComponentType = rootComponentType;\n }\n\n /**\n * Sets up the location change listener and performs the initial navigation.\n */\n initialNavigation(): void {\n this.setUpLocationChangeListener();\n if (!this.navigationTransitions.hasRequestedNavigation) {\n const state = this.location.getState() as RestoredState;\n this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, state);\n }\n }\n\n /**\n * Sets up the location change listener. This listener detects navigations triggered from outside\n * the Router (the browser back/forward buttons, for example) and schedules a corresponding Router\n * navigation so that the correct events, guards, etc. are triggered.\n */\n setUpLocationChangeListener(): void {\n // Don't need to use Zone.wrap any more, because zone.js\n // already patch onPopState, so location change callback will\n // run into ngZone\n if (!this.locationSubscription) {\n this.locationSubscription = this.location.subscribe(event => {\n const source = event['type'] === 'popstate' ? 'popstate' : 'hashchange';\n if (source === 'popstate') {\n // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS\n // hybrid apps.\n setTimeout(() => {\n this.navigateToSyncWithBrowser(event['url']!, source, event.state);\n }, 0);\n }\n });\n }\n }\n\n /**\n * Schedules a router navigation to synchronize Router state with the browser state.\n *\n * This is done as a response to a popstate event and the initial navigation. These\n * two scenarios represent times when the browser URL/state has been updated and\n * the Router needs to respond to ensure its internal state matches.\n */\n private navigateToSyncWithBrowser(\n url: string, source: NavigationTrigger, state: RestoredState|undefined) {\n const extras: NavigationExtras = {replaceUrl: true};\n\n // TODO: restoredState should always include the entire state, regardless\n // of navigationId. This requires a breaking change to update the type on\n // NavigationStart’s restoredState, which currently requires navigationId\n // to always be present. The Router used to only restore history state if\n // a navigationId was present.\n\n // The stored navigationId is used by the RouterScroller to retrieve the scroll\n // position for the page.\n const restoredState = state?.navigationId ? state : null;\n\n // Separate to NavigationStart.restoredState, we must also restore the state to\n // history.state and generate a new navigationId, since it will be overwritten\n if (state) {\n const stateCopy = {...state} as Partial<RestoredState>;\n delete stateCopy.navigationId;\n delete stateCopy.ɵrouterPageId;\n if (Object.keys(stateCopy).length !== 0) {\n extras.state = stateCopy;\n }\n }\n\n const urlTree = this.parseUrl(url);\n this.scheduleNavigation(urlTree, source, restoredState, extras);\n }\n\n /** The current URL. */\n get url(): string {\n return this.serializeUrl(this.currentUrlTree);\n }\n\n /**\n * Returns the current `Navigation` object when the router is navigating,\n * and `null` when idle.\n */\n getCurrentNavigation(): Navigation|null {\n return this.navigationTransitions.currentNavigation;\n }\n\n /**\n * Resets the route configuration used for navigation and generating links.\n *\n * @param config The route array for the new configuration.\n *\n * @usageNotes\n *\n * ```\n * router.resetConfig([\n * { path: 'team/:id', component: TeamCmp, children: [\n * { path: 'simple', component: SimpleCmp },\n * { path: 'user/:name', component: UserCmp }\n * ]}\n * ]);\n * ```\n */\n resetConfig(config: Routes): void {\n NG_DEV_MODE && validateConfig(config);\n this.config = config.map(standardizeConfig);\n this.navigated = false;\n this.lastSuccessfulId = -1;\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n this.dispose();\n }\n\n /** Disposes of the router. */\n dispose(): void {\n this.navigationTransitions.complete();\n if (this.locationSubscription) {\n this.locationSubscription.unsubscribe();\n this.locationSubscription = undefined;\n }\n this.disposed = true;\n }\n\n /**\n * Appends URL segments to the current URL tree to create a new URL tree.\n *\n * @param commands An array of URL fragments with which to construct the new URL tree.\n * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path\n * segments, followed by the parameters for each segment.\n * The fragments are applied to the current URL tree or the one provided in the `relativeTo`\n * property of the options object, if supplied.\n * @param navigationExtras Options that control the navigation strategy.\n * @returns The new URL tree.\n *\n * @usageNotes\n *\n * ```\n * // create /team/33/user/11\n * router.createUrlTree(['/team', 33, 'user', 11]);\n *\n * // create /team/33;expand=true/user/11\n * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);\n *\n * // you can collapse static segments like this (this works only with the first passed-in value):\n * router.createUrlTree(['/team/33/user', userId]);\n *\n * // If the first segment can contain slashes, and you do not want the router to split it,\n * // you can do the following:\n * router.createUrlTree([{segmentPath: '/one/two'}]);\n *\n * // create /team/33/(user/11//right:chat)\n * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);\n *\n * // remove the right secondary node\n * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);\n *\n * // assuming the current url is `/team/33/user/11` and the route points to `user/11`\n *\n * // navigate to /team/33/user/11/details\n * router.createUrlTree(['details'], {relativeTo: route});\n *\n * // navigate to /team/33/user/22\n * router.createUrlTree(['../22'], {relativeTo: route});\n *\n * // navigate to /team/44/user/22\n * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});\n *\n * Note that a value of `null` or `undefined` for `relativeTo` indicates that the\n * tree should be created relative to the root.\n * ```\n */\n createUrlTree(commands: any[], navigationExtras: UrlCreationOptions = {}): UrlTree {\n const {relativeTo, queryParams, fragment, queryParamsHandling, preserveFragment} =\n navigationExtras;\n const f = preserveFragment ? this.currentUrlTree.fragment : fragment;\n let q: Params|null = null;\n switch (queryParamsHandling) {\n case 'merge':\n q = {...this.currentUrlTree.queryParams, ...queryParams};\n break;\n case 'preserve':\n q = this.currentUrlTree.queryParams;\n break;\n default:\n q = queryParams || null;\n }\n if (q !== null) {\n q = this.removeEmptyProps(q);\n }\n return this.urlCreationStrategy.createUrlTree(\n relativeTo, this.routerState, this.currentUrlTree, commands, q, f ?? null);\n }\n\n /**\n * Navigates to a view using an absolute route path.\n *\n * @param url An absolute path for a defined route. The function does not apply any delta to the\n * current URL.\n * @param extras An object containing properties that modify the navigation strategy.\n *\n * @returns A Promise that resolves to 'true' when navigation succeeds,\n * to 'false' when navigation fails, or is rejected on error.\n *\n * @usageNotes\n *\n * The following calls request navigation to an absolute path.\n *\n * ```\n * router.navigateByUrl(\"/team/33/user/11\");\n *\n * // Navigate without updating the URL\n * router.navigateByUrl(\"/team/33/user/11\", { skipLocationChange: true });\n * ```\n *\n * @see [Routing and Navigation guide](guide/router)\n *\n */\n navigateByUrl(url: string|UrlTree, extras: NavigationBehaviorOptions = {\n skipLocationChange: false\n }): Promise<boolean> {\n if (NG_DEV_MODE) {\n if (this.isNgZoneEnabled && !NgZone.isInAngularZone()) {\n this.console.warn(\n `Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);\n }\n if (url instanceof UrlTree && url._warnIfUsedForNavigation) {\n this.console.warn(url._warnIfUsedForNavigation);\n }\n }\n\n const urlTree = isUrlTree(url) ? url : this.parseUrl(url);\n const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);\n\n return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);\n }\n\n /**\n * Navigate based on the provided array of commands and a starting point.\n * If no starting route is provided, the navigation is absolute.\n *\n * @param commands An array of URL fragments with which to construct the target URL.\n * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path\n * segments, followed by the parameters for each segment.\n * The fragments are applied to the current URL or the one provided in the `relativeTo` property\n * of the options object, if supplied.\n * @param extras An options object that determines how the URL should be constructed or\n * interpreted.\n *\n * @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation\n * fails,\n * or is rejected on error.\n *\n * @usageNotes\n *\n * The following calls request navigation to a dynamic route path relative to the current URL.\n *\n * ```\n * router.navigate(['team', 33, 'user', 11], {relativeTo: route});\n *\n * // Navigate without updating the URL, overriding the default behavior\n * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});\n * ```\n *\n * @see [Routing and Navigation guide](guide/router)\n *\n */\n navigate(commands: any[], extras: NavigationExtras = {skipLocationChange: false}):\n Promise<boolean> {\n validateCommands(commands);\n return this.navigateByUrl(this.createUrlTree(commands, extras), extras);\n }\n\n /** Serializes a `UrlTree` into a string */\n serializeUrl(url: UrlTree): string {\n return this.urlSerializer.serialize(url);\n }\n\n /** Parses a string into a `UrlTree` */\n parseUrl(url: string): UrlTree {\n let urlTree: UrlTree;\n try {\n urlTree = this.urlSerializer.parse(url);\n } catch (e) {\n urlTree = this.malformedUriErrorHandler(e as URIError, this.urlSerializer, url);\n }\n return urlTree;\n }\n\n /**\n * Returns whether the url is activated.\n *\n * @deprecated\n * Use `IsActiveMatchOptions` instead.\n *\n * - The equivalent `IsActiveMatchOptions` for `true` is\n * `{paths: 'exact', queryParams: 'exact', fragment: 'ignored', matrixParams: 'ignored'}`.\n * - The equivalent for `false` is\n * `{paths: 'subset', queryParams: 'subset', fragment: 'ignored', matrixParams: 'ignored'}`.\n */\n isActive(url: string|UrlTree, exact: boolean): boolean;\n /**\n * Returns whether the url is activated.\n */\n isActive(url: string|UrlTree, matchOptions: IsActiveMatchOptions): boolean;\n /** @internal */\n isActive(url: string|UrlTree, matchOptions: boolean|IsActiveMatchOptions): boolean;\n isActive(url: string|UrlTree, matchOptions: boolean|IsActiveMatchOptions): boolean {\n let options: IsActiveMatchOptions;\n if (matchOptions === true) {\n options = {...exactMatchOptions};\n } else if (matchOptions === false) {\n options = {...subsetMatchOptions};\n } else {\n options = matchOptions;\n }\n if (isUrlTree(url)) {\n return containsTree(this.currentUrlTree, url, options);\n }\n\n const urlTree = this.parseUrl(url);\n return containsTree(this.currentUrlTree, urlTree, options);\n }\n\n private removeEmptyProps(params: Params): Params {\n return Object.keys(params).reduce((result: Params, key: string) => {\n const value: any = params[key];\n if (value !== null && value !== undefined) {\n result[key] = value;\n }\n return result;\n }, {});\n }\n\n /** @internal */\n scheduleNavigation(\n rawUrl: UrlTree, source: NavigationTrigger, restoredState: RestoredState|null,\n extras: NavigationExtras,\n priorPromise?: {resolve: any, reject: any, promise: Promise<boolean>}): Promise<boolean> {\n if (this.disposed) {\n return Promise.resolve(false);\n }\n\n let resolve: any;\n let reject: any;\n let promise: Promise<boolean>;\n if (priorPromise) {\n resolve = priorPromise.resolve;\n reject = priorPromise.reject;\n promise = priorPromise.promise;\n } else {\n promise = new Promise<boolean>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n }\n\n let targetPageId: number;\n if (this.canceledNavigationResolution === 'computed') {\n // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of\n // `ɵrouterPageId`. This is the case for something like a page refresh where we assign the\n // target id to the previously set value for that page.\n if (restoredState && restoredState.ɵrouterPageId) {\n targetPageId = restoredState.ɵrouterPageId;\n } else {\n // Otherwise, targetPageId should be the next number in the event of a `pushState`\n // navigation.\n targetPageId = (this.browserPageId ?? 0) + 1;\n }\n } else {\n // This is unused when `canceledNavigationResolution` is not computed.\n targetPageId = 0;\n }\n\n this.navigationTransitions.handleNavigationRequest({\n targetPageId,\n source,\n restoredState,\n currentUrlTree: this.currentUrlTree,\n currentRawUrl: this.currentUrlTree,\n rawUrl,\n extras,\n resolve,\n reject,\n promise,\n currentSnapshot: this.routerState.snapshot,\n currentRouterState: this.routerState\n });\n\n // Make sure that the error is propagated even though `processNavigations` catch\n // handler does not rethrow\n return promise.catch((e: any) => {\n return Promise.reject(e);\n });\n }\n\n /** @internal */\n setBrowserUrl(url: UrlTree, transition: NavigationTransition) {\n const path = this.urlSerializer.serialize(url);\n if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {\n // replacements do not update the target page\n const currentBrowserPageId = this.browserPageId;\n const state = {\n ...transition.extras.state,\n ...this.generateNgRouterState(transition.id, currentBrowserPageId)\n };\n this.location.replaceState(path, '', state);\n } else {\n const state = {\n ...transition.extras.state,\n ...this.generateNgRouterState(transition.id, transition.targetPageId)\n };\n this.location.go(path, '', state);\n }\n }\n\n /**\n * Performs the necessary rollback action to restore the browser URL to the\n * state before the transition.\n * @internal\n */\n restoreHistory(transition: NavigationTransition, restoringFromCaughtError = false) {\n if (this.canceledNavigationResolution === 'computed') {\n const currentBrowserPageId = this.browserPageId ?? this.currentPageId;\n const targetPagePosition = this.currentPageId - currentBrowserPageId;\n if (targetPagePosition !== 0) {\n this.location.historyGo(targetPagePosition);\n } else if (\n this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&\n targetPagePosition === 0) {\n // We got to the activation stage (where currentUrlTree is set to the navigation's\n // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).\n // We still need to reset the router state back to what it was when the navigation started.\n this.resetState(transition);\n // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.\n // Investigate if this can be done by running TGP.\n this.browserUrlTree = transition.currentUrlTree;\n this.resetUrlToCurrentUrlTree();\n } else {\n // The browser URL and router state was not updated before the navigation cancelled so\n // there's no restoration needed.\n }\n } else if (this.canceledNavigationResolution === 'replace') {\n // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op\n // for `deferred` navigations that haven't change the internal state yet because guards\n // reject. For 'eager' navigations, it seems like we also really should reset the state\n // because the navigation was cancelled. Investigate if this can be done by running TGP.\n if (restoringFromCaughtError) {\n this.resetState(transition);\n }\n this.resetUrlToCurrentUrlTree();\n }\n }\n\n private resetState(t: NavigationTransition): void {\n (this as {routerState: RouterState}).routerState = t.currentRouterState;\n this.currentUrlTree = t.currentUrlTree;\n // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be\n // configured to handle only part of the navigation URL. This means we would only want to reset\n // the part of the navigation handled by the Angular router rather than the whole URL. In\n // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL\n // when merging, such as the query params so they are not lost on a refresh.\n this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);\n }\n\n private resetUrlToCurrentUrlTree(): void {\n this.location.replaceState(\n this.urlSerializer.serialize(this.rawUrlTree), '',\n this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));\n }\n\n private generateNgRouterState(navigationId: number, routerPageId?: number) {\n if (this.canceledNavigationResolution === 'computed') {\n return {navigationId, ɵrouterPageId: routerPageId};\n }\n return {navigationId};\n }\n}\n\nfunction validateCommands(commands: string[]): void {\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (cmd == null) {\n throw new RuntimeError(\n RuntimeErrorCode.NULLISH_COMMAND,\n NG_DEV_MODE && `The requested path contains ${cmd} segment at index ${i}`);\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {LocationStrategy} from '@angular/common';\nimport {Attribute, Directive, ElementRef, HostBinding, HostListener, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges, ɵcoerceToBoolean as coerceToBoolean, ɵɵsanitizeUrlOrResourceUrl} from '@angular/core';\nimport {Subject, Subscription} from 'rxjs';\n\nimport {Event, NavigationEnd} from '../events';\nimport {QueryParamsHandling} from '../models';\nimport {Router} from '../router';\nimport {ActivatedRoute} from '../router_state';\nimport {Params} from '../shared';\nimport {UrlTree} from '../url_tree';\n\n\n/**\n * @description\n *\n * When applied to an element in a template, makes that element a link\n * that initiates navigation to a route. Navigation opens one or more routed components\n * in one or more `<router-outlet>` locations on the page.\n *\n * Given a route configuration `[{ path: 'user/:name', component: UserCmp }]`,\n * the following creates a static link to the route:\n * `<a routerLink=\"/user/bob\">link to user component</a>`\n *\n * You can use dynamic values to generate the link.\n * For a dynamic link, pass an array of path segments,\n * followed by the params for each segment.\n * For example, `['/team', teamId, 'user', userName, {details: true}]`\n * generates a link to `/team/11/user/bob;details=true`.\n *\n * Multiple static segments can be merged into one term and combined with dynamic segments.\n * For example, `['/team/11/user', userName, {details: true}]`\n *\n * The input that you provide to the link is treated as a delta to the current URL.\n * For instance, suppose the current URL is `/user/(box//aux:team)`.\n * The link `<a [routerLink]=\"['/user/jim']\">Jim</a>` creates the URL\n * `/user/(jim//aux:team)`.\n * See {@link Router#createUrlTree createUrlTree} for more information.\n *\n * @usageNotes\n *\n * You can use absolute or relative paths in a link, set query parameters,\n * control how parameters are handled, and keep a history of navigation states.\n *\n * ### Relative link paths\n *\n * The first segment name can be prepended with `/`, `./`, or `../`.\n * * If the first segment begins with `/`, the router looks up the route from the root of the\n * app.\n * * If the first segment begins with `./`, or doesn't begin with a slash, the router\n * looks in the children of the current activated route.\n * * If the first segment begins with `../`, the router goes up one level in the route tree.\n *\n * ### Setting and handling query params and fragments\n *\n * The following link adds a query parameter and a fragment to the generated URL:\n *\n * ```\n * <a [routerLink]=\"['/user/bob']\" [queryParams]=\"{debug: true}\" fragment=\"education\">\n * link to user component\n * </a>\n * ```\n * By default, the directive constructs the new URL using the given query parameters.\n * The example generates the link: `/user/bob?debug=true#education`.\n *\n * You can instruct the directive to handle query parameters differently\n * by specifying the `queryParamsHandling` option in the link.\n * Allowed values are:\n *\n * - `'merge'`: Merge the given `queryParams` into the current query params.\n * - `'preserve'`: Preserve the current query params.\n *\n * For example:\n *\n * ```\n * <a [routerLink]=\"['/user/bob']\" [queryParams]=\"{debug: true}\" queryParamsHandling=\"merge\">\n * link to user component\n * </a>\n * ```\n *\n * See {@link UrlCreationOptions.queryParamsHandling UrlCreationOptions#queryParamsHandling}.\n *\n * ### Preserving navigation history\n *\n * You can provide a `state` value to be persisted to the browser's\n * [`History.state` property](https://developer.mozilla.org/en-US/docs/Web/API/History#Properties).\n * For example:\n *\n * ```\n * <a [routerLink]=\"['/user/bob']\" [state]=\"{tracingId: 123}\">\n * link to user component\n * </a>\n * ```\n *\n * Use {@link Router.getCurrentNavigation() Router#getCurrentNavigation} to retrieve a saved\n * navigation-state value. For example, to capture the `tracingId` during the `NavigationStart`\n * event:\n *\n * ```\n * // Get NavigationStart events\n * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {\n * const navigation = router.getCurrentNavigation();\n * tracingService.trace({id: navigation.extras.state.tracingId});\n * });\n * ```\n *\n * @ngModule RouterModule\n *\n * @publicApi\n */\n@Directive({\n selector: '[routerLink]',\n standalone: true,\n})\nexport class RouterLink implements OnChanges, OnDestroy {\n private _preserveFragment = false;\n private _skipLocationChange = false;\n private _replaceUrl = false;\n\n /**\n * Represents an `href` attribute value applied to a host element,\n * when a host element is `<a>`. For other tags, the value is `null`.\n */\n href: string|null = null;\n\n /**\n * Represents the `target` attribute on a host element.\n * This is only used when the host element is an `<a>` tag.\n */\n @HostBinding('attr.target') @Input() target?: string;\n\n /**\n * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the\n * `UrlCreationOptions`.\n * @see {@link UrlCreationOptions#queryParams UrlCreationOptions#queryParams}\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input() queryParams?: Params|null;\n /**\n * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the\n * `UrlCreationOptions`.\n * @see {@link UrlCreationOptions#fragment UrlCreationOptions#fragment}\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input() fragment?: string;\n /**\n * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the\n * `UrlCreationOptions`.\n * @see {@link UrlCreationOptions#queryParamsHandling UrlCreationOptions#queryParamsHandling}\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input() queryParamsHandling?: QueryParamsHandling|null;\n /**\n * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the\n * `NavigationBehaviorOptions`.\n * @see {@link NavigationBehaviorOptions#state NavigationBehaviorOptions#state}\n * @see {@link Router#navigateByUrl Router#navigateByUrl}\n */\n @Input() state?: {[k: string]: any};\n /**\n * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the\n * `UrlCreationOptions`.\n * Specify a value here when you do not want to use the default value\n * for `routerLink`, which is the current activated route.\n * Note that a value of `undefined` here will use the `routerLink` default.\n * @see {@link UrlCreationOptions#relativeTo UrlCreationOptions#relativeTo}\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input() relativeTo?: ActivatedRoute|null;\n\n private commands: any[]|null = null;\n\n /** Whether a host element is an `<a>` tag. */\n private isAnchorElement: boolean;\n\n private subscription?: Subscription;\n\n /** @internal */\n onChanges = new Subject<RouterLink>();\n\n constructor(\n private router: Router, private route: ActivatedRoute,\n @Attribute('tabindex') private readonly tabIndexAttribute: string|null|undefined,\n private readonly renderer: Renderer2, private readonly el: ElementRef,\n private locationStrategy?: LocationStrategy) {\n const tagName = el.nativeElement.tagName?.toLowerCase();\n this.isAnchorElement = tagName === 'a' || tagName === 'area';\n\n if (this.isAnchorElement) {\n this.subscription = router.events.subscribe((s: Event) => {\n if (s instanceof NavigationEnd) {\n this.updateHref();\n }\n });\n } else {\n this.setTabIndexIfNotOnNativeEl('0');\n }\n }\n\n /**\n * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the\n * `UrlCreationOptions`.\n * @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment}\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input()\n set preserveFragment(preserveFragment: boolean|string|null|undefined) {\n this._preserveFragment = coerceToBoolean(preserveFragment);\n }\n\n get preserveFragment(): boolean {\n return this._preserveFragment;\n }\n\n /**\n * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the\n * `NavigationBehaviorOptions`.\n * @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange}\n * @see {@link Router#navigateByUrl Router#navigateByUrl}\n */\n @Input()\n set skipLocationChange(skipLocationChange: boolean|string|null|undefined) {\n this._skipLocationChange = coerceToBoolean(skipLocationChange);\n }\n\n get skipLocationChange(): boolean {\n return this._skipLocationChange;\n }\n\n /**\n * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the\n * `NavigationBehaviorOptions`.\n * @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl}\n * @see {@link Router#navigateByUrl Router#navigateByUrl}\n */\n @Input()\n set replaceUrl(replaceUrl: boolean|string|null|undefined) {\n this._replaceUrl = coerceToBoolean(replaceUrl);\n }\n\n get replaceUrl(): boolean {\n return this._replaceUrl;\n }\n\n /**\n * Modifies the tab index if there was not a tabindex attribute on the element during\n * instantiation.\n */\n private setTabIndexIfNotOnNativeEl(newTabIndex: string|null) {\n if (this.tabIndexAttribute != null /* both `null` and `undefined` */ || this.isAnchorElement) {\n return;\n }\n this.applyAttributeValue('tabindex', newTabIndex);\n }\n\n /** @nodoc */\n ngOnChanges(changes: SimpleChanges) {\n if (this.isAnchorElement) {\n this.updateHref();\n }\n // This is subscribed to by `RouterLinkActive` so that it knows to update when there are changes\n // to the RouterLinks it's tracking.\n this.onChanges.next(this);\n }\n\n /**\n * Commands to pass to {@link Router#createUrlTree Router#createUrlTree}.\n * - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}.\n * - **string**: shorthand for array of commands with just the string, i.e. `['/route']`\n * - **null|undefined**: effectively disables the `routerLink`\n * @see {@link Router#createUrlTree Router#createUrlTree}\n */\n @Input()\n set routerLink(commands: any[]|string|null|undefined) {\n if (commands != null) {\n this.commands = Array.isArray(commands) ? commands : [commands];\n this.setTabIndexIfNotOnNativeEl('0');\n } else {\n this.commands = null;\n this.setTabIndexIfNotOnNativeEl(null);\n }\n }\n\n /** @nodoc */\n @HostListener(\n 'click',\n ['$event.button', '$event.ctrlKey', '$event.shiftKey', '$event.altKey', '$event.metaKey'])\n onClick(button: number, ctrlKey: boolean, shiftKey: boolean, altKey: boolean, metaKey: boolean):\n boolean {\n if (this.urlTree === null) {\n return true;\n }\n\n if (this.isAnchorElement) {\n if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) {\n return true;\n }\n\n if (typeof this.target === 'string' && this.target != '_self') {\n return true;\n }\n }\n\n const extras = {\n skipLocationChange: this.skipLocationChange,\n replaceUrl: this.replaceUrl,\n state: this.state,\n };\n this.router.navigateByUrl(this.urlTree, extras);\n\n // Return `false` for `<a>` elements to prevent default action\n // and cancel the native behavior, since the navigation is handled\n // by the Router.\n return !this.isAnchorElement;\n }\n\n /** @nodoc */\n ngOnDestroy(): any {\n this.subscription?.unsubscribe();\n }\n\n private updateHref(): void {\n this.href = this.urlTree !== null && this.locationStrategy ?\n this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(this.urlTree)) :\n null;\n\n const sanitizedValue = this.href === null ?\n null :\n // This class represents a directive that can be added to both `<a>` elements,\n // as well as other elements. As a result, we can't define security context at\n // compile time. So the security context is deferred to runtime.\n // The `ɵɵsanitizeUrlOrResourceUrl` selects the necessary sanitizer function\n // based on the tag and property names. The logic mimics the one from\n // `packages/compiler/src/schema/dom_security_schema.ts`, which is used at compile time.\n //\n // Note: we should investigate whether we can switch to using `@HostBinding('attr.href')`\n // instead of applying a value via a renderer, after a final merge of the\n // `RouterLinkWithHref` directive.\n ɵɵsanitizeUrlOrResourceUrl(this.href, this.el.nativeElement.tagName.toLowerCase(), 'href');\n this.applyAttributeValue('href', sanitizedValue);\n }\n\n private applyAttributeValue(attrName: string, attrValue: string|null) {\n const renderer = this.renderer;\n const nativeElement = this.el.nativeElement;\n if (attrValue !== null) {\n renderer.setAttribute(nativeElement, attrName, attrValue);\n } else {\n renderer.removeAttribute(nativeElement, attrName);\n }\n }\n\n get urlTree(): UrlTree|null {\n if (this.commands === null) {\n return null;\n }\n return this.router.createUrlTree(this.commands, {\n // If the `relativeTo` input is not defined, we want to use `this.route` by default.\n // Otherwise, we should use the value provided by the user in the input.\n relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,\n queryParams: this.queryParams,\n fragment: this.fragment,\n queryParamsHandling: this.queryParamsHandling,\n preserveFragment: this.preserveFragment,\n });\n }\n}\n\n/**\n * @description\n * An alias for the `RouterLink` directive.\n * Deprecated since v15, use `RouterLink` directive instead.\n *\n * @deprecated use `RouterLink` directive instead.\n * @publicApi\n */\nexport {RouterLink as RouterLinkWithHref};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Compiler, createEnvironmentInjector, EnvironmentInjector, Injectable, OnDestroy} from '@angular/core';\nimport {from, Observable, of, Subscription} from 'rxjs';\nimport {catchError, concatMap, filter, mergeAll, mergeMap} from 'rxjs/operators';\n\nimport {Event, NavigationEnd} from './events';\nimport {LoadedRouterConfig, Route, Routes} from './models';\nimport {Router} from './router';\nimport {RouterConfigLoader} from './router_config_loader';\n\n\n/**\n * @description\n *\n * Provides a preloading strategy.\n *\n * @publicApi\n */\nexport abstract class PreloadingStrategy {\n abstract preload(route: Route, fn: () => Observable<any>): Observable<any>;\n}\n\n/**\n * @description\n *\n * Provides a preloading strategy that preloads all modules as quickly as possible.\n *\n * ```\n * RouterModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})\n * ```\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class PreloadAllModules implements PreloadingStrategy {\n preload(route: Route, fn: () => Observable<any>): Observable<any> {\n return fn().pipe(catchError(() => of(null)));\n }\n}\n\n/**\n * @description\n *\n * Provides a preloading strategy that does not preload any modules.\n *\n * This strategy is enabled by default.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class NoPreloading implements PreloadingStrategy {\n preload(route: Route, fn: () => Observable<any>): Observable<any> {\n return of(null);\n }\n}\n\n/**\n * The preloader optimistically loads all router configurations to\n * make navigations into lazily-loaded sections of the application faster.\n *\n * The preloader runs in the background. When the router bootstraps, the preloader\n * starts listening to all navigation events. After every such event, the preloader\n * will check if any configurations can be loaded lazily.\n *\n * If a route is protected by `canLoad` guards, the preloaded will not load it.\n *\n * @publicApi\n */\n@Injectable({providedIn: 'root'})\nexport class RouterPreloader implements OnDestroy {\n private subscription?: Subscription;\n\n constructor(\n private router: Router, compiler: Compiler, private injector: EnvironmentInjector,\n private preloadingStrategy: PreloadingStrategy, private loader: RouterConfigLoader) {}\n\n setUpPreloading(): void {\n this.subscription =\n this.router.events\n .pipe(filter((e: Event) => e instanceof NavigationEnd), concatMap(() => this.preload()))\n .subscribe(() => {});\n }\n\n preload(): Observable<any> {\n return this.processRoutes(this.injector, this.router.config);\n }\n\n /** @nodoc */\n ngOnDestroy(): void {\n if (this.subscription) {\n this.subscription.unsubscribe();\n }\n }\n\n private processRoutes(injector: EnvironmentInjector, routes: Routes): Observable<void> {\n const res: Observable<any>[] = [];\n for (const route of routes) {\n if (route.providers && !route._injector) {\n route._injector =\n createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);\n }\n\n const injectorForCurrentRoute = route._injector ?? injector;\n const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;\n\n // Note that `canLoad` is only checked as a condition that prevents `loadChildren` and not\n // `loadComponent`. `canLoad` guards only block loading of child routes by design. This\n // happens as a consequence of needing to descend into children for route matching immediately\n // while component loading is deferred until route activation. Because `canLoad` guards can\n // have side effects, we cannot execute them here so we instead skip preloading altogether\n // when present. Lastly, it remains to be decided whether `canLoad` should behave this way\n // at all. Code splitting and lazy loading is separate from client-side authorization checks\n // and should not be used as a security measure to prevent loading of code.\n if ((route.loadChildren && !route._loadedRoutes && route.canLoad === undefined) ||\n (route.loadComponent && !route._loadedComponent)) {\n res.push(this.preloadConfig(injectorForCurrentRoute, route));\n }\n if (route.children || route._loadedRoutes) {\n res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)!));\n }\n }\n return from(res).pipe(mergeAll());\n }\n\n private preloadConfig(injector: EnvironmentInjector, route: Route): Observable<void> {\n return this.preloadingStrategy.preload(route, () => {\n let loadedChildren$: Observable<LoadedRouterConfig|null>;\n if (route.loadChildren && route.canLoad === undefined) {\n loadedChildren$ = this.loader.loadChildren(injector, route);\n } else {\n loadedChildren$ = of(null);\n }\n\n const recursiveLoadChildren$ =\n loadedChildren$.pipe(mergeMap((config: LoadedRouterConfig|null) => {\n if (config === null) {\n return of(void 0);\n }\n route._loadedRoutes = config.routes;\n route._loadedInjector = config.injector;\n // If the loaded config was a module, use that as the module/module injector going\n // forward. Otherwise, continue using the current module/module injector.\n return this.processRoutes(config.injector ?? injector, config.routes);\n }));\n if (route.loadComponent && !route._loadedComponent) {\n const loadComponent$ = this.loader.loadComponent(route);\n return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());\n } else {\n return recursiveLoadChildren$;\n }\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ViewportScroller} from '@angular/common';\nimport {Injectable, InjectionToken, NgZone, OnDestroy} from '@angular/core';\nimport {Unsubscribable} from 'rxjs';\n\nimport {NavigationEnd, NavigationStart, Scroll} from './events';\nimport {NavigationTransitions} from './navigation_transition';\nimport {Router} from './router';\nimport {UrlSerializer} from './url_tree';\n\nexport const ROUTER_SCROLLER = new InjectionToken<RouterScroller>('');\n\n@Injectable()\nexport class RouterScroller implements OnDestroy {\n private routerEventsSubscription?: Unsubscribable;\n private scrollEventsSubscription?: Unsubscribable;\n\n private lastId = 0;\n private lastSource: 'imperative'|'popstate'|'hashchange'|undefined = 'imperative';\n private restoredId = 0;\n private store: {[key: string]: [number, number]} = {};\n\n /** @nodoc */\n constructor(\n readonly urlSerializer: UrlSerializer, private transitions: NavigationTransitions,\n public readonly viewportScroller: ViewportScroller, private readonly zone: NgZone,\n private options: {\n scrollPositionRestoration?: 'disabled'|'enabled'|'top',\n anchorScrolling?: 'disabled'|'enabled'\n } = {}) {\n // Default both options to 'disabled'\n options.scrollPositionRestoration = options.scrollPositionRestoration || 'disabled';\n options.anchorScrolling = options.anchorScrolling || 'disabled';\n }\n\n init(): void {\n // we want to disable the automatic scrolling because having two places\n // responsible for scrolling results race conditions, especially given\n // that browser don't implement this behavior consistently\n if (this.options.scrollPositionRestoration !== 'disabled') {\n this.viewportScroller.setHistoryScrollRestoration('manual');\n }\n this.routerEventsSubscription = this.createScrollEvents();\n this.scrollEventsSubscription = this.consumeScrollEvents();\n }\n\n private createScrollEvents() {\n return this.transitions.events.subscribe(e => {\n if (e instanceof NavigationStart) {\n // store the scroll position of the current stable navigations.\n this.store[this.lastId] = this.viewportScroller.getScrollPosition();\n this.lastSource = e.navigationTrigger;\n this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;\n } else if (e instanceof NavigationEnd) {\n this.lastId = e.id;\n this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);\n }\n });\n }\n\n private consumeScrollEvents() {\n return this.transitions.events.subscribe(e => {\n if (!(e instanceof Scroll)) return;\n // a popstate event. The pop state event will always ignore anchor scrolling.\n if (e.position) {\n if (this.options.scrollPositionRestoration === 'top') {\n this.viewportScroller.scrollToPosition([0, 0]);\n } else if (this.options.scrollPositionRestoration === 'enabled') {\n this.viewportScroller.scrollToPosition(e.position);\n }\n // imperative navigation \"forward\"\n } else {\n if (e.anchor && this.options.anchorScrolling === 'enabled') {\n this.viewportScroller.scrollToAnchor(e.anchor);\n } else if (this.options.scrollPositionRestoration !== 'disabled') {\n this.viewportScroller.scrollToPosition([0, 0]);\n }\n }\n });\n }\n\n private scheduleScrollEvent(routerEvent: NavigationEnd, anchor: string|null): void {\n this.zone.runOutsideAngular(() => {\n // The scroll event needs to be delayed until after change detection. Otherwise, we may\n // attempt to restore the scroll position before the router outlet has fully rendered the\n // component by executing its update block of the template function.\n setTimeout(() => {\n this.zone.run(() => {\n this.transitions.events.next(new Scroll(\n routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null,\n anchor));\n });\n }, 0);\n });\n }\n\n /** @nodoc */\n ngOnDestroy() {\n this.routerEventsSubscription?.unsubscribe();\n this.scrollEventsSubscription?.unsubscribe();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {filter, map, take} from 'rxjs/operators';\n\nimport {NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped} from '../events';\nimport {Router} from '../router';\n\nenum NavigationResult {\n COMPLETE,\n FAILED,\n REDIRECTING,\n}\n\n/**\n * Performs the given action once the router finishes its next/current navigation.\n *\n * The navigation is considered complete under the following conditions:\n * - `NavigationCancel` event emits and the code is not `NavigationCancellationCode.Redirect` or\n * `NavigationCancellationCode.SupersededByNewNavigation`. In these cases, the\n * redirecting/superseding navigation must finish.\n * - `NavigationError`, `NavigationEnd`, or `NavigationSkipped` event emits\n */\nexport function afterNextNavigation(router: Router, action: () => void) {\n router.events\n .pipe(\n filter(\n (e): e is NavigationEnd|NavigationCancel|NavigationError|NavigationSkipped =>\n e instanceof NavigationEnd || e instanceof NavigationCancel ||\n e instanceof NavigationError || e instanceof NavigationSkipped),\n map(e => {\n if (e instanceof NavigationEnd || e instanceof NavigationSkipped) {\n return NavigationResult.COMPLETE;\n }\n const redirecting = e instanceof NavigationCancel ?\n (e.code === NavigationCancellationCode.Redirect ||\n e.code === NavigationCancellationCode.SupersededByNewNavigation) :\n false;\n return redirecting ? NavigationResult.REDIRECTING : NavigationResult.FAILED;\n }),\n filter(\n (result): result is NavigationResult.COMPLETE|NavigationResult.FAILED =>\n result !== NavigationResult.REDIRECTING),\n take(1),\n )\n .subscribe(() => {\n action();\n });\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {HashLocationStrategy, LOCATION_INITIALIZED, LocationStrategy, ViewportScroller} from '@angular/common';\nimport {APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, ApplicationRef, ComponentRef, ENVIRONMENT_INITIALIZER, EnvironmentInjector, EnvironmentProviders, inject, InjectFlags, InjectionToken, Injector, makeEnvironmentProviders, NgZone, Provider, Type} from '@angular/core';\nimport {of, Subject} from 'rxjs';\nimport {filter, map, take} from 'rxjs/operators';\n\nimport {Event, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, stringifyEvent} from './events';\nimport {Routes} from './models';\nimport {NavigationTransitions} from './navigation_transition';\nimport {Router} from './router';\nimport {InMemoryScrollingOptions, ROUTER_CONFIGURATION, RouterConfigOptions} from './router_config';\nimport {ROUTES} from './router_config_loader';\nimport {PreloadingStrategy, RouterPreloader} from './router_preloader';\nimport {ROUTER_SCROLLER, RouterScroller} from './router_scroller';\nimport {ActivatedRoute} from './router_state';\nimport {UrlSerializer} from './url_tree';\nimport {afterNextNavigation} from './utils/navigations';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n/**\n * Sets up providers necessary to enable `Router` functionality for the application.\n * Allows to configure a set of routes as well as extra features that should be enabled.\n *\n * @usageNotes\n *\n * Basic example of how you can add a Router to your application:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent, {\n * providers: [provideRouter(appRoutes)]\n * });\n * ```\n *\n * You can also enable optional features in the Router by adding functions from the `RouterFeatures`\n * type:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes,\n * withDebugTracing(),\n * withRouterConfig({paramsInheritanceStrategy: 'always'}))\n * ]\n * }\n * );\n * ```\n *\n * @see `RouterFeatures`\n *\n * @publicApi\n * @param routes A set of `Route`s to use for the application routing table.\n * @param features Optional features to configure additional router behaviors.\n * @returns A set of providers to setup a Router.\n */\nexport function provideRouter(routes: Routes, ...features: RouterFeatures[]): EnvironmentProviders {\n return makeEnvironmentProviders([\n {provide: ROUTES, multi: true, useValue: routes},\n NG_DEV_MODE ? {provide: ROUTER_IS_PROVIDED, useValue: true} : [],\n {provide: ActivatedRoute, useFactory: rootRoute, deps: [Router]},\n {provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: getBootstrapListener},\n features.map(feature => feature.ɵproviders),\n ]);\n}\n\nexport function rootRoute(router: Router): ActivatedRoute {\n return router.routerState.root;\n}\n\n/**\n * Helper type to represent a Router feature.\n *\n * @publicApi\n */\nexport interface RouterFeature<FeatureKind extends RouterFeatureKind> {\n ɵkind: FeatureKind;\n ɵproviders: Provider[];\n}\n\n/**\n * Helper function to create an object that represents a Router feature.\n */\nfunction routerFeature<FeatureKind extends RouterFeatureKind>(\n kind: FeatureKind, providers: Provider[]): RouterFeature<FeatureKind> {\n return {ɵkind: kind, ɵproviders: providers};\n}\n\n\n/**\n * An Injection token used to indicate whether `provideRouter` or `RouterModule.forRoot` was ever\n * called.\n */\nexport const ROUTER_IS_PROVIDED =\n new InjectionToken<boolean>('', {providedIn: 'root', factory: () => false});\n\nconst routerIsProvidedDevModeCheck = {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useFactory() {\n return () => {\n if (!inject(ROUTER_IS_PROVIDED)) {\n console.warn(\n '`provideRoutes` was called without `provideRouter` or `RouterModule.forRoot`. ' +\n 'This is likely a mistake.');\n }\n };\n }\n};\n\n/**\n * Registers a [DI provider](guide/glossary#provider) for a set of routes.\n * @param routes The route configuration to provide.\n *\n * @usageNotes\n *\n * ```\n * @NgModule({\n * providers: [provideRoutes(ROUTES)]\n * })\n * class LazyLoadedChildModule {}\n * ```\n *\n * @deprecated If necessary, provide routes using the `ROUTES` `InjectionToken`.\n * @see `ROUTES`\n * @publicApi\n */\nexport function provideRoutes(routes: Routes): Provider[] {\n return [\n {provide: ROUTES, multi: true, useValue: routes},\n NG_DEV_MODE ? routerIsProvidedDevModeCheck : [],\n ];\n}\n\n/**\n * A type alias for providers returned by `withInMemoryScrolling` for use with `provideRouter`.\n *\n * @see `withInMemoryScrolling`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type InMemoryScrollingFeature = RouterFeature<RouterFeatureKind.InMemoryScrollingFeature>;\n\n/**\n * Enables customizable scrolling behavior for router navigations.\n *\n * @usageNotes\n *\n * Basic example of how you can enable scrolling feature:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withInMemoryScrolling())\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n * @see `ViewportScroller`\n *\n * @publicApi\n * @param options Set of configuration parameters to customize scrolling behavior, see\n * `InMemoryScrollingOptions` for additional information.\n * @returns A set of providers for use with `provideRouter`.\n */\nexport function withInMemoryScrolling(options: InMemoryScrollingOptions = {}):\n InMemoryScrollingFeature {\n const providers = [{\n provide: ROUTER_SCROLLER,\n useFactory: () => {\n const viewportScroller = inject(ViewportScroller);\n const zone = inject(NgZone);\n const transitions = inject(NavigationTransitions);\n const urlSerializer = inject(UrlSerializer);\n return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);\n },\n }];\n return routerFeature(RouterFeatureKind.InMemoryScrollingFeature, providers);\n}\n\nexport function getBootstrapListener() {\n const injector = inject(Injector);\n return (bootstrappedComponentRef: ComponentRef<unknown>) => {\n const ref = injector.get(ApplicationRef);\n\n if (bootstrappedComponentRef !== ref.components[0]) {\n return;\n }\n\n const router = injector.get(Router);\n const bootstrapDone = injector.get(BOOTSTRAP_DONE);\n\n if (injector.get(INITIAL_NAVIGATION) === InitialNavigation.EnabledNonBlocking) {\n router.initialNavigation();\n }\n\n injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();\n injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();\n router.resetRootComponentType(ref.componentTypes[0]);\n if (!bootstrapDone.closed) {\n bootstrapDone.next();\n bootstrapDone.complete();\n bootstrapDone.unsubscribe();\n }\n };\n}\n\n/**\n * A subject used to indicate that the bootstrapping phase is done. When initial navigation is\n * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing\n * to the activation phase.\n */\nconst BOOTSTRAP_DONE =\n new InjectionToken<Subject<void>>(NG_DEV_MODE ? 'bootstrap done indicator' : '', {\n factory: () => {\n return new Subject<void>();\n }\n });\n\n/**\n * This and the INITIAL_NAVIGATION token are used internally only. The public API side of this is\n * configured through the `ExtraOptions`.\n *\n * When set to `EnabledBlocking`, the initial navigation starts before the root\n * component is created. The bootstrap is blocked until the initial navigation is complete. This\n * value is required for [server-side rendering](guide/universal) to work.\n *\n * When set to `EnabledNonBlocking`, the initial navigation starts after the root component has been\n * created. The bootstrap is not blocked on the completion of the initial navigation.\n *\n * When set to `Disabled`, the initial navigation is not performed. The location listener is set up\n * before the root component gets created. Use if there is a reason to have more control over when\n * the router starts its initial navigation due to some complex initialization logic.\n *\n * @see `ExtraOptions`\n */\nconst enum InitialNavigation {\n EnabledBlocking,\n EnabledNonBlocking,\n Disabled,\n}\n\nconst INITIAL_NAVIGATION = new InjectionToken<InitialNavigation>(\n NG_DEV_MODE ? 'initial navigation' : '',\n {providedIn: 'root', factory: () => InitialNavigation.EnabledNonBlocking});\n\n/**\n * A type alias for providers returned by `withEnabledBlockingInitialNavigation` for use with\n * `provideRouter`.\n *\n * @see `withEnabledBlockingInitialNavigation`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type EnabledBlockingInitialNavigationFeature =\n RouterFeature<RouterFeatureKind.EnabledBlockingInitialNavigationFeature>;\n\n/**\n * A type alias for providers returned by `withEnabledBlockingInitialNavigation` or\n * `withDisabledInitialNavigation` functions for use with `provideRouter`.\n *\n * @see `withEnabledBlockingInitialNavigation`\n * @see `withDisabledInitialNavigation`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type InitialNavigationFeature =\n EnabledBlockingInitialNavigationFeature|DisabledInitialNavigationFeature;\n\n/**\n * Configures initial navigation to start before the root component is created.\n *\n * The bootstrap is blocked until the initial navigation is complete. This value is required for\n * [server-side rendering](guide/universal) to work.\n *\n * @usageNotes\n *\n * Basic example of how you can enable this navigation behavior:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withEnabledBlockingInitialNavigation())\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n *\n * @publicApi\n * @returns A set of providers for use with `provideRouter`.\n */\nexport function withEnabledBlockingInitialNavigation(): EnabledBlockingInitialNavigationFeature {\n const providers = [\n {provide: INITIAL_NAVIGATION, useValue: InitialNavigation.EnabledBlocking},\n {\n provide: APP_INITIALIZER,\n multi: true,\n deps: [Injector],\n useFactory: (injector: Injector) => {\n const locationInitialized: Promise<any> =\n injector.get(LOCATION_INITIALIZED, Promise.resolve());\n\n return () => {\n return locationInitialized.then(() => {\n return new Promise(resolve => {\n const router = injector.get(Router);\n const bootstrapDone = injector.get(BOOTSTRAP_DONE);\n afterNextNavigation(router, () => {\n // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored\n // without a redirect.\n resolve(true);\n });\n\n injector.get(NavigationTransitions).afterPreactivation = () => {\n // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we\n // assume activation will complete successfully (even though this is not\n // guaranteed).\n resolve(true);\n return bootstrapDone.closed ? of(void 0) : bootstrapDone;\n };\n router.initialNavigation();\n });\n });\n };\n }\n },\n ];\n return routerFeature(RouterFeatureKind.EnabledBlockingInitialNavigationFeature, providers);\n}\n\n/**\n * A type alias for providers returned by `withDisabledInitialNavigation` for use with\n * `provideRouter`.\n *\n * @see `withDisabledInitialNavigation`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type DisabledInitialNavigationFeature =\n RouterFeature<RouterFeatureKind.DisabledInitialNavigationFeature>;\n\n/**\n * Disables initial navigation.\n *\n * Use if there is a reason to have more control over when the router starts its initial navigation\n * due to some complex initialization logic.\n *\n * @usageNotes\n *\n * Basic example of how you can disable initial navigation:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withDisabledInitialNavigation())\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n *\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withDisabledInitialNavigation(): DisabledInitialNavigationFeature {\n const providers = [\n {\n provide: APP_INITIALIZER,\n multi: true,\n useFactory: () => {\n const router = inject(Router);\n return () => {\n router.setUpLocationChangeListener();\n };\n }\n },\n {provide: INITIAL_NAVIGATION, useValue: InitialNavigation.Disabled}\n ];\n return routerFeature(RouterFeatureKind.DisabledInitialNavigationFeature, providers);\n}\n\n/**\n * A type alias for providers returned by `withDebugTracing` for use with `provideRouter`.\n *\n * @see `withDebugTracing`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type DebugTracingFeature = RouterFeature<RouterFeatureKind.DebugTracingFeature>;\n\n/**\n * Enables logging of all internal navigation events to the console.\n * Extra logging might be useful for debugging purposes to inspect Router event sequence.\n *\n * @usageNotes\n *\n * Basic example of how you can enable debug tracing:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withDebugTracing())\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n *\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withDebugTracing(): DebugTracingFeature {\n let providers: Provider[] = [];\n if (NG_DEV_MODE) {\n providers = [{\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useFactory: () => {\n const router = inject(Router);\n return () => router.events.subscribe((e: Event) => {\n // tslint:disable:no-console\n console.group?.(`Router Event: ${(<any>e.constructor).name}`);\n console.log(stringifyEvent(e));\n console.log(e);\n console.groupEnd?.();\n // tslint:enable:no-console\n });\n }\n }];\n } else {\n providers = [];\n }\n return routerFeature(RouterFeatureKind.DebugTracingFeature, providers);\n}\n\nconst ROUTER_PRELOADER = new InjectionToken<RouterPreloader>(NG_DEV_MODE ? 'router preloader' : '');\n\n/**\n * A type alias that represents a feature which enables preloading in Router.\n * The type is used to describe the return value of the `withPreloading` function.\n *\n * @see `withPreloading`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type PreloadingFeature = RouterFeature<RouterFeatureKind.PreloadingFeature>;\n\n/**\n * Allows to configure a preloading strategy to use. The strategy is configured by providing a\n * reference to a class that implements a `PreloadingStrategy`.\n *\n * @usageNotes\n *\n * Basic example of how you can configure preloading:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withPreloading(PreloadAllModules))\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n *\n * @param preloadingStrategy A reference to a class that implements a `PreloadingStrategy` that\n * should be used.\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withPreloading(preloadingStrategy: Type<PreloadingStrategy>): PreloadingFeature {\n const providers = [\n {provide: ROUTER_PRELOADER, useExisting: RouterPreloader},\n {provide: PreloadingStrategy, useExisting: preloadingStrategy},\n ];\n return routerFeature(RouterFeatureKind.PreloadingFeature, providers);\n}\n\n/**\n * A type alias for providers returned by `withRouterConfig` for use with `provideRouter`.\n *\n * @see `withRouterConfig`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type RouterConfigurationFeature =\n RouterFeature<RouterFeatureKind.RouterConfigurationFeature>;\n\n/**\n * Allows to provide extra parameters to configure Router.\n *\n * @usageNotes\n *\n * Basic example of how you can provide extra configuration options:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withRouterConfig({\n * onSameUrlNavigation: 'reload'\n * }))\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n *\n * @param options A set of parameters to configure Router, see `RouterConfigOptions` for\n * additional information.\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withRouterConfig(options: RouterConfigOptions): RouterConfigurationFeature {\n const providers = [\n {provide: ROUTER_CONFIGURATION, useValue: options},\n ];\n return routerFeature(RouterFeatureKind.RouterConfigurationFeature, providers);\n}\n\n/**\n * A type alias for providers returned by `withHashLocation` for use with `provideRouter`.\n *\n * @see `withHashLocation`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type RouterHashLocationFeature = RouterFeature<RouterFeatureKind.RouterHashLocationFeature>;\n\n/**\n * Provides the location strategy that uses the URL fragment instead of the history API.\n *\n * @usageNotes\n *\n * Basic example of how you can use the hash location option:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withHashLocation())\n * ]\n * }\n * );\n * ```\n *\n * @see `provideRouter`\n * @see `HashLocationStrategy`\n *\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withHashLocation(): RouterConfigurationFeature {\n const providers = [\n {provide: LocationStrategy, useClass: HashLocationStrategy},\n ];\n return routerFeature(RouterFeatureKind.RouterConfigurationFeature, providers);\n}\n\n/**\n * A type alias for providers returned by `withNavigationErrorHandler` for use with `provideRouter`.\n *\n * @see `withNavigationErrorHandler`\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type NavigationErrorHandlerFeature =\n RouterFeature<RouterFeatureKind.NavigationErrorHandlerFeature>;\n\n/**\n * Subscribes to the Router's navigation events and calls the given function when a\n * `NavigationError` happens.\n *\n * This function is run inside application's injection context so you can use the `inject` function.\n *\n * @usageNotes\n *\n * Basic example of how you can use the error handler option:\n * ```\n * const appRoutes: Routes = [];\n * bootstrapApplication(AppComponent,\n * {\n * providers: [\n * provideRouter(appRoutes, withNavigationErrorHandler((e: NavigationError) =>\n * inject(MyErrorTracker).trackError(e)))\n * ]\n * }\n * );\n * ```\n *\n * @see `NavigationError`\n * @see `inject`\n * @see `EnvironmentInjector#runInContext`\n *\n * @returns A set of providers for use with `provideRouter`.\n *\n * @publicApi\n */\nexport function withNavigationErrorHandler(fn: (error: NavigationError) => void):\n NavigationErrorHandlerFeature {\n const providers = [{\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useValue: () => {\n const injector = inject(EnvironmentInjector);\n inject(Router).events.subscribe((e) => {\n if (e instanceof NavigationError) {\n injector.runInContext(() => fn(e));\n }\n });\n }\n }];\n return routerFeature(RouterFeatureKind.NavigationErrorHandlerFeature, providers);\n}\n\n/**\n * A type alias that represents all Router features available for use with `provideRouter`.\n * Features can be enabled by adding special functions to the `provideRouter` call.\n * See documentation for each symbol to find corresponding function name. See also `provideRouter`\n * documentation on how to use those functions.\n *\n * @see `provideRouter`\n *\n * @publicApi\n */\nexport type RouterFeatures = PreloadingFeature|DebugTracingFeature|InitialNavigationFeature|\n InMemoryScrollingFeature|RouterConfigurationFeature|NavigationErrorHandlerFeature;\n\n/**\n * The list of features as an enum to uniquely type each feature.\n */\nexport const enum RouterFeatureKind {\n PreloadingFeature,\n DebugTracingFeature,\n EnabledBlockingInitialNavigationFeature,\n DisabledInitialNavigationFeature,\n InMemoryScrollingFeature,\n RouterConfigurationFeature,\n RouterHashLocationFeature,\n NavigationErrorHandlerFeature,\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {HashLocationStrategy, Location, LocationStrategy, PathLocationStrategy, ViewportScroller} from '@angular/common';\nimport {APP_BOOTSTRAP_LISTENER, ComponentRef, inject, Inject, InjectionToken, ModuleWithProviders, NgModule, NgProbeToken, NgZone, Optional, Provider, SkipSelf, ɵRuntimeError as RuntimeError} from '@angular/core';\n\nimport {EmptyOutletComponent} from './components/empty_outlet';\nimport {RouterLink} from './directives/router_link';\nimport {RouterLinkActive} from './directives/router_link_active';\nimport {RouterOutlet} from './directives/router_outlet';\nimport {RuntimeErrorCode} from './errors';\nimport {Routes} from './models';\nimport {NavigationTransitions} from './navigation_transition';\nimport {getBootstrapListener, rootRoute, ROUTER_IS_PROVIDED, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withPreloading} from './provide_router';\nimport {Router} from './router';\nimport {ExtraOptions, ROUTER_CONFIGURATION} from './router_config';\nimport {RouterConfigLoader, ROUTES} from './router_config_loader';\nimport {ChildrenOutletContexts} from './router_outlet_context';\nimport {ROUTER_SCROLLER, RouterScroller} from './router_scroller';\nimport {ActivatedRoute} from './router_state';\nimport {DefaultUrlSerializer, UrlSerializer} from './url_tree';\n\nconst NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;\n\n/**\n * The directives defined in the `RouterModule`.\n */\nconst ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, EmptyOutletComponent];\n\n/**\n * @docsNotRequired\n */\nexport const ROUTER_FORROOT_GUARD = new InjectionToken<void>(\n NG_DEV_MODE ? 'router duplicate forRoot guard' : 'ROUTER_FORROOT_GUARD');\n\n// TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept\n// here to avoid a breaking change whereby the provider order matters based on where the\n// `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a \"breaking\"\n// change in a major version.\nexport const ROUTER_PROVIDERS: Provider[] = [\n Location,\n {provide: UrlSerializer, useClass: DefaultUrlSerializer},\n Router,\n ChildrenOutletContexts,\n {provide: ActivatedRoute, useFactory: rootRoute, deps: [Router]},\n RouterConfigLoader,\n // Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can\n // be removed when `provideRoutes` is removed.\n NG_DEV_MODE ? {provide: ROUTER_IS_PROVIDED, useValue: true} : [],\n];\n\nexport function routerNgProbeToken() {\n return new NgProbeToken('Router', Router);\n}\n\n/**\n * @description\n *\n * Adds directives and providers for in-app navigation among views defined in an application.\n * Use the Angular `Router` service to declaratively specify application states and manage state\n * transitions.\n *\n * You can import this NgModule multiple times, once for each lazy-loaded bundle.\n * However, only one `Router` service can be active.\n * To ensure this, there are two ways to register routes when importing this module:\n *\n * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given\n * routes, and the `Router` service itself.\n * * The `forChild()` method creates an `NgModule` that contains all the directives and the given\n * routes, but does not include the `Router` service.\n *\n * @see [Routing and Navigation guide](guide/router) for an\n * overview of how the `Router` service should be used.\n *\n * @publicApi\n */\n@NgModule({\n imports: ROUTER_DIRECTIVES,\n exports: ROUTER_DIRECTIVES,\n})\nexport class RouterModule {\n constructor(@Optional() @Inject(ROUTER_FORROOT_GUARD) guard: any) {}\n\n /**\n * Creates and configures a module with all the router providers and directives.\n * Optionally sets up an application listener to perform an initial navigation.\n *\n * When registering the NgModule at the root, import as follows:\n *\n * ```\n * @NgModule({\n * imports: [RouterModule.forRoot(ROUTES)]\n * })\n * class MyNgModule {}\n * ```\n *\n * @param routes An array of `Route` objects that define the navigation paths for the application.\n * @param config An `ExtraOptions` configuration object that controls how navigation is performed.\n * @return The new `NgModule`.\n *\n */\n static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders<RouterModule> {\n return {\n ngModule: RouterModule,\n providers: [\n ROUTER_PROVIDERS,\n NG_DEV_MODE ? (config?.enableTracing ? withDebugTracing().ɵproviders : []) : [],\n {provide: ROUTES, multi: true, useValue: routes},\n {\n provide: ROUTER_FORROOT_GUARD,\n useFactory: provideForRootGuard,\n deps: [[Router, new Optional(), new SkipSelf()]]\n },\n {provide: ROUTER_CONFIGURATION, useValue: config ? config : {}},\n config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(),\n provideRouterScroller(),\n config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [],\n {provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken},\n config?.initialNavigation ? provideInitialNavigation(config) : [],\n provideRouterInitializer(),\n ],\n };\n }\n\n /**\n * Creates a module with all the router directives and a provider registering routes,\n * without creating a new Router service.\n * When registering for submodules and lazy-loaded submodules, create the NgModule as follows:\n *\n * ```\n * @NgModule({\n * imports: [RouterModule.forChild(ROUTES)]\n * })\n * class MyNgModule {}\n * ```\n *\n * @param routes An array of `Route` objects that define the navigation paths for the submodule.\n * @return The new NgModule.\n *\n */\n static forChild(routes: Routes): ModuleWithProviders<RouterModule> {\n return {\n ngModule: RouterModule,\n providers: [{provide: ROUTES, multi: true, useValue: routes}],\n };\n }\n}\n\n/**\n * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller`\n * because it reads from the `ExtraOptions` which should not be used in the standalone world.\n */\nexport function provideRouterScroller(): Provider {\n return {\n provide: ROUTER_SCROLLER,\n useFactory: () => {\n const viewportScroller = inject(ViewportScroller);\n const zone = inject(NgZone);\n const config: ExtraOptions = inject(ROUTER_CONFIGURATION);\n const transitions = inject(NavigationTransitions);\n const urlSerializer = inject(UrlSerializer);\n if (config.scrollOffset) {\n viewportScroller.setOffset(config.scrollOffset);\n }\n return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);\n },\n };\n}\n\n// Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should\n// provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`.\nfunction provideHashLocationStrategy(): Provider {\n return {provide: LocationStrategy, useClass: HashLocationStrategy};\n}\n\n// Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not\n// need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`.\nfunction providePathLocationStrategy(): Provider {\n return {provide: LocationStrategy, useClass: PathLocationStrategy};\n}\n\nexport function provideForRootGuard(router: Router): any {\n if (NG_DEV_MODE && router) {\n throw new RuntimeError(\n RuntimeErrorCode.FOR_ROOT_CALLED_TWICE,\n `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` +\n ` Lazy loaded modules should use RouterModule.forChild() instead.`);\n }\n return 'guarded';\n}\n\n// Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter`\n// users call `withXInitialNavigation` directly.\nfunction provideInitialNavigation(config: Pick<ExtraOptions, 'initialNavigation'>): Provider[] {\n return [\n config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [],\n config.initialNavigation === 'enabledBlocking' ?\n withEnabledBlockingInitialNavigation().ɵproviders :\n [],\n ];\n}\n\n// TODO(atscott): This should not be in the public API\n/**\n * A [DI token](guide/glossary/#di-token) for the router initializer that\n * is called after the app is bootstrapped.\n *\n * @publicApi\n */\nexport const ROUTER_INITIALIZER = new InjectionToken<(compRef: ComponentRef<any>) => void>(\n NG_DEV_MODE ? 'Router Initializer' : '');\n\nfunction provideRouterInitializer(): Provider[] {\n return [\n // ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just\n // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.\n {provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener},\n {provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER},\n ];\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Injectable, OnDestroy} from '@angular/core';\n\n// Users of the Dispatcher never need to see this type, but TypeScript requires it to be exported.\nexport type UniqueSelectionDispatcherListener = (id: string, name: string) => void;\n\n/**\n * Class to coordinate unique selection based on name.\n * Intended to be consumed as an Angular service.\n * This service is needed because native radio change events are only fired on the item currently\n * being selected, and we still need to uncheck the previous selection.\n *\n * This service does not *store* any IDs and names because they may change at any time, so it is\n * less error-prone if they are simply passed through when the events occur.\n */\n@Injectable({providedIn: 'root'})\nexport class UniqueSelectionDispatcher implements OnDestroy {\n private _listeners: UniqueSelectionDispatcherListener[] = [];\n\n /**\n * Notify other items that selection for the given name has been set.\n * @param id ID of the item.\n * @param name Name of the item.\n */\n notify(id: string, name: string) {\n for (let listener of this._listeners) {\n listener(id, name);\n }\n }\n\n /**\n * Listen for future changes to item selection.\n * @return Function used to deregister listener\n */\n listen(listener: UniqueSelectionDispatcherListener): () => void {\n this._listeners.push(listener);\n return () => {\n this._listeners = this._listeners.filter((registered: UniqueSelectionDispatcherListener) => {\n return listener !== registered;\n });\n };\n }\n\n ngOnDestroy() {\n this._listeners = [];\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {Directive, InjectionToken, Input, OnChanges, OnDestroy, SimpleChanges} from '@angular/core';\nimport {Subject} from 'rxjs';\n\n/** Used to generate unique ID for each accordion. */\nlet nextId = 0;\n\n/**\n * Injection token that can be used to reference instances of `CdkAccordion`. It serves\n * as alternative token to the actual `CdkAccordion` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const CDK_ACCORDION = new InjectionToken<CdkAccordion>('CdkAccordion');\n\n/**\n * Directive whose purpose is to manage the expanded state of CdkAccordionItem children.\n */\n@Directive({\n selector: 'cdk-accordion, [cdkAccordion]',\n exportAs: 'cdkAccordion',\n providers: [{provide: CDK_ACCORDION, useExisting: CdkAccordion}],\n})\nexport class CdkAccordion implements OnDestroy, OnChanges {\n /** Emits when the state of the accordion changes */\n readonly _stateChanges = new Subject<SimpleChanges>();\n\n /** Stream that emits true/false when openAll/closeAll is triggered. */\n readonly _openCloseAllActions: Subject<boolean> = new Subject<boolean>();\n\n /** A readonly id value to use for unique selection coordination. */\n readonly id: string = `cdk-accordion-${nextId++}`;\n\n /** Whether the accordion should allow multiple expanded accordion items simultaneously. */\n @Input()\n get multi(): boolean {\n return this._multi;\n }\n set multi(multi: BooleanInput) {\n this._multi = coerceBooleanProperty(multi);\n }\n private _multi: boolean = false;\n\n /** Opens all enabled accordion items in an accordion where multi is enabled. */\n openAll(): void {\n if (this._multi) {\n this._openCloseAllActions.next(true);\n }\n }\n\n /** Closes all enabled accordion items. */\n closeAll(): void {\n this._openCloseAllActions.next(false);\n }\n\n ngOnChanges(changes: SimpleChanges) {\n this._stateChanges.next(changes);\n }\n\n ngOnDestroy() {\n this._stateChanges.complete();\n this._openCloseAllActions.complete();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n Output,\n Directive,\n EventEmitter,\n Input,\n OnDestroy,\n Optional,\n ChangeDetectorRef,\n SkipSelf,\n Inject,\n} from '@angular/core';\nimport {UniqueSelectionDispatcher} from '@angular/cdk/collections';\nimport {CDK_ACCORDION, CdkAccordion} from './accordion';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {Subscription} from 'rxjs';\n\n/** Used to generate unique ID for each accordion item. */\nlet nextId = 0;\n\n/**\n * An basic directive expected to be extended and decorated as a component. Sets up all\n * events and attributes needed to be managed by a CdkAccordion parent.\n */\n@Directive({\n selector: 'cdk-accordion-item, [cdkAccordionItem]',\n exportAs: 'cdkAccordionItem',\n providers: [\n // Provide `CDK_ACCORDION` as undefined to prevent nested accordion items from\n // registering to the same accordion.\n {provide: CDK_ACCORDION, useValue: undefined},\n ],\n})\nexport class CdkAccordionItem implements OnDestroy {\n /** Subscription to openAll/closeAll events. */\n private _openCloseAllSubscription = Subscription.EMPTY;\n /** Event emitted every time the AccordionItem is closed. */\n @Output() readonly closed: EventEmitter<void> = new EventEmitter<void>();\n /** Event emitted every time the AccordionItem is opened. */\n @Output() readonly opened: EventEmitter<void> = new EventEmitter<void>();\n /** Event emitted when the AccordionItem is destroyed. */\n @Output() readonly destroyed: EventEmitter<void> = new EventEmitter<void>();\n\n /**\n * Emits whenever the expanded state of the accordion changes.\n * Primarily used to facilitate two-way binding.\n * @docs-private\n */\n @Output() readonly expandedChange: EventEmitter<boolean> = new EventEmitter<boolean>();\n\n /** The unique AccordionItem id. */\n readonly id: string = `cdk-accordion-child-${nextId++}`;\n\n /** Whether the AccordionItem is expanded. */\n @Input()\n get expanded(): boolean {\n return this._expanded;\n }\n set expanded(expanded: BooleanInput) {\n expanded = coerceBooleanProperty(expanded);\n\n // Only emit events and update the internal value if the value changes.\n if (this._expanded !== expanded) {\n this._expanded = expanded;\n this.expandedChange.emit(expanded);\n\n if (expanded) {\n this.opened.emit();\n /**\n * In the unique selection dispatcher, the id parameter is the id of the CdkAccordionItem,\n * the name value is the id of the accordion.\n */\n const accordionId = this.accordion ? this.accordion.id : this.id;\n this._expansionDispatcher.notify(this.id, accordionId);\n } else {\n this.closed.emit();\n }\n\n // Ensures that the animation will run when the value is set outside of an `@Input`.\n // This includes cases like the open, close and toggle methods.\n this._changeDetectorRef.markForCheck();\n }\n }\n private _expanded = false;\n\n /** Whether the AccordionItem is disabled. */\n @Input()\n get disabled(): boolean {\n return this._disabled;\n }\n set disabled(disabled: BooleanInput) {\n this._disabled = coerceBooleanProperty(disabled);\n }\n private _disabled = false;\n\n /** Unregister function for _expansionDispatcher. */\n private _removeUniqueSelectionListener: () => void = () => {};\n\n constructor(\n @Optional() @Inject(CDK_ACCORDION) @SkipSelf() public accordion: CdkAccordion,\n private _changeDetectorRef: ChangeDetectorRef,\n protected _expansionDispatcher: UniqueSelectionDispatcher,\n ) {\n this._removeUniqueSelectionListener = _expansionDispatcher.listen(\n (id: string, accordionId: string) => {\n if (\n this.accordion &&\n !this.accordion.multi &&\n this.accordion.id === accordionId &&\n this.id !== id\n ) {\n this.expanded = false;\n }\n },\n );\n\n // When an accordion item is hosted in an accordion, subscribe to open/close events.\n if (this.accordion) {\n this._openCloseAllSubscription = this._subscribeToOpenCloseAllActions();\n }\n }\n\n /** Emits an event for the accordion item being destroyed. */\n ngOnDestroy() {\n this.opened.complete();\n this.closed.complete();\n this.destroyed.emit();\n this.destroyed.complete();\n this._removeUniqueSelectionListener();\n this._openCloseAllSubscription.unsubscribe();\n }\n\n /** Toggles the expanded state of the accordion item. */\n toggle(): void {\n if (!this.disabled) {\n this.expanded = !this.expanded;\n }\n }\n\n /** Sets the expanded state of the accordion item to false. */\n close(): void {\n if (!this.disabled) {\n this.expanded = false;\n }\n }\n\n /** Sets the expanded state of the accordion item to true. */\n open(): void {\n if (!this.disabled) {\n this.expanded = true;\n }\n }\n\n private _subscribeToOpenCloseAllActions(): Subscription {\n return this.accordion._openCloseAllActions.subscribe(expanded => {\n // Only change expanded state if item is enabled\n if (!this.disabled) {\n this.expanded = expanded;\n }\n });\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {CdkAccordion} from './accordion';\nimport {CdkAccordionItem} from './accordion-item';\n\n@NgModule({\n exports: [CdkAccordion, CdkAccordionItem],\n declarations: [CdkAccordion, CdkAccordionItem],\n})\nexport class CdkAccordionModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\nimport {CdkAccordion} from '@angular/cdk/accordion';\n\n/** MatAccordion's display modes. */\nexport type MatAccordionDisplayMode = 'default' | 'flat';\n\n/** MatAccordion's toggle positions. */\nexport type MatAccordionTogglePosition = 'before' | 'after';\n\n/**\n * Base interface for a `MatAccordion`.\n * @docs-private\n */\nexport interface MatAccordionBase extends CdkAccordion {\n /** Whether the expansion indicator should be hidden. */\n hideToggle: boolean;\n\n /** Display mode used for all expansion panels in the accordion. */\n displayMode: MatAccordionDisplayMode;\n\n /** The position of the expansion indicator. */\n togglePosition: MatAccordionTogglePosition;\n\n /** Handles keyboard events coming in from the panel headers. */\n _handleHeaderKeydown: (event: KeyboardEvent) => void;\n\n /** Handles focus events on the panel headers. */\n _handleHeaderFocus: (header: any) => void;\n}\n\n/**\n * Token used to provide a `MatAccordion` to `MatExpansionPanel`.\n * Used primarily to avoid circular imports between `MatAccordion` and `MatExpansionPanel`.\n */\nexport const MAT_ACCORDION = new InjectionToken<MatAccordionBase>('MAT_ACCORDION');\n","<span class=\"mat-content\" [class.mat-content-hide-toggle]=\"!_showToggle()\">\n <ng-content select=\"mat-panel-title\"></ng-content>\n <ng-content select=\"mat-panel-description\"></ng-content>\n <ng-content></ng-content>\n</span>\n<span [@indicatorRotate]=\"_getExpandedState()\" *ngIf=\"_showToggle()\"\n class=\"mat-expansion-indicator\"></span>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directive, TemplateRef, Inject, Optional} from '@angular/core';\nimport {MAT_EXPANSION_PANEL, MatExpansionPanelBase} from './expansion-panel-base';\n\n/**\n * Expansion panel content that will be rendered lazily\n * after the panel is opened for the first time.\n */\n@Directive({\n selector: 'ng-template[matExpansionPanelContent]',\n})\nexport class MatExpansionPanelContent {\n constructor(\n public _template: TemplateRef<any>,\n @Inject(MAT_EXPANSION_PANEL) @Optional() public _expansionPanel?: MatExpansionPanelBase,\n ) {}\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport {\n animate,\n AnimationTriggerMetadata,\n state,\n style,\n transition,\n trigger,\n} from '@angular/animations';\n\n/** Time and timing curve for expansion panel animations. */\n// Note: Keep this in sync with the Sass variable for the panel header animation.\nexport const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,1)';\n\n/**\n * Animations used by the Material expansion panel.\n *\n * A bug in angular animation's `state` when ViewContainers are moved using ViewContainerRef.move()\n * causes the animation state of moved components to become `void` upon exit, and not update again\n * upon reentry into the DOM. This can lead a to situation for the expansion panel where the state\n * of the panel is `expanded` or `collapsed` but the animation state is `void`.\n *\n * To correctly handle animating to the next state, we animate between `void` and `collapsed` which\n * are defined to have the same styles. Since angular animates from the current styles to the\n * destination state's style definition, in situations where we are moving from `void`'s styles to\n * `collapsed` this acts a noop since no style values change.\n *\n * In the case where angular's animation state is out of sync with the expansion panel's state, the\n * expansion panel being `expanded` and angular animations being `void`, the animation from the\n * `expanded`'s effective styles (though in a `void` animation state) to the collapsed state will\n * occur as expected.\n *\n * Angular Bug: https://github.com/angular/angular/issues/18847\n *\n * @docs-private\n */\nexport const matExpansionAnimations: {\n readonly indicatorRotate: AnimationTriggerMetadata;\n readonly bodyExpansion: AnimationTriggerMetadata;\n} = {\n /** Animation that rotates the indicator arrow. */\n indicatorRotate: trigger('indicatorRotate', [\n state('collapsed, void', style({transform: 'rotate(0deg)'})),\n state('expanded', style({transform: 'rotate(180deg)'})),\n transition(\n 'expanded <=> collapsed, void => collapsed',\n animate(EXPANSION_PANEL_ANIMATION_TIMING),\n ),\n ]),\n /** Animation that expands and collapses the panel content. */\n bodyExpansion: trigger('bodyExpansion', [\n state('collapsed, void', style({height: '0px', visibility: 'hidden'})),\n state('expanded', style({height: '*', visibility: 'visible'})),\n transition(\n 'expanded <=> collapsed, void => collapsed',\n animate(EXPANSION_PANEL_ANIMATION_TIMING),\n ),\n ]),\n};\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {InjectionToken} from '@angular/core';\nimport {CdkAccordionItem} from '@angular/cdk/accordion';\n\n/**\n * Base interface for a `MatExpansionPanel`.\n * @docs-private\n */\nexport interface MatExpansionPanelBase extends CdkAccordionItem {\n /** Whether the toggle indicator should be hidden. */\n hideToggle: boolean;\n}\n\n/**\n * Token used to provide a `MatExpansionPanel` to `MatExpansionPanelContent`.\n * Used to avoid circular imports between `MatExpansionPanel` and `MatExpansionPanelContent`.\n */\nexport const MAT_EXPANSION_PANEL = new InjectionToken<MatExpansionPanelBase>('MAT_EXPANSION_PANEL');\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {AnimationEvent} from '@angular/animations';\nimport {CdkAccordionItem} from '@angular/cdk/accordion';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {UniqueSelectionDispatcher} from '@angular/cdk/collections';\nimport {TemplatePortal} from '@angular/cdk/portal';\nimport {DOCUMENT} from '@angular/common';\nimport {\n AfterContentInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n Directive,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Input,\n OnChanges,\n OnDestroy,\n Optional,\n Output,\n SimpleChanges,\n SkipSelf,\n ViewChild,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\nimport {Subject} from 'rxjs';\nimport {distinctUntilChanged, filter, startWith, take} from 'rxjs/operators';\nimport {MatAccordionBase, MatAccordionTogglePosition, MAT_ACCORDION} from './accordion-base';\nimport {matExpansionAnimations} from './expansion-animations';\nimport {MAT_EXPANSION_PANEL} from './expansion-panel-base';\nimport {MatExpansionPanelContent} from './expansion-panel-content';\n\n/** MatExpansionPanel's states. */\nexport type MatExpansionPanelState = 'expanded' | 'collapsed';\n\n/** Counter for generating unique element ids. */\nlet uniqueId = 0;\n\n/**\n * Object that can be used to override the default options\n * for all of the expansion panels in a module.\n */\nexport interface MatExpansionPanelDefaultOptions {\n /** Height of the header while the panel is expanded. */\n expandedHeight: string;\n\n /** Height of the header while the panel is collapsed. */\n collapsedHeight: string;\n\n /** Whether the toggle indicator should be hidden. */\n hideToggle: boolean;\n}\n\n/**\n * Injection token that can be used to configure the default\n * options for the expansion panel component.\n */\nexport const MAT_EXPANSION_PANEL_DEFAULT_OPTIONS =\n new InjectionToken<MatExpansionPanelDefaultOptions>('MAT_EXPANSION_PANEL_DEFAULT_OPTIONS');\n\n/**\n * This component can be used as a single element to show expandable content, or as one of\n * multiple children of an element with the MatAccordion directive attached.\n */\n@Component({\n styleUrls: ['expansion-panel.css'],\n selector: 'mat-expansion-panel',\n exportAs: 'matExpansionPanel',\n templateUrl: 'expansion-panel.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n inputs: ['disabled', 'expanded'],\n outputs: ['opened', 'closed', 'expandedChange'],\n animations: [matExpansionAnimations.bodyExpansion],\n providers: [\n // Provide MatAccordion as undefined to prevent nested expansion panels from registering\n // to the same accordion.\n {provide: MAT_ACCORDION, useValue: undefined},\n {provide: MAT_EXPANSION_PANEL, useExisting: MatExpansionPanel},\n ],\n host: {\n 'class': 'mat-expansion-panel',\n '[class.mat-expanded]': 'expanded',\n '[class._mat-animation-noopable]': '_animationMode === \"NoopAnimations\"',\n '[class.mat-expansion-panel-spacing]': '_hasSpacing()',\n },\n})\nexport class MatExpansionPanel\n extends CdkAccordionItem\n implements AfterContentInit, OnChanges, OnDestroy\n{\n private _document: Document;\n private _hideToggle = false;\n private _togglePosition: MatAccordionTogglePosition;\n\n /** Whether the toggle indicator should be hidden. */\n @Input()\n get hideToggle(): boolean {\n return this._hideToggle || (this.accordion && this.accordion.hideToggle);\n }\n set hideToggle(value: BooleanInput) {\n this._hideToggle = coerceBooleanProperty(value);\n }\n\n /** The position of the expansion indicator. */\n @Input()\n get togglePosition(): MatAccordionTogglePosition {\n return this._togglePosition || (this.accordion && this.accordion.togglePosition);\n }\n set togglePosition(value: MatAccordionTogglePosition) {\n this._togglePosition = value;\n }\n\n /** An event emitted after the body's expansion animation happens. */\n @Output() readonly afterExpand = new EventEmitter<void>();\n\n /** An event emitted after the body's collapse animation happens. */\n @Output() readonly afterCollapse = new EventEmitter<void>();\n\n /** Stream that emits for changes in `@Input` properties. */\n readonly _inputChanges = new Subject<SimpleChanges>();\n\n /** Optionally defined accordion the expansion panel belongs to. */\n override accordion: MatAccordionBase;\n\n /** Content that will be rendered lazily. */\n @ContentChild(MatExpansionPanelContent) _lazyContent: MatExpansionPanelContent;\n\n /** Element containing the panel's user-provided content. */\n @ViewChild('body') _body: ElementRef<HTMLElement>;\n\n /** Portal holding the user's content. */\n _portal: TemplatePortal;\n\n /** ID for the associated header element. Used for a11y labelling. */\n _headerId = `mat-expansion-panel-header-${uniqueId++}`;\n\n /** Stream of body animation done events. */\n readonly _bodyAnimationDone = new Subject<AnimationEvent>();\n\n constructor(\n @Optional() @SkipSelf() @Inject(MAT_ACCORDION) accordion: MatAccordionBase,\n _changeDetectorRef: ChangeDetectorRef,\n _uniqueSelectionDispatcher: UniqueSelectionDispatcher,\n private _viewContainerRef: ViewContainerRef,\n @Inject(DOCUMENT) _document: any,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode: string,\n @Inject(MAT_EXPANSION_PANEL_DEFAULT_OPTIONS)\n @Optional()\n defaultOptions?: MatExpansionPanelDefaultOptions,\n ) {\n super(accordion, _changeDetectorRef, _uniqueSelectionDispatcher);\n this.accordion = accordion;\n this._document = _document;\n\n // We need a Subject with distinctUntilChanged, because the `done` event\n // fires twice on some browsers. See https://github.com/angular/angular/issues/24084\n this._bodyAnimationDone\n .pipe(\n distinctUntilChanged((x, y) => {\n return x.fromState === y.fromState && x.toState === y.toState;\n }),\n )\n .subscribe(event => {\n if (event.fromState !== 'void') {\n if (event.toState === 'expanded') {\n this.afterExpand.emit();\n } else if (event.toState === 'collapsed') {\n this.afterCollapse.emit();\n }\n }\n });\n\n if (defaultOptions) {\n this.hideToggle = defaultOptions.hideToggle;\n }\n }\n\n /** Determines whether the expansion panel should have spacing between it and its siblings. */\n _hasSpacing(): boolean {\n if (this.accordion) {\n return this.expanded && this.accordion.displayMode === 'default';\n }\n return false;\n }\n\n /** Gets the expanded state string. */\n _getExpandedState(): MatExpansionPanelState {\n return this.expanded ? 'expanded' : 'collapsed';\n }\n\n /** Toggles the expanded state of the expansion panel. */\n override toggle(): void {\n this.expanded = !this.expanded;\n }\n\n /** Sets the expanded state of the expansion panel to false. */\n override close(): void {\n this.expanded = false;\n }\n\n /** Sets the expanded state of the expansion panel to true. */\n override open(): void {\n this.expanded = true;\n }\n\n ngAfterContentInit() {\n if (this._lazyContent && this._lazyContent._expansionPanel === this) {\n // Render the content as soon as the panel becomes open.\n this.opened\n .pipe(\n startWith(null),\n filter(() => this.expanded && !this._portal),\n take(1),\n )\n .subscribe(() => {\n this._portal = new TemplatePortal(this._lazyContent._template, this._viewContainerRef);\n });\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n this._inputChanges.next(changes);\n }\n\n override ngOnDestroy() {\n super.ngOnDestroy();\n this._bodyAnimationDone.complete();\n this._inputChanges.complete();\n }\n\n /** Checks whether the expansion panel's content contains the currently-focused element. */\n _containsFocus(): boolean {\n if (this._body) {\n const focusedElement = this._document.activeElement;\n const bodyElement = this._body.nativeElement;\n return focusedElement === bodyElement || bodyElement.contains(focusedElement);\n }\n\n return false;\n }\n}\n\n/**\n * Actions of a `<mat-expansion-panel>`.\n */\n@Directive({\n selector: 'mat-action-row',\n host: {\n class: 'mat-action-row',\n },\n})\nexport class MatExpansionPanelActionRow {}\n","<ng-content select=\"mat-expansion-panel-header\"></ng-content>\n<div class=\"mat-expansion-panel-content\"\n role=\"region\"\n [@bodyExpansion]=\"_getExpandedState()\"\n (@bodyExpansion.done)=\"_bodyAnimationDone.next($event)\"\n [attr.aria-labelledby]=\"_headerId\"\n [id]=\"id\"\n #body>\n <div class=\"mat-expansion-panel-body\">\n <ng-content></ng-content>\n <ng-template [cdkPortalOutlet]=\"_portal\"></ng-template>\n </div>\n <ng-content select=\"mat-action-row\"></ng-content>\n</div>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {FocusableOption, FocusMonitor, FocusOrigin} from '@angular/cdk/a11y';\nimport {ENTER, hasModifierKey, SPACE} from '@angular/cdk/keycodes';\nimport {\n AfterViewInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n Directive,\n ElementRef,\n Host,\n Inject,\n Input,\n OnDestroy,\n Optional,\n ViewEncapsulation,\n} from '@angular/core';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\nimport {HasTabIndex, mixinTabIndex} from '@angular/material/core';\nimport {EMPTY, merge, Subscription} from 'rxjs';\nimport {filter} from 'rxjs/operators';\nimport {MatAccordionTogglePosition} from './accordion-base';\nimport {matExpansionAnimations} from './expansion-animations';\nimport {\n MatExpansionPanel,\n MatExpansionPanelDefaultOptions,\n MAT_EXPANSION_PANEL_DEFAULT_OPTIONS,\n} from './expansion-panel';\n\n// Boilerplate for applying mixins to MatExpansionPanelHeader.\n/** @docs-private */\nabstract class MatExpansionPanelHeaderBase {\n abstract readonly disabled: boolean;\n}\nconst _MatExpansionPanelHeaderMixinBase = mixinTabIndex(MatExpansionPanelHeaderBase);\n\n/**\n * Header element of a `<mat-expansion-panel>`.\n */\n@Component({\n selector: 'mat-expansion-panel-header',\n styleUrls: ['expansion-panel-header.css'],\n templateUrl: 'expansion-panel-header.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n inputs: ['tabIndex'],\n animations: [matExpansionAnimations.indicatorRotate],\n host: {\n 'class': 'mat-expansion-panel-header mat-focus-indicator',\n 'role': 'button',\n '[attr.id]': 'panel._headerId',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-controls]': '_getPanelId()',\n '[attr.aria-expanded]': '_isExpanded()',\n '[attr.aria-disabled]': 'panel.disabled',\n '[class.mat-expanded]': '_isExpanded()',\n '[class.mat-expansion-toggle-indicator-after]': `_getTogglePosition() === 'after'`,\n '[class.mat-expansion-toggle-indicator-before]': `_getTogglePosition() === 'before'`,\n '[class._mat-animation-noopable]': '_animationMode === \"NoopAnimations\"',\n '[style.height]': '_getHeaderHeight()',\n '(click)': '_toggle()',\n '(keydown)': '_keydown($event)',\n },\n})\nexport class MatExpansionPanelHeader\n extends _MatExpansionPanelHeaderMixinBase\n implements AfterViewInit, OnDestroy, FocusableOption, HasTabIndex\n{\n private _parentChangeSubscription = Subscription.EMPTY;\n\n constructor(\n @Host() public panel: MatExpansionPanel,\n private _element: ElementRef,\n private _focusMonitor: FocusMonitor,\n private _changeDetectorRef: ChangeDetectorRef,\n @Inject(MAT_EXPANSION_PANEL_DEFAULT_OPTIONS)\n @Optional()\n defaultOptions?: MatExpansionPanelDefaultOptions,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode?: string,\n @Attribute('tabindex') tabIndex?: string,\n ) {\n super();\n const accordionHideToggleChange = panel.accordion\n ? panel.accordion._stateChanges.pipe(\n filter(changes => !!(changes['hideToggle'] || changes['togglePosition'])),\n )\n : EMPTY;\n this.tabIndex = parseInt(tabIndex || '') || 0;\n\n // Since the toggle state depends on an @Input on the panel, we\n // need to subscribe and trigger change detection manually.\n this._parentChangeSubscription = merge(\n panel.opened,\n panel.closed,\n accordionHideToggleChange,\n panel._inputChanges.pipe(\n filter(changes => {\n return !!(changes['hideToggle'] || changes['disabled'] || changes['togglePosition']);\n }),\n ),\n ).subscribe(() => this._changeDetectorRef.markForCheck());\n\n // Avoids focus being lost if the panel contained the focused element and was closed.\n panel.closed\n .pipe(filter(() => panel._containsFocus()))\n .subscribe(() => _focusMonitor.focusVia(_element, 'program'));\n\n if (defaultOptions) {\n this.expandedHeight = defaultOptions.expandedHeight;\n this.collapsedHeight = defaultOptions.collapsedHeight;\n }\n }\n\n /** Height of the header while the panel is expanded. */\n @Input() expandedHeight: string;\n\n /** Height of the header while the panel is collapsed. */\n @Input() collapsedHeight: string;\n\n /**\n * Whether the associated panel is disabled. Implemented as a part of `FocusableOption`.\n * @docs-private\n */\n get disabled(): boolean {\n return this.panel.disabled;\n }\n\n /** Toggles the expanded state of the panel. */\n _toggle(): void {\n if (!this.disabled) {\n this.panel.toggle();\n }\n }\n\n /** Gets whether the panel is expanded. */\n _isExpanded(): boolean {\n return this.panel.expanded;\n }\n\n /** Gets the expanded state string of the panel. */\n _getExpandedState(): string {\n return this.panel._getExpandedState();\n }\n\n /** Gets the panel id. */\n _getPanelId(): string {\n return this.panel.id;\n }\n\n /** Gets the toggle position for the header. */\n _getTogglePosition(): MatAccordionTogglePosition {\n return this.panel.togglePosition;\n }\n\n /** Gets whether the expand indicator should be shown. */\n _showToggle(): boolean {\n return !this.panel.hideToggle && !this.panel.disabled;\n }\n\n /**\n * Gets the current height of the header. Null if no custom height has been\n * specified, and if the default height from the stylesheet should be used.\n */\n _getHeaderHeight(): string | null {\n const isExpanded = this._isExpanded();\n if (isExpanded && this.expandedHeight) {\n return this.expandedHeight;\n } else if (!isExpanded && this.collapsedHeight) {\n return this.collapsedHeight;\n }\n return null;\n }\n\n /** Handle keydown event calling to toggle() if appropriate. */\n _keydown(event: KeyboardEvent) {\n switch (event.keyCode) {\n // Toggle for space and enter keys.\n case SPACE:\n case ENTER:\n if (!hasModifierKey(event)) {\n event.preventDefault();\n this._toggle();\n }\n\n break;\n default:\n if (this.panel.accordion) {\n this.panel.accordion._handleHeaderKeydown(event);\n }\n\n return;\n }\n }\n\n /**\n * Focuses the panel header. Implemented as a part of `FocusableOption`.\n * @param origin Origin of the action that triggered the focus.\n * @docs-private\n */\n focus(origin?: FocusOrigin, options?: FocusOptions) {\n if (origin) {\n this._focusMonitor.focusVia(this._element, origin, options);\n } else {\n this._element.nativeElement.focus(options);\n }\n }\n\n ngAfterViewInit() {\n this._focusMonitor.monitor(this._element).subscribe(origin => {\n if (origin && this.panel.accordion) {\n this.panel.accordion._handleHeaderFocus(this);\n }\n });\n }\n\n ngOnDestroy() {\n this._parentChangeSubscription.unsubscribe();\n this._focusMonitor.stopMonitoring(this._element);\n }\n}\n\n/**\n * Description element of a `<mat-expansion-panel-header>`.\n */\n@Directive({\n selector: 'mat-panel-description',\n host: {\n class: 'mat-expansion-panel-header-description',\n },\n})\nexport class MatExpansionPanelDescription {}\n\n/**\n * Title element of a `<mat-expansion-panel-header>`.\n */\n@Directive({\n selector: 'mat-panel-title',\n host: {\n class: 'mat-expansion-panel-header-title',\n },\n})\nexport class MatExpansionPanelTitle {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n Directive,\n Input,\n ContentChildren,\n QueryList,\n AfterContentInit,\n OnDestroy,\n} from '@angular/core';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {CdkAccordion} from '@angular/cdk/accordion';\nimport {FocusKeyManager} from '@angular/cdk/a11y';\nimport {startWith} from 'rxjs/operators';\nimport {\n MAT_ACCORDION,\n MatAccordionBase,\n MatAccordionDisplayMode,\n MatAccordionTogglePosition,\n} from './accordion-base';\nimport {MatExpansionPanelHeader} from './expansion-panel-header';\n\n/**\n * Directive for a Material Design Accordion.\n */\n@Directive({\n selector: 'mat-accordion',\n exportAs: 'matAccordion',\n inputs: ['multi'],\n providers: [\n {\n provide: MAT_ACCORDION,\n useExisting: MatAccordion,\n },\n ],\n host: {\n class: 'mat-accordion',\n // Class binding which is only used by the test harness as there is no other\n // way for the harness to detect if multiple panel support is enabled.\n '[class.mat-accordion-multi]': 'this.multi',\n },\n})\nexport class MatAccordion\n extends CdkAccordion\n implements MatAccordionBase, AfterContentInit, OnDestroy\n{\n private _keyManager: FocusKeyManager<MatExpansionPanelHeader>;\n\n /** Headers belonging to this accordion. */\n private _ownHeaders = new QueryList<MatExpansionPanelHeader>();\n\n /** All headers inside the accordion. Includes headers inside nested accordions. */\n @ContentChildren(MatExpansionPanelHeader, {descendants: true})\n _headers: QueryList<MatExpansionPanelHeader>;\n\n /** Whether the expansion indicator should be hidden. */\n @Input()\n get hideToggle(): boolean {\n return this._hideToggle;\n }\n set hideToggle(show: BooleanInput) {\n this._hideToggle = coerceBooleanProperty(show);\n }\n private _hideToggle: boolean = false;\n\n /**\n * Display mode used for all expansion panels in the accordion. Currently two display\n * modes exist:\n * default - a gutter-like spacing is placed around any expanded panel, placing the expanded\n * panel at a different elevation from the rest of the accordion.\n * flat - no spacing is placed around expanded panels, showing all panels at the same\n * elevation.\n */\n @Input() displayMode: MatAccordionDisplayMode = 'default';\n\n /** The position of the expansion indicator. */\n @Input() togglePosition: MatAccordionTogglePosition = 'after';\n\n ngAfterContentInit() {\n this._headers.changes\n .pipe(startWith(this._headers))\n .subscribe((headers: QueryList<MatExpansionPanelHeader>) => {\n this._ownHeaders.reset(headers.filter(header => header.panel.accordion === this));\n this._ownHeaders.notifyOnChanges();\n });\n\n this._keyManager = new FocusKeyManager(this._ownHeaders).withWrap().withHomeAndEnd();\n }\n\n /** Handles keyboard events coming in from the panel headers. */\n _handleHeaderKeydown(event: KeyboardEvent) {\n this._keyManager.onKeydown(event);\n }\n\n _handleHeaderFocus(header: MatExpansionPanelHeader) {\n this._keyManager.updateActiveItem(header);\n }\n\n override ngOnDestroy() {\n super.ngOnDestroy();\n this._keyManager?.destroy();\n this._ownHeaders.destroy();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {CdkAccordionModule} from '@angular/cdk/accordion';\nimport {PortalModule} from '@angular/cdk/portal';\nimport {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '@angular/material/core';\nimport {MatAccordion} from './accordion';\nimport {MatExpansionPanel, MatExpansionPanelActionRow} from './expansion-panel';\nimport {MatExpansionPanelContent} from './expansion-panel-content';\nimport {\n MatExpansionPanelDescription,\n MatExpansionPanelHeader,\n MatExpansionPanelTitle,\n} from './expansion-panel-header';\n\n@NgModule({\n imports: [CommonModule, MatCommonModule, CdkAccordionModule, PortalModule],\n exports: [\n MatAccordion,\n MatExpansionPanel,\n MatExpansionPanelActionRow,\n MatExpansionPanelHeader,\n MatExpansionPanelTitle,\n MatExpansionPanelDescription,\n MatExpansionPanelContent,\n ],\n declarations: [\n MatAccordion,\n MatExpansionPanel,\n MatExpansionPanelActionRow,\n MatExpansionPanelHeader,\n MatExpansionPanelTitle,\n MatExpansionPanelDescription,\n MatExpansionPanelContent,\n ],\n})\nexport class MatExpansionModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {DOCUMENT} from '@angular/common';\nimport {\n AfterViewChecked,\n Attribute,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ErrorHandler,\n inject,\n Inject,\n InjectionToken,\n Input,\n OnDestroy,\n OnInit,\n Optional,\n ViewEncapsulation,\n} from '@angular/core';\nimport {CanColor, ThemePalette, mixinColor} from '@angular/material/core';\nimport {Subscription} from 'rxjs';\nimport {take} from 'rxjs/operators';\n\nimport {MatIconRegistry} from './icon-registry';\n\n// Boilerplate for applying mixins to MatIcon.\n/** @docs-private */\nconst _MatIconBase = mixinColor(\n class {\n constructor(public _elementRef: ElementRef) {}\n },\n);\n\n/** Default options for `mat-icon`. */\nexport interface MatIconDefaultOptions {\n /** Default color of the icon. */\n color?: ThemePalette;\n /** Font set that the icon is a part of. */\n fontSet?: string;\n}\n\n/** Injection token to be used to override the default options for `mat-icon`. */\nexport const MAT_ICON_DEFAULT_OPTIONS = new InjectionToken<MatIconDefaultOptions>(\n 'MAT_ICON_DEFAULT_OPTIONS',\n);\n\n/**\n * Injection token used to provide the current location to `MatIcon`.\n * Used to handle server-side rendering and to stub out during unit tests.\n * @docs-private\n */\nexport const MAT_ICON_LOCATION = new InjectionToken<MatIconLocation>('mat-icon-location', {\n providedIn: 'root',\n factory: MAT_ICON_LOCATION_FACTORY,\n});\n\n/**\n * Stubbed out location for `MatIcon`.\n * @docs-private\n */\nexport interface MatIconLocation {\n getPathname: () => string;\n}\n\n/** @docs-private */\nexport function MAT_ICON_LOCATION_FACTORY(): MatIconLocation {\n const _document = inject(DOCUMENT);\n const _location = _document ? _document.location : null;\n\n return {\n // Note that this needs to be a function, rather than a property, because Angular\n // will only resolve it once, but we want the current path on each call.\n getPathname: () => (_location ? _location.pathname + _location.search : ''),\n };\n}\n\n/** SVG attributes that accept a FuncIRI (e.g. `url(<something>)`). */\nconst funcIriAttributes = [\n 'clip-path',\n 'color-profile',\n 'src',\n 'cursor',\n 'fill',\n 'filter',\n 'marker',\n 'marker-start',\n 'marker-mid',\n 'marker-end',\n 'mask',\n 'stroke',\n];\n\n/** Selector that can be used to find all elements that are using a `FuncIRI`. */\nconst funcIriAttributeSelector = funcIriAttributes.map(attr => `[${attr}]`).join(', ');\n\n/** Regex that can be used to extract the id out of a FuncIRI. */\nconst funcIriPattern = /^url\\(['\"]?#(.*?)['\"]?\\)$/;\n\n/**\n * Component to display an icon. It can be used in the following ways:\n *\n * - Specify the svgIcon input to load an SVG icon from a URL previously registered with the\n * addSvgIcon, addSvgIconInNamespace, addSvgIconSet, or addSvgIconSetInNamespace methods of\n * MatIconRegistry. If the svgIcon value contains a colon it is assumed to be in the format\n * \"[namespace]:[name]\", if not the value will be the name of an icon in the default namespace.\n * Examples:\n * `<mat-icon svgIcon=\"left-arrow\"></mat-icon>\n * <mat-icon svgIcon=\"animals:cat\"></mat-icon>`\n *\n * - Use a font ligature as an icon by putting the ligature text in the `fontIcon` attribute or the\n * content of the `<mat-icon>` component. If you register a custom font class, don't forget to also\n * include the special class `mat-ligature-font`. It is recommended to use the attribute alternative\n * to prevent the ligature text to be selectable and to appear in search engine results.\n * By default, the Material icons font is used as described at\n * http://google.github.io/material-design-icons/#icon-font-for-the-web. You can specify an\n * alternate font by setting the fontSet input to either the CSS class to apply to use the\n * desired font, or to an alias previously registered with MatIconRegistry.registerFontClassAlias.\n * Examples:\n * `<mat-icon fontIcon=\"home\"></mat-icon>\n * <mat-icon>home</mat-icon>\n * <mat-icon fontSet=\"myfont\" fontIcon=\"sun\"></mat-icon>\n * <mat-icon fontSet=\"myfont\">sun</mat-icon>`\n *\n * - Specify a font glyph to be included via CSS rules by setting the fontSet input to specify the\n * font, and the fontIcon input to specify the icon. Typically the fontIcon will specify a\n * CSS class which causes the glyph to be displayed via a :before selector, as in\n * https://fortawesome.github.io/Font-Awesome/examples/\n * Example:\n * `<mat-icon fontSet=\"fa\" fontIcon=\"alarm\"></mat-icon>`\n */\n@Component({\n template: '<ng-content></ng-content>',\n selector: 'mat-icon',\n exportAs: 'matIcon',\n styleUrls: ['icon.css'],\n inputs: ['color'],\n host: {\n 'role': 'img',\n 'class': 'mat-icon notranslate',\n '[attr.data-mat-icon-type]': '_usingFontIcon() ? \"font\" : \"svg\"',\n '[attr.data-mat-icon-name]': '_svgName || fontIcon',\n '[attr.data-mat-icon-namespace]': '_svgNamespace || fontSet',\n '[attr.fontIcon]': '_usingFontIcon() ? fontIcon : null',\n '[class.mat-icon-inline]': 'inline',\n '[class.mat-icon-no-color]': 'color !== \"primary\" && color !== \"accent\" && color !== \"warn\"',\n },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MatIcon extends _MatIconBase implements OnInit, AfterViewChecked, CanColor, OnDestroy {\n /**\n * Whether the icon should be inlined, automatically sizing the icon to match the font size of\n * the element the icon is contained in.\n */\n @Input()\n get inline(): boolean {\n return this._inline;\n }\n set inline(inline: BooleanInput) {\n this._inline = coerceBooleanProperty(inline);\n }\n private _inline: boolean = false;\n\n /** Name of the icon in the SVG icon set. */\n @Input()\n get svgIcon(): string {\n return this._svgIcon;\n }\n set svgIcon(value: string) {\n if (value !== this._svgIcon) {\n if (value) {\n this._updateSvgIcon(value);\n } else if (this._svgIcon) {\n this._clearSvgElement();\n }\n this._svgIcon = value;\n }\n }\n private _svgIcon: string;\n\n /** Font set that the icon is a part of. */\n @Input()\n get fontSet(): string {\n return this._fontSet;\n }\n set fontSet(value: string) {\n const newValue = this._cleanupFontValue(value);\n\n if (newValue !== this._fontSet) {\n this._fontSet = newValue;\n this._updateFontIconClasses();\n }\n }\n private _fontSet: string;\n\n /** Name of an icon within a font set. */\n @Input()\n get fontIcon(): string {\n return this._fontIcon;\n }\n set fontIcon(value: string) {\n const newValue = this._cleanupFontValue(value);\n\n if (newValue !== this._fontIcon) {\n this._fontIcon = newValue;\n this._updateFontIconClasses();\n }\n }\n private _fontIcon: string;\n\n private _previousFontSetClass: string[] = [];\n private _previousFontIconClass: string;\n\n _svgName: string | null;\n _svgNamespace: string | null;\n\n /** Keeps track of the current page path. */\n private _previousPath?: string;\n\n /** Keeps track of the elements and attributes that we've prefixed with the current path. */\n private _elementsWithExternalReferences?: Map<Element, {name: string; value: string}[]>;\n\n /** Subscription to the current in-progress SVG icon request. */\n private _currentIconFetch = Subscription.EMPTY;\n\n constructor(\n elementRef: ElementRef<HTMLElement>,\n private _iconRegistry: MatIconRegistry,\n @Attribute('aria-hidden') ariaHidden: string,\n @Inject(MAT_ICON_LOCATION) private _location: MatIconLocation,\n private readonly _errorHandler: ErrorHandler,\n @Optional()\n @Inject(MAT_ICON_DEFAULT_OPTIONS)\n defaults?: MatIconDefaultOptions,\n ) {\n super(elementRef);\n\n if (defaults) {\n if (defaults.color) {\n this.color = this.defaultColor = defaults.color;\n }\n\n if (defaults.fontSet) {\n this.fontSet = defaults.fontSet;\n }\n }\n\n // If the user has not explicitly set aria-hidden, mark the icon as hidden, as this is\n // the right thing to do for the majority of icon use-cases.\n if (!ariaHidden) {\n elementRef.nativeElement.setAttribute('aria-hidden', 'true');\n }\n }\n\n /**\n * Splits an svgIcon binding value into its icon set and icon name components.\n * Returns a 2-element array of [(icon set), (icon name)].\n * The separator for the two fields is ':'. If there is no separator, an empty\n * string is returned for the icon set and the entire value is returned for\n * the icon name. If the argument is falsy, returns an array of two empty strings.\n * Throws an error if the name contains two or more ':' separators.\n * Examples:\n * `'social:cake' -> ['social', 'cake']\n * 'penguin' -> ['', 'penguin']\n * null -> ['', '']\n * 'a:b:c' -> (throws Error)`\n */\n private _splitIconName(iconName: string): [string, string] {\n if (!iconName) {\n return ['', ''];\n }\n const parts = iconName.split(':');\n switch (parts.length) {\n case 1:\n return ['', parts[0]]; // Use default namespace.\n case 2:\n return <[string, string]>parts;\n default:\n throw Error(`Invalid icon name: \"${iconName}\"`); // TODO: add an ngDevMode check\n }\n }\n\n ngOnInit() {\n // Update font classes because ngOnChanges won't be called if none of the inputs are present,\n // e.g. <mat-icon>arrow</mat-icon> In this case we need to add a CSS class for the default font.\n this._updateFontIconClasses();\n }\n\n ngAfterViewChecked() {\n const cachedElements = this._elementsWithExternalReferences;\n\n if (cachedElements && cachedElements.size) {\n const newPath = this._location.getPathname();\n\n // We need to check whether the URL has changed on each change detection since\n // the browser doesn't have an API that will let us react on link clicks and\n // we can't depend on the Angular router. The references need to be updated,\n // because while most browsers don't care whether the URL is correct after\n // the first render, Safari will break if the user navigates to a different\n // page and the SVG isn't re-rendered.\n if (newPath !== this._previousPath) {\n this._previousPath = newPath;\n this._prependPathToReferences(newPath);\n }\n }\n }\n\n ngOnDestroy() {\n this._currentIconFetch.unsubscribe();\n\n if (this._elementsWithExternalReferences) {\n this._elementsWithExternalReferences.clear();\n }\n }\n\n _usingFontIcon(): boolean {\n return !this.svgIcon;\n }\n\n private _setSvgElement(svg: SVGElement) {\n this._clearSvgElement();\n\n // Note: we do this fix here, rather than the icon registry, because the\n // references have to point to the URL at the time that the icon was created.\n const path = this._location.getPathname();\n this._previousPath = path;\n this._cacheChildrenWithExternalReferences(svg);\n this._prependPathToReferences(path);\n this._elementRef.nativeElement.appendChild(svg);\n }\n\n private _clearSvgElement() {\n const layoutElement: HTMLElement = this._elementRef.nativeElement;\n let childCount = layoutElement.childNodes.length;\n\n if (this._elementsWithExternalReferences) {\n this._elementsWithExternalReferences.clear();\n }\n\n // Remove existing non-element child nodes and SVGs, and add the new SVG element. Note that\n // we can't use innerHTML, because IE will throw if the element has a data binding.\n while (childCount--) {\n const child = layoutElement.childNodes[childCount];\n\n // 1 corresponds to Node.ELEMENT_NODE. We remove all non-element nodes in order to get rid\n // of any loose text nodes, as well as any SVG elements in order to remove any old icons.\n if (child.nodeType !== 1 || child.nodeName.toLowerCase() === 'svg') {\n child.remove();\n }\n }\n }\n\n private _updateFontIconClasses() {\n if (!this._usingFontIcon()) {\n return;\n }\n\n const elem: HTMLElement = this._elementRef.nativeElement;\n const fontSetClasses = (\n this.fontSet\n ? this._iconRegistry.classNameForFontAlias(this.fontSet).split(/ +/)\n : this._iconRegistry.getDefaultFontSetClass()\n ).filter(className => className.length > 0);\n\n this._previousFontSetClass.forEach(className => elem.classList.remove(className));\n fontSetClasses.forEach(className => elem.classList.add(className));\n this._previousFontSetClass = fontSetClasses;\n\n if (\n this.fontIcon !== this._previousFontIconClass &&\n !fontSetClasses.includes('mat-ligature-font')\n ) {\n if (this._previousFontIconClass) {\n elem.classList.remove(this._previousFontIconClass);\n }\n if (this.fontIcon) {\n elem.classList.add(this.fontIcon);\n }\n this._previousFontIconClass = this.fontIcon;\n }\n }\n\n /**\n * Cleans up a value to be used as a fontIcon or fontSet.\n * Since the value ends up being assigned as a CSS class, we\n * have to trim the value and omit space-separated values.\n */\n private _cleanupFontValue(value: string) {\n return typeof value === 'string' ? value.trim().split(' ')[0] : value;\n }\n\n /**\n * Prepends the current path to all elements that have an attribute pointing to a `FuncIRI`\n * reference. This is required because WebKit browsers require references to be prefixed with\n * the current path, if the page has a `base` tag.\n */\n private _prependPathToReferences(path: string) {\n const elements = this._elementsWithExternalReferences;\n\n if (elements) {\n elements.forEach((attrs, element) => {\n attrs.forEach(attr => {\n element.setAttribute(attr.name, `url('${path}#${attr.value}')`);\n });\n });\n }\n }\n\n /**\n * Caches the children of an SVG element that have `url()`\n * references that we need to prefix with the current path.\n */\n private _cacheChildrenWithExternalReferences(element: SVGElement) {\n const elementsWithFuncIri = element.querySelectorAll(funcIriAttributeSelector);\n const elements = (this._elementsWithExternalReferences =\n this._elementsWithExternalReferences || new Map());\n\n for (let i = 0; i < elementsWithFuncIri.length; i++) {\n funcIriAttributes.forEach(attr => {\n const elementWithReference = elementsWithFuncIri[i];\n const value = elementWithReference.getAttribute(attr);\n const match = value ? value.match(funcIriPattern) : null;\n\n if (match) {\n let attributes = elements.get(elementWithReference);\n\n if (!attributes) {\n attributes = [];\n elements.set(elementWithReference, attributes);\n }\n\n attributes!.push({name: attr, value: match[1]});\n }\n });\n }\n }\n\n /** Sets a new SVG icon with a particular name. */\n private _updateSvgIcon(rawName: string | undefined) {\n this._svgNamespace = null;\n this._svgName = null;\n this._currentIconFetch.unsubscribe();\n\n if (rawName) {\n const [namespace, iconName] = this._splitIconName(rawName);\n\n if (namespace) {\n this._svgNamespace = namespace;\n }\n\n if (iconName) {\n this._svgName = iconName;\n }\n\n this._currentIconFetch = this._iconRegistry\n .getNamedSvgIcon(iconName, namespace)\n .pipe(take(1))\n .subscribe(\n svg => this._setSvgElement(svg),\n (err: Error) => {\n const errorMessage = `Error retrieving icon ${namespace}:${iconName}! ${err.message}`;\n this._errorHandler.handleError(new Error(errorMessage));\n },\n );\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '@angular/material/core';\nimport {MatIcon} from './icon';\n\n@NgModule({\n imports: [MatCommonModule],\n exports: [MatIcon, MatCommonModule],\n declarations: [MatIcon],\n})\nexport class MatIconModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {DOCUMENT} from '@angular/common';\nimport {HttpClient, HttpErrorResponse} from '@angular/common/http';\nimport {\n ErrorHandler,\n Inject,\n Injectable,\n InjectionToken,\n OnDestroy,\n Optional,\n SecurityContext,\n SkipSelf,\n} from '@angular/core';\nimport {DomSanitizer, SafeHtml, SafeResourceUrl} from '@angular/platform-browser';\nimport {forkJoin, Observable, of as observableOf, throwError as observableThrow} from 'rxjs';\nimport {catchError, finalize, map, share, tap} from 'rxjs/operators';\nimport {TrustedHTML, trustedHTMLFromString} from './trusted-types';\n\n/**\n * Returns an exception to be thrown in the case when attempting to\n * load an icon with a name that cannot be found.\n * @docs-private\n */\nexport function getMatIconNameNotFoundError(iconName: string): Error {\n return Error(`Unable to find icon with the name \"${iconName}\"`);\n}\n\n/**\n * Returns an exception to be thrown when the consumer attempts to use\n * `<mat-icon>` without including @angular/common/http.\n * @docs-private\n */\nexport function getMatIconNoHttpProviderError(): Error {\n return Error(\n 'Could not find HttpClient provider for use with Angular Material icons. ' +\n 'Please include the HttpClientModule from @angular/common/http in your ' +\n 'app imports.',\n );\n}\n\n/**\n * Returns an exception to be thrown when a URL couldn't be sanitized.\n * @param url URL that was attempted to be sanitized.\n * @docs-private\n */\nexport function getMatIconFailedToSanitizeUrlError(url: SafeResourceUrl): Error {\n return Error(\n `The URL provided to MatIconRegistry was not trusted as a resource URL ` +\n `via Angular's DomSanitizer. Attempted URL was \"${url}\".`,\n );\n}\n\n/**\n * Returns an exception to be thrown when a HTML string couldn't be sanitized.\n * @param literal HTML that was attempted to be sanitized.\n * @docs-private\n */\nexport function getMatIconFailedToSanitizeLiteralError(literal: SafeHtml): Error {\n return Error(\n `The literal provided to MatIconRegistry was not trusted as safe HTML by ` +\n `Angular's DomSanitizer. Attempted literal was \"${literal}\".`,\n );\n}\n\n/** Options that can be used to configure how an icon or the icons in an icon set are presented. */\nexport interface IconOptions {\n /** View box to set on the icon. */\n viewBox?: string;\n\n /** Whether or not to fetch the icon or icon set using HTTP credentials. */\n withCredentials?: boolean;\n}\n\n/**\n * Function that will be invoked by the icon registry when trying to resolve the\n * URL from which to fetch an icon. The returned URL will be used to make a request for the icon.\n */\nexport type IconResolver = (\n name: string,\n namespace: string,\n) => SafeResourceUrl | SafeResourceUrlWithIconOptions | null;\n\n/** Object that specifies a URL from which to fetch an icon and the options to use for it. */\nexport interface SafeResourceUrlWithIconOptions {\n url: SafeResourceUrl;\n options: IconOptions;\n}\n\n/**\n * Configuration for an icon, including the URL and possibly the cached SVG element.\n * @docs-private\n */\nclass SvgIconConfig {\n svgElement: SVGElement | null;\n\n constructor(\n public url: SafeResourceUrl,\n public svgText: TrustedHTML | null,\n public options?: IconOptions,\n ) {}\n}\n\n/** Icon configuration whose content has already been loaded. */\ntype LoadedSvgIconConfig = SvgIconConfig & {svgText: TrustedHTML};\n\n/**\n * Service to register and display icons used by the `<mat-icon>` component.\n * - Registers icon URLs by namespace and name.\n * - Registers icon set URLs by namespace.\n * - Registers aliases for CSS classes, for use with icon fonts.\n * - Loads icons from URLs and extracts individual icons from icon sets.\n */\n@Injectable({providedIn: 'root'})\nexport class MatIconRegistry implements OnDestroy {\n private _document: Document;\n\n /**\n * URLs and cached SVG elements for individual icons. Keys are of the format \"[namespace]:[icon]\".\n */\n private _svgIconConfigs = new Map<string, SvgIconConfig>();\n\n /**\n * SvgIconConfig objects and cached SVG elements for icon sets, keyed by namespace.\n * Multiple icon sets can be registered under the same namespace.\n */\n private _iconSetConfigs = new Map<string, SvgIconConfig[]>();\n\n /** Cache for icons loaded by direct URLs. */\n private _cachedIconsByUrl = new Map<string, SVGElement>();\n\n /** In-progress icon fetches. Used to coalesce multiple requests to the same URL. */\n private _inProgressUrlFetches = new Map<string, Observable<TrustedHTML>>();\n\n /** Map from font identifiers to their CSS class names. Used for icon fonts. */\n private _fontCssClassesByAlias = new Map<string, string>();\n\n /** Registered icon resolver functions. */\n private _resolvers: IconResolver[] = [];\n\n /**\n * The CSS classes to apply when an `<mat-icon>` component has no icon name, url, or font\n * specified. The default 'material-icons' value assumes that the material icon font has been\n * loaded as described at http://google.github.io/material-design-icons/#icon-font-for-the-web\n */\n private _defaultFontSetClass = ['material-icons', 'mat-ligature-font'];\n\n constructor(\n @Optional() private _httpClient: HttpClient,\n private _sanitizer: DomSanitizer,\n @Optional() @Inject(DOCUMENT) document: any,\n private readonly _errorHandler: ErrorHandler,\n ) {\n this._document = document;\n }\n\n /**\n * Registers an icon by URL in the default namespace.\n * @param iconName Name under which the icon should be registered.\n * @param url\n */\n addSvgIcon(iconName: string, url: SafeResourceUrl, options?: IconOptions): this {\n return this.addSvgIconInNamespace('', iconName, url, options);\n }\n\n /**\n * Registers an icon using an HTML string in the default namespace.\n * @param iconName Name under which the icon should be registered.\n * @param literal SVG source of the icon.\n */\n addSvgIconLiteral(iconName: string, literal: SafeHtml, options?: IconOptions): this {\n return this.addSvgIconLiteralInNamespace('', iconName, literal, options);\n }\n\n /**\n * Registers an icon by URL in the specified namespace.\n * @param namespace Namespace in which the icon should be registered.\n * @param iconName Name under which the icon should be registered.\n * @param url\n */\n addSvgIconInNamespace(\n namespace: string,\n iconName: string,\n url: SafeResourceUrl,\n options?: IconOptions,\n ): this {\n return this._addSvgIconConfig(namespace, iconName, new SvgIconConfig(url, null, options));\n }\n\n /**\n * Registers an icon resolver function with the registry. The function will be invoked with the\n * name and namespace of an icon when the registry tries to resolve the URL from which to fetch\n * the icon. The resolver is expected to return a `SafeResourceUrl` that points to the icon,\n * an object with the icon URL and icon options, or `null` if the icon is not supported. Resolvers\n * will be invoked in the order in which they have been registered.\n * @param resolver Resolver function to be registered.\n */\n addSvgIconResolver(resolver: IconResolver): this {\n this._resolvers.push(resolver);\n return this;\n }\n\n /**\n * Registers an icon using an HTML string in the specified namespace.\n * @param namespace Namespace in which the icon should be registered.\n * @param iconName Name under which the icon should be registered.\n * @param literal SVG source of the icon.\n */\n addSvgIconLiteralInNamespace(\n namespace: string,\n iconName: string,\n literal: SafeHtml,\n options?: IconOptions,\n ): this {\n const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);\n\n // TODO: add an ngDevMode check\n if (!cleanLiteral) {\n throw getMatIconFailedToSanitizeLiteralError(literal);\n }\n\n // Security: The literal is passed in as SafeHtml, and is thus trusted.\n const trustedLiteral = trustedHTMLFromString(cleanLiteral);\n return this._addSvgIconConfig(\n namespace,\n iconName,\n new SvgIconConfig('', trustedLiteral, options),\n );\n }\n\n /**\n * Registers an icon set by URL in the default namespace.\n * @param url\n */\n addSvgIconSet(url: SafeResourceUrl, options?: IconOptions): this {\n return this.addSvgIconSetInNamespace('', url, options);\n }\n\n /**\n * Registers an icon set using an HTML string in the default namespace.\n * @param literal SVG source of the icon set.\n */\n addSvgIconSetLiteral(literal: SafeHtml, options?: IconOptions): this {\n return this.addSvgIconSetLiteralInNamespace('', literal, options);\n }\n\n /**\n * Registers an icon set by URL in the specified namespace.\n * @param namespace Namespace in which to register the icon set.\n * @param url\n */\n addSvgIconSetInNamespace(namespace: string, url: SafeResourceUrl, options?: IconOptions): this {\n return this._addSvgIconSetConfig(namespace, new SvgIconConfig(url, null, options));\n }\n\n /**\n * Registers an icon set using an HTML string in the specified namespace.\n * @param namespace Namespace in which to register the icon set.\n * @param literal SVG source of the icon set.\n */\n addSvgIconSetLiteralInNamespace(\n namespace: string,\n literal: SafeHtml,\n options?: IconOptions,\n ): this {\n const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);\n\n if (!cleanLiteral) {\n throw getMatIconFailedToSanitizeLiteralError(literal);\n }\n\n // Security: The literal is passed in as SafeHtml, and is thus trusted.\n const trustedLiteral = trustedHTMLFromString(cleanLiteral);\n return this._addSvgIconSetConfig(namespace, new SvgIconConfig('', trustedLiteral, options));\n }\n\n /**\n * Defines an alias for CSS class names to be used for icon fonts. Creating an matIcon\n * component with the alias as the fontSet input will cause the class name to be applied\n * to the `<mat-icon>` element.\n *\n * If the registered font is a ligature font, then don't forget to also include the special\n * class `mat-ligature-font` to allow the usage via attribute. So register like this:\n *\n * ```ts\n * iconRegistry.registerFontClassAlias('f1', 'font1 mat-ligature-font');\n * ```\n *\n * And use like this:\n *\n * ```html\n * <mat-icon fontSet=\"f1\" fontIcon=\"home\"></mat-icon>\n * ```\n *\n * @param alias Alias for the font.\n * @param classNames Class names override to be used instead of the alias.\n */\n registerFontClassAlias(alias: string, classNames: string = alias): this {\n this._fontCssClassesByAlias.set(alias, classNames);\n return this;\n }\n\n /**\n * Returns the CSS class name associated with the alias by a previous call to\n * registerFontClassAlias. If no CSS class has been associated, returns the alias unmodified.\n */\n classNameForFontAlias(alias: string): string {\n return this._fontCssClassesByAlias.get(alias) || alias;\n }\n\n /**\n * Sets the CSS classes to be used for icon fonts when an `<mat-icon>` component does not\n * have a fontSet input value, and is not loading an icon by name or URL.\n */\n setDefaultFontSetClass(...classNames: string[]): this {\n this._defaultFontSetClass = classNames;\n return this;\n }\n\n /**\n * Returns the CSS classes to be used for icon fonts when an `<mat-icon>` component does not\n * have a fontSet input value, and is not loading an icon by name or URL.\n */\n getDefaultFontSetClass(): string[] {\n return this._defaultFontSetClass;\n }\n\n /**\n * Returns an Observable that produces the icon (as an `<svg>` DOM element) from the given URL.\n * The response from the URL may be cached so this will not always cause an HTTP request, but\n * the produced element will always be a new copy of the originally fetched icon. (That is,\n * it will not contain any modifications made to elements previously returned).\n *\n * @param safeUrl URL from which to fetch the SVG icon.\n */\n getSvgIconFromUrl(safeUrl: SafeResourceUrl): Observable<SVGElement> {\n const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);\n\n if (!url) {\n throw getMatIconFailedToSanitizeUrlError(safeUrl);\n }\n\n const cachedIcon = this._cachedIconsByUrl.get(url);\n\n if (cachedIcon) {\n return observableOf(cloneSvg(cachedIcon));\n }\n\n return this._loadSvgIconFromConfig(new SvgIconConfig(safeUrl, null)).pipe(\n tap(svg => this._cachedIconsByUrl.set(url!, svg)),\n map(svg => cloneSvg(svg)),\n );\n }\n\n /**\n * Returns an Observable that produces the icon (as an `<svg>` DOM element) with the given name\n * and namespace. The icon must have been previously registered with addIcon or addIconSet;\n * if not, the Observable will throw an error.\n *\n * @param name Name of the icon to be retrieved.\n * @param namespace Namespace in which to look for the icon.\n */\n getNamedSvgIcon(name: string, namespace: string = ''): Observable<SVGElement> {\n const key = iconKey(namespace, name);\n let config = this._svgIconConfigs.get(key);\n\n // Return (copy of) cached icon if possible.\n if (config) {\n return this._getSvgFromConfig(config);\n }\n\n // Otherwise try to resolve the config from one of the resolver functions.\n config = this._getIconConfigFromResolvers(namespace, name);\n\n if (config) {\n this._svgIconConfigs.set(key, config);\n return this._getSvgFromConfig(config);\n }\n\n // See if we have any icon sets registered for the namespace.\n const iconSetConfigs = this._iconSetConfigs.get(namespace);\n\n if (iconSetConfigs) {\n return this._getSvgFromIconSetConfigs(name, iconSetConfigs);\n }\n\n return observableThrow(getMatIconNameNotFoundError(key));\n }\n\n ngOnDestroy() {\n this._resolvers = [];\n this._svgIconConfigs.clear();\n this._iconSetConfigs.clear();\n this._cachedIconsByUrl.clear();\n }\n\n /**\n * Returns the cached icon for a SvgIconConfig if available, or fetches it from its URL if not.\n */\n private _getSvgFromConfig(config: SvgIconConfig): Observable<SVGElement> {\n if (config.svgText) {\n // We already have the SVG element for this icon, return a copy.\n return observableOf(cloneSvg(this._svgElementFromConfig(config as LoadedSvgIconConfig)));\n } else {\n // Fetch the icon from the config's URL, cache it, and return a copy.\n return this._loadSvgIconFromConfig(config).pipe(map(svg => cloneSvg(svg)));\n }\n }\n\n /**\n * Attempts to find an icon with the specified name in any of the SVG icon sets.\n * First searches the available cached icons for a nested element with a matching name, and\n * if found copies the element to a new `<svg>` element. If not found, fetches all icon sets\n * that have not been cached, and searches again after all fetches are completed.\n * The returned Observable produces the SVG element if possible, and throws\n * an error if no icon with the specified name can be found.\n */\n private _getSvgFromIconSetConfigs(\n name: string,\n iconSetConfigs: SvgIconConfig[],\n ): Observable<SVGElement> {\n // For all the icon set SVG elements we've fetched, see if any contain an icon with the\n // requested name.\n const namedIcon = this._extractIconWithNameFromAnySet(name, iconSetConfigs);\n\n if (namedIcon) {\n // We could cache namedIcon in _svgIconConfigs, but since we have to make a copy every\n // time anyway, there's probably not much advantage compared to just always extracting\n // it from the icon set.\n return observableOf(namedIcon);\n }\n\n // Not found in any cached icon sets. If there are icon sets with URLs that we haven't\n // fetched, fetch them now and look for iconName in the results.\n const iconSetFetchRequests: Observable<TrustedHTML | null>[] = iconSetConfigs\n .filter(iconSetConfig => !iconSetConfig.svgText)\n .map(iconSetConfig => {\n return this._loadSvgIconSetFromConfig(iconSetConfig).pipe(\n catchError((err: HttpErrorResponse) => {\n const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, iconSetConfig.url);\n\n // Swallow errors fetching individual URLs so the\n // combined Observable won't necessarily fail.\n const errorMessage = `Loading icon set URL: ${url} failed: ${err.message}`;\n this._errorHandler.handleError(new Error(errorMessage));\n return observableOf(null);\n }),\n );\n });\n\n // Fetch all the icon set URLs. When the requests complete, every IconSet should have a\n // cached SVG element (unless the request failed), and we can check again for the icon.\n return forkJoin(iconSetFetchRequests).pipe(\n map(() => {\n const foundIcon = this._extractIconWithNameFromAnySet(name, iconSetConfigs);\n\n // TODO: add an ngDevMode check\n if (!foundIcon) {\n throw getMatIconNameNotFoundError(name);\n }\n\n return foundIcon;\n }),\n );\n }\n\n /**\n * Searches the cached SVG elements for the given icon sets for a nested icon element whose \"id\"\n * tag matches the specified name. If found, copies the nested element to a new SVG element and\n * returns it. Returns null if no matching element is found.\n */\n private _extractIconWithNameFromAnySet(\n iconName: string,\n iconSetConfigs: SvgIconConfig[],\n ): SVGElement | null {\n // Iterate backwards, so icon sets added later have precedence.\n for (let i = iconSetConfigs.length - 1; i >= 0; i--) {\n const config = iconSetConfigs[i];\n\n // Parsing the icon set's text into an SVG element can be expensive. We can avoid some of\n // the parsing by doing a quick check using `indexOf` to see if there's any chance for the\n // icon to be in the set. This won't be 100% accurate, but it should help us avoid at least\n // some of the parsing.\n if (config.svgText && config.svgText.toString().indexOf(iconName) > -1) {\n const svg = this._svgElementFromConfig(config as LoadedSvgIconConfig);\n const foundIcon = this._extractSvgIconFromSet(svg, iconName, config.options);\n if (foundIcon) {\n return foundIcon;\n }\n }\n }\n return null;\n }\n\n /**\n * Loads the content of the icon URL specified in the SvgIconConfig and creates an SVG element\n * from it.\n */\n private _loadSvgIconFromConfig(config: SvgIconConfig): Observable<SVGElement> {\n return this._fetchIcon(config).pipe(\n tap(svgText => (config.svgText = svgText)),\n map(() => this._svgElementFromConfig(config as LoadedSvgIconConfig)),\n );\n }\n\n /**\n * Loads the content of the icon set URL specified in the\n * SvgIconConfig and attaches it to the config.\n */\n private _loadSvgIconSetFromConfig(config: SvgIconConfig): Observable<TrustedHTML | null> {\n if (config.svgText) {\n return observableOf(null);\n }\n\n return this._fetchIcon(config).pipe(tap(svgText => (config.svgText = svgText)));\n }\n\n /**\n * Searches the cached element of the given SvgIconConfig for a nested icon element whose \"id\"\n * tag matches the specified name. If found, copies the nested element to a new SVG element and\n * returns it. Returns null if no matching element is found.\n */\n private _extractSvgIconFromSet(\n iconSet: SVGElement,\n iconName: string,\n options?: IconOptions,\n ): SVGElement | null {\n // Use the `id=\"iconName\"` syntax in order to escape special\n // characters in the ID (versus using the #iconName syntax).\n const iconSource = iconSet.querySelector(`[id=\"${iconName}\"]`);\n\n if (!iconSource) {\n return null;\n }\n\n // Clone the element and remove the ID to prevent multiple elements from being added\n // to the page with the same ID.\n const iconElement = iconSource.cloneNode(true) as Element;\n iconElement.removeAttribute('id');\n\n // If the icon node is itself an <svg> node, clone and return it directly. If not, set it as\n // the content of a new <svg> node.\n if (iconElement.nodeName.toLowerCase() === 'svg') {\n return this._setSvgAttributes(iconElement as SVGElement, options);\n }\n\n // If the node is a <symbol>, it won't be rendered so we have to convert it into <svg>. Note\n // that the same could be achieved by referring to it via <use href=\"#id\">, however the <use>\n // tag is problematic on Firefox, because it needs to include the current page path.\n if (iconElement.nodeName.toLowerCase() === 'symbol') {\n return this._setSvgAttributes(this._toSvgElement(iconElement), options);\n }\n\n // createElement('SVG') doesn't work as expected; the DOM ends up with\n // the correct nodes, but the SVG content doesn't render. Instead we\n // have to create an empty SVG node using innerHTML and append its content.\n // Elements created using DOMParser.parseFromString have the same problem.\n // http://stackoverflow.com/questions/23003278/svg-innerhtml-in-firefox-can-not-display\n const svg = this._svgElementFromString(trustedHTMLFromString('<svg></svg>'));\n // Clone the node so we don't remove it from the parent icon set element.\n svg.appendChild(iconElement);\n\n return this._setSvgAttributes(svg, options);\n }\n\n /**\n * Creates a DOM element from the given SVG string.\n */\n private _svgElementFromString(str: TrustedHTML): SVGElement {\n const div = this._document.createElement('DIV');\n div.innerHTML = str as unknown as string;\n const svg = div.querySelector('svg') as SVGElement;\n\n // TODO: add an ngDevMode check\n if (!svg) {\n throw Error('<svg> tag not found');\n }\n\n return svg;\n }\n\n /**\n * Converts an element into an SVG node by cloning all of its children.\n */\n private _toSvgElement(element: Element): SVGElement {\n const svg = this._svgElementFromString(trustedHTMLFromString('<svg></svg>'));\n const attributes = element.attributes;\n\n // Copy over all the attributes from the `symbol` to the new SVG, except the id.\n for (let i = 0; i < attributes.length; i++) {\n const {name, value} = attributes[i];\n\n if (name !== 'id') {\n svg.setAttribute(name, value);\n }\n }\n\n for (let i = 0; i < element.childNodes.length; i++) {\n if (element.childNodes[i].nodeType === this._document.ELEMENT_NODE) {\n svg.appendChild(element.childNodes[i].cloneNode(true));\n }\n }\n\n return svg;\n }\n\n /**\n * Sets the default attributes for an SVG element to be used as an icon.\n */\n private _setSvgAttributes(svg: SVGElement, options?: IconOptions): SVGElement {\n svg.setAttribute('fit', '');\n svg.setAttribute('height', '100%');\n svg.setAttribute('width', '100%');\n svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\n svg.setAttribute('focusable', 'false'); // Disable IE11 default behavior to make SVGs focusable.\n\n if (options && options.viewBox) {\n svg.setAttribute('viewBox', options.viewBox);\n }\n\n return svg;\n }\n\n /**\n * Returns an Observable which produces the string contents of the given icon. Results may be\n * cached, so future calls with the same URL may not cause another HTTP request.\n */\n private _fetchIcon(iconConfig: SvgIconConfig): Observable<TrustedHTML> {\n const {url: safeUrl, options} = iconConfig;\n const withCredentials = options?.withCredentials ?? false;\n\n if (!this._httpClient) {\n throw getMatIconNoHttpProviderError();\n }\n\n // TODO: add an ngDevMode check\n if (safeUrl == null) {\n throw Error(`Cannot fetch icon from URL \"${safeUrl}\".`);\n }\n\n const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);\n\n // TODO: add an ngDevMode check\n if (!url) {\n throw getMatIconFailedToSanitizeUrlError(safeUrl);\n }\n\n // Store in-progress fetches to avoid sending a duplicate request for a URL when there is\n // already a request in progress for that URL. It's necessary to call share() on the\n // Observable returned by http.get() so that multiple subscribers don't cause multiple XHRs.\n const inProgressFetch = this._inProgressUrlFetches.get(url);\n\n if (inProgressFetch) {\n return inProgressFetch;\n }\n\n const req = this._httpClient.get(url, {responseType: 'text', withCredentials}).pipe(\n map(svg => {\n // Security: This SVG is fetched from a SafeResourceUrl, and is thus\n // trusted HTML.\n return trustedHTMLFromString(svg);\n }),\n finalize(() => this._inProgressUrlFetches.delete(url)),\n share(),\n );\n\n this._inProgressUrlFetches.set(url, req);\n return req;\n }\n\n /**\n * Registers an icon config by name in the specified namespace.\n * @param namespace Namespace in which to register the icon config.\n * @param iconName Name under which to register the config.\n * @param config Config to be registered.\n */\n private _addSvgIconConfig(namespace: string, iconName: string, config: SvgIconConfig): this {\n this._svgIconConfigs.set(iconKey(namespace, iconName), config);\n return this;\n }\n\n /**\n * Registers an icon set config in the specified namespace.\n * @param namespace Namespace in which to register the icon config.\n * @param config Config to be registered.\n */\n private _addSvgIconSetConfig(namespace: string, config: SvgIconConfig): this {\n const configNamespace = this._iconSetConfigs.get(namespace);\n\n if (configNamespace) {\n configNamespace.push(config);\n } else {\n this._iconSetConfigs.set(namespace, [config]);\n }\n\n return this;\n }\n\n /** Parses a config's text into an SVG element. */\n private _svgElementFromConfig(config: LoadedSvgIconConfig): SVGElement {\n if (!config.svgElement) {\n const svg = this._svgElementFromString(config.svgText);\n this._setSvgAttributes(svg, config.options);\n config.svgElement = svg;\n }\n\n return config.svgElement;\n }\n\n /** Tries to create an icon config through the registered resolver functions. */\n private _getIconConfigFromResolvers(namespace: string, name: string): SvgIconConfig | undefined {\n for (let i = 0; i < this._resolvers.length; i++) {\n const result = this._resolvers[i](name, namespace);\n\n if (result) {\n return isSafeUrlWithOptions(result)\n ? new SvgIconConfig(result.url, null, result.options)\n : new SvgIconConfig(result, null);\n }\n }\n\n return undefined;\n }\n}\n\n/** @docs-private */\nexport function ICON_REGISTRY_PROVIDER_FACTORY(\n parentRegistry: MatIconRegistry,\n httpClient: HttpClient,\n sanitizer: DomSanitizer,\n errorHandler: ErrorHandler,\n document?: any,\n) {\n return parentRegistry || new MatIconRegistry(httpClient, sanitizer, document, errorHandler);\n}\n\n/** @docs-private */\nexport const ICON_REGISTRY_PROVIDER = {\n // If there is already an MatIconRegistry available, use that. Otherwise, provide a new one.\n provide: MatIconRegistry,\n deps: [\n [new Optional(), new SkipSelf(), MatIconRegistry],\n [new Optional(), HttpClient],\n DomSanitizer,\n ErrorHandler,\n [new Optional(), DOCUMENT as InjectionToken<any>],\n ],\n useFactory: ICON_REGISTRY_PROVIDER_FACTORY,\n};\n\n/** Clones an SVGElement while preserving type information. */\nfunction cloneSvg(svg: SVGElement): SVGElement {\n return svg.cloneNode(true) as SVGElement;\n}\n\n/** Returns the cache key to use for an icon namespace and name. */\nfunction iconKey(namespace: string, name: string) {\n return namespace + ':' + name;\n}\n\nfunction isSafeUrlWithOptions(value: any): value is SafeResourceUrlWithIconOptions {\n return !!(value.url && value.options);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Directionality} from '@angular/cdk/bidi';\nimport {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';\nimport {\n AfterContentChecked,\n AfterContentInit,\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n ElementRef,\n Inject,\n Input,\n NgZone,\n Optional,\n QueryList,\n ViewChild,\n ViewEncapsulation,\n OnDestroy,\n InjectionToken,\n} from '@angular/core';\nimport {CanColor, mixinColor, ThemePalette} from '@angular/material/core';\nimport {fromEvent, merge, Subject} from 'rxjs';\nimport {startWith, take, takeUntil} from 'rxjs/operators';\nimport {MatLegacyError} from './error';\nimport {_MAT_LEGACY_HINT, MatLegacyHint} from './hint';\nimport {MatLegacyLabel} from './label';\nimport {MatLegacyPlaceholder} from './placeholder';\nimport {MatLegacyPrefix} from './prefix';\nimport {MatLegacySuffix} from './suffix';\nimport {Platform} from '@angular/cdk/platform';\nimport {AbstractControlDirective} from '@angular/forms';\nimport {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';\nimport {\n getMatFormFieldDuplicatedHintError,\n getMatFormFieldMissingControlError,\n getMatFormFieldPlaceholderConflictError,\n matFormFieldAnimations,\n MatFormFieldControl,\n MAT_ERROR,\n MAT_FORM_FIELD,\n MAT_PREFIX,\n MAT_SUFFIX,\n} from '@angular/material/form-field';\n\nlet nextUniqueId = 0;\nconst floatingLabelScale = 0.75;\nconst outlineGapPadding = 5;\n\n/**\n * Boilerplate for applying mixins to MatFormField.\n * @docs-private\n */\nconst _MatFormFieldBase = mixinColor(\n class {\n constructor(public _elementRef: ElementRef) {}\n },\n 'primary',\n);\n\n/**\n * Possible appearance styles for the form field.\n * @deprecated Use `MatFormFieldAppearance` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport type MatLegacyFormFieldAppearance = 'legacy' | 'standard' | 'fill' | 'outline';\n\n/**\n * Possible values for the \"floatLabel\" form field input.\n * @deprecated Use `FloatLabelType` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport type LegacyFloatLabelType = 'always' | 'never' | 'auto';\n\n/**\n * Represents the default options for the form field that can be configured\n * using the `MAT_FORM_FIELD_DEFAULT_OPTIONS` injection token.\n * @deprecated Use `MatFormFieldDefaultOptions` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport interface MatLegacyFormFieldDefaultOptions {\n /** Default form field appearance style. */\n appearance?: MatLegacyFormFieldAppearance;\n /** Default color of the form field. */\n color?: ThemePalette;\n /** Whether the required marker should be hidden by default. */\n hideRequiredMarker?: boolean;\n /**\n * Whether the label for form fields should by default float `always`,\n * `never`, or `auto` (only when necessary).\n */\n floatLabel?: LegacyFloatLabelType;\n}\n\n/**\n * Injection token that can be used to configure the\n * default options for all form field within an app.\n * @deprecated Use `MAT_FORM_FIELD_DEFAULT_OPTIONS` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const MAT_LEGACY_FORM_FIELD_DEFAULT_OPTIONS =\n new InjectionToken<MatLegacyFormFieldDefaultOptions>('MAT_FORM_FIELD_DEFAULT_OPTIONS');\n\n/**\n * Container for form controls that applies Material Design styling and behavior.\n * @deprecated Use `MatFormField` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Component({\n selector: 'mat-form-field',\n exportAs: 'matFormField',\n templateUrl: 'form-field.html',\n // MatInput is a directive and can't have styles, so we need to include its styles here\n // in form-field-input.css. The MatInput styles are fairly minimal so it shouldn't be a\n // big deal for people who aren't using MatInput.\n styleUrls: [\n 'form-field.css',\n 'form-field-fill.css',\n 'form-field-input.css',\n 'form-field-legacy.css',\n 'form-field-outline.css',\n 'form-field-standard.css',\n ],\n animations: [matFormFieldAnimations.transitionMessages],\n host: {\n 'class': 'mat-form-field',\n '[class.mat-form-field-appearance-standard]': 'appearance == \"standard\"',\n '[class.mat-form-field-appearance-fill]': 'appearance == \"fill\"',\n '[class.mat-form-field-appearance-outline]': 'appearance == \"outline\"',\n '[class.mat-form-field-appearance-legacy]': 'appearance == \"legacy\"',\n '[class.mat-form-field-invalid]': '_control.errorState',\n '[class.mat-form-field-can-float]': '_canLabelFloat()',\n '[class.mat-form-field-should-float]': '_shouldLabelFloat()',\n '[class.mat-form-field-has-label]': '_hasFloatingLabel()',\n '[class.mat-form-field-hide-placeholder]': '_hideControlPlaceholder()',\n '[class.mat-form-field-disabled]': '_control.disabled',\n '[class.mat-form-field-autofilled]': '_control.autofilled',\n '[class.mat-focused]': '_control.focused',\n '[class.ng-untouched]': '_shouldForward(\"untouched\")',\n '[class.ng-touched]': '_shouldForward(\"touched\")',\n '[class.ng-pristine]': '_shouldForward(\"pristine\")',\n '[class.ng-dirty]': '_shouldForward(\"dirty\")',\n '[class.ng-valid]': '_shouldForward(\"valid\")',\n '[class.ng-invalid]': '_shouldForward(\"invalid\")',\n '[class.ng-pending]': '_shouldForward(\"pending\")',\n '[class._mat-animation-noopable]': '!_animationsEnabled',\n },\n inputs: ['color'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{provide: MAT_FORM_FIELD, useExisting: MatLegacyFormField}],\n})\nexport class MatLegacyFormField\n extends _MatFormFieldBase\n implements AfterContentInit, AfterContentChecked, AfterViewInit, OnDestroy, CanColor\n{\n /**\n * Whether the outline gap needs to be calculated\n * immediately on the next change detection run.\n */\n private _outlineGapCalculationNeededImmediately = false;\n\n /** Whether the outline gap needs to be calculated next time the zone has stabilized. */\n private _outlineGapCalculationNeededOnStable = false;\n\n private readonly _destroyed = new Subject<void>();\n\n /** The form field appearance style. */\n @Input()\n get appearance(): MatLegacyFormFieldAppearance {\n return this._appearance;\n }\n set appearance(value: MatLegacyFormFieldAppearance) {\n const oldValue = this._appearance;\n\n this._appearance = value || this._defaults?.appearance || 'legacy';\n\n if (this._appearance === 'outline' && oldValue !== value) {\n this._outlineGapCalculationNeededOnStable = true;\n }\n }\n _appearance: MatLegacyFormFieldAppearance;\n\n /** Whether the required marker should be hidden. */\n @Input()\n get hideRequiredMarker(): boolean {\n return this._hideRequiredMarker;\n }\n set hideRequiredMarker(value: BooleanInput) {\n this._hideRequiredMarker = coerceBooleanProperty(value);\n }\n private _hideRequiredMarker = false;\n\n /** Override for the logic that disables the label animation in certain cases. */\n private _showAlwaysAnimate = false;\n\n /** Whether the floating label should always float or not. */\n _shouldAlwaysFloat(): boolean {\n return this.floatLabel === 'always' && !this._showAlwaysAnimate;\n }\n\n /** Whether the label can float or not. */\n _canLabelFloat(): boolean {\n return this.floatLabel !== 'never';\n }\n\n /** State of the mat-hint and mat-error animations. */\n _subscriptAnimationState: string = '';\n\n /** Text for the form field hint. */\n @Input()\n get hintLabel(): string {\n return this._hintLabel;\n }\n set hintLabel(value: string) {\n this._hintLabel = value;\n this._processHints();\n }\n private _hintLabel = '';\n\n // Unique id for the hint label.\n readonly _hintLabelId: string = `mat-hint-${nextUniqueId++}`;\n\n // Unique id for the label element.\n readonly _labelId = `mat-form-field-label-${nextUniqueId++}`;\n\n /**\n * Whether the label should always float, never float or float as the user types.\n *\n * Note: only the legacy appearance supports the `never` option. `never` was originally added as a\n * way to make the floating label emulate the behavior of a standard input placeholder. However\n * the form field now supports both floating labels and placeholders. Therefore in the non-legacy\n * appearances the `never` option has been disabled in favor of just using the placeholder.\n */\n @Input()\n get floatLabel(): LegacyFloatLabelType {\n return this.appearance !== 'legacy' && this._floatLabel === 'never' ? 'auto' : this._floatLabel;\n }\n set floatLabel(value: LegacyFloatLabelType) {\n if (value !== this._floatLabel) {\n this._floatLabel = value || this._getDefaultFloatLabelState();\n this._changeDetectorRef.markForCheck();\n }\n }\n private _floatLabel: LegacyFloatLabelType;\n\n /** Whether the Angular animations are enabled. */\n _animationsEnabled: boolean;\n\n @ViewChild('connectionContainer', {static: true}) _connectionContainerRef: ElementRef;\n @ViewChild('inputContainer') _inputContainerRef: ElementRef;\n @ViewChild('label') private _label: ElementRef<HTMLElement>;\n\n @ContentChild(MatFormFieldControl) _controlNonStatic: MatFormFieldControl<any>;\n @ContentChild(MatFormFieldControl, {static: true}) _controlStatic: MatFormFieldControl<any>;\n get _control() {\n // TODO(crisbeto): we need this workaround in order to support both Ivy and ViewEngine.\n // We should clean this up once Ivy is the default renderer.\n return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;\n }\n set _control(value) {\n this._explicitFormFieldControl = value;\n }\n private _explicitFormFieldControl: MatFormFieldControl<any>;\n\n @ContentChild(MatLegacyLabel) _labelChildNonStatic: MatLegacyLabel;\n @ContentChild(MatLegacyLabel, {static: true}) _labelChildStatic: MatLegacyLabel;\n @ContentChild(MatLegacyPlaceholder) _placeholderChild: MatLegacyPlaceholder;\n\n @ContentChildren(MAT_ERROR, {descendants: true}) _errorChildren: QueryList<MatLegacyError>;\n @ContentChildren(_MAT_LEGACY_HINT, {descendants: true}) _hintChildren: QueryList<MatLegacyHint>;\n @ContentChildren(MAT_PREFIX, {descendants: true})\n _prefixChildren: QueryList<MatLegacyPrefix>;\n @ContentChildren(MAT_SUFFIX, {descendants: true})\n _suffixChildren: QueryList<MatLegacySuffix>;\n\n constructor(\n elementRef: ElementRef,\n private _changeDetectorRef: ChangeDetectorRef,\n @Optional() private _dir: Directionality,\n @Optional()\n @Inject(MAT_LEGACY_FORM_FIELD_DEFAULT_OPTIONS)\n private _defaults: MatLegacyFormFieldDefaultOptions,\n private _platform: Platform,\n private _ngZone: NgZone,\n @Optional() @Inject(ANIMATION_MODULE_TYPE) _animationMode: string,\n ) {\n super(elementRef);\n\n this.floatLabel = this._getDefaultFloatLabelState();\n this._animationsEnabled = _animationMode !== 'NoopAnimations';\n\n // Set the default through here so we invoke the setter on the first run.\n this.appearance = _defaults?.appearance || 'legacy';\n if (_defaults) {\n this._hideRequiredMarker = Boolean(_defaults.hideRequiredMarker);\n if (_defaults.color) {\n this.color = this.defaultColor = _defaults.color;\n }\n }\n }\n\n /**\n * Gets the id of the label element. If no label is present, returns `null`.\n */\n getLabelId(): string | null {\n return this._hasFloatingLabel() ? this._labelId : null;\n }\n\n /**\n * Gets an ElementRef for the element that a overlay attached to the form field should be\n * positioned relative to.\n */\n getConnectedOverlayOrigin(): ElementRef {\n return this._connectionContainerRef || this._elementRef;\n }\n\n ngAfterContentInit() {\n this._validateControlChild();\n\n const control = this._control;\n\n if (control.controlType) {\n this._elementRef.nativeElement.classList.add(`mat-form-field-type-${control.controlType}`);\n }\n\n // Subscribe to changes in the child control state in order to update the form field UI.\n control.stateChanges.pipe(startWith(null)).subscribe(() => {\n this._validatePlaceholders();\n this._syncDescribedByIds();\n this._changeDetectorRef.markForCheck();\n });\n\n // Run change detection if the value changes.\n if (control.ngControl && control.ngControl.valueChanges) {\n control.ngControl.valueChanges\n .pipe(takeUntil(this._destroyed))\n .subscribe(() => this._changeDetectorRef.markForCheck());\n }\n\n // Note that we have to run outside of the `NgZone` explicitly,\n // in order to avoid throwing users into an infinite loop\n // if `zone-patch-rxjs` is included.\n this._ngZone.runOutsideAngular(() => {\n this._ngZone.onStable.pipe(takeUntil(this._destroyed)).subscribe(() => {\n if (this._outlineGapCalculationNeededOnStable) {\n this.updateOutlineGap();\n }\n });\n });\n\n // Run change detection and update the outline if the suffix or prefix changes.\n merge(this._prefixChildren.changes, this._suffixChildren.changes).subscribe(() => {\n this._outlineGapCalculationNeededOnStable = true;\n this._changeDetectorRef.markForCheck();\n });\n\n // Re-validate when the number of hints changes.\n this._hintChildren.changes.pipe(startWith(null)).subscribe(() => {\n this._processHints();\n this._changeDetectorRef.markForCheck();\n });\n\n // Update the aria-described by when the number of errors changes.\n this._errorChildren.changes.pipe(startWith(null)).subscribe(() => {\n this._syncDescribedByIds();\n this._changeDetectorRef.markForCheck();\n });\n\n if (this._dir) {\n this._dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => {\n if (typeof requestAnimationFrame === 'function') {\n this._ngZone.runOutsideAngular(() => {\n requestAnimationFrame(() => this.updateOutlineGap());\n });\n } else {\n this.updateOutlineGap();\n }\n });\n }\n }\n\n ngAfterContentChecked() {\n this._validateControlChild();\n if (this._outlineGapCalculationNeededImmediately) {\n this.updateOutlineGap();\n }\n }\n\n ngAfterViewInit() {\n // Avoid animations on load.\n this._subscriptAnimationState = 'enter';\n this._changeDetectorRef.detectChanges();\n }\n\n ngOnDestroy() {\n this._destroyed.next();\n this._destroyed.complete();\n }\n\n /**\n * Determines whether a class from the AbstractControlDirective\n * should be forwarded to the host element.\n */\n _shouldForward(prop: keyof AbstractControlDirective): boolean {\n const control = this._control ? this._control.ngControl : null;\n return control && control[prop];\n }\n\n _hasPlaceholder() {\n return !!((this._control && this._control.placeholder) || this._placeholderChild);\n }\n\n _hasLabel() {\n return !!(this._labelChildNonStatic || this._labelChildStatic);\n }\n\n _shouldLabelFloat() {\n return (\n this._canLabelFloat() &&\n ((this._control && this._control.shouldLabelFloat) || this._shouldAlwaysFloat())\n );\n }\n\n _hideControlPlaceholder() {\n // In the legacy appearance the placeholder is promoted to a label if no label is given.\n return (\n (this.appearance === 'legacy' && !this._hasLabel()) ||\n (this._hasLabel() && !this._shouldLabelFloat())\n );\n }\n\n _hasFloatingLabel() {\n // In the legacy appearance the placeholder is promoted to a label if no label is given.\n return this._hasLabel() || (this.appearance === 'legacy' && this._hasPlaceholder());\n }\n\n /** Determines whether to display hints or errors. */\n _getDisplayedMessages(): 'error' | 'hint' {\n return this._errorChildren && this._errorChildren.length > 0 && this._control.errorState\n ? 'error'\n : 'hint';\n }\n\n /** Animates the placeholder up and locks it in position. */\n _animateAndLockLabel(): void {\n if (this._hasFloatingLabel() && this._canLabelFloat()) {\n // If animations are disabled, we shouldn't go in here,\n // because the `transitionend` will never fire.\n if (this._animationsEnabled && this._label) {\n this._showAlwaysAnimate = true;\n\n fromEvent(this._label.nativeElement, 'transitionend')\n .pipe(take(1))\n .subscribe(() => {\n this._showAlwaysAnimate = false;\n });\n }\n\n this.floatLabel = 'always';\n this._changeDetectorRef.markForCheck();\n }\n }\n\n /**\n * Ensure that there is only one placeholder (either `placeholder` attribute on the child control\n * or child element with the `mat-placeholder` directive).\n */\n private _validatePlaceholders() {\n if (\n this._control.placeholder &&\n this._placeholderChild &&\n (typeof ngDevMode === 'undefined' || ngDevMode)\n ) {\n throw getMatFormFieldPlaceholderConflictError();\n }\n }\n\n /** Does any extra processing that is required when handling the hints. */\n private _processHints() {\n this._validateHints();\n this._syncDescribedByIds();\n }\n\n /**\n * Ensure that there is a maximum of one of each `<mat-hint>` alignment specified, with the\n * attribute being considered as `align=\"start\"`.\n */\n private _validateHints() {\n if (this._hintChildren && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n let startHint: MatLegacyHint;\n let endHint: MatLegacyHint;\n this._hintChildren.forEach((hint: MatLegacyHint) => {\n if (hint.align === 'start') {\n if (startHint || this.hintLabel) {\n throw getMatFormFieldDuplicatedHintError('start');\n }\n startHint = hint;\n } else if (hint.align === 'end') {\n if (endHint) {\n throw getMatFormFieldDuplicatedHintError('end');\n }\n endHint = hint;\n }\n });\n }\n }\n\n /** Gets the default float label state. */\n private _getDefaultFloatLabelState(): LegacyFloatLabelType {\n return (this._defaults && this._defaults.floatLabel) || 'auto';\n }\n\n /**\n * Sets the list of element IDs that describe the child control. This allows the control to update\n * its `aria-describedby` attribute accordingly.\n */\n private _syncDescribedByIds() {\n if (this._control) {\n let ids: string[] = [];\n\n // TODO(wagnermaciel): Remove the type check when we find the root cause of this bug.\n if (\n this._control.userAriaDescribedBy &&\n typeof this._control.userAriaDescribedBy === 'string'\n ) {\n ids.push(...this._control.userAriaDescribedBy.split(' '));\n }\n\n if (this._getDisplayedMessages() === 'hint') {\n const startHint = this._hintChildren\n ? this._hintChildren.find(hint => hint.align === 'start')\n : null;\n const endHint = this._hintChildren\n ? this._hintChildren.find(hint => hint.align === 'end')\n : null;\n\n if (startHint) {\n ids.push(startHint.id);\n } else if (this._hintLabel) {\n ids.push(this._hintLabelId);\n }\n\n if (endHint) {\n ids.push(endHint.id);\n }\n } else if (this._errorChildren) {\n ids.push(...this._errorChildren.map(error => error.id));\n }\n\n this._control.setDescribedByIds(ids);\n }\n }\n\n /** Throws an error if the form field's control is missing. */\n protected _validateControlChild() {\n if (!this._control && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatFormFieldMissingControlError();\n }\n }\n\n /**\n * Updates the width and position of the gap in the outline. Only relevant for the outline\n * appearance.\n */\n updateOutlineGap() {\n const labelEl = this._label ? this._label.nativeElement : null;\n const container = this._connectionContainerRef.nativeElement;\n const outlineStartSelector = '.mat-form-field-outline-start';\n const outlineGapSelector = '.mat-form-field-outline-gap';\n\n // getBoundingClientRect isn't available on the server.\n if (this.appearance !== 'outline' || !this._platform.isBrowser) {\n return;\n }\n\n // If there is no content, set the gap elements to zero.\n if (!labelEl || !labelEl.children.length || !labelEl.textContent!.trim()) {\n const gapElements = container.querySelectorAll(\n `${outlineStartSelector}, ${outlineGapSelector}`,\n );\n for (let i = 0; i < gapElements.length; i++) {\n gapElements[i].style.width = '0';\n }\n return;\n }\n\n // If the element is not present in the DOM, the outline gap will need to be calculated\n // the next time it is checked and in the DOM.\n if (!this._isAttachedToDOM()) {\n this._outlineGapCalculationNeededImmediately = true;\n return;\n }\n\n let startWidth = 0;\n let gapWidth = 0;\n\n const startEls = container.querySelectorAll(outlineStartSelector);\n const gapEls = container.querySelectorAll(outlineGapSelector);\n\n if (this._label && this._label.nativeElement.children.length) {\n const containerRect = container.getBoundingClientRect();\n\n // If the container's width and height are zero, it means that the element is\n // invisible and we can't calculate the outline gap. Mark the element as needing\n // to be checked the next time the zone stabilizes. We can't do this immediately\n // on the next change detection, because even if the element becomes visible,\n // the `ClientRect` won't be recalculated immediately. We reset the\n // `_outlineGapCalculationNeededImmediately` flag some we don't run the checks twice.\n if (containerRect.width === 0 && containerRect.height === 0) {\n this._outlineGapCalculationNeededOnStable = true;\n this._outlineGapCalculationNeededImmediately = false;\n return;\n }\n\n const containerStart = this._getStartEnd(containerRect);\n const labelChildren = labelEl.children;\n const labelStart = this._getStartEnd(labelChildren[0].getBoundingClientRect());\n let labelWidth = 0;\n\n for (let i = 0; i < labelChildren.length; i++) {\n labelWidth += (labelChildren[i] as HTMLElement).offsetWidth;\n }\n startWidth = Math.abs(labelStart - containerStart) - outlineGapPadding;\n gapWidth = labelWidth > 0 ? labelWidth * floatingLabelScale + outlineGapPadding * 2 : 0;\n }\n\n for (let i = 0; i < startEls.length; i++) {\n startEls[i].style.width = `${startWidth}px`;\n }\n for (let i = 0; i < gapEls.length; i++) {\n gapEls[i].style.width = `${gapWidth}px`;\n }\n\n this._outlineGapCalculationNeededOnStable = this._outlineGapCalculationNeededImmediately =\n false;\n }\n\n /** Gets the start end of the rect considering the current directionality. */\n private _getStartEnd(rect: ClientRect): number {\n return this._dir && this._dir.value === 'rtl' ? rect.right : rect.left;\n }\n\n /** Checks whether the form field is attached to the DOM. */\n private _isAttachedToDOM(): boolean {\n const element: HTMLElement = this._elementRef.nativeElement;\n\n if (element.getRootNode) {\n const rootNode = element.getRootNode();\n // If the element is inside the DOM the root node will be either the document\n // or the closest shadow root, otherwise it'll be the element itself.\n return rootNode && rootNode !== element;\n }\n\n // Otherwise fall back to checking if it's in the document. This doesn't account for\n // shadow DOM, however browser that support shadow DOM should support `getRootNode` as well.\n return document.documentElement!.contains(element);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ObserversModule} from '@angular/cdk/observers';\nimport {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '@angular/material/core';\nimport {MatLegacyError} from './error';\nimport {MatLegacyFormField} from './form-field';\nimport {MatLegacyHint} from './hint';\nimport {MatLegacyLabel} from './label';\nimport {MatLegacyPlaceholder} from './placeholder';\nimport {MatLegacyPrefix} from './prefix';\nimport {MatLegacySuffix} from './suffix';\n\n/**\n * @deprecated Use `MatFormFieldModule` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@NgModule({\n declarations: [\n MatLegacyError,\n MatLegacyFormField,\n MatLegacyHint,\n MatLegacyLabel,\n MatLegacyPlaceholder,\n MatLegacyPrefix,\n MatLegacySuffix,\n ],\n imports: [CommonModule, MatCommonModule, ObserversModule],\n exports: [\n MatCommonModule,\n MatLegacyError,\n MatLegacyFormField,\n MatLegacyHint,\n MatLegacyLabel,\n MatLegacyPlaceholder,\n MatLegacyPrefix,\n MatLegacySuffix,\n ],\n})\nexport class MatLegacyFormFieldModule {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {Attribute, Directive, ElementRef, Input} from '@angular/core';\nimport {MAT_ERROR} from '@angular/material/form-field';\n\nlet nextUniqueId = 0;\n\n/**\n * Single error message to be shown underneath the form field.\n * @deprecated Use `MatError` from `@angular/material/form-field` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Directive({\n selector: 'mat-error',\n host: {\n 'class': 'mat-error',\n '[attr.id]': 'id',\n 'aria-atomic': 'true',\n },\n providers: [{provide: MAT_ERROR, useExisting: MatLegacyError}],\n})\nexport class MatLegacyError {\n @Input() id: string = `mat-error-${nextUniqueId++}`;\n\n constructor(@Attribute('aria-live') ariaLive: string, elementRef: ElementRef) {\n // If no aria-live value is set add 'polite' as a default. This is preferred over setting\n // role='alert' so that screen readers do not interrupt the current task to read this aloud.\n if (!ariaLive) {\n elementRef.nativeElement.setAttribute('aria-live', 'polite');\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core';\nimport {MAT_OPTGROUP, _MatOptgroupBase} from '@angular/material/core';\n\n/**\n * Component that is used to group instances of `mat-option`.\n * @deprecated Use `MatOptgroup` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Component({\n selector: 'mat-optgroup',\n exportAs: 'matOptgroup',\n templateUrl: 'optgroup.html',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n inputs: ['disabled'],\n styleUrls: ['optgroup.css'],\n host: {\n 'class': 'mat-optgroup',\n '[attr.role]': '_inert ? null : \"group\"',\n '[attr.aria-disabled]': '_inert ? null : disabled.toString()',\n '[attr.aria-labelledby]': '_inert ? null : _labelId',\n '[class.mat-optgroup-disabled]': 'disabled',\n },\n providers: [{provide: MAT_OPTGROUP, useExisting: MatLegacyOptgroup}],\n})\nexport class MatLegacyOptgroup extends _MatOptgroupBase {}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {CommonModule} from '@angular/common';\nimport {MatRippleModule, MatPseudoCheckboxModule, MatCommonModule} from '@angular/material/core';\nimport {MatLegacyOption} from './option';\nimport {MatLegacyOptgroup} from './optgroup';\n\n/**\n * @deprecated Use `MatOptionModule` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@NgModule({\n imports: [MatRippleModule, CommonModule, MatCommonModule, MatPseudoCheckboxModule],\n exports: [MatLegacyOption, MatLegacyOptgroup],\n declarations: [MatLegacyOption, MatLegacyOptgroup],\n})\nexport class MatLegacyOptionModule {}\n\nexport * from './option';\nexport * from './optgroup';\n\nexport {\n /**\n * @deprecated Use `MAT_OPTGROUP` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n MAT_OPTGROUP as MAT_LEGACY_OPTGROUP,\n\n /**\n * @deprecated Use `MatOptionSelectionChange` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n MatOptionSelectionChange as MatLegacyOptionSelectionChange,\n\n /**\n * @deprecated Use `MatOptionParentComponent` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n MatOptionParentComponent as MatLegacyOptionParentComponent,\n\n /**\n * @deprecated Use `MAT_OPTION_PARENT_COMPONENT` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n MAT_OPTION_PARENT_COMPONENT as MAT_LEGACY_OPTION_PARENT_COMPONENT,\n\n /**\n * @deprecated Use `_countGroupLabelsBeforeOption` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n _countGroupLabelsBeforeOption as _countGroupLabelsBeforeLegacyOption,\n\n /**\n * @deprecated Use `_getOptionScrollPosition` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n _getOptionScrollPosition as _getLegacyOptionScrollPosition,\n\n /**\n * @deprecated Use `_MatOptionBase` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n _MatOptionBase as _MatLegacyOptionBase,\n\n /**\n * @deprecated Use `_MatOptgroupBase` from `@angular/material/core` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n _MatOptgroupBase as _MatLegacyOptgroupBase,\n} from '@angular/material/core';\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ActiveDescendantKeyManager, LiveAnnouncer} from '@angular/cdk/a11y';\nimport {Directionality} from '@angular/cdk/bidi';\nimport {\n BooleanInput,\n coerceBooleanProperty,\n coerceNumberProperty,\n NumberInput,\n} from '@angular/cdk/coercion';\nimport {SelectionModel} from '@angular/cdk/collections';\nimport {\n A,\n DOWN_ARROW,\n ENTER,\n hasModifierKey,\n LEFT_ARROW,\n RIGHT_ARROW,\n SPACE,\n UP_ARROW,\n} from '@angular/cdk/keycodes';\nimport {\n CdkConnectedOverlay,\n CdkOverlayOrigin,\n ConnectedPosition,\n Overlay,\n ScrollStrategy,\n} from '@angular/cdk/overlay';\nimport {ViewportRuler} from '@angular/cdk/scrolling';\nimport {\n AfterContentInit,\n AfterViewInit,\n Attribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n DoCheck,\n ElementRef,\n EventEmitter,\n Inject,\n InjectionToken,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n OnInit,\n Optional,\n Output,\n QueryList,\n Self,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport {\n AbstractControl,\n ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n Validators,\n} from '@angular/forms';\nimport {\n CanDisable,\n CanDisableRipple,\n CanUpdateErrorState,\n ErrorStateMatcher,\n HasTabIndex,\n MatOptgroup,\n MatOption,\n MatOptionSelectionChange,\n MAT_OPTGROUP,\n MAT_OPTION_PARENT_COMPONENT,\n mixinDisabled,\n mixinDisableRipple,\n mixinErrorState,\n mixinTabIndex,\n _countGroupLabelsBeforeOption,\n _getOptionScrollPosition,\n _MatOptionBase,\n} from '@angular/material/core';\nimport {MatFormField, MatFormFieldControl, MAT_FORM_FIELD} from '@angular/material/form-field';\nimport {defer, merge, Observable, Subject} from 'rxjs';\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n take,\n takeUntil,\n} from 'rxjs/operators';\nimport {matSelectAnimations} from './select-animations';\nimport {\n getMatSelectDynamicMultipleError,\n getMatSelectNonArrayValueError,\n getMatSelectNonFunctionValueError,\n} from './select-errors';\n\nlet nextUniqueId = 0;\n\n/** Injection token that determines the scroll handling while a select is open. */\nexport const MAT_SELECT_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'mat-select-scroll-strategy',\n);\n\n/** @docs-private */\nexport function MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY(\n overlay: Overlay,\n): () => ScrollStrategy {\n return () => overlay.scrollStrategies.reposition();\n}\n\n/** Object that can be used to configure the default options for the select module. */\nexport interface MatSelectConfig {\n /** Whether option centering should be disabled. */\n disableOptionCentering?: boolean;\n\n /** Time to wait in milliseconds after the last keystroke before moving focus to an item. */\n typeaheadDebounceInterval?: number;\n\n /** Class or list of classes to be applied to the menu's overlay panel. */\n overlayPanelClass?: string | string[];\n\n /** Wheter icon indicators should be hidden for single-selection. */\n hideSingleSelectionIndicator?: boolean;\n}\n\n/** Injection token that can be used to provide the default options the select module. */\nexport const MAT_SELECT_CONFIG = new InjectionToken<MatSelectConfig>('MAT_SELECT_CONFIG');\n\n/** @docs-private */\nexport const MAT_SELECT_SCROLL_STRATEGY_PROVIDER = {\n provide: MAT_SELECT_SCROLL_STRATEGY,\n deps: [Overlay],\n useFactory: MAT_SELECT_SCROLL_STRATEGY_PROVIDER_FACTORY,\n};\n\n/**\n * Injection token that can be used to reference instances of `MatSelectTrigger`. It serves as\n * alternative token to the actual `MatSelectTrigger` class which could cause unnecessary\n * retention of the class and its directive metadata.\n */\nexport const MAT_SELECT_TRIGGER = new InjectionToken<MatSelectTrigger>('MatSelectTrigger');\n\n/** Change event object that is emitted when the select value has changed. */\nexport class MatSelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: MatSelect,\n /** Current value of the select that emitted the event. */\n public value: any,\n ) {}\n}\n\n// Boilerplate for applying mixins to MatSelect.\n/** @docs-private */\nconst _MatSelectMixinBase = mixinDisableRipple(\n mixinTabIndex(\n mixinDisabled(\n mixinErrorState(\n class {\n /**\n * Emits whenever the component state changes and should cause the parent\n * form-field to update. Implemented as part of `MatFormFieldControl`.\n * @docs-private\n */\n readonly stateChanges = new Subject<void>();\n\n constructor(\n public _elementRef: ElementRef,\n public _defaultErrorStateMatcher: ErrorStateMatcher,\n public _parentForm: NgForm,\n public _parentFormGroup: FormGroupDirective,\n /**\n * Form control bound to the component.\n * Implemented as part of `MatFormFieldControl`.\n * @docs-private\n */\n public ngControl: NgControl,\n ) {}\n },\n ),\n ),\n ),\n);\n\n/** Base class with all of the `MatSelect` functionality. */\n@Directive()\nexport abstract class _MatSelectBase<C>\n extends _MatSelectMixinBase\n implements\n AfterContentInit,\n OnChanges,\n OnDestroy,\n OnInit,\n DoCheck,\n ControlValueAccessor,\n CanDisable,\n HasTabIndex,\n MatFormFieldControl<any>,\n CanUpdateErrorState,\n CanDisableRipple\n{\n /** All of the defined select options. */\n abstract options: QueryList<_MatOptionBase>;\n\n // TODO(crisbeto): this is only necessary for the non-MDC select, but it's technically a\n // public API so we have to keep it. It should be deprecated and removed eventually.\n /** All of the defined groups of options. */\n abstract optionGroups: QueryList<MatOptgroup>;\n\n /** User-supplied override of the trigger element. */\n abstract customTrigger: {};\n\n /**\n * This position config ensures that the top \"start\" corner of the overlay\n * is aligned with with the top \"start\" of the origin by default (overlapping\n * the trigger completely). If the panel cannot fit below the trigger, it\n * will fall back to a position above the trigger.\n */\n abstract _positions: ConnectedPosition[];\n\n /** Scrolls a particular option into the view. */\n protected abstract _scrollOptionIntoView(index: number): void;\n\n /** Called when the panel has been opened and the overlay has settled on its final position. */\n protected abstract _positioningSettled(): void;\n\n /** Creates a change event object that should be emitted by the select. */\n protected abstract _getChangeEvent(value: any): C;\n\n /** Factory function used to create a scroll strategy for this select. */\n private _scrollStrategyFactory: () => ScrollStrategy;\n\n /** Whether or not the overlay panel is open. */\n private _panelOpen = false;\n\n /** Comparison function to specify which option is displayed. Defaults to object equality. */\n private _compareWith = (o1: any, o2: any) => o1 === o2;\n\n /** Unique id for this input. */\n private _uid = `mat-select-${nextUniqueId++}`;\n\n /** Current `aria-labelledby` value for the select trigger. */\n private _triggerAriaLabelledBy: string | null = null;\n\n /**\n * Keeps track of the previous form control assigned to the select.\n * Used to detect if it has changed.\n */\n private _previousControl: AbstractControl | null | undefined;\n\n /** Emits whenever the component is destroyed. */\n protected readonly _destroy = new Subject<void>();\n\n /**\n * Implemented as part of MatFormFieldControl.\n * @docs-private\n */\n @Input('aria-describedby') userAriaDescribedBy: string;\n\n /** Deals with the selection logic. */\n _selectionModel: SelectionModel<MatOption>;\n\n /** Manages keyboard events for options in the panel. */\n _keyManager: ActiveDescendantKeyManager<MatOption>;\n\n /** `View -> model callback called when value changes` */\n _onChange: (value: any) => void = () => {};\n\n /** `View -> model callback called when select has been touched` */\n _onTouched = () => {};\n\n /** ID for the DOM node containing the select's value. */\n _valueId = `mat-select-value-${nextUniqueId++}`;\n\n /** Emits when the panel element is finished transforming in. */\n readonly _panelDoneAnimatingStream = new Subject<string>();\n\n /** Strategy that will be used to handle scrolling while the select panel is open. */\n _scrollStrategy: ScrollStrategy;\n\n _overlayPanelClass: string | string[] = this._defaultOptions?.overlayPanelClass || '';\n\n /** Whether the select is focused. */\n get focused(): boolean {\n return this._focused || this._panelOpen;\n }\n private _focused = false;\n\n /** A name for this control that can be used by `mat-form-field`. */\n controlType = 'mat-select';\n\n /** Trigger that opens the select. */\n @ViewChild('trigger') trigger: ElementRef;\n\n /** Panel containing the select options. */\n @ViewChild('panel') panel: ElementRef;\n\n /** Overlay pane containing the options. */\n @ViewChild(CdkConnectedOverlay)\n protected _overlayDir: CdkConnectedOverlay;\n\n /** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */\n @Input() panelClass: string | string[] | Set<string> | {[key: string]: any};\n\n /** Placeholder to be shown if no value has been selected. */\n @Input()\n get placeholder(): string {\n return this._placeholder;\n }\n set placeholder(value: string) {\n this._placeholder = value;\n this.stateChanges.next();\n }\n private _placeholder: string;\n\n /** Whether the component is required. */\n @Input()\n get required(): boolean {\n return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;\n }\n set required(value: BooleanInput) {\n this._required = coerceBooleanProperty(value);\n this.stateChanges.next();\n }\n private _required: boolean | undefined;\n\n /** Whether the user should be allowed to select multiple options. */\n @Input()\n get multiple(): boolean {\n return this._multiple;\n }\n set multiple(value: BooleanInput) {\n if (this._selectionModel && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatSelectDynamicMultipleError();\n }\n\n this._multiple = coerceBooleanProperty(value);\n }\n private _multiple: boolean = false;\n\n /** Whether to center the active option over the trigger. */\n @Input()\n get disableOptionCentering(): boolean {\n return this._disableOptionCentering;\n }\n set disableOptionCentering(value: BooleanInput) {\n this._disableOptionCentering = coerceBooleanProperty(value);\n }\n private _disableOptionCentering = this._defaultOptions?.disableOptionCentering ?? false;\n\n /**\n * Function to compare the option values with the selected values. The first argument\n * is a value from an option. The second is a value from the selection. A boolean\n * should be returned.\n */\n @Input()\n get compareWith() {\n return this._compareWith;\n }\n set compareWith(fn: (o1: any, o2: any) => boolean) {\n if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatSelectNonFunctionValueError();\n }\n this._compareWith = fn;\n if (this._selectionModel) {\n // A different comparator means the selection could change.\n this._initializeSelection();\n }\n }\n\n /** Value of the select control. */\n @Input()\n get value(): any {\n return this._value;\n }\n set value(newValue: any) {\n const hasAssigned = this._assignValue(newValue);\n\n if (hasAssigned) {\n this._onChange(newValue);\n }\n }\n private _value: any;\n\n /** Aria label of the select. */\n @Input('aria-label') ariaLabel: string = '';\n\n /** Input that can be used to specify the `aria-labelledby` attribute. */\n @Input('aria-labelledby') ariaLabelledby: string;\n\n /** Object used to control when error messages are shown. */\n @Input() override errorStateMatcher: ErrorStateMatcher;\n\n /** Time to wait in milliseconds after the last keystroke before moving focus to an item. */\n @Input()\n get typeaheadDebounceInterval(): number {\n return this._typeaheadDebounceInterval;\n }\n set typeaheadDebounceInterval(value: NumberInput) {\n this._typeaheadDebounceInterval = coerceNumberProperty(value);\n }\n private _typeaheadDebounceInterval: number;\n\n /**\n * Function used to sort the values in a select in multiple mode.\n * Follows the same logic as `Array.prototype.sort`.\n */\n @Input() sortComparator: (a: MatOption, b: MatOption, options: MatOption[]) => number;\n\n /** Unique id of the element. */\n @Input()\n get id(): string {\n return this._id;\n }\n set id(value: string) {\n this._id = value || this._uid;\n this.stateChanges.next();\n }\n private _id: string;\n\n /** Combined stream of all of the child options' change events. */\n readonly optionSelectionChanges: Observable<MatOptionSelectionChange> = defer(() => {\n const options = this.options;\n\n if (options) {\n return options.changes.pipe(\n startWith(options),\n switchMap(() => merge(...options.map(option => option.onSelectionChange))),\n );\n }\n\n return this._ngZone.onStable.pipe(\n take(1),\n switchMap(() => this.optionSelectionChanges),\n );\n }) as Observable<MatOptionSelectionChange>;\n\n /** Event emitted when the select panel has been toggled. */\n @Output() readonly openedChange: EventEmitter<boolean> = new EventEmitter<boolean>();\n\n /** Event emitted when the select has been opened. */\n @Output('opened') readonly _openedStream: Observable<void> = this.openedChange.pipe(\n filter(o => o),\n map(() => {}),\n );\n\n /** Event emitted when the select has been closed. */\n @Output('closed') readonly _closedStream: Observable<void> = this.openedChange.pipe(\n filter(o => !o),\n map(() => {}),\n );\n\n /** Event emitted when the selected value has been changed by the user. */\n @Output() readonly selectionChange: EventEmitter<C> = new EventEmitter<C>();\n\n /**\n * Event that emits whenever the raw value of the select changes. This is here primarily\n * to facilitate the two-way binding for the `value` input.\n * @docs-private\n */\n @Output() readonly valueChange: EventEmitter<any> = new EventEmitter<any>();\n\n constructor(\n protected _viewportRuler: ViewportRuler,\n protected _changeDetectorRef: ChangeDetectorRef,\n protected _ngZone: NgZone,\n _defaultErrorStateMatcher: ErrorStateMatcher,\n elementRef: ElementRef,\n @Optional() private _dir: Directionality,\n @Optional() _parentForm: NgForm,\n @Optional() _parentFormGroup: FormGroupDirective,\n @Optional() @Inject(MAT_FORM_FIELD) protected _parentFormField: MatFormField,\n @Self() @Optional() ngControl: NgControl,\n @Attribute('tabindex') tabIndex: string,\n @Inject(MAT_SELECT_SCROLL_STRATEGY) scrollStrategyFactory: any,\n private _liveAnnouncer: LiveAnnouncer,\n @Optional() @Inject(MAT_SELECT_CONFIG) protected _defaultOptions?: MatSelectConfig,\n ) {\n super(elementRef, _defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl);\n\n if (this.ngControl) {\n // Note: we provide the value accessor through here, instead of\n // the `providers` to avoid running into a circular import.\n this.ngControl.valueAccessor = this;\n }\n\n // Note that we only want to set this when the defaults pass it in, otherwise it should\n // stay as `undefined` so that it falls back to the default in the key manager.\n if (_defaultOptions?.typeaheadDebounceInterval != null) {\n this._typeaheadDebounceInterval = _defaultOptions.typeaheadDebounceInterval;\n }\n\n this._scrollStrategyFactory = scrollStrategyFactory;\n this._scrollStrategy = this._scrollStrategyFactory();\n this.tabIndex = parseInt(tabIndex) || 0;\n\n // Force setter to be called in case id was not specified.\n this.id = this.id;\n }\n\n ngOnInit() {\n this._selectionModel = new SelectionModel<MatOption>(this.multiple);\n this.stateChanges.next();\n\n // We need `distinctUntilChanged` here, because some browsers will\n // fire the animation end event twice for the same animation. See:\n // https://github.com/angular/angular/issues/24084\n this._panelDoneAnimatingStream\n .pipe(distinctUntilChanged(), takeUntil(this._destroy))\n .subscribe(() => this._panelDoneAnimating(this.panelOpen));\n }\n\n ngAfterContentInit() {\n this._initKeyManager();\n\n this._selectionModel.changed.pipe(takeUntil(this._destroy)).subscribe(event => {\n event.added.forEach(option => option.select());\n event.removed.forEach(option => option.deselect());\n });\n\n this.options.changes.pipe(startWith(null), takeUntil(this._destroy)).subscribe(() => {\n this._resetOptions();\n this._initializeSelection();\n });\n }\n\n ngDoCheck() {\n const newAriaLabelledby = this._getTriggerAriaLabelledby();\n const ngControl = this.ngControl;\n\n // We have to manage setting the `aria-labelledby` ourselves, because part of its value\n // is computed as a result of a content query which can cause this binding to trigger a\n // \"changed after checked\" error.\n if (newAriaLabelledby !== this._triggerAriaLabelledBy) {\n const element: HTMLElement = this._elementRef.nativeElement;\n this._triggerAriaLabelledBy = newAriaLabelledby;\n if (newAriaLabelledby) {\n element.setAttribute('aria-labelledby', newAriaLabelledby);\n } else {\n element.removeAttribute('aria-labelledby');\n }\n }\n\n if (ngControl) {\n // The disabled state might go out of sync if the form group is swapped out. See #17860.\n if (this._previousControl !== ngControl.control) {\n if (\n this._previousControl !== undefined &&\n ngControl.disabled !== null &&\n ngControl.disabled !== this.disabled\n ) {\n this.disabled = ngControl.disabled;\n }\n\n this._previousControl = ngControl.control;\n }\n\n this.updateErrorState();\n }\n }\n\n ngOnChanges(changes: SimpleChanges) {\n // Updating the disabled state is handled by `mixinDisabled`, but we need to additionally let\n // the parent form field know to run change detection when the disabled state changes.\n if (changes['disabled'] || changes['userAriaDescribedBy']) {\n this.stateChanges.next();\n }\n\n if (changes['typeaheadDebounceInterval'] && this._keyManager) {\n this._keyManager.withTypeAhead(this._typeaheadDebounceInterval);\n }\n }\n\n ngOnDestroy() {\n this._keyManager?.destroy();\n this._destroy.next();\n this._destroy.complete();\n this.stateChanges.complete();\n }\n\n /** Toggles the overlay panel open or closed. */\n toggle(): void {\n this.panelOpen ? this.close() : this.open();\n }\n\n /** Opens the overlay panel. */\n open(): void {\n if (this._canOpen()) {\n this._panelOpen = true;\n this._keyManager.withHorizontalOrientation(null);\n this._highlightCorrectOption();\n this._changeDetectorRef.markForCheck();\n }\n }\n\n /** Closes the overlay panel and focuses the host element. */\n close(): void {\n if (this._panelOpen) {\n this._panelOpen = false;\n this._keyManager.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');\n this._changeDetectorRef.markForCheck();\n this._onTouched();\n }\n }\n\n /**\n * Sets the select's value. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param value New value to be written to the model.\n */\n writeValue(value: any): void {\n this._assignValue(value);\n }\n\n /**\n * Saves a callback function to be invoked when the select's value\n * changes from user input. Part of the ControlValueAccessor interface\n * required to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the value changes.\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Saves a callback function to be invoked when the select is blurred\n * by the user. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param fn Callback to be triggered when the component has been touched.\n */\n registerOnTouched(fn: () => {}): void {\n this._onTouched = fn;\n }\n\n /**\n * Disables the select. Part of the ControlValueAccessor interface required\n * to integrate with Angular's core forms API.\n *\n * @param isDisabled Sets whether the component is disabled.\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n\n /** Whether or not the overlay panel is open. */\n get panelOpen(): boolean {\n return this._panelOpen;\n }\n\n /** The currently selected option. */\n get selected(): MatOption | MatOption[] {\n return this.multiple ? this._selectionModel?.selected || [] : this._selectionModel?.selected[0];\n }\n\n /** The value displayed in the trigger. */\n get triggerValue(): string {\n if (this.empty) {\n return '';\n }\n\n if (this._multiple) {\n const selectedOptions = this._selectionModel.selected.map(option => option.viewValue);\n\n if (this._isRtl()) {\n selectedOptions.reverse();\n }\n\n // TODO(crisbeto): delimiter should be configurable for proper localization.\n return selectedOptions.join(', ');\n }\n\n return this._selectionModel.selected[0].viewValue;\n }\n\n /** Whether the element is in RTL mode. */\n _isRtl(): boolean {\n return this._dir ? this._dir.value === 'rtl' : false;\n }\n\n /** Handles all keydown events on the select. */\n _handleKeydown(event: KeyboardEvent): void {\n if (!this.disabled) {\n this.panelOpen ? this._handleOpenKeydown(event) : this._handleClosedKeydown(event);\n }\n }\n\n /** Handles keyboard events while the select is closed. */\n private _handleClosedKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n const isArrowKey =\n keyCode === DOWN_ARROW ||\n keyCode === UP_ARROW ||\n keyCode === LEFT_ARROW ||\n keyCode === RIGHT_ARROW;\n const isOpenKey = keyCode === ENTER || keyCode === SPACE;\n const manager = this._keyManager;\n\n // Open the select on ALT + arrow key to match the native <select>\n if (\n (!manager.isTyping() && isOpenKey && !hasModifierKey(event)) ||\n ((this.multiple || event.altKey) && isArrowKey)\n ) {\n event.preventDefault(); // prevents the page from scrolling down when pressing space\n this.open();\n } else if (!this.multiple) {\n const previouslySelectedOption = this.selected;\n manager.onKeydown(event);\n const selectedOption = this.selected;\n\n // Since the value has changed, we need to announce it ourselves.\n if (selectedOption && previouslySelectedOption !== selectedOption) {\n // We set a duration on the live announcement, because we want the live element to be\n // cleared after a while so that users can't navigate to it using the arrow keys.\n this._liveAnnouncer.announce((selectedOption as MatOption).viewValue, 10000);\n }\n }\n }\n\n /** Handles keyboard events when the selected is open. */\n private _handleOpenKeydown(event: KeyboardEvent): void {\n const manager = this._keyManager;\n const keyCode = event.keyCode;\n const isArrowKey = keyCode === DOWN_ARROW || keyCode === UP_ARROW;\n const isTyping = manager.isTyping();\n\n if (isArrowKey && event.altKey) {\n // Close the select on ALT + arrow key to match the native <select>\n event.preventDefault();\n this.close();\n // Don't do anything in this case if the user is typing,\n // because the typing sequence can include the space key.\n } else if (\n !isTyping &&\n (keyCode === ENTER || keyCode === SPACE) &&\n manager.activeItem &&\n !hasModifierKey(event)\n ) {\n event.preventDefault();\n manager.activeItem._selectViaInteraction();\n } else if (!isTyping && this._multiple && keyCode === A && event.ctrlKey) {\n event.preventDefault();\n const hasDeselectedOptions = this.options.some(opt => !opt.disabled && !opt.selected);\n\n this.options.forEach(option => {\n if (!option.disabled) {\n hasDeselectedOptions ? option.select() : option.deselect();\n }\n });\n } else {\n const previouslyFocusedIndex = manager.activeItemIndex;\n\n manager.onKeydown(event);\n\n if (\n this._multiple &&\n isArrowKey &&\n event.shiftKey &&\n manager.activeItem &&\n manager.activeItemIndex !== previouslyFocusedIndex\n ) {\n manager.activeItem._selectViaInteraction();\n }\n }\n }\n\n _onFocus() {\n if (!this.disabled) {\n this._focused = true;\n this.stateChanges.next();\n }\n }\n\n /**\n * Calls the touched callback only if the panel is closed. Otherwise, the trigger will\n * \"blur\" to the panel when it opens, causing a false positive.\n */\n _onBlur() {\n this._focused = false;\n this._keyManager?.cancelTypeahead();\n\n if (!this.disabled && !this.panelOpen) {\n this._onTouched();\n this._changeDetectorRef.markForCheck();\n this.stateChanges.next();\n }\n }\n\n /**\n * Callback that is invoked when the overlay panel has been attached.\n */\n _onAttached(): void {\n this._overlayDir.positionChange.pipe(take(1)).subscribe(() => {\n this._changeDetectorRef.detectChanges();\n this._positioningSettled();\n });\n }\n\n /** Returns the theme to be used on the panel. */\n _getPanelTheme(): string {\n return this._parentFormField ? `mat-${this._parentFormField.color}` : '';\n }\n\n /** Whether the select has a value. */\n get empty(): boolean {\n return !this._selectionModel || this._selectionModel.isEmpty();\n }\n\n private _initializeSelection(): void {\n // Defer setting the value in order to avoid the \"Expression\n // has changed after it was checked\" errors from Angular.\n Promise.resolve().then(() => {\n if (this.ngControl) {\n this._value = this.ngControl.value;\n }\n\n this._setSelectionByValue(this._value);\n this.stateChanges.next();\n });\n }\n\n /**\n * Sets the selected option based on a value. If no option can be\n * found with the designated value, the select trigger is cleared.\n */\n private _setSelectionByValue(value: any | any[]): void {\n this.options.forEach(option => option.setInactiveStyles());\n this._selectionModel.clear();\n\n if (this.multiple && value) {\n if (!Array.isArray(value) && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw getMatSelectNonArrayValueError();\n }\n\n value.forEach((currentValue: any) => this._selectOptionByValue(currentValue));\n this._sortValues();\n } else {\n const correspondingOption = this._selectOptionByValue(value);\n\n // Shift focus to the active item. Note that we shouldn't do this in multiple\n // mode, because we don't know what option the user interacted with last.\n if (correspondingOption) {\n this._keyManager.updateActiveItem(correspondingOption);\n } else if (!this.panelOpen) {\n // Otherwise reset the highlighted option. Note that we only want to do this while\n // closed, because doing it while open can shift the user's focus unnecessarily.\n this._keyManager.updateActiveItem(-1);\n }\n }\n\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Finds and selects and option based on its value.\n * @returns Option that has the corresponding value.\n */\n private _selectOptionByValue(value: any): MatOption | undefined {\n const correspondingOption = this.options.find((option: MatOption) => {\n // Skip options that are already in the model. This allows us to handle cases\n // where the same primitive value is selected multiple times.\n if (this._selectionModel.isSelected(option)) {\n return false;\n }\n\n try {\n // Treat null as a special reset value.\n return option.value != null && this._compareWith(option.value, value);\n } catch (error) {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n // Notify developers of errors in their comparator.\n console.warn(error);\n }\n return false;\n }\n });\n\n if (correspondingOption) {\n this._selectionModel.select(correspondingOption);\n }\n\n return correspondingOption;\n }\n\n /** Assigns a specific value to the select. Returns whether the value has changed. */\n private _assignValue(newValue: any | any[]): boolean {\n // Always re-assign an array, because it might have been mutated.\n if (newValue !== this._value || (this._multiple && Array.isArray(newValue))) {\n if (this.options) {\n this._setSelectionByValue(newValue);\n }\n\n this._value = newValue;\n return true;\n }\n return false;\n }\n\n /** Sets up a key manager to listen to keyboard events on the overlay panel. */\n private _initKeyManager() {\n this._keyManager = new ActiveDescendantKeyManager<MatOption>(this.options)\n .withTypeAhead(this._typeaheadDebounceInterval)\n .withVerticalOrientation()\n .withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr')\n .withHomeAndEnd()\n .withPageUpDown()\n .withAllowedModifierKeys(['shiftKey']);\n\n this._keyManager.tabOut.subscribe(() => {\n if (this.panelOpen) {\n // Select the active item when tabbing away. This is consistent with how the native\n // select behaves. Note that we only want to do this in single selection mode.\n if (!this.multiple && this._keyManager.activeItem) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n\n // Restore focus to the trigger before closing. Ensures that the focus\n // position won't be lost if the user got focus into the overlay.\n this.focus();\n this.close();\n }\n });\n\n this._keyManager.change.subscribe(() => {\n if (this._panelOpen && this.panel) {\n this._scrollOptionIntoView(this._keyManager.activeItemIndex || 0);\n } else if (!this._panelOpen && !this.multiple && this._keyManager.activeItem) {\n this._keyManager.activeItem._selectViaInteraction();\n }\n });\n }\n\n /** Drops current option subscriptions and IDs and resets from scratch. */\n private _resetOptions(): void {\n const changedOrDestroyed = merge(this.options.changes, this._destroy);\n\n this.optionSelectionChanges.pipe(takeUntil(changedOrDestroyed)).subscribe(event => {\n this._onSelect(event.source, event.isUserInput);\n\n if (event.isUserInput && !this.multiple && this._panelOpen) {\n this.close();\n this.focus();\n }\n });\n\n // Listen to changes in the internal state of the options and react accordingly.\n // Handles cases like the labels of the selected options changing.\n merge(...this.options.map(option => option._stateChanges))\n .pipe(takeUntil(changedOrDestroyed))\n .subscribe(() => {\n // `_stateChanges` can fire as a result of a change in the label's DOM value which may\n // be the result of an expression changing. We have to use `detectChanges` in order\n // to avoid \"changed after checked\" errors (see #14793).\n this._changeDetectorRef.detectChanges();\n this.stateChanges.next();\n });\n }\n\n /** Invoked when an option is clicked. */\n private _onSelect(option: MatOption, isUserInput: boolean): void {\n const wasSelected = this._selectionModel.isSelected(option);\n\n if (option.value == null && !this._multiple) {\n option.deselect();\n this._selectionModel.clear();\n\n if (this.value != null) {\n this._propagateChanges(option.value);\n }\n } else {\n if (wasSelected !== option.selected) {\n option.selected\n ? this._selectionModel.select(option)\n : this._selectionModel.deselect(option);\n }\n\n if (isUserInput) {\n this._keyManager.setActiveItem(option);\n }\n\n if (this.multiple) {\n this._sortValues();\n\n if (isUserInput) {\n // In case the user selected the option with their mouse, we\n // want to restore focus back to the trigger, in order to\n // prevent the select keyboard controls from clashing with\n // the ones from `mat-option`.\n this.focus();\n }\n }\n }\n\n if (wasSelected !== this._selectionModel.isSelected(option)) {\n this._propagateChanges();\n }\n\n this.stateChanges.next();\n }\n\n /** Sorts the selected values in the selected based on their order in the panel. */\n private _sortValues() {\n if (this.multiple) {\n const options = this.options.toArray();\n\n this._selectionModel.sort((a, b) => {\n return this.sortComparator\n ? this.sortComparator(a, b, options)\n : options.indexOf(a) - options.indexOf(b);\n });\n this.stateChanges.next();\n }\n }\n\n /** Emits change event to set the model value. */\n private _propagateChanges(fallbackValue?: any): void {\n let valueToEmit: any = null;\n\n if (this.multiple) {\n valueToEmit = (this.selected as MatOption[]).map(option => option.value);\n } else {\n valueToEmit = this.selected ? (this.selected as MatOption).value : fallbackValue;\n }\n\n this._value = valueToEmit;\n this.valueChange.emit(valueToEmit);\n this._onChange(valueToEmit);\n this.selectionChange.emit(this._getChangeEvent(valueToEmit));\n this._changeDetectorRef.markForCheck();\n }\n\n /**\n * Highlights the selected item. If no option is selected, it will highlight\n * the first item instead.\n */\n private _highlightCorrectOption(): void {\n if (this._keyManager) {\n if (this.empty) {\n this._keyManager.setFirstItemActive();\n } else {\n this._keyManager.setActiveItem(this._selectionModel.selected[0]);\n }\n }\n }\n\n /** Whether the panel is allowed to open. */\n protected _canOpen(): boolean {\n return !this._panelOpen && !this.disabled && this.options?.length > 0;\n }\n\n /** Focuses the select element. */\n focus(options?: FocusOptions): void {\n this._elementRef.nativeElement.focus(options);\n }\n\n /** Gets the aria-labelledby for the select panel. */\n _getPanelAriaLabelledby(): string | null {\n if (this.ariaLabel) {\n return null;\n }\n\n const labelId = this._parentFormField?.getLabelId();\n const labelExpression = labelId ? labelId + ' ' : '';\n return this.ariaLabelledby ? labelExpression + this.ariaLabelledby : labelId;\n }\n\n /** Determines the `aria-activedescendant` to be set on the host. */\n _getAriaActiveDescendant(): string | null {\n if (this.panelOpen && this._keyManager && this._keyManager.activeItem) {\n return this._keyManager.activeItem.id;\n }\n\n return null;\n }\n\n /** Gets the aria-labelledby of the select component trigger. */\n private _getTriggerAriaLabelledby(): string | null {\n if (this.ariaLabel) {\n return null;\n }\n\n const labelId = this._parentFormField?.getLabelId();\n let value = (labelId ? labelId + ' ' : '') + this._valueId;\n\n if (this.ariaLabelledby) {\n value += ' ' + this.ariaLabelledby;\n }\n\n return value;\n }\n\n /** Called when the overlay panel is done animating. */\n protected _panelDoneAnimating(isOpen: boolean) {\n this.openedChange.emit(isOpen);\n }\n\n /**\n * Implemented as part of MatFormFieldControl.\n * @docs-private\n */\n setDescribedByIds(ids: string[]) {\n if (ids.length) {\n this._elementRef.nativeElement.setAttribute('aria-describedby', ids.join(' '));\n } else {\n this._elementRef.nativeElement.removeAttribute('aria-describedby');\n }\n }\n\n /**\n * Implemented as part of MatFormFieldControl.\n * @docs-private\n */\n onContainerClick() {\n this.focus();\n this.open();\n }\n\n /**\n * Implemented as part of MatFormFieldControl.\n * @docs-private\n */\n get shouldLabelFloat(): boolean {\n return this._panelOpen || !this.empty || (this._focused && !!this._placeholder);\n }\n}\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n */\n@Directive({\n selector: 'mat-select-trigger',\n providers: [{provide: MAT_SELECT_TRIGGER, useExisting: MatSelectTrigger}],\n})\nexport class MatSelectTrigger {}\n\n@Component({\n selector: 'mat-select',\n exportAs: 'matSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.css'],\n inputs: ['disabled', 'disableRipple', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n 'role': 'combobox',\n 'aria-autocomplete': 'none',\n 'aria-haspopup': 'listbox',\n 'class': 'mat-mdc-select',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-controls]': 'panelOpen ? id + \"-panel\" : null',\n '[attr.aria-expanded]': 'panelOpen',\n '[attr.aria-label]': 'ariaLabel || null',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.mat-mdc-select-disabled]': 'disabled',\n '[class.mat-mdc-select-invalid]': 'errorState',\n '[class.mat-mdc-select-required]': 'required',\n '[class.mat-mdc-select-empty]': 'empty',\n '[class.mat-mdc-select-multiple]': 'multiple',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n animations: [matSelectAnimations.transformPanel],\n providers: [\n {provide: MatFormFieldControl, useExisting: MatSelect},\n {provide: MAT_OPTION_PARENT_COMPONENT, useExisting: MatSelect},\n ],\n})\nexport class MatSelect extends _MatSelectBase<MatSelectChange> implements OnInit, AfterViewInit {\n @ContentChildren(MatOption, {descendants: true}) options: QueryList<MatOption>;\n @ContentChildren(MAT_OPTGROUP, {descendants: true}) optionGroups: QueryList<MatOptgroup>;\n @ContentChild(MAT_SELECT_TRIGGER) customTrigger: MatSelectTrigger;\n\n _positions: ConnectedPosition[] = [\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n panelClass: 'mat-mdc-select-panel-above',\n },\n ];\n\n /** Ideal origin for the overlay panel. */\n _preferredOverlayOrigin: CdkOverlayOrigin | ElementRef | undefined;\n\n /** Width of the overlay panel. */\n _overlayWidth: number;\n\n override get shouldLabelFloat(): boolean {\n // Since the panel doesn't overlap the trigger, we\n // want the label to only float when there's a value.\n return this.panelOpen || !this.empty || (this.focused && !!this.placeholder);\n }\n\n override ngOnInit() {\n super.ngOnInit();\n this._viewportRuler\n .change()\n .pipe(takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._overlayWidth = this._getOverlayWidth();\n this._changeDetectorRef.detectChanges();\n }\n });\n }\n\n ngAfterViewInit() {\n // Note that it's important that we read this in `ngAfterViewInit`, because\n // reading it earlier will cause the form field to return a different element.\n if (this._parentFormField) {\n this._preferredOverlayOrigin = this._parentFormField.getConnectedOverlayOrigin();\n }\n }\n\n override open() {\n this._overlayWidth = this._getOverlayWidth();\n super.open();\n // Required for the MDC form field to pick up when the overlay has been opened.\n this.stateChanges.next();\n }\n\n override close() {\n super.close();\n // Required for the MDC form field to pick up when the overlay has been closed.\n this.stateChanges.next();\n }\n\n /** Scrolls the active option into view. */\n protected _scrollOptionIntoView(index: number): void {\n const option = this.options.toArray()[index];\n\n if (option) {\n const panel: HTMLElement = this.panel.nativeElement;\n const labelCount = _countGroupLabelsBeforeOption(index, this.options, this.optionGroups);\n const element = option._getHostElement();\n\n if (index === 0 && labelCount === 1) {\n // If we've got one group label before the option and we're at the top option,\n // scroll the list to the top. This is better UX than scrolling the list to the\n // top of the option, because it allows the user to read the top group's label.\n panel.scrollTop = 0;\n } else {\n panel.scrollTop = _getOptionScrollPosition(\n element.offsetTop,\n element.offsetHeight,\n panel.scrollTop,\n panel.offsetHeight,\n );\n }\n }\n }\n\n protected _positioningSettled() {\n this._scrollOptionIntoView(this._keyManager.activeItemIndex || 0);\n }\n\n protected _getChangeEvent(value: any) {\n return new MatSelectChange(this, value);\n }\n\n /** Gets how wide the overlay panel should be. */\n private _getOverlayWidth() {\n const refToMeasure =\n this._preferredOverlayOrigin instanceof CdkOverlayOrigin\n ? this._preferredOverlayOrigin.elementRef\n : this._preferredOverlayOrigin || this._elementRef;\n return refToMeasure.nativeElement.getBoundingClientRect().width;\n }\n\n /** Whether checkmark indicator for single-selection options is hidden. */\n @Input()\n get hideSingleSelectionIndicator(): boolean {\n return this._hideSingleSelectionIndicator;\n }\n set hideSingleSelectionIndicator(value: BooleanInput) {\n this._hideSingleSelectionIndicator = coerceBooleanProperty(value);\n this._syncParentProperties();\n }\n private _hideSingleSelectionIndicator: boolean =\n this._defaultOptions?.hideSingleSelectionIndicator ?? false;\n\n /** Syncs the parent state with the individual options. */\n _syncParentProperties(): void {\n if (this.options) {\n for (const option of this.options) {\n option._changeDetectorRef.markForCheck();\n }\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ConnectedPosition} from '@angular/cdk/overlay';\nimport {\n ChangeDetectionStrategy,\n Component,\n ContentChild,\n ContentChildren,\n Directive,\n OnInit,\n QueryList,\n ViewEncapsulation,\n} from '@angular/core';\nimport {\n _countGroupLabelsBeforeLegacyOption,\n _getLegacyOptionScrollPosition,\n MAT_LEGACY_OPTGROUP,\n MAT_LEGACY_OPTION_PARENT_COMPONENT,\n MatLegacyOption,\n MatLegacyOptgroup,\n} from '@angular/material/legacy-core';\nimport {MAT_SELECT_TRIGGER, _MatSelectBase} from '@angular/material/select';\nimport {MatLegacyFormFieldControl} from '@angular/material/legacy-form-field';\nimport {take, takeUntil} from 'rxjs/operators';\nimport {matLegacySelectAnimations} from './select-animations';\n\n/**\n * The following style constants are necessary to save here in order\n * to properly calculate the alignment of the selected option over\n * the trigger element.\n */\n\n/**\n * The max height of the select's overlay panel.\n * @deprecated Use `SELECT_PANEL_MAX_HEIGHT` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_PANEL_MAX_HEIGHT = 256;\n\n/**\n * The panel's padding on the x-axis.\n * @deprecated Use `SELECT_PANEL_PADDING_X` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_PANEL_PADDING_X = 16;\n\n/**\n * The panel's x axis padding if it is indented (e.g. there is an option group).\n * @deprecated Use `SELECT_PANEL_INDENT_PADDING_X` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_PANEL_INDENT_PADDING_X = SELECT_PANEL_PADDING_X * 2;\n\n/**\n * The height of the select items in `em` units.\n * @deprecated Use `SELECT_ITEM_HEIGHT_EM` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_ITEM_HEIGHT_EM = 3;\n\n// TODO(josephperrott): Revert to a constant after 2018 spec updates are fully merged.\n/**\n * Distance between the panel edge and the option text in\n * multi-selection mode.\n *\n * Calculated as:\n * (SELECT_PANEL_PADDING_X * 1.5) + 16 = 40\n * The padding is multiplied by 1.5 because the checkbox's margin is half the padding.\n * The checkbox width is 16px.\n *\n * @deprecated Use `SELECT_MULTIPLE_PANEL_PADDING_X` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_MULTIPLE_PANEL_PADDING_X = SELECT_PANEL_PADDING_X * 1.5 + 16;\n\n/**\n * The select panel will only \"fit\" inside the viewport if it is positioned at\n * this value or more away from the viewport boundary.\n * @deprecated Use `SELECT_PANEL_VIEWPORT_PADDING` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport const SELECT_PANEL_VIEWPORT_PADDING = 8;\n\n/**\n * Change event object that is emitted when the select value has changed.\n * @deprecated Use `MatSelectChange` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\nexport class MatLegacySelectChange {\n constructor(\n /** Reference to the select that emitted the change event. */\n public source: MatLegacySelect,\n /** Current value of the select that emitted the event. */\n public value: any,\n ) {}\n}\n\n/**\n * Allows the user to customize the trigger that is displayed when the select has a value.\n * @deprecated Use `MatSelectTrigger` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Directive({\n selector: 'mat-select-trigger',\n providers: [{provide: MAT_SELECT_TRIGGER, useExisting: MatLegacySelectTrigger}],\n})\nexport class MatLegacySelectTrigger {}\n\n/**\n * @deprecated Use `MatSelect` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@Component({\n selector: 'mat-select',\n exportAs: 'matSelect',\n templateUrl: 'select.html',\n styleUrls: ['select.css'],\n inputs: ['disabled', 'disableRipple', 'tabIndex'],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n 'role': 'combobox',\n 'aria-autocomplete': 'none',\n // TODO(crisbeto): the value for aria-haspopup should be `listbox`, but currently it's difficult\n // to sync into Google, because of an outdated automated a11y check which flags it as an invalid\n // value. At some point we should try to switch it back to being `listbox`.\n 'aria-haspopup': 'true',\n 'class': 'mat-select',\n '[attr.id]': 'id',\n '[attr.tabindex]': 'tabIndex',\n '[attr.aria-controls]': 'panelOpen ? id + \"-panel\" : null',\n '[attr.aria-expanded]': 'panelOpen',\n '[attr.aria-label]': 'ariaLabel || null',\n '[attr.aria-required]': 'required.toString()',\n '[attr.aria-disabled]': 'disabled.toString()',\n '[attr.aria-invalid]': 'errorState',\n '[attr.aria-activedescendant]': '_getAriaActiveDescendant()',\n '[class.mat-select-disabled]': 'disabled',\n '[class.mat-select-invalid]': 'errorState',\n '[class.mat-select-required]': 'required',\n '[class.mat-select-empty]': 'empty',\n '[class.mat-select-multiple]': 'multiple',\n '(keydown)': '_handleKeydown($event)',\n '(focus)': '_onFocus()',\n '(blur)': '_onBlur()',\n },\n animations: [\n matLegacySelectAnimations.transformPanelWrap,\n matLegacySelectAnimations.transformPanel,\n ],\n providers: [\n {provide: MatLegacyFormFieldControl, useExisting: MatLegacySelect},\n {provide: MAT_LEGACY_OPTION_PARENT_COMPONENT, useExisting: MatLegacySelect},\n ],\n})\nexport class MatLegacySelect extends _MatSelectBase<MatLegacySelectChange> implements OnInit {\n /** The scroll position of the overlay panel, calculated to center the selected option. */\n private _scrollTop = 0;\n\n /** The last measured value for the trigger's client bounding rect. */\n private _triggerRect: ClientRect;\n\n /** The cached font-size of the trigger element. */\n _triggerFontSize = 0;\n\n /** The value of the select panel's transform-origin property. */\n _transformOrigin: string = 'top';\n\n /**\n * The y-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text.\n * when the panel opens. Will change based on the y-position of the selected option.\n */\n _offsetY = 0;\n\n @ContentChildren(MatLegacyOption, {descendants: true}) options: QueryList<MatLegacyOption>;\n\n @ContentChildren(MAT_LEGACY_OPTGROUP, {descendants: true})\n optionGroups: QueryList<MatLegacyOptgroup>;\n\n @ContentChild(MAT_SELECT_TRIGGER) customTrigger: MatLegacySelectTrigger;\n\n _positions: ConnectedPosition[] = [\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'bottom',\n },\n ];\n\n /**\n * Calculates the scroll position of the select's overlay panel.\n *\n * Attempts to center the selected option in the panel. If the option is\n * too high or too low in the panel to be scrolled to the center, it clamps the\n * scroll position to the min or max scroll positions respectively.\n */\n _calculateOverlayScroll(selectedIndex: number, scrollBuffer: number, maxScroll: number): number {\n const itemHeight = this._getItemHeight();\n const optionOffsetFromScrollTop = itemHeight * selectedIndex;\n const halfOptionHeight = itemHeight / 2;\n\n // Starts at the optionOffsetFromScrollTop, which scrolls the option to the top of the\n // scroll container, then subtracts the scroll buffer to scroll the option down to\n // the center of the overlay panel. Half the option height must be re-added to the\n // scrollTop so the option is centered based on its middle, not its top edge.\n const optimalScrollPosition = optionOffsetFromScrollTop - scrollBuffer + halfOptionHeight;\n return Math.min(Math.max(0, optimalScrollPosition), maxScroll);\n }\n\n override ngOnInit() {\n super.ngOnInit();\n this._viewportRuler\n .change()\n .pipe(takeUntil(this._destroy))\n .subscribe(() => {\n if (this.panelOpen) {\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n this._changeDetectorRef.markForCheck();\n }\n });\n }\n\n override open(): void {\n if (super._canOpen()) {\n super.open();\n this._triggerRect = this.trigger.nativeElement.getBoundingClientRect();\n // Note: The computed font-size will be a string pixel value (e.g. \"16px\").\n // `parseInt` ignores the trailing 'px' and converts this to a number.\n this._triggerFontSize = parseInt(\n getComputedStyle(this.trigger.nativeElement).fontSize || '0',\n );\n this._calculateOverlayPosition();\n\n // Set the font size on the panel element once it exists.\n this._ngZone.onStable.pipe(take(1)).subscribe(() => {\n if (\n this._triggerFontSize &&\n this._overlayDir.overlayRef &&\n this._overlayDir.overlayRef.overlayElement\n ) {\n this._overlayDir.overlayRef.overlayElement.style.fontSize = `${this._triggerFontSize}px`;\n }\n });\n }\n }\n\n /** Scrolls the active option into view. */\n protected _scrollOptionIntoView(index: number): void {\n const labelCount = _countGroupLabelsBeforeLegacyOption(index, this.options, this.optionGroups);\n const itemHeight = this._getItemHeight();\n\n if (index === 0 && labelCount === 1) {\n // If we've got one group label before the option and we're at the top option,\n // scroll the list to the top. This is better UX than scrolling the list to the\n // top of the option, because it allows the user to read the top group's label.\n this.panel.nativeElement.scrollTop = 0;\n } else {\n this.panel.nativeElement.scrollTop = _getLegacyOptionScrollPosition(\n (index + labelCount) * itemHeight,\n itemHeight,\n this.panel.nativeElement.scrollTop,\n SELECT_PANEL_MAX_HEIGHT,\n );\n }\n }\n\n protected _positioningSettled() {\n this._calculateOverlayOffsetX();\n this.panel.nativeElement.scrollTop = this._scrollTop;\n }\n\n protected override _panelDoneAnimating(isOpen: boolean) {\n if (this.panelOpen) {\n this._scrollTop = 0;\n } else {\n this._overlayDir.offsetX = 0;\n this._changeDetectorRef.markForCheck();\n }\n\n super._panelDoneAnimating(isOpen);\n }\n\n protected _getChangeEvent(value: any) {\n return new MatLegacySelectChange(this, value);\n }\n\n protected _getOverlayMinWidth(): number {\n return this._triggerRect?.width;\n }\n\n /**\n * Sets the x-offset of the overlay panel in relation to the trigger's top start corner.\n * This must be adjusted to align the selected option text over the trigger text when\n * the panel opens. Will change based on LTR or RTL text direction. Note that the offset\n * can't be calculated until the panel has been attached, because we need to know the\n * content width in order to constrain the panel within the viewport.\n */\n private _calculateOverlayOffsetX(): void {\n const overlayRect = this._overlayDir.overlayRef.overlayElement.getBoundingClientRect();\n const viewportSize = this._viewportRuler.getViewportSize();\n const isRtl = this._isRtl();\n const paddingWidth = this.multiple\n ? SELECT_MULTIPLE_PANEL_PADDING_X + SELECT_PANEL_PADDING_X\n : SELECT_PANEL_PADDING_X * 2;\n let offsetX: number;\n\n // Adjust the offset, depending on the option padding.\n if (this.multiple) {\n offsetX = SELECT_MULTIPLE_PANEL_PADDING_X;\n } else if (this.disableOptionCentering) {\n offsetX = SELECT_PANEL_PADDING_X;\n } else {\n let selected = this._selectionModel.selected[0] || this.options.first;\n offsetX = selected && selected.group ? SELECT_PANEL_INDENT_PADDING_X : SELECT_PANEL_PADDING_X;\n }\n\n // Invert the offset in LTR.\n if (!isRtl) {\n offsetX *= -1;\n }\n\n // Determine how much the select overflows on each side.\n const leftOverflow = 0 - (overlayRect.left + offsetX - (isRtl ? paddingWidth : 0));\n const rightOverflow =\n overlayRect.right + offsetX - viewportSize.width + (isRtl ? 0 : paddingWidth);\n\n // If the element overflows on either side, reduce the offset to allow it to fit.\n if (leftOverflow > 0) {\n offsetX += leftOverflow + SELECT_PANEL_VIEWPORT_PADDING;\n } else if (rightOverflow > 0) {\n offsetX -= rightOverflow + SELECT_PANEL_VIEWPORT_PADDING;\n }\n\n // Set the offset directly in order to avoid having to go through change detection and\n // potentially triggering \"changed after it was checked\" errors. Round the value to avoid\n // blurry content in some browsers.\n this._overlayDir.offsetX = Math.round(offsetX);\n this._overlayDir.overlayRef.updatePosition();\n }\n\n /**\n * Calculates the y-offset of the select's overlay panel in relation to the\n * top start corner of the trigger. It has to be adjusted in order for the\n * selected option to be aligned over the trigger when the panel opens.\n */\n private _calculateOverlayOffsetY(\n selectedIndex: number,\n scrollBuffer: number,\n maxScroll: number,\n ): number {\n const itemHeight = this._getItemHeight();\n const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;\n const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);\n let optionOffsetFromPanelTop: number;\n\n // Disable offset if requested by user by returning 0 as value to offset\n if (this.disableOptionCentering) {\n return 0;\n }\n\n if (this._scrollTop === 0) {\n optionOffsetFromPanelTop = selectedIndex * itemHeight;\n } else if (this._scrollTop === maxScroll) {\n const firstDisplayedIndex = this._getItemCount() - maxOptionsDisplayed;\n const selectedDisplayIndex = selectedIndex - firstDisplayedIndex;\n\n // The first item is partially out of the viewport. Therefore we need to calculate what\n // portion of it is shown in the viewport and account for it in our offset.\n let partialItemHeight =\n itemHeight - ((this._getItemCount() * itemHeight - SELECT_PANEL_MAX_HEIGHT) % itemHeight);\n\n // Because the panel height is longer than the height of the options alone,\n // there is always extra padding at the top or bottom of the panel. When\n // scrolled to the very bottom, this padding is at the top of the panel and\n // must be added to the offset.\n optionOffsetFromPanelTop = selectedDisplayIndex * itemHeight + partialItemHeight;\n } else {\n // If the option was scrolled to the middle of the panel using a scroll buffer,\n // its offset will be the scroll buffer minus the half height that was added to\n // center it.\n optionOffsetFromPanelTop = scrollBuffer - itemHeight / 2;\n }\n\n // The final offset is the option's offset from the top, adjusted for the height difference,\n // multiplied by -1 to ensure that the overlay moves in the correct direction up the page.\n // The value is rounded to prevent some browsers from blurring the content.\n return Math.round(optionOffsetFromPanelTop * -1 - optionHeightAdjustment);\n }\n\n /**\n * Checks that the attempted overlay position will fit within the viewport.\n * If it will not fit, tries to adjust the scroll position and the associated\n * y-offset so the panel can open fully on-screen. If it still won't fit,\n * sets the offset back to 0 to allow the fallback position to take over.\n */\n private _checkOverlayWithinViewport(maxScroll: number): void {\n const itemHeight = this._getItemHeight();\n const viewportSize = this._viewportRuler.getViewportSize();\n\n const topSpaceAvailable = this._triggerRect.top - SELECT_PANEL_VIEWPORT_PADDING;\n const bottomSpaceAvailable =\n viewportSize.height - this._triggerRect.bottom - SELECT_PANEL_VIEWPORT_PADDING;\n\n const panelHeightTop = Math.abs(this._offsetY);\n const totalPanelHeight = Math.min(this._getItemCount() * itemHeight, SELECT_PANEL_MAX_HEIGHT);\n const panelHeightBottom = totalPanelHeight - panelHeightTop - this._triggerRect.height;\n\n if (panelHeightBottom > bottomSpaceAvailable) {\n this._adjustPanelUp(panelHeightBottom, bottomSpaceAvailable);\n } else if (panelHeightTop > topSpaceAvailable) {\n this._adjustPanelDown(panelHeightTop, topSpaceAvailable, maxScroll);\n } else {\n this._transformOrigin = this._getOriginBasedOnOption();\n }\n }\n\n /** Adjusts the overlay panel up to fit in the viewport. */\n private _adjustPanelUp(panelHeightBottom: number, bottomSpaceAvailable: number) {\n // Browsers ignore fractional scroll offsets, so we need to round.\n const distanceBelowViewport = Math.round(panelHeightBottom - bottomSpaceAvailable);\n\n // Scrolls the panel up by the distance it was extending past the boundary, then\n // adjusts the offset by that amount to move the panel up into the viewport.\n this._scrollTop -= distanceBelowViewport;\n this._offsetY -= distanceBelowViewport;\n this._transformOrigin = this._getOriginBasedOnOption();\n\n // If the panel is scrolled to the very top, it won't be able to fit the panel\n // by scrolling, so set the offset to 0 to allow the fallback position to take\n // effect.\n if (this._scrollTop <= 0) {\n this._scrollTop = 0;\n this._offsetY = 0;\n this._transformOrigin = `50% bottom 0px`;\n }\n }\n\n /** Adjusts the overlay panel down to fit in the viewport. */\n private _adjustPanelDown(panelHeightTop: number, topSpaceAvailable: number, maxScroll: number) {\n // Browsers ignore fractional scroll offsets, so we need to round.\n const distanceAboveViewport = Math.round(panelHeightTop - topSpaceAvailable);\n\n // Scrolls the panel down by the distance it was extending past the boundary, then\n // adjusts the offset by that amount to move the panel down into the viewport.\n this._scrollTop += distanceAboveViewport;\n this._offsetY += distanceAboveViewport;\n this._transformOrigin = this._getOriginBasedOnOption();\n\n // If the panel is scrolled to the very bottom, it won't be able to fit the\n // panel by scrolling, so set the offset to 0 to allow the fallback position\n // to take effect.\n if (this._scrollTop >= maxScroll) {\n this._scrollTop = maxScroll;\n this._offsetY = 0;\n this._transformOrigin = `50% top 0px`;\n return;\n }\n }\n\n /** Calculates the scroll position and x- and y-offsets of the overlay panel. */\n private _calculateOverlayPosition(): void {\n const itemHeight = this._getItemHeight();\n const items = this._getItemCount();\n const panelHeight = Math.min(items * itemHeight, SELECT_PANEL_MAX_HEIGHT);\n const scrollContainerHeight = items * itemHeight;\n\n // The farthest the panel can be scrolled before it hits the bottom\n const maxScroll = scrollContainerHeight - panelHeight;\n\n // If no value is selected we open the popup to the first item.\n let selectedOptionOffset: number;\n\n if (this.empty) {\n selectedOptionOffset = 0;\n } else {\n selectedOptionOffset = Math.max(\n this.options.toArray().indexOf(this._selectionModel.selected[0]),\n 0,\n );\n }\n\n selectedOptionOffset += _countGroupLabelsBeforeLegacyOption(\n selectedOptionOffset,\n this.options,\n this.optionGroups,\n );\n\n // We must maintain a scroll buffer so the selected option will be scrolled to the\n // center of the overlay panel rather than the top.\n const scrollBuffer = panelHeight / 2;\n this._scrollTop = this._calculateOverlayScroll(selectedOptionOffset, scrollBuffer, maxScroll);\n this._offsetY = this._calculateOverlayOffsetY(selectedOptionOffset, scrollBuffer, maxScroll);\n\n this._checkOverlayWithinViewport(maxScroll);\n }\n\n /** Sets the transform origin point based on the selected option. */\n private _getOriginBasedOnOption(): string {\n const itemHeight = this._getItemHeight();\n const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;\n const originY = Math.abs(this._offsetY) - optionHeightAdjustment + itemHeight / 2;\n return `50% ${originY}px 0px`;\n }\n\n /** Calculates the height of the select's options. */\n private _getItemHeight(): number {\n return this._triggerFontSize * SELECT_ITEM_HEIGHT_EM;\n }\n\n /** Calculates the amount of items in the select. This includes options and group labels. */\n private _getItemCount(): number {\n return this.options.length + this.optionGroups.length;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {OverlayModule} from '@angular/cdk/overlay';\nimport {CommonModule} from '@angular/common';\nimport {NgModule} from '@angular/core';\nimport {MatCommonModule} from '@angular/material/core';\nimport {MatLegacyOptionModule} from '@angular/material/legacy-core';\nimport {MatLegacyFormFieldModule} from '@angular/material/legacy-form-field';\nimport {CdkScrollableModule} from '@angular/cdk/scrolling';\nimport {MAT_SELECT_SCROLL_STRATEGY_PROVIDER} from '@angular/material/select';\nimport {MatLegacySelect, MatLegacySelectTrigger} from './select';\n\n/**\n * @deprecated Use `MatSelectModule` from `@angular/material/select` instead. See https://material.angular.io/guide/mdc-migration for information about migrating.\n * @breaking-change 17.0.0\n */\n@NgModule({\n imports: [CommonModule, OverlayModule, MatLegacyOptionModule, MatCommonModule],\n exports: [\n CdkScrollableModule,\n MatLegacyFormFieldModule,\n MatLegacySelect,\n MatLegacySelectTrigger,\n MatLegacyOptionModule,\n MatCommonModule,\n ],\n declarations: [MatLegacySelect, MatLegacySelectTrigger],\n providers: [MAT_SELECT_SCROLL_STRATEGY_PROVIDER],\n})\nexport class MatLegacySelectModule {}\n","/** A soft bezier curve for nice transitions. */\nexport const softBezier = 'cubic-bezier(0.4, 0, 0.2, 1)';\n","<label class=\"checkbox\" tabindex=\"0\" [attr.data-variant]=\"variant\" (keydown.enter)=\"onEnterKeydown()\">\n <input type=\"checkbox\" [(ngModel)]=\"checked\" (change)=\"onChange(checked)\" />\n <i *ngIf=\"!semiChecked\"><lru-icon [icon]=\"{ path: 'felib-check', size: size }\"></lru-icon></i>\n <i *ngIf=\"semiChecked && !checked\" class=\"semi\"\n ><lru-icon [icon]=\"{ path: 'felib-multiple-selection-checkbox-icon', size: size }\"></lru-icon\n ></i>\n <span>\n <ng-content></ng-content>\n </span>\n</label>\n","<div\n class=\"dropdown-button-container\"\n (click)=\"onClickToggleDropdown()\"\n [attr.data-id]=\"id\"\n [attr.data-open]=\"isOpen\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.data-axis]=\"axis\"\n [attr.data-horizontal-direction]=\"appliedHorizontalDirection\"\n [attr.data-vertical-direction]=\"appliedVerticalDirection\"\n [attr.data-variant]=\"variant\"\n [attr.data-pop-over]=\"popOver\"\n [attr.data-spacing-from-button]=\"spacingFromButton\"\n [style.zIndex]=\"zIndex$ | async\"\n #domOpenDropdownButton\n>\n <ng-content select=\"[button]\"></ng-content>\n</div>\n<ng-template cdk-portal>\n <ng-container *ngIf=\"zIndex$ | async as zIndex\">\n <div *ngIf=\"isOpen\" class=\"dropdown-overlay\" [style.zIndex]=\"zIndex - 1\" (click)=\"onCloseClick()\"></div>\n <div\n [style.zIndex]=\"zIndex\"\n *ngIf=\"isOpen\"\n class=\"dropdown-wrapper\"\n [attr.data-id]=\"id\"\n [attr.data-axis]=\"axis\"\n [attr.data-horizontal-direction]=\"appliedHorizontalDirection\"\n [attr.data-vertical-direction]=\"appliedVerticalDirection\"\n [attr.data-fill-width]=\"appliedFillWidth\"\n [attr.data-fill-height]=\"appliedFillHeight\"\n [attr.data-variant]=\"variant\"\n [attr.data-pop-over]=\"popOver\"\n [attr.data-spacing-from-window]=\"spacingFromWindow\"\n [attr.data-spacing-from-button]=\"spacingFromButton\"\n [style.top]=\"appliedTop\"\n [style.bottom]=\"appliedBottom\"\n [style.left]=\"appliedLeft\"\n [style.right]=\"appliedRight\"\n [style.max-height]=\"appliedMaxHeight\"\n [style.max-width]=\"appliedMaxWidth\"\n [style.width]=\"appliedWidth\"\n [style.height]=\"appliedHeight\"\n [style.visibility]=\"appliedVisibility\"\n >\n <!-- Used to trap focus inside of the dropdown -->\n <div tabindex=\"0\" class=\"focus-trap focus-trap-begin\"></div>\n <div class=\"dropdown-content\" #domDropdownContent>\n <div class=\"dropdown-close\" (click)=\"onCloseClick()\">\n <ng-content select=\"[close]\"></ng-content>\n </div>\n <ng-content *ngIf=\"dropdownService.open$ | async\"></ng-content>\n </div>\n <!-- Used to trap focus inside of the dropdown -->\n <div tabindex=\"0\" class=\"focus-trap focus-trap-end\"></div></div\n ></ng-container>\n</ng-template>\n","<ng-template cdk-portal>\n <ng-container *ngIf=\"zIndex$ | async as zIndex\">\n <div\n class=\"modal-overlay\"\n *ngIf=\"showBackgroundOverLay\"\n [attr.data-variant]=\"variant\"\n [@modal-overlay-enter-leave]\n [attr.data-variant]=\"variant\"\n [class.overflow-visible]=\"overflowVisible\"\n [style.zIndex]=\"zIndex\"\n ></div>\n <div\n *ngIf=\"isVisible\"\n class=\"modal-wrapper\"\n [style.zIndex]=\"zIndex\"\n (click)=\"onWrapperClick($event)\"\n [@modal-enter-leave]=\"useTransition\"\n [@.disabled]=\"!useTransition\"\n (@modal-enter-leave.done)=\"animationDone($event)\"\n [class.overflow-visible]=\"overflowVisible\"\n [attr.data-variant]=\"variant\"\n >\n <div\n (click)=\"onWrapperClick($event)\"\n [attr.data-use-transitions]=\"useTransition\"\n class=\"modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [style.paddingLeft]=\"spacingFromWindow\"\n [style.paddingRight]=\"spacingFromWindow\"\n >\n <!-- Used to trap focus inside of the modal -->\n <div tabindex=\"0\" class=\"focus-trap focus-trap-begin\"></div>\n <div\n class=\"modal-content\"\n #modalContent\n [style.marginTop]=\"spacingFromWindow\"\n [style.marginBottom]=\"spacingFromWindow\"\n [style.width]=\"width\"\n [style.height]=\"height\"\n >\n <ng-content></ng-content>\n </div>\n <!-- Used to trap focus inside of the modal -->\n <div tabindex=\"0\" class=\"focus-trap focus-trap-end\"></div>\n </div>\n </div>\n </ng-container>\n</ng-template>\n","<div class=\"search\">\n <input type=\"text\" placeholder=\"Søg i elever\" [(ngModel)]=\"searchTerm\" />\n <lru-icon [icon]=\"{ path: 'felib-search', size: 14 }\"></lru-icon>\n</div>\n\n<lru-dropdown\n [variant]=\"'lounge'\"\n [sameWidth]=\"true\"\n [spacingFromWindow]=\"10\"\n #dropdownLevel\n *ngIf=\"(loungeService.fullLevel$ | async)?.levels as levels; else levelsLoading\"\n>\n <ng-container button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\">\n <span>{{ getLevelsLabel() }}</span>\n <lru-icon [icon]=\"{ path: 'felib-chevron-down', size: 16 }\" class=\"arrow\"></lru-icon>\n </lru-button>\n </ng-container>\n <ng-container>\n <ul>\n <li *ngFor=\"let item of levels\">\n <lru-checkbox\n [checked]=\"isLevelSelected(item.id)\"\n [size]=\"12\"\n variant=\"lounge\"\n (changed)=\"onClickLevel(item, $event)\"\n >{{ item.mediumForm }}</lru-checkbox\n >\n </li>\n </ul>\n </ng-container>\n</lru-dropdown>\n\n<div class=\"classes\" *ngIf=\"loungeService.dlpClassWithStudentsList$ | async as classes; else classesLoading\">\n <mat-accordion\n data-variant=\"lounge\"\n *ngIf=\"classes | searchClassWithUsers : searchTerm : selectedLevels as filteredClasses\"\n >\n <mat-expansion-panel hideToggle *ngFor=\"let classDto of filteredClasses; trackBy: classTrackBy\">\n <mat-expansion-panel-header *ngIf=\"classDto.users.length > 0\">\n <mat-panel-title>\n <lru-checkbox\n [checked]=\"classDto.class.selected\"\n [semiChecked]=\"isClassSemiSelected(classDto)\"\n [size]=\"12\"\n variant=\"lounge\"\n (changed)=\"onClickClass(classDto.class.id, $event)\"\n >\n {{ classDto.class.name }}\n </lru-checkbox>\n <lru-icon [icon]=\"{ path: 'felib-chevron-down', size: 16 }\" class=\"expansion-panel-arrow\"></lru-icon>\n </mat-panel-title>\n </mat-expansion-panel-header>\n\n <ul>\n <li *ngFor=\"let user of classDto.users\">\n <lru-checkbox\n [checked]=\"user.selected\"\n [size]=\"12\"\n variant=\"lounge\"\n (changed)=\"onClickUser(classDto.class.id, user.id, $event)\"\n >{{ user.name }}</lru-checkbox\n >\n </li>\n </ul>\n </mat-expansion-panel>\n <div class=\"no-items\">Intet fundet ud fra de valgte kriterier</div>\n </mat-accordion>\n</div>\n\n<ng-template #classesLoading>\n <lru-loading-animation *ngIf=\"loadingService.loading$(sharedLoadingKeys.dlpClasses) | async\"></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.dlpClasses) | async as error\">{{ error }}</p>\n</ng-template>\n<ng-template #levelsLoading>\n <lru-loading-animation *ngIf=\"loadingService.loading$(sharedLoadingKeys.fullLevel) | async\"></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.fullLevel) | async as error\">{{ error }}</p>\n</ng-template>\n","<div class=\"buttons\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'icon-button'\" *ngIf=\"backFunc\" (click)=\"onClickBack()\">\n <lru-icon [icon]=\"{ path: 'felib-chevron-down', size: 16, rotate: 90 }\"></lru-icon>\n </lru-button>\n <lru-button class=\"close\" [variant]=\"'lounge'\" [theme]=\"'icon-button'\" *ngIf=\"closeFunc\" (click)=\"onClickClose()\">\n <lru-icon [icon]=\"{ path: 'felib-x-mark', size: 12 }\"></lru-icon>\n </lru-button>\n</div>\n<div class=\"headlines\">\n <h1 *ngIf=\"header\">{{ header }}</h1>\n <p *ngIf=\"subHeader\">{{ subHeader }}</p>\n</div>\n","<div class=\"main\">\n <lru-team-picker></lru-team-picker>\n</div>\n<div class=\"footer\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickSave()\">\n <ng-container\n *ngIf=\"(loadingService.loading$(sharedLoadingKeys.teamSaveStudentsToTeam) | async) === false; else loading\"\n >Gem ({{ (loungeService.selectedUsersList$ | async)?.length }} valgte)</ng-container\n >\n </lru-button>\n</div>\n<lru-team-header\n [closeFunc]=\"onClickClose()\"\n [header]=\"'Rediger elever'\"\n [subHeader]=\"'Tilføj og fjern elever fra holdet'\"\n></lru-team-header>\n\n<ng-template #loading\n ><lru-loading-animation [variant]=\"loadingAnimationVariants.BUTTON\"></lru-loading-animation\n></ng-template>\n","<div>\n <h2>Holdnavn</h2>\n <div [formGroup]=\"form\" class=\"form-control\">\n <input formControlName=\"title\" type=\"text\" placeholder=\"Holdnavn\" />\n <div *ngIf=\"title && title.invalid && title.errors && (title.dirty || title.touched)\" class=\"error\">\n <ng-container *ngIf=\"title.errors.required\"><span>Holdnavn</span> er påkrævet.</ng-container>\n <ng-container *ngIf=\"title.errors.minlength\"\n ><span>Holdnavn</span> skal mindst være 2 karakterer lang.</ng-container\n >\n <ng-container *ngIf=\"title.errors.maxlength\"\n ><span>Holdnavn</span> kan maksimalt være 25 karakterer lang.</ng-container\n >\n </div>\n </div>\n</div>\n<div>\n <h2>Klassetrin</h2>\n <ng-container *ngIf=\"(loungeService.fullLevel$ | async)?.levels as levels\">\n <lru-dropdown [variant]=\"'lounge'\" [sameWidth]=\"true\" [spacingFromWindow]=\"10\" #dropdownLevel>\n <ng-container button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\">\n <span>{{ this.selectedLevel?.text ? this.selectedLevel?.text : 'Vælg klassetrin' }}</span>\n <lru-icon [icon]=\"{ path: 'felib-chevron-down', size: 24 }\" class=\"arrow\"></lru-icon>\n </lru-button>\n </ng-container>\n <ng-container>\n <ul>\n <li *ngFor=\"let item of levels\">\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"onClickLevel(item); dropdownLevel.onCloseClick()\"\n [class.active]=\"item.id === selectedLevel?.id\"\n >\n <span>{{ item.mediumForm }}</span>\n </lru-button>\n </li>\n </ul>\n </ng-container>\n </lru-dropdown>\n <div\n *ngIf=\"level && level.invalid && level.errors && (level.dirty || level.touched) && level.errors.required\"\n class=\"error\"\n >\n <span>Klassetrin</span> er påkrævet.\n </div>\n </ng-container>\n</div>\n","<form [formGroup]=\"form\" *ngIf=\"loungeService.teamEdit$ | async as teamEdit\">\n <div class=\"main\">\n <lru-team-details-form [form]=\"form\"></lru-team-details-form>\n </div>\n <div class=\"footer\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\" [hollow]=\"true\" (click)=\"onClickClose()()\">Annuller</lru-button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickSave(teamEdit.id)\"\n ><ng-container\n *ngIf=\"(loadingService.loading$(sharedLoadingKeys.saveDetailsToTeam) | async) === false; else loading\"\n >Gem</ng-container\n ></lru-button\n >\n </div>\n <lru-team-header\n [closeFunc]=\"onClickClose()\"\n [header]=\"'Rediger ' + teamEdit.title\"\n [subHeader]=\"'Skriv navn og trin'\"\n ></lru-team-header>\n</form>\n\n<ng-template #loading>\n <lru-loading-animation\n [variant]=\"loadingAnimationVariants.BUTTON\"\n *ngIf=\"loadingService.loading$(sharedLoadingKeys.saveDetailsToTeam) | async\"\n ></lru-loading-animation>\n</ng-template>\n","<ng-container *ngIf=\"loungeService.dlpTeachersListWithoutCurrentUser$ | async as teachers; else loading\"\n ><div class=\"search\">\n <input type=\"text\" placeholder=\"Søg i lærere\" [(ngModel)]=\"searchTerm\" />\n <lru-icon [icon]=\"{ path: 'felib-search', size: 14 }\"></lru-icon>\n </div>\n\n <div class=\"classes\">\n <mat-accordion data-variant=\"lounge\" *ngIf=\"teachers.length > 0; else noTeachers\">\n <mat-expansion-panel\n hideToggle\n *ngFor=\"let teacher of teachers | searchUserPermissionWithSelectedList : searchTerm; trackBy: teacherTrackBy\"\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <lru-checkbox\n [checked]=\"teacher.user.selected\"\n [size]=\"12\"\n variant=\"lounge\"\n (changed)=\"onClickTeacher(teacher.user.id, $event)\"\n >{{ teacher.user.name }}</lru-checkbox\n >\n </mat-panel-title>\n </mat-expansion-panel-header>\n </mat-expansion-panel>\n </mat-accordion>\n </div>\n</ng-container>\n<ng-template #loading>\n <lru-loading-animation\n *ngIf=\"loadingService.loading$(sharedLoadingKeys.teachersWithoutCurrentUser) | async\"\n ></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.teachersWithoutCurrentUser) | async as error\">{{ error }}</p>\n</ng-template>\n\n<ng-template #noTeachers>\n <p>Kunne ikke finde nogle lærere</p>\n</ng-template>\n","<div class=\"main\">\n <lru-team-picker-teacher></lru-team-picker-teacher>\n</div>\n<div class=\"footer\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickSave()\">\n <ng-container\n *ngIf=\"(loadingService.loading$(sharedLoadingKeys.teamSaveTeachersToTeam) | async) === false; else loading\"\n >Gem ({{ (loungeService.selectedTeachersList$ | async)?.length }} valgte)</ng-container\n >\n </lru-button>\n</div>\n<lru-team-header\n *ngIf=\"teamEdit\"\n [closeFunc]=\"onClickClose()\"\n [header]=\"'Del ' + teamEdit.title + ' med lærere'\"\n [subHeader]=\"'Tilføj og fjern lærere fra holdet'\"\n>\n</lru-team-header>\n\n<ng-template #loading>\n <lru-loading-animation\n [variant]=\"loadingAnimationVariants.BUTTON\"\n *ngIf=\"loadingService.loading$(sharedLoadingKeys.teamSaveTeachersToTeam) | async\"\n ></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.teamSaveTeachersToTeam) | async as error\">{{ error }}</p>\n</ng-template>\n","<lru-dropdown\n [variant]=\"'lounge'\"\n [sameWidth]=\"false\"\n [spacingFromWindow]=\"10\"\n [spacingFromButton]=\"10\"\n horizontalDirection=\"left\"\n [maxWidth]=\"300\"\n #editDropdown\n>\n <ng-container button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\">\n <span>Rediger</span>\n </lru-button>\n </ng-container>\n <ng-container>\n <div class=\"team-edit-menu\">\n <div class=\"team-edit-menu__section\">\n <label class=\"team-edit-menu__section__header\">ELEVER</label>\n <ul class=\"team-edit-menu__section__content\">\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"loungeService.teamEditAssignStudents(); editDropdown.onCloseClick()\"\n >\n <span>Tilføj/fjern elever</span>\n <lru-icon [icon]=\"{ path: 'felib-add-students', size: 16 }\"></lru-icon>\n </lru-button>\n </li>\n </ul>\n </div>\n <div class=\"team-edit-menu__section\">\n <label class=\"team-edit-menu__section__header\">LÆRER</label>\n <ul class=\"team-edit-menu__section__content\">\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"\n loungeService.teamEditAssignTeachers(sharedLoadingKeys.teachersWithoutCurrentUser);\n editDropdown.onCloseClick()\n \"\n >\n <span>{{ team.teachers.length === 1 ? 'Del med lærere' : 'Rediger lærerdeling' }}</span>\n <lru-icon [icon]=\"{ path: 'felib-share-with-teacher', size: 16 }\"></lru-icon>\n </lru-button>\n </li>\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"loungeService.teamRemoveTeacherSelfModal(); editDropdown.onCloseClick()\"\n >\n <span>Fjern dig som lærer</span>\n <lru-icon [icon]=\"{ path: 'felib-remove-myself-as-teacher', size: 16 }\"></lru-icon>\n </lru-button>\n </li>\n </ul>\n </div>\n <div class=\"team-edit-menu__section\">\n <div class=\"team-edit-menu__section__header\">HOLD</div>\n <ul class=\"team-edit-menu__section__content\">\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"loungeService.teamEditDetailsModal(); editDropdown.onCloseClick()\"\n >\n <span>Ret holdnavn og klassetrin</span>\n <lru-icon [icon]=\"{ path: 'felib-edit', size: 16 }\"></lru-icon>\n </lru-button>\n </li>\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n (click)=\"loungeService.teamDeleteModal(); editDropdown.onCloseClick()\"\n >\n <span>Slet hold</span>\n <lru-icon [icon]=\"{ path: 'felib-trash', size: 16 }\"></lru-icon>\n </lru-button>\n </li>\n </ul>\n </div>\n </div>\n </ng-container>\n <lru-modal\n [isVisible]=\"loungeModalService.modalActive || false\"\n (isVisibleChange)=\"onModalVisibilityChange($event)\"\n [variant]=\"'lounge'\"\n [height]=\"(loungeModalService.modalHeight$ | async) ?? undefined\"\n >\n <lru-team-edit-assign-students *ngIf=\"(loungeModalService.page$ | async) === pageEnum.studentPicker\">\n </lru-team-edit-assign-students>\n <lru-team-edit-assign-teachers\n *ngIf=\"(loungeModalService.page$ | async) === pageEnum.shareWithTeachers\"\n [teamEdit]=\"team\"\n >\n </lru-team-edit-assign-teachers>\n <lru-team-edit-delete *ngIf=\"(loungeModalService.page$ | async) === pageEnum.deleteTeam\" [teamEdit]=\"team\">\n </lru-team-edit-delete>\n <lru-team-edit-details *ngIf=\"(loungeModalService.page$ | async) === pageEnum.detailsInput\"></lru-team-edit-details>\n <lru-team-edit-remove-teacher-self\n *ngIf=\"(loungeModalService.page$ | async) === pageEnum.removeTeacherSelf\"\n [teamEdit]=\"team\"\n >\n </lru-team-edit-remove-teacher-self>\n </lru-modal>\n</lru-dropdown>\n","<ng-container *ngIf=\"loungeService.teamEdit$ | async as team; else loading\">\n <div class=\"header\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'icon-button'\" (click)=\"loungeService.teamEditCancel()\">\n <lru-icon [icon]=\"{ path: 'felib-chevron-down', size: 16, rotate: 90 }\"></lru-icon>\n </lru-button>\n <h1>{{ team.title }}</h1>\n <lru-team-edit-dropdown [team]=\"team\"></lru-team-edit-dropdown>\n </div>\n <div class=\"content\">\n <div class=\"main\">\n <lru-box [theme]=\"'primary-student'\" [hollow]=\"true\">\n <h1 header>{{ team.studentCount }} elever</h1>\n <ul content>\n <ng-container *ngIf=\"loadingService.loaded$(sharedLoadingKeys.teamStudents) | async; else studentsLoading\"\n ><ng-container *ngIf=\"team.students.length > 0; else noStudents\"\n ><li *ngFor=\"let student of team.students\">\n {{ student.firstName }} {{ student.lastName }}\n </li></ng-container\n ></ng-container\n >\n </ul>\n </lru-box>\n </div>\n <div class=\"aside\">\n <lru-box [theme]=\"'primary-student'\" [hollow]=\"true\">\n <h1 header>Delt med:</h1>\n <ul content>\n <li *ngFor=\"let teacher of team.teachers\">{{ teacher.user.firstName }} {{ teacher.user.lastName }}</li>\n </ul>\n </lru-box>\n </div>\n </div>\n</ng-container>\n\n<ng-template #loading>\n <lru-loading-animation *ngIf=\"loadingService.loading$(sharedLoadingKeys.editTeam) | async\"></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.editTeam) | async as error\">{{ error }}</p>\n</ng-template>\n\n<ng-template #studentsLoading>\n <lru-loading-animation\n *ngIf=\"loadingService.loading$(sharedLoadingKeys.teamStudents) | async\"\n ></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.teamStudents) | async as error\">{{ error }}</p>\n</ng-template>\n\n<ng-template #noStudents>\n <p>Ingen elever tildelt holdet</p>\n</ng-template>\n","<div class=\"content\">\n <label class=\"students-count\">{{ model.studentCount }} elever</label>\n <h2 class=\"title\">{{ model.title }}</h2>\n <div class=\"hr\"></div>\n <label class=\"shared-with-title\">Delt med:</label>\n <ul>\n <li *ngFor=\"let teachers of model.teachers\">{{ teachers.user.firstName }} {{ teachers.user.lastName }}</li>\n </ul>\n</div>\n<div class=\"buttons\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickEdit(model)\">Rediger</lru-button>\n</div>\n","<form [formGroup]=\"form\">\n <div class=\"main\">\n <lru-team-picker *ngIf=\"(loungeModalService.page$ | async) === pageEnum.studentPicker\"></lru-team-picker>\n <lru-team-details-form\n *ngIf=\"(loungeModalService.page$ | async) === pageEnum.detailsInput\"\n [form]=\"form\"\n ></lru-team-details-form>\n </div>\n <div class=\"footer\">\n <lru-button\n *ngIf=\"(loungeModalService.page$ | async) === pageEnum.studentPicker\"\n [variant]=\"'lounge'\"\n [theme]=\"'primary-teacher'\"\n [disabled]=\"(loungeService.selectedUsersList$ | async)?.length === 0\"\n (click)=\"goToDetailsPage()\"\n >\n Næste ({{ (loungeService.selectedUsersList$ | async)?.length }} valgte)\n </lru-button>\n <ng-container *ngIf=\"(loungeModalService.page$ | async) === pageEnum.detailsInput\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\" (click)=\"onClickCancel()\" [hollow]=\"true\">Annuller</lru-button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickSubmit()\"\n ><ng-container *ngIf=\"(loadingService.loading$(sharedLoadingKeys.createTeam) | async) === false; else loading\"\n >Opret nyt hold</ng-container\n >\n </lru-button>\n </ng-container>\n </div>\n <lru-team-header\n [closeFunc]=\"onClickClose()\"\n [backFunc]=\"(loungeModalService.page$ | async) === pageEnum.detailsInput ? onClickBack() : undefined\"\n [header]=\"'Opret nyt hold'\"\n [subHeader]=\"\n (loungeModalService.page$ | async) === pageEnum.studentPicker\n ? 'Vælg klasser og elever fra skolens UNI-login data her'\n : 'Vælg navn og klassetrin på dit nye hold'\n \"\n ></lru-team-header>\n</form>\n\n<ng-template #loading\n ><lru-loading-animation [variant]=\"loadingAnimationVariants.BUTTON\"></lru-loading-animation\n></ng-template>\n","<h1>Dine hold</h1>\n<div class=\"hr\"></div>\n<div class=\"buttons\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" [hollow]=\"true\" (click)=\"onClickCreateTeam()\"\n >Opret hold</lru-button\n >\n</div>\n<lru-modal\n [isVisible]=\"loungeModalService.modalActive || false\"\n (isVisibleChange)=\"onModalVisibilityChange($event)\"\n [variant]=\"'lounge'\"\n [height]=\"(loungeModalService.modalHeight$ | async) ?? undefined\"\n>\n <lru-team-creation></lru-team-creation>\n</lru-modal>\n<div class=\"sort\">\n <lru-dropdown\n [variant]=\"'lounge'\"\n [sameWidth]=\"false\"\n [spacingFromWindow]=\"10\"\n [spacingFromButton]=\"10\"\n horizontalDirection=\"left\"\n #sort\n >\n <ng-container button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\">\n <span>Sorter</span>\n <lru-icon [icon]=\"{ path: 'felib-sort', size: 12 }\"></lru-icon>\n </lru-button>\n </ng-container>\n <ng-container>\n <ul class=\"sort-content\">\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n [class.active]=\"(sortMode$ | async) === sortModeEnum.alphabetically\"\n (click)=\"onClickSort(sortModeEnum.alphabetically); sort.onCloseClick()\"\n >\n <span>Alfabetisk</span>\n <lru-icon\n *ngIf=\"(sortMode$ | async) === sortModeEnum.alphabetically\"\n [icon]=\"{ path: 'felib-check', size: 12 }\"\n ></lru-icon>\n </lru-button>\n </li>\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n [class.active]=\"(sortMode$ | async) === sortModeEnum.creationDate\"\n (click)=\"onClickSort(sortModeEnum.creationDate); sort.onCloseClick()\"\n >\n <span>Nyeste først</span>\n <lru-icon\n *ngIf=\"(sortMode$ | async) === sortModeEnum.creationDate\"\n [icon]=\"{ path: 'felib-check', size: 12 }\"\n ></lru-icon>\n </lru-button>\n </li>\n <li>\n <lru-button\n [variant]=\"'lounge'\"\n [theme]=\"'white'\"\n [class.active]=\"(sortMode$ | async) === sortModeEnum.updatedDate\"\n (click)=\"onClickSort(sortModeEnum.updatedDate); sort.onCloseClick()\"\n >\n <span>Senest ændret</span>\n <lru-icon\n *ngIf=\"(sortMode$ | async) === sortModeEnum.updatedDate\"\n [icon]=\"{ path: 'felib-check', size: 12 }\"\n ></lru-icon>\n </lru-button>\n </li>\n </ul>\n </ng-container>\n </lru-dropdown>\n</div>\n<ng-container *ngIf=\"(loadingService.loading$(sharedLoadingKeys.teams) | async) === false; else loading\">\n <ng-container *ngIf=\"teams$ | async as teams; else loading\">\n <div class=\"teams\" *ngIf=\"teams.length > 0\">\n <lru-team-box *ngFor=\"let item of teams\" [model]=\"item\"></lru-team-box>\n </div>\n <p *ngIf=\"teams.length === 0\">Du har ikke oprettet nogen hold.</p>\n </ng-container>\n</ng-container>\n\n<ng-template #loading>\n <lru-loading-animation *ngIf=\"loadingService.loading$(sharedLoadingKeys.teams) | async\"></lru-loading-animation>\n <p *ngIf=\"loadingService.error$(sharedLoadingKeys.teams) | async as error\">{{ error }}</p>\n</ng-template>\n","<lru-icon *ngIf=\"message.icon\" [icon]=\"message.icon\"></lru-icon>\n<label class=\"toast-message-message\">{{ message.message }}</label>\n<lru-button\n class=\"close\"\n [variant]=\"'lounge'\"\n [theme]=\"'icon-button'\"\n *ngIf=\"message.canDismiss\"\n (click)=\"onDismissClick()\"\n>\n <lru-icon [icon]=\"{ path: 'felib-x-mark', size: 12 }\"></lru-icon>\n</lru-button>\n","<ng-container *ngIf=\"{ messages: messages$ | async, zIndex: zIndex$ | async } as sub\">\n <ul\n class=\"toast-message-list\"\n [@animateInOut]=\"sub.messages?.length ?? 0\"\n [attr.data-horizontal-position]=\"appliedHorizontalPosition\"\n [attr.data-vertical-position]=\"appliedVerticalPosition\"\n [style.gap]=\"appliedSpacingBetweenToasts\"\n [style.padding]=\"appliedSpacingFromWindow\"\n [attr.data-variant]=\"appliedVariant\"\n [style.zIndex]=\"sub.zIndex\"\n >\n <li\n *ngFor=\"let message of sub.messages\"\n class=\"toast-message-list-item\"\n (mouseenter)=\"onMouseenter($event)\"\n (mouseleave)=\"onMouseleave()\"\n >\n <lru-toast-message [message]=\"message\"></lru-toast-message>\n </li>\n </ul>\n</ng-container>\n","/** Enum used for defining the variant of the loading animation */\nexport enum LoadingAnimationVariant {\n BLOCK = 'block',\n INLINE = 'inline',\n OVERLAY = 'overlay',\n BUTTON = 'button',\n}\n","import { Component, HostBinding, Input } from '@angular/core';\nimport { LoadingAnimationVariant } from '../enum/loading-animation-variant.enum';\n\n/**\n * Component to display loading indicator\n */\n@Component({\n selector: 'lru-loading-animation',\n templateUrl: './loading-animation.component.html',\n styleUrls: ['./loading-animation.component.scss'],\n})\nexport class LoadingAnimationComponent {\n /** Set how big the line in the loading indicator should be */\n @Input() strokeWidth: number;\n\n /** Set specific loading variant */\n @Input() variant: LoadingAnimationVariant;\n\n /** Set the varient as class on the component */\n @HostBinding('class') get className(): string {\n return `loading-animation loading-animation-${this.variant}`;\n }\n\n /** Change size of loading indicator\n * @input 1 === 1.25rem */\n @HostBinding('style.--size') @Input() size: number | undefined;\n\n /** @ignore */\n constructor() {\n this.variant = LoadingAnimationVariant.BLOCK;\n this.strokeWidth = 10;\n }\n\n /** Ensure the loading indicator stays within the svg no matter the size of strokeWidth */\n get radius(): number {\n return 50 - this.strokeWidth / 2;\n }\n\n /** Used to remove part of the circle that is the loading indicator */\n get circleCutout(): number {\n return (2 * this.radius * Math.PI) / 3;\n }\n}\n","<svg class=\"loading-animation-svg\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\">\n <circle\n cx=\"50\"\n cy=\"50\"\n fill=\"none\"\n [attr.r]=\"radius\"\n stroke=\"currentColor\"\n [attr.stroke-dasharray]=\"circleCutout + ' ' + circleCutout * 2\"\n stroke-linecap=\"round\"\n [attr.stroke-width]=\"strokeWidth\"\n />\n</svg>\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { LoadingAnimationComponent } from './components/loading-animation.component';\n\n@NgModule({\n declarations: [LoadingAnimationComponent],\n imports: [CommonModule],\n exports: [LoadingAnimationComponent],\n})\nexport class LoadingAnimationModule {}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\n\nexport type theme = 'primary-student' | 'primary-teacher' | 'white' | 'icon-button' | undefined;\ntype size = 'small' | 'medium' | 'large';\ntype type = 'button' | 'reset' | 'submit';\n\n/** Component that should be used for all types of buttons */\n@Component({\n selector: 'lru-button',\n templateUrl: './button.component.html',\n styleUrls: ['./button.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ButtonComponent {\n /** What kind of button is it? */\n @Input() theme: theme = undefined;\n\n /** Makes it possible to make custom styling */\n @Input() variant?: string;\n\n /** Button size */\n @Input() size: size = 'medium';\n\n /** Extra classes to be added to the button */\n @Input() classes?: string;\n\n /** Should the button be disabled? */\n @Input() disabled: boolean = false;\n\n /** Is it hollow variant of the button? (color is on border instead of background) */\n @Input() hollow: boolean = false;\n\n /** Button type */\n @Input() type: type = 'button';\n\n /** The padding to be used around the button */\n @Input() padding?: number;\n\n /** Converts {@link padding} from a number to a string with 'px' after the number. */\n get paddingPX(): string | undefined {\n return this.padding ? `${this.padding}px` : undefined;\n }\n}\n","<button\n [attr.data-variant]=\"variant\"\n [attr.data-theme]=\"theme\"\n [attr.data-size]=\"size\"\n [attr.data-hollow]=\"hollow\"\n [class]=\"classes\"\n [disabled]=\"disabled\"\n [attr.type]=\"type\"\n [style.padding]=\"paddingPX\"\n>\n <ng-content></ng-content>\n</button>\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { ButtonComponent } from './button.component';\n\n@NgModule({\n declarations: [ButtonComponent],\n imports: [CommonModule],\n exports: [ButtonComponent],\n})\nexport class ButtonModule {}\n","import { ILoungeConfig, IReplaceSvg } from './lounge-config.interface';\n\n/** Config for supplying configuration for the Lounge module */\nexport class LoungeConfig implements ILoungeConfig {\n /** Used for defining which SVG icons to replace.\n * @see {@link IReplaceSvg} */\n replaceSvgs: IReplaceSvg[] = [];\n}\n","import { Component, HostBinding, Input, Optional } from '@angular/core';\nimport { LoungeConfig } from '../lounge/lounge-config';\nimport { IReplaceSvg } from '../lounge/lounge-config.interface';\nimport { IIcon } from './icon.interface';\nimport { iconRotate } from './types/icon-rotate';\nimport { iconSize } from './types/icon-size';\n\n/** Component that can be used to inject svg icons.\n * \"baseUrl\" in icon.module.ts defines where it looks for SVG */\n@Component({\n selector: 'lru-icon[icon]',\n templateUrl: './icon.component.html',\n styleUrls: ['./icon.component.scss'],\n})\nexport class IconComponent {\n /** instance of icon */\n @Input() icon!: IIcon;\n\n /** Property to store which SVGs to replace */\n private replaceSvgs: IReplaceSvg[];\n\n /** Handles loading Dependency Injected config and if no config is supplied use the default config */\n constructor(@Optional() loungeConfig: LoungeConfig) {\n const defaultConfig = new LoungeConfig();\n\n this.replaceSvgs = loungeConfig?.replaceSvgs || defaultConfig.replaceSvgs;\n }\n\n /** Get path for svg.\n * If path is in list of of replaceSvgs then the path will be replaced with the new path specified in replaceSvgs item. */\n get iconPath(): string | undefined {\n return this.replaceSvgs.find((x: IReplaceSvg) => x.old === this.icon.path)?.new || this.icon.path;\n }\n\n /** Get color of icon. Defaults to 'currentColor' if no color is specified. */\n @HostBinding('style.color')\n get styleColor(): string {\n return this.icon.colors?.color || 'currentColor';\n }\n\n /** Set css variable for foreground color if specified */\n @HostBinding('style.--svg-foreground')\n get styleColorForeground(): string | undefined {\n return this.icon.colors?.foreground;\n }\n\n /** Set css variable for background color if specified */\n @HostBinding('style.--svg-background')\n get styleColorBackground(): string | undefined {\n return this.icon.colors?.background;\n }\n\n /** Get size of icon in pixel. Default to 16px if no size is specified. */\n @HostBinding('attr.data-size')\n get dataSize(): iconSize {\n return this.icon.size ? this.icon.size : 16;\n }\n\n /** Get rotation information for icon. Default to 0deg if no rotation is specified. */\n @HostBinding('attr.data-rotate')\n get dataRotate(): iconRotate {\n return this.icon.rotate ? this.icon.rotate : 0;\n }\n}\n","<i inlineSVG=\"{{ iconPath }}.svg\"></i>\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { iconSize } from '../icon/types/icon-size';\n\n/** Component that should be used for all types of checkboxes. */\n@Component({\n selector: 'lru-checkbox[checked]',\n templateUrl: './checkbox.component.html',\n styleUrls: ['./checkbox.component.scss'],\n})\nexport class CheckboxComponent {\n /** Should the checkbox be checked to begin with? */\n @Input() checked!: boolean;\n\n /** This is for checkbox parent of child list of checkboxes where not all children are checked.\n * It will add a line in the checkbox instead of checkmark icon. */\n @Input() semiChecked?: boolean;\n\n /** Size of icon within the checkbox */\n @Input() size: iconSize = 16;\n\n /** makes it possible to make custom styling */\n @Input() variant?: string;\n\n /** Emits checked changes so the place that contains the checkbox can run custom logic when it happens */\n @Output() changed = new EventEmitter<boolean>();\n\n /** When chexkbox is clicked */\n onChange(value: boolean): void {\n this.changed.emit(value);\n }\n\n /** When enter is pressed it should cound as click on the checkbox */\n onEnterKeydown(): void {\n this.onChange(!this.checked);\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\nimport { NgModule } from '@angular/core';\nimport { InlineSVGModule } from 'ng-inline-svg-2';\nimport { IconComponent } from './icon.component';\n\n@NgModule({\n declarations: [IconComponent],\n imports: [CommonModule, InlineSVGModule.forRoot({ baseUrl: '/assets/svg/' }), HttpClientModule],\n exports: [IconComponent],\n})\nexport class IconModule {}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { IconModule } from '../icon/icon.module';\nimport { CheckboxComponent } from './checkbox.component';\n\n@NgModule({\n declarations: [CheckboxComponent],\n imports: [CommonModule, IconModule, FormsModule],\n exports: [CheckboxComponent],\n})\nexport class CheckboxModule {}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { fromEvent, merge, share } from 'rxjs';\n\n/** Service for adding functionality to mouse and keyboard events */\n@Injectable({\n providedIn: 'root',\n})\nexport class MouseKeyboardService implements OnDestroy {\n /** DOM element currently having .js-focus class */\n private focus?: HTMLElement;\n /** DOM element currently hacing .js-hover class */\n private hover?: HTMLElement;\n\n /** Observable that outputs all key up events */\n keyUp$ = fromEvent<KeyboardEvent>(document, 'keyup').pipe(share());\n\n /** Private subscription for adding the FELIB functionality even if {@link keyUp$} is not subscribed to in dependent projects */\n private keyUpSubscription = this.keyUp$.subscribe((event) => {\n if (event.key === 'Tab') {\n let target = event.target as HTMLElement;\n\n this.removeHover();\n this.addFocus(target);\n }\n });\n\n /** Observable that outputs all key down events */\n keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown').pipe(share());\n\n /** Private subscription for adding the FELIB functionality even if {@link keyDown$} is not subscribed to in dependent projects */\n private keyDownSubscription = this.keyDown$.subscribe();\n\n /** Used by {@link clickOrTouch$} to make it easy to listen for touch and click events */\n private touchStart = fromEvent<TouchEvent>(document, 'touchstart');\n\n /** Used by {@link clickOrTouch$} to make it easy to listen for touch and click events */\n private click = fromEvent<MouseEvent>(document, 'click');\n\n /** Observable that outputs all click or touchStart events */\n clickOrTouch$ = merge(this.touchStart, this.click).pipe(share());\n\n /** Private subscription for adding the FELIB functionality even if {@link clickOrTouch$} is not subscribed to in dependent projects */\n private clickOrTouchSubscription = this.clickOrTouch$.subscribe((event) => {\n this.removeFocus();\n this.removeHover();\n });\n\n /** Angular OnDestroy lifecycle to unsubscribe from subscriptions */\n ngOnDestroy(): void {\n this.clickOrTouchSubscription?.unsubscribe();\n this.keyDownSubscription?.unsubscribe();\n this.keyUpSubscription?.unsubscribe();\n }\n\n /**\n * Give DOM element .js-focus class\n * @param target DOM element\n */\n public addFocus(target: HTMLElement): void {\n this.removeFocus();\n this.focus = target;\n this.focus.classList.add('js-focus');\n }\n\n /**\n * Remove .js-focus class from focus element, if there is a focus element\n */\n public removeFocus(): void {\n this.focus?.classList.remove('js-focus');\n }\n\n /**\n * Add .js-hover class to DOM element and set it as {@link hover} element\n * @param element Element to give .js-hover and set as {@link hover} element\n * @param scrollIntoView should the browser scroll so the hover element is within viewport\n */\n public addHover(element: HTMLElement, scrollIntoView?: boolean): void {\n this.removeHover();\n if (scrollIntoView) {\n element.scrollIntoView(false);\n }\n\n element.classList.add('js-hover');\n this.hover = element;\n }\n\n /** remove .js-hover class from {@link hover} and set object to undefined */\n public removeHover(): void {\n if (this.hover) {\n this.hover.classList.remove('js-hover');\n this.hover = undefined;\n }\n }\n\n /**\n * Get next or first item in array of items\n * @param items DOM elements\n * @param wrapAround Should it wrap aroound when at the last item?\n * @returns DOM element or undefined\n */\n selectNext(items: HTMLElement[], wrapAround: boolean): HTMLElement | undefined {\n let element: HTMLElement | undefined = undefined;\n\n if (items?.length) {\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n\n if (item.classList.contains('js-hover') && i < items.length) {\n element = items[i + 1];\n }\n }\n\n if (!element) {\n if (wrapAround) {\n element = items[0];\n } else {\n element = items[items.length - 1];\n }\n }\n }\n\n return element;\n }\n\n /**\n * Get previous or last item in array of items\n * @param items DOM elements\n * @param wrapAround Should it wrap aroound when at the first item?\n * @returns DOM element or undefined\n */\n selectPrev(items: HTMLElement[], wrapAround: boolean): HTMLElement | undefined {\n let element: HTMLElement | undefined = undefined;\n\n if (items?.length) {\n for (let i = items.length - 1; i >= 0; i--) {\n const item = items[i];\n\n if (item.classList.contains('js-hover') && i > 0) {\n element = items[i - 1];\n }\n }\n\n if (!element) {\n if (wrapAround) {\n element = items[items.length - 1];\n } else {\n element = items[0];\n }\n }\n }\n\n return element;\n }\n}\n","import { DomPortalOutlet } from '@angular/cdk/portal';\nimport { Injectable, OnDestroy } from '@angular/core';\nimport { BehaviorSubject, firstValueFrom } from 'rxjs';\nimport { distinctUntilChanged, filter, withLatestFrom } from 'rxjs/operators';\nimport { MouseKeyboardService } from '../../services/mouse-keyboard/mouse-keyboard.service';\nimport { DropdownComponent } from './components/dropdown/dropdown.component';\n\n/** Handles all dropdowns and makes sure we're only displaying a single dropdown at a time.\n * Dropdowns are created using the <app-dropdown> component in any template and displayed using the <app--dropdown-output> component in the app component. */\n@Injectable({\n providedIn: 'root',\n})\nexport class DropdownService implements OnDestroy {\n /** Portal outlet used by the dropdowns */\n private outlet?: DomPortalOutlet;\n\n /** @see BehaviorSubject for {@link open$} */\n private open = new BehaviorSubject<DropdownComponent | undefined>(undefined);\n\n /** Observable that returns a {@link DropdownComponent} if dropdown is open and undefined if not */\n open$ = this.open.asObservable();\n\n /** @see BehaviorSubject for {@link zIndex$} */\n private zIndex = new BehaviorSubject(0);\n\n /** Observable that returns the zIndex for the dropdown */\n zIndex$ = this.zIndex.pipe(distinctUntilChanged());\n\n /** Selector for elements that can be selected with arrow keys */\n validElements = '[tabindex=\"0\"], a:not([tabindex=\"-1\"]), button:not([tabindex=\"-1\"])';\n\n /** listen for keyDown event */\n private keyDownSubscription = this.mouseKeyboardService.keyDown$\n .pipe(\n withLatestFrom(this.open$),\n filter(([_, open]) => open !== undefined),\n distinctUntilChanged(([prevEvent, _], [event, _2]) => prevEvent === event)\n )\n .subscribe(([event, _]) => {\n if (event.key === 'Escape') {\n this.closeDropdown();\n } else if (\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp' ||\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight'\n ) {\n event.preventDefault(); // needed so the browser window doesnt scroll\n const targetItems = this.outlet?.outletElement\n .querySelector('.dropdown-content')\n ?.querySelectorAll<HTMLElement>(this.validElements);\n\n if (targetItems) {\n let elementToSetFocusTo: HTMLElement | undefined = undefined;\n\n let next = event.key === 'ArrowDown' || event.key === 'ArrowRight';\n\n if (next) {\n elementToSetFocusTo = this.mouseKeyboardService.selectNext(Array.from(targetItems), true);\n } else {\n elementToSetFocusTo = this.mouseKeyboardService.selectPrev(Array.from(targetItems), true);\n }\n\n if (elementToSetFocusTo) {\n this.mouseKeyboardService.removeFocus();\n this.mouseKeyboardService.addHover(elementToSetFocusTo);\n }\n }\n }\n });\n\n /** listen for click/touch event */\n private clickOrTouchSubscription = this.mouseKeyboardService.clickOrTouch$\n .pipe(\n withLatestFrom(this.open$),\n filter(([_, open]) => open !== undefined),\n distinctUntilChanged(([prevEvent, _], [event, _2]) => prevEvent === event)\n )\n .subscribe(([event, _]) => {\n let target = event.target as HTMLElement;\n\n if (target === this.outlet?.outletElement) {\n this.closeDropdown();\n }\n });\n\n /** @ignore */\n constructor(private mouseKeyboardService: MouseKeyboardService) {}\n\n /** Setter for {@link zIndex$} */\n setZIndex(zindex: number): void {\n this.zIndex.next(zindex);\n }\n\n /** Sets the portal outlet which should be used by the dropdowns.\n * Should only be called from the <app-dropdown-outlet> component. */\n setPortalOutlet(outlet: DomPortalOutlet): void {\n this.outlet = outlet;\n }\n\n /** Hides the current dropdown if a dropdown is open. */\n async closeDropdown(): Promise<void> {\n const current = await firstValueFrom(this.open);\n\n if (current) {\n current.closeDropdown();\n this.open.next(undefined);\n this.detachCurrentDropdown();\n }\n }\n\n /** Stores the visibility of a dropdown in the service and reacts to it.\n * Should only be called from the <app-dropdown> component.\n *\n * If a dropdown is hidden, the next Open dropdown in the stack will be displayed.\n * If a dropdown is shown, the previously dropdown in the stack will be hidden, if one exists.\n *\n * Updates the overlay subject with true if any dropdown is Open or false if no dropdown is Open. */\n async setState(dropdown: DropdownComponent, open: boolean): Promise<void> {\n const current = await firstValueFrom(this.open);\n const attached = current === dropdown;\n\n if (current && !attached) {\n current.closeDropdown();\n }\n\n if (open && !attached) {\n this.attachDropdown(dropdown);\n this.open.next(dropdown);\n } else if (!open && current) {\n this.detachCurrentDropdown();\n this.open.next(undefined);\n }\n }\n\n /** @ignore */\n ngOnDestroy(): void {\n this.keyDownSubscription?.unsubscribe();\n this.clickOrTouchSubscription?.unsubscribe();\n }\n\n /** Attaches the given dropdown to the outlet and removes any old dropdown from the outlet. */\n private attachDropdown(dropdown: DropdownComponent): void {\n if (!this.outlet) {\n return;\n }\n\n this.detachCurrentDropdown();\n this.outlet.attach(dropdown.portal);\n }\n\n /** Detaches the current dropdown from the outlet. */\n private detachCurrentDropdown(): void {\n if (!this.outlet) {\n return;\n }\n\n this.outlet.detach();\n }\n\n /** Relays focus events from the <app-dropdown-outlet> component to the current <app-dropdown> component. */\n async handleFocus(event: FocusEvent): Promise<void> {\n const current = await firstValueFrom(this.open);\n\n if (current && event.target) {\n current.trapFocus(event.target);\n }\n }\n}\n","import { DomPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n AfterViewInit,\n ApplicationRef,\n ChangeDetectionStrategy,\n Component,\n ComponentFactoryResolver,\n ElementRef,\n Inject,\n Injector,\n OnDestroy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { DropdownService } from '../../dropdown.service';\n\n/** The outlet for dropdowns.\n * This component is controlled by the dropdown service and relays global keypress\n * and focus events back to the service for further processing. */\n@Component({\n selector: 'lru-dropdown-outlet',\n template: '',\n styleUrls: ['./dropdown-outlet.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DropdownOutletComponent implements AfterViewInit, OnDestroy {\n /** Subscribe to state of dropdown */\n private dropdownSubscription = this.dropdownService.open$.subscribe((open) => {\n if (open) {\n this.setUpFocusHandler();\n } else {\n this.destroyFocusHandler();\n }\n });\n\n /** @ignore */\n constructor(\n @Inject(DOCUMENT) private document: Document,\n private componentFactoryResolver: ComponentFactoryResolver,\n private appRef: ApplicationRef,\n private injector: Injector,\n private dropdownService: DropdownService,\n private elementRef: ElementRef\n ) {}\n\n /** Set up a dom portal outlet and pass it on to the dropdown service */\n ngAfterViewInit(): void {\n const outlet = new DomPortalOutlet(\n this.elementRef.nativeElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n this.dropdownService.setPortalOutlet(outlet);\n }\n\n /** Add event listener that traps focus */\n private setUpFocusHandler(): void {\n // It would be nicer to use Angular host bindings for the event handling, but angular doesn't support capture instead of bubbling\n this.document.addEventListener('focus', this.focusHandler, true);\n }\n\n /** Remove event listener that traps focus */\n private destroyFocusHandler(): void {\n this.document.removeEventListener('focus', this.focusHandler, true);\n }\n\n /** Relays focus event on to the dropdown service. */\n private focusHandler = (event: FocusEvent): void => {\n this.dropdownService.handleFocus(event);\n };\n\n /** Unsubscribe from subscriptions when component is destroyed */\n ngOnDestroy(): void {\n this.dropdownSubscription.unsubscribe();\n }\n}\n","/**\n * Interface for getting first and last element of array\n */\nexport interface ArrayExtremes<T> {\n /** first item from array */\n first: T | undefined;\n /** last item from array */\n last: T | undefined;\n}\n\n/**\n * Returns true if the given arrays contains exactly the same items at the same indexes.\n */\nexport function arrayEqualsArray(array1: any[], array2: any[]): boolean {\n let equals = false;\n\n if (array1.length === array2.length) {\n for (let i = 0; i < array1.length; i++) {\n equals = array2.indexOf(array1[i]) === i;\n\n if (!equals) {\n break;\n }\n }\n }\n\n return equals;\n}\n\n/**\n * Returns the first and last item of the given array.\n */\nexport function getArrayExtremes<T>(array: T[]): ArrayExtremes<T> {\n return { first: array[0], last: array[array.length - 1] };\n}\n\n/**\n * Creates an array with the given length filled with the given value.\n */\nexport function createFillerArray<Type>(length: number, fillValue: Type): Type[] {\n const array = [];\n\n while (length--) {\n array.push(fillValue);\n }\n\n return array;\n}\n\n/**\n * Removes the given item from the given array.\n * Returns `true` if something was removed.\n */\nexport function removeFromArray(array: any[], item: any): boolean {\n const index = array.indexOf(item);\n\n if (index !== -1) {\n array.splice(index, 1);\n return true;\n }\n\n return false;\n}\n\n/**\n * Removes any items from the given array matching the given filter.\n * Returns `true` if something was removed.\n */\nexport function removeFromArrayByFilter<T>(array: any[], filter: (item: T) => boolean): boolean {\n const index = array.findIndex(filter);\n\n if (index !== -1) {\n array.splice(index, 1);\n // Remove the next matching element, if any, before returning true\n return removeFromArrayByFilter(array, filter) || true;\n }\n\n return false;\n}\n\n/**\n * Returns the last item from the given array or undefined if the array is empty.\n */\nexport function getLastItemFromArray<Type>(array: Type[]): Type | undefined {\n return array[array.length - 1];\n}\n","/**\n * A list of focusable elements for use in `document.querySelector` and `document.querySelectorAll`\n */\nexport const focusableElements = 'button, [href], input, select, textarea, [tabindex]';\n","import { IDropdownConfig } from './dropdown-config.interface';\nimport { dropdownAxis, dropdownHorizontalDirection, dropdownVerticalDirection } from './dropdown-types';\n\n/**\n * Settings for dropdowns\n */\nexport class DropdownConfig implements IDropdownConfig {\n /** Function that will get triggered when dropdown is opened */\n openFunc = undefined;\n\n /** Function that will get triggered when dropdown is closed */\n closeFunc = undefined;\n\n /** Should dropdown content be the same width as the button? */\n sameWidth = true;\n\n /** Should dropdown content be the same height as the button? */\n sameHeight = false;\n\n /** Which horizontal direction should dropdown content go from the button? */\n horizontalDirection: dropdownHorizontalDirection = 'right';\n\n /** Which vertical direction should dropdown content go from the button? */\n verticalDirection: dropdownVerticalDirection = 'down';\n\n /** What is the minimum width of dropdown content before it should start ignoring its position relative to the button? */\n toleranceWidth = 100;\n\n /** What is the minimum height of dropdown content before it should start ignoring its position relative to the button? */\n toleranceHeight = 100;\n\n /** How many pixels space should there be between dropdown button and dropdown content? */\n spacingFromButton = 0;\n\n /** How many pixels space should there be from dropdown content to the browser window? */\n spacingFromWindow = 0;\n\n /** Should dropdown content be on top of dropdown button? */\n popOver = false;\n\n /** Should dropdown content be displayed over/under the dropdown? Then the axis should be \"vertical\" */\n axis: dropdownAxis = 'vertical';\n\n /** How often should the dropdown content position be checked on window scroll and resize? */\n throttleTime = 100;\n\n /** Should dropdown content fill out the browser window width minus spacingFromWindow? */\n fillWidth = false;\n\n /** Should dropdown content fill out the browser window height minus spacingFromWindow? */\n fillHeight = false;\n\n /** How wide can the dropdown content become? */\n maxWidth = undefined;\n\n /** How high can the dropdown content become? */\n maxHeight = undefined;\n\n /** Data-attribute to make it easier to add custom styling */\n variant = undefined;\n}\n","import { createAction, props } from '@ngrx/store';\nimport { IZIndexConfig } from '../z-index-config.interface';\n\nconst modulePrefix = '[ZIndexModule]';\n\nexport const setConfig = createAction(`${modulePrefix} Set config`, props<{ config: IZIndexConfig }>());\n\nexport const setItem = createAction(`${modulePrefix} Set Item`, props<{ id: string }>());\n","import { createReducer, on } from '@ngrx/store';\nimport * as ZIndexActions from './z-index.actions';\nimport { initialZIndexState } from './z-index.state';\n\nexport const zIndexFeatureKey = 'zIndexState';\n\nexport const zIndexReducer = createReducer(\n initialZIndexState,\n on(ZIndexActions.setConfig, (state, action) => {\n return {\n ...state,\n currentZIndex: action.config.zIndex ?? 0,\n config: action.config,\n };\n }),\n on(ZIndexActions.setItem, (state, action) => {\n return {\n ...state,\n currentZIndex: state.currentZIndex + 2,\n items: [\n ...state.items.filter((x) => x.id !== action.id),\n {\n id: action.id,\n zIndex: state.currentZIndex + 2,\n },\n ],\n };\n })\n);\n","import { IZIndexConfig } from '../z-index-config.interface';\n\nexport interface ZIndexState {\n config: IZIndexConfig;\n currentZIndex: number;\n items: ZIndexItem[];\n}\n\nexport interface ZIndexItem {\n id: string;\n zIndex: number;\n}\n\nexport const initialZIndexState: ZIndexState = {\n config: {},\n currentZIndex: 0,\n items: [],\n};\n","import { createFeatureSelector, createSelector, DefaultProjectorFn, MemoizedSelector } from '@ngrx/store';\nimport { zIndexFeatureKey } from './z-index.reducers';\nimport { ZIndexState } from './z-index.state';\n\nexport const selectZIndexState = createFeatureSelector<ZIndexState>(zIndexFeatureKey);\n\nexport const selectConfig = createSelector(selectZIndexState, (state) => state.config);\n\nexport const selectCurrentZIndex = createSelector(selectZIndexState, (state) => state.currentZIndex);\n\nexport const getItemById = (\n id: string\n): MemoizedSelector<object, number | undefined, DefaultProjectorFn<number | undefined>> =>\n createSelector(selectZIndexState, (state) => {\n return state.items.find((x) => x.id === id)?.zIndex;\n });\n","import { IZIndexConfig } from './z-index-config.interface';\n\n/**\n * Settings for z-index\n */\nexport class ZIndexConfig implements IZIndexConfig {\n /** Start z-index the z-index service/store should use */\n zIndex = 0;\n}\n","import { Injectable, Optional } from '@angular/core';\nimport { Store } from '@ngrx/store';\nimport { Observable } from 'rxjs';\nimport * as ZIndexActions from '../store/z-index.actions';\nimport * as ZIndexSelectors from '../store/z-index.selectors';\nimport { ZIndexState } from '../store/z-index.state';\nimport { ZIndexConfig } from '../z-index-config';\n\n/**\n * Service used to give elements a new higher z-index to ensure an element is on top\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class ZIndexService {\n /** Get config set for z-index store */\n public config$ = this.store.select(ZIndexSelectors.selectConfig);\n\n /**\n * Get z-index info for item with specific ID\n * @param id item to get z-index info for\n * @returns z-index item or undefined if not found\n */\n item$ = (id: string): Observable<number | undefined> => this.store.select(ZIndexSelectors.getItemById(id));\n\n /** the z-index currently being applied */\n public currentZIndex$ = this.store.select(ZIndexSelectors.selectCurrentZIndex);\n\n /** @ignore */\n constructor(private store: Store<ZIndexState>, @Optional() private config?: ZIndexConfig) {\n this.store.dispatch(\n ZIndexActions.setConfig({\n config: {\n zIndex: this.config?.zIndex,\n },\n })\n );\n }\n\n /**\n * Set z-index item in store\n * @param id name of item that is getting the new z-index\n */\n setItem(id: string): void {\n this.store.dispatch(ZIndexActions.setItem({ id: id }));\n }\n}\n","import { CdkPortal } from '@angular/cdk/portal';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n Input,\n OnDestroy,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { throttle } from 'throttle-debounce';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getLastItemFromArray } from '../../../../utils/array';\nimport { focusableElements } from '../../../../utils/query-selectors';\nimport { ZIndexService } from '../../../z-index/services/z-index.service';\nimport { DropdownConfig } from '../../dropdown-config';\nimport {\n dropdownAxis,\n dropdownHorizontalDirection,\n dropdownVerticalDirection,\n dropdownVisibility,\n} from '../../dropdown-types';\nimport { DropdownService } from '../../dropdown.service';\n\n/** A component for displaying dropdowns.\n * The content passed will be the content of the dropdown.\n * The dropdownOpen is controlled by the `isOpen` attribute.\n * If the dropdown is hidden (or displayed) by user interaction an `isOpenChange` event will be fired.\n * The component isn't rendered in place, but moved to the <app-dropdown-outlet> component automatically to prevent issues with semantics and style bleeding. */\n@Component({\n selector: 'lru-dropdown',\n templateUrl: './dropdown.component.html',\n styleUrls: ['./dropdown.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class DropdownComponent implements OnDestroy, AfterViewInit {\n /** Should the dropdown be open to begin with? */\n @Input() isOpen: boolean = false;\n\n /** Enforce openFunc different from what is specified in the config {@link DropdownConfig} */\n @Input() openFunc?: Function;\n\n /** Enforce closeFunc different from what is specified in the config {@link DropdownConfig} */\n @Input() closeFunc?: Function;\n\n /** Enforce sameWidth different from what is specified in the config {@link DropdownConfig} */\n @Input() sameWidth: boolean;\n\n /** Enforce sameHeight different from what is specified in the config {@link DropdownConfig} */\n @Input() sameHeight: boolean;\n\n /** Enforce horizontalDirection different from what is specified in the config {@link DropdownConfig} */\n @Input() horizontalDirection: dropdownHorizontalDirection;\n\n /** Enforce verticalDirection different from what is specified in the config {@link DropdownConfig} */\n @Input() verticalDirection: dropdownVerticalDirection;\n\n /** Enforce toleranceWidth different from what is specified in the config {@link DropdownConfig} */\n @Input() toleranceWidth: number;\n\n /** Enforce toleranceHeight different from what is specified in the config {@link DropdownConfig} */\n @Input() toleranceHeight: number;\n\n /** Enforce spacingFromButton different from what is specified in the config {@link DropdownConfig} */\n @Input() spacingFromButton: number;\n\n /** Enforce spacingFromWindow different from what is specified in the config {@link DropdownConfig} */\n @Input() spacingFromWindow: number;\n\n /** Enforce popOver different from what is specified in the config {@link DropdownConfig} */\n @Input() popOver: boolean;\n\n /** Enforce axis different from what is specified in the config {@link DropdownConfig} */\n @Input() axis: dropdownAxis;\n\n /** Enforce throttleTime different from what is specified in the config {@link DropdownConfig} */\n @Input() throttleTime: number;\n\n /** Enforce fillWidth different from what is specified in the config {@link DropdownConfig} */\n @Input() fillWidth: boolean;\n\n /** Enforce fillHeight different from what is specified in the config {@link DropdownConfig} */\n @Input() fillHeight: boolean;\n\n /** Enforce maxWidth different from what is specified in the config {@link DropdownConfig} */\n @Input() maxWidth?: number;\n\n /** Enforce maxHeight different from what is specified in the config {@link DropdownConfig} */\n @Input() maxHeight?: number;\n\n /** Enforce variant different from what is specified in the config {@link DropdownConfig} */\n @Input() variant?: string;\n\n /** Enforce ariaLabel different from what is specified in the config {@link DropdownConfig} */\n @Input() ariaLabel?: string;\n\n /** Pixel width the dropdown should have if possible */\n @Input() width?: number;\n\n /** Pixel height the dropdown should have if possible */\n @Input() height?: number;\n\n /** add data-id */\n @Input() id?: string;\n\n /** Used by the dropdown service to get a reference of the internal dropdown portal. */\n @ViewChild(CdkPortal) readonly portal?: CdkPortal;\n\n /** The element reference to the dropdown content */\n @ViewChild('domDropdownContent') private domDropdownContent: ElementRef | undefined;\n\n /** The element reference to the dropdown button */\n @ViewChild('domOpenDropdownButton') domOpenDropdownButton!: ElementRef<HTMLButtonElement>;\n\n /** style.top. Generated by setDropdownStyling() */\n appliedTop: string | null = null;\n\n /** style.bottom. Generated by setDropdownStyling() */\n appliedBottom: string | null = null;\n\n /** style.left. Generated by setDropdownStyling() */\n appliedLeft: string | null = null;\n\n /** style.right. Generated by setDropdownStyling() */\n appliedRight: string | null = null;\n\n /** style.max-width. Generated by setDropdownStyling() */\n appliedMaxWidth: string | null = null;\n\n /** style.max-height. Generated by setDropdownStyling() */\n appliedMaxHeight: string | null = null;\n\n /** style.width. Generated by setDropdownStyling() */\n appliedWidth: string | null = null;\n\n /** style.height. Generated by setDropdownStyling() */\n appliedHeight: string | null = null;\n\n /** style.visibility. Generated by setDropdownStyling() */\n appliedVisibility: dropdownVisibility = 'hidden';\n\n /** attr.data-horizontal-direction.\n * Generated by setDropdownStyling().\n * Used to make it possible to add specific styling for this. */\n appliedHorizontalDirection: dropdownHorizontalDirection | null = null;\n\n /** attr.data-vertical-direction.\n * Generated by setDropdownStyling().\n * Used to make it possible to add specific styling for this. */\n appliedVerticalDirection: dropdownVerticalDirection | null = null;\n\n /** attr.data-fill-width.\n * Generated by setDropdownStyling().\n * Used to make it possible to add specific styling for this. */\n appliedFillWidth: boolean | null = null;\n\n /** attr.data-fill-height.\n * Generated by setDropdownStyling().\n * Used to make it possible to add specific styling for this. */\n appliedFillHeight: boolean | null = null;\n\n /** A reference to the last focus event target. Used to prevent unnecessary focus jumps. */\n private lastFocusEventTarget: EventTarget | null = null;\n\n /** unique id for this component */\n private uuid = uuidv4();\n\n /** z-index for dropdown content */\n public readonly zIndex$ = this.zIndexService.item$(this.uuid);\n\n /** @ignore */\n constructor(\n private window: Window,\n public dropdownService: DropdownService,\n private changeDetectorRef: ChangeDetectorRef,\n private zIndexService: ZIndexService,\n private config?: DropdownConfig\n ) {\n const defaultConfig = new DropdownConfig();\n\n this.sameWidth = this.config?.sameWidth ?? defaultConfig.sameWidth;\n this.sameHeight = this.config?.sameHeight ?? defaultConfig.sameHeight;\n this.horizontalDirection = this.config?.horizontalDirection ?? defaultConfig.horizontalDirection;\n this.verticalDirection = this.config?.verticalDirection ?? defaultConfig.verticalDirection;\n this.toleranceWidth = this.config?.toleranceWidth ?? defaultConfig.toleranceWidth;\n this.toleranceHeight = this.config?.toleranceHeight ?? defaultConfig.toleranceHeight;\n this.spacingFromButton = this.config?.spacingFromButton ?? defaultConfig.spacingFromButton;\n this.spacingFromWindow = this.config?.spacingFromWindow ?? defaultConfig.spacingFromWindow;\n this.popOver = this.config?.popOver ?? defaultConfig.popOver;\n this.axis = this.config?.axis ?? defaultConfig.axis;\n this.throttleTime = this.config?.throttleTime ?? defaultConfig.throttleTime;\n this.fillWidth = this.config?.fillWidth ?? defaultConfig.fillWidth;\n this.fillHeight = this.config?.fillHeight ?? defaultConfig.fillHeight;\n this.maxWidth = this.config?.maxWidth ?? defaultConfig.maxWidth;\n this.maxHeight = this.config?.maxHeight ?? defaultConfig.maxHeight;\n this.variant = this.config?.variant ?? defaultConfig.variant;\n this.openFunc = this.config?.openFunc ?? defaultConfig.openFunc;\n this.closeFunc = this.config?.closeFunc ?? defaultConfig.closeFunc;\n }\n\n /** Calls {@link setState} if modal is open */\n ngAfterViewInit(): void {\n if (this.isOpen) {\n this.setState();\n }\n }\n\n /**\n * Interval for checking if button has changed position.\n * Used by {@link listenForPositionChanges}\n * */\n positionChangeInterval?: NodeJS.Timeout;\n\n /**\n * Old dropdown button rect to compare against to see if the button has changed position.\n * Used by {@link listenForPositionChanges} */\n currentRect?: DOMRect;\n\n /**\n * While the dropdown is open we need to check often if the dropdown button has changed position.\n * If we dont do this then dropdown button and dropdown content could come out of sync if the DOM changes.\n * If for example the page gets more content, then a scrollbar might get displayed that shifts all content on the page, then the button for the dropdown will move and then dropdown content needs to recalculate its position.\n */\n listenForPositionChanges(): void {\n if (this.isOpen) {\n if (this.positionChangeInterval) {\n clearInterval(this.positionChangeInterval);\n }\n\n this.positionChangeInterval = setInterval(() => {\n const rect = this.domOpenDropdownButton.nativeElement.getBoundingClientRect();\n\n if (this.currentRect && JSON.stringify(rect) !== JSON.stringify(this.currentRect)) {\n this.setDropdownStyling();\n }\n\n this.currentRect = rect;\n }, 50);\n } else if (this.positionChangeInterval) {\n clearInterval(this.positionChangeInterval);\n }\n }\n\n /** When dropdown is no longer in the DOM then we close dropdown and clears the interval that monitors the position of dropdown content relative to its button if its open. */\n async ngOnDestroy(): Promise<void> {\n await this.dropdownService.closeDropdown();\n if (this.positionChangeInterval) {\n clearInterval(this.positionChangeInterval);\n }\n }\n\n /** Sets state of dropdown in {@link DropdownService} and applies dropdown styling. If open set focus to dropdown. */\n private setState(): void {\n this.dropdownService.setState(this, this.isOpen);\n if (this.isOpen) {\n setTimeout(() => {\n this.focusOnDropdown();\n });\n }\n\n this.listenForPositionChanges();\n this.setDropdownStyling();\n }\n\n /** Setter for {@link isOpen} */\n closeDropdown(): void {\n this.isOpen = false;\n this.changeDetectorRef.detectChanges();\n if (this.closeFunc) {\n this.closeFunc();\n }\n }\n\n /** Calls {@link DropdownService.closeDropdown} */\n async onCloseClick(): Promise<void> {\n await this.dropdownService.closeDropdown();\n }\n\n /** Traps focus within the dropdown as long as it's open. Called from the dropdown service. */\n trapFocus(eventTarget: EventTarget): void {\n const isValidFocusElement = this.domDropdownContent?.nativeElement.contains(eventTarget);\n\n if (!isValidFocusElement) {\n if (eventTarget instanceof HTMLElement && eventTarget.classList.contains('focus-trap')) {\n if (eventTarget.classList.contains('focus-trap-begin')) {\n // If no timeout is set, we're constantly brought back to the last focus item for some strange reason\n setTimeout(() => {\n this.focusOnLastDescendant();\n });\n } else if (eventTarget.classList.contains('focus-trap-end')) {\n this.focusOnFirstDescendant();\n }\n } else if (this.lastFocusEventTarget === eventTarget) {\n return;\n }\n\n this.lastFocusEventTarget = eventTarget;\n\n this.focusOnDropdown();\n }\n }\n\n /** Sets focus on the most relevant element in the dropdown. */\n private focusOnDropdown(): void {\n const dropdownElement = this.domDropdownContent?.nativeElement;\n\n if (!dropdownElement) {\n return;\n }\n\n // Try to find an element with the autofocus attribute\n const autofocusElement = dropdownElement.querySelector('[autofocus]');\n\n if (autofocusElement) {\n autofocusElement.focus();\n return;\n }\n\n // Try to find any focusable element\n dropdownElement.querySelector(focusableElements)?.focus();\n }\n\n /** Sets focus on the first focusable element in the dropdown. */\n private focusOnFirstDescendant(): void {\n this.domDropdownContent?.nativeElement.querySelector(focusableElements)?.focus();\n }\n\n /** Sets focus on the last focusable element in the dropdown. */\n private focusOnLastDescendant(): void {\n const lastElement = getLastItemFromArray(\n this.domDropdownContent?.nativeElement.querySelectorAll(focusableElements) || []\n );\n\n if (lastElement instanceof HTMLElement) {\n lastElement.focus();\n }\n }\n\n /** Convert number to px value\n * @param value number\n * @returns px value */\n private px(value: number): string {\n return `${value}px`;\n }\n\n /**\n * Resets all applied styling for dropdown content and hides it.\n * This is used before calculating new position for dropdown content, to ensure no old values are removes.\n */\n private resetDropdownStyling(): void {\n this.appliedTop = null;\n this.appliedBottom = null;\n this.appliedLeft = null;\n this.appliedRight = null;\n this.appliedMaxWidth = null;\n this.appliedMaxHeight = null;\n this.appliedWidth = null;\n this.appliedHeight = null;\n this.appliedFillWidth = null;\n this.appliedFillHeight = null;\n this.appliedVisibility = 'hidden';\n }\n\n /** Figure out how to dropdown content should be placed based on a multitude of factors like screen-size or inputs */\n private setDropdownStyling(): void {\n if (this.isOpen) {\n this.resetDropdownStyling();\n\n const rect = this.domOpenDropdownButton.nativeElement.getBoundingClientRect();\n let buttonOffsetTop: number = rect.top;\n let buttonOffsetBottom: number = this.window.innerHeight - (rect.top + rect.height);\n let buttonOffsetLeft: number = rect.left;\n let buttonOffsetRight: number = document.body.clientWidth - (rect.left + rect.width);\n\n this.appliedHorizontalDirection = this.horizontalDirection;\n this.appliedVerticalDirection = this.verticalDirection;\n\n if (this.fillWidth) {\n this.appliedFillWidth = true;\n } else if (this.sameWidth) {\n this.toleranceWidth = rect.width;\n }\n\n if (this.fillHeight) {\n this.appliedFillHeight = true;\n } else if (this.sameHeight) {\n this.toleranceHeight = rect.height;\n }\n\n // check if dirrection is possible or reverse it - start\n if (\n this.appliedHorizontalDirection === 'left' &&\n rect.left + (this.axis === 'vertical' ? rect.width : 0) - (this.spacingFromButton + this.spacingFromWindow) <\n this.toleranceWidth\n ) {\n if (buttonOffsetRight - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceWidth) {\n this.appliedFillWidth = true;\n } else {\n this.appliedHorizontalDirection = 'right';\n }\n } else if (\n this.appliedHorizontalDirection === 'right' &&\n buttonOffsetRight +\n (this.axis === 'vertical' ? rect.width : 0) -\n (this.spacingFromButton + this.spacingFromWindow) <\n this.toleranceWidth\n ) {\n if (buttonOffsetLeft - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceWidth) {\n this.appliedFillWidth = true;\n } else {\n this.appliedHorizontalDirection = 'left';\n }\n } else if (this.width && this.width - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceWidth) {\n this.appliedFillWidth = true;\n }\n\n if (\n this.appliedVerticalDirection === 'up' &&\n buttonOffsetTop - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceHeight\n ) {\n if (buttonOffsetBottom - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceHeight) {\n this.appliedFillHeight = true;\n } else {\n this.appliedVerticalDirection = 'down';\n }\n } else if (\n this.appliedVerticalDirection === 'down' &&\n buttonOffsetBottom - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceHeight\n ) {\n if (buttonOffsetTop - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceHeight) {\n this.appliedFillHeight = true;\n } else {\n this.appliedVerticalDirection = 'up';\n }\n } else if (\n this.height &&\n this.height - (this.spacingFromButton + this.spacingFromWindow) < this.toleranceHeight\n ) {\n this.appliedFillHeight = true;\n }\n // check if dirrection is possible or reverse it - end\n\n // width start\n if (this.appliedFillWidth) {\n this.appliedLeft = this.px(this.spacingFromWindow);\n this.appliedRight = this.px(this.spacingFromWindow);\n } else {\n let width =\n (this.appliedHorizontalDirection === 'left' ? buttonOffsetLeft : buttonOffsetRight) -\n this.spacingFromWindow -\n (this.axis === 'horizontal' ? this.spacingFromButton : 0) +\n (this.popOver || this.axis === 'vertical' ? rect.width : 0);\n\n if (this.maxWidth && width > this.maxWidth) {\n width = this.maxWidth;\n }\n\n if (width < this.toleranceWidth || (this.width && this.width < this.toleranceWidth)) {\n this.appliedFillWidth = true;\n } else {\n if (this.sameWidth) {\n this.appliedMaxWidth = this.px(rect.width);\n this.appliedWidth = '100%';\n } else {\n if (this.width) {\n this.appliedMaxWidth = this.px(this.width);\n this.appliedWidth = '100%';\n } else {\n this.appliedMaxWidth = this.px(width);\n }\n }\n }\n\n if (this.axis === 'horizontal') {\n if (this.appliedHorizontalDirection === 'left') {\n this.appliedRight = this.px(buttonOffsetRight + this.spacingFromButton + (!this.popOver ? rect.width : 0));\n } else if (this.appliedHorizontalDirection === 'right') {\n this.appliedLeft = this.px(buttonOffsetLeft + this.spacingFromButton + (!this.popOver ? rect.width : 0));\n }\n } else if (this.axis === 'vertical') {\n if (this.appliedHorizontalDirection === 'left') {\n this.appliedRight = this.px(buttonOffsetRight);\n } else if (this.appliedHorizontalDirection === 'right') {\n this.appliedLeft = this.px(buttonOffsetLeft);\n }\n }\n }\n // width end\n\n // height start\n if (this.appliedFillHeight) {\n this.appliedTop = this.px(this.spacingFromWindow);\n this.appliedBottom = this.px(this.spacingFromWindow);\n } else {\n let height =\n (this.appliedVerticalDirection === 'down' ? buttonOffsetBottom : buttonOffsetTop) -\n this.spacingFromWindow -\n (this.axis === 'vertical' ? this.spacingFromButton : 0) +\n (this.popOver || this.axis === 'horizontal' ? rect.height : 0);\n\n if (this.maxHeight && height > this.maxHeight) {\n height = this.maxHeight;\n }\n\n if (height < this.toleranceHeight || (this.height && this.height < this.toleranceHeight)) {\n this.appliedFillHeight = true;\n } else {\n if (this.sameHeight) {\n this.appliedMaxHeight = this.px(rect.height);\n this.appliedHeight = '100%';\n } else {\n if (this.height) {\n this.appliedMaxHeight = this.px(this.height);\n this.appliedHeight = '100%';\n } else {\n this.appliedMaxHeight = this.px(height);\n }\n }\n }\n\n if (this.axis === 'horizontal') {\n if (this.appliedVerticalDirection === 'up') {\n this.appliedBottom = this.px(buttonOffsetBottom);\n } else if (this.appliedVerticalDirection === 'down') {\n this.appliedTop = this.px(buttonOffsetTop);\n }\n } else if (this.axis === 'vertical') {\n if (this.appliedVerticalDirection === 'up') {\n this.appliedBottom = this.px(\n buttonOffsetBottom + this.spacingFromButton + (!this.popOver ? rect.height : 0)\n );\n } else if (this.appliedVerticalDirection === 'down') {\n this.appliedTop = this.px(buttonOffsetTop + this.spacingFromButton + (!this.popOver ? rect.height : 0));\n }\n }\n }\n // height end\n\n this.appliedVisibility = 'visible';\n }\n\n this.changeDetectorRef.detectChanges();\n }\n\n /**\n * Toggle between open/close state for dropdown.\n * Sets dropdown to have the highest z-index to ensure it is on top.\n * Triggers {@link openFunc} or {@link closeFunc} if specified\n */\n onClickToggleDropdown(): void {\n this.isOpen = !this.isOpen;\n this.setState();\n if (this.isOpen) {\n this.zIndexService.setItem(this.uuid);\n if (this.openFunc) {\n this.openFunc();\n }\n } else {\n if (this.closeFunc) {\n this.closeFunc();\n }\n }\n }\n\n /** When the window is scrolled it will need to recalculate where dropdown content should be placed. */\n @HostListener('window:scroll') onScroll(): void {\n throttle(this.throttleTime, () => {\n this.setDropdownStyling();\n })();\n }\n\n /** When the window is resized it will need to recalculate where dropdown content should be placed. */\n @HostListener('window:resize') onResize(): void {\n throttle(this.throttleTime, () => {\n this.setDropdownStyling();\n })();\n }\n}\n","import { PortalModule } from '@angular/cdk/portal';\nimport { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { ButtonModule } from '../button/button.module';\nimport { DropdownComponent } from './components/dropdown/dropdown.component';\nimport { DropdownOutletComponent } from './components/dropdown-outlet/dropdown-outlet.component';\nimport { DropdownConfig } from './dropdown-config';\nimport { IDropdownConfig } from './dropdown-config.interface';\n\n@NgModule({\n declarations: [DropdownComponent, DropdownOutletComponent],\n imports: [CommonModule, PortalModule, ButtonModule],\n exports: [DropdownComponent, DropdownOutletComponent],\n providers: [{ provide: Window, useValue: window }],\n})\nexport class DropdownModule {\n static forRoot(config: IDropdownConfig): ModuleWithProviders<DropdownModule> {\n return {\n ngModule: DropdownModule,\n providers: [{ provide: DropdownConfig, useValue: config }],\n };\n }\n\n static forChild(config: IDropdownConfig): ModuleWithProviders<DropdownModule> {\n return {\n ngModule: DropdownModule,\n providers: [{ provide: DropdownConfig, useValue: config }],\n };\n }\n}\n","/** Enum for common shared loading keys used for starting and stopping loading */\nexport enum SharedLoadingKeys {\n fullLevel = 'fullLevel',\n teams = 'teams',\n dlpClasses = 'dlpClasses',\n teachers = 'teachers',\n teachersWithoutCurrentUser = 'teachersWithoutCurrentUser',\n teamStudents = 'teamStudents',\n createTeam = 'createTeam',\n editTeam = 'editTeam',\n saveDetailsToTeam = 'saveDetailsToTeam',\n teamDelete = 'teamDelete',\n teamSaveTeachersToTeam = 'teamSaveTeachersToTeam',\n teamSaveStudentsToTeam = 'teamSaveStudentsToTeam',\n teamRemoveTeacherSelf = 'teamRemoveTeacherSelf',\n}\n","export const GTMJS = 'gtm.js';\n\nexport const Page = 'page';\n\nexport const LoungeCreateTeam = 'lounge-create-team-start';\n\nexport const LoungeCreateTeamDone = 'lounge-create-team-done';\n\nexport const LoungeEditTeam = 'lounge-edit-team-start';\n\nexport const LoungeEditTeamDone = 'lounge-edit-team-done';\n\nexport const LoungeEditTeacher = 'lounge-edit-teacher-start';\n\nexport const LoungeEditTeacherDone = 'lounge-edit-teacher-done';\n\nexport const LoungeRemoveTeacherDone = 'lounge-remove-teacher-done';\n\nexport const LoungeEditTeamSettingsDone = 'lounge-edit-teamsettings-done';\n\nexport const LoungeDeleteTeamDone = 'lounge-delete-team-done';\n\nexport const LoungeSort = 'lounge-sort';\n","import { createAction, props } from '@ngrx/store';\nimport { ErrorWithLoadingKey } from '../../../services/loading/store/loading.actions';\nimport { FullLevelDto } from '../interfaces/endpoint/dtos/dto-level.interface';\nimport { PermissionDto } from '../interfaces/endpoint/dtos/dto-permission.interface';\nimport { StudentDto } from '../interfaces/endpoint/dtos/dto-student.interface';\nimport { TeamWithTeachersDto } from '../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { AddTeacher, ILoungePostBodyTeam_CreateTeam } from '../interfaces/endpoint/team.interface';\nimport { IClassWithUsers, IUserPermissionWithSelected } from './interfaces/team-edit.interface';\n\nconst modulePrefix = '[LoungeModule]';\n\n//#region LEVEL ########################################################\n\nexport const levelLoadLevels = createAction(`${modulePrefix} levels/load`, props<{ loadingKey: string }>());\n\nexport const levelLoadLevelsSuccess = createAction(\n `${modulePrefix} levels/load success`,\n props<{ loadingKey: string; fullLevel: FullLevelDto }>()\n);\n\nexport const levelLoadLevelsFailure = createAction(`${modulePrefix} levels/load failure`, props<ErrorWithLoadingKey>());\n\n//#endregion LEVEL ########################################################\n\nexport const markTeacherForSelection = createAction(\n `${modulePrefix} mark teacher for selection`,\n props<{ teacherId: string; selected: boolean }>()\n);\n\nexport const markTeacherForSelectionSuccess = createAction(\n `${modulePrefix} mark teacher for selection/success`,\n props<{ teacherId: string; selected: boolean; permission: PermissionDto }>()\n);\n\nexport const markClassForSelection = createAction(\n `${modulePrefix} mark class for selection`,\n props<{ classId: string; selected: boolean; searchTerm: string }>()\n);\n\nexport const markClassForSelectionSuccess = createAction(\n `${modulePrefix} mark class for selection/success`,\n props<{ classId: string; selected: boolean; searchTerm: string }>()\n);\n\nexport const markStudentForSelection = createAction(\n `${modulePrefix} mark student for selection`,\n props<{ classId: string; userId: string; selected: boolean }>()\n);\n\nexport const markStudentForSelectionSuccess = createAction(\n `${modulePrefix} mark student for selection/success`,\n props<{ classId: string; userId: string; selected: boolean }>()\n);\n\nexport const removeSelectionsFromStudents = createAction(`${modulePrefix} remove selections for students`);\n\nexport const removeSelectionsFromStudentsSuccess = createAction(\n `${modulePrefix} remove selections for students/success`\n);\n\nexport const removeSelectionsFromTeachers = createAction(`${modulePrefix} remove selections for teachers`);\n\nexport const removeSelectionsFromTeachersSuccess = createAction(\n `${modulePrefix} remove selections for teachers/success`\n);\n\nexport const dlpLoadTeachers = createAction(`${modulePrefix} teachers/load`, props<{ loadingKey: string }>());\n\nexport const dlpLoadTeachersSuccess = createAction(\n `${modulePrefix} teachers/load success`,\n props<{ teachers: IUserPermissionWithSelected[] }>()\n);\n\nexport const dlpLoadTeachersFailure = createAction(\n `${modulePrefix} teachers/load failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const dlpLoadClassesWithStudents = createAction(\n `${modulePrefix} classes with students/load`,\n props<{ loadingKey: string }>()\n);\n\nexport const dlpLoadClassesWithStudentsSuccess = createAction(\n `${modulePrefix} classes with students/load success`,\n props<{ loadingKey: string; classes: IClassWithUsers[] }>()\n);\n\nexport const dlpLoadClassesWithStudentsFailure = createAction(\n `${modulePrefix} classes with students/load failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamLoadTeams = createAction(`${modulePrefix} teams/load`, props<{ loadingKey: string }>());\n\nexport const teamLoadTeamsSuccess = createAction(\n `${modulePrefix} teams/load success`,\n props<{ loadingKey: string; teamList: TeamWithTeachersDto[] }>()\n);\n\nexport const teamLoadTeamsFailure = createAction(`${modulePrefix} teams/load failure`, props<ErrorWithLoadingKey>());\n\nexport const teamCreateTeam = createAction(\n `${modulePrefix} team/create`,\n props<{ loadingKey: string; team: ILoungePostBodyTeam_CreateTeam }>()\n);\n\nexport const teamCreateTeamSuccess = createAction(\n `${modulePrefix} team/create success`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamCreateTeamFailure = createAction(`${modulePrefix} team/create failure`, props<ErrorWithLoadingKey>());\n\nexport const teamEditTeam = createAction(\n `${modulePrefix} team/edit`,\n props<{ loadingKey: string; team: TeamWithTeachersDto }>()\n);\n\nexport const teamEditTeamCancel = createAction(`${modulePrefix} team/edit cancel`);\n\nexport const teamEditAssignTeachers = createAction(\n `${modulePrefix} team/edit assign teachers`,\n props<{ loadingKey: string }>()\n);\n\nexport const teamEditAssignTeachersSuccess = createAction(\n `${modulePrefix} team/edit assign teachers success`,\n props<{ loadingKey: string; teachers: IUserPermissionWithSelected[] }>()\n);\n\nexport const teamEditAssignStudents = createAction(`${modulePrefix} team/edit assign students`);\n\nexport const teamEditAssignStudentsSuccess = createAction(\n `${modulePrefix} team/edit assign students success`,\n props<{ classWithSelectedUsersList: IClassWithUsers[] }>()\n);\n\nexport const teamLoadStudents = createAction(\n `${modulePrefix} team/load students`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamLoadStudentsSuccess = createAction(\n `${modulePrefix} team/load students success`,\n props<{ loadingKey: string; studentList: StudentDto[] }>()\n);\n\nexport const teamLoadStudentsFailure = createAction(\n `${modulePrefix} team/load students failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamSaveStudentsToTeam = createAction(\n `${modulePrefix} team/save students`,\n props<{ loadingKey: string; teamId: string; studentIds: string[] }>()\n);\n\nexport const teamSaveStudentsToTeamSuccess = createAction(\n `${modulePrefix} team/save students success`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamSaveStudentsToTeamFailure = createAction(\n `${modulePrefix} team/save students failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamDeleteModal = createAction(`${modulePrefix} team/delete modal`);\n\nexport const teamDeleteTeam = createAction(\n `${modulePrefix} team/delete`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamDeleteTeamSuccess = createAction(`${modulePrefix} team/delete success`, props<{ teamId: string }>());\n\nexport const teamDeleteTeamFailure = createAction(`${modulePrefix} team/delete failure`, props<ErrorWithLoadingKey>());\n\nexport const teamEditDetailsModal = createAction(`${modulePrefix} team/edit details modal`);\n\nexport const teamEditDetails = createAction(`${modulePrefix} team/edit details`);\n\nexport const teamEditDetailsSuccess = createAction(`${modulePrefix} team/edit details success`);\n\nexport const teamEditDetailsFailure = createAction(\n `${modulePrefix} team/edit details failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamSaveDetailsToTeam = createAction(\n `${modulePrefix} team/edit details save`,\n props<{ loadingKey: string; teamId: string; title: string; levelIds: string[] }>()\n);\n\nexport const teamSaveDetailsToTeamSuccess = createAction(\n `${modulePrefix} team/edit details save success`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamSaveDetailsToTeamFailure = createAction(\n `${modulePrefix} team/edit details save failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamRemoveTeacherSelfModal = createAction(`${modulePrefix} team/remove teacher self modal`);\n\nexport const teamRemoveTeacherSelf = createAction(\n `${modulePrefix} team/remove teacher self`,\n props<{ loadingKey: string; team: TeamWithTeachersDto }>()\n);\n\nexport const teamRemoveTeacherSelfSuccess = createAction(\n `${modulePrefix} team/remove teacher self success`,\n props<{ team: TeamWithTeachersDto }>()\n);\n\nexport const teamRemoveTeacherSelfFailure = createAction(\n `${modulePrefix} team/remove teacher self failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamAddTeacher = createAction(\n `${modulePrefix} team/add teacher`,\n props<{ loadingKey: string; teamId: string; teacher: AddTeacher }>()\n);\n\nexport const teamAddTeacherSuccess = createAction(\n `${modulePrefix} team/add teacher success`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamAddTeacherFailure = createAction(\n `${modulePrefix} team/add teacher failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamAddTeachers = createAction(\n `${modulePrefix} team/add teachers`,\n props<{ loadingKey: string; teamId: string; teachers: AddTeacher[] }>()\n);\n\nexport const teamAddTeachersSuccess = createAction(\n `${modulePrefix} team/add teachers success`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamAddTeachersFailure = createAction(\n `${modulePrefix} team/add teachers failure`,\n props<ErrorWithLoadingKey>()\n);\n\nexport const teamLoadSingleTeamForEdit = createAction(\n `${modulePrefix} team/load for edit`,\n props<{ loadingKey: string; teamId: string }>()\n);\n\nexport const teamLoadSingleTeamForEditFailure = createAction(\n `${modulePrefix} team/load for edit failure`,\n props<ErrorWithLoadingKey>()\n);\n","/** Simple comparer that takes 2 simple types and compares them.\n * Can be used for {@link Array.prototype.sort} etc.\n * @parameters has to be of the same type\n * @returns If a is less than b returns -1\n * @returns If a is bigger than b returns 1\n * @returns If they're the same returns 0 */\nexport function sortComparer<T>(a: T, b: T, ascending: boolean = false): -1 | 0 | 1 {\n return a < b ? (ascending ? -1 : 1) : a > b ? (ascending ? 1 : -1) : 0;\n}\n","import { FullLevelDto } from '../interfaces/endpoint/dtos/dto-level.interface';\nimport { TeamWithTeachersDto } from '../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { IClassWithUsers, IUserPermissionWithSelected, ITeamEdit } from './interfaces/team-edit.interface';\n\nexport interface LoungeState {\n fullLevel?: FullLevelDto;\n dlpTeachersList?: IUserPermissionWithSelected[];\n dlpClassWithStudentsList?: IClassWithUsers[];\n teamWithTeachersList?: TeamWithTeachersDto[];\n teamEdit?: ITeamEdit;\n}\n\nexport const initialLoungeState: LoungeState = {\n fullLevel: undefined,\n dlpTeachersList: undefined,\n dlpClassWithStudentsList: undefined,\n teamWithTeachersList: undefined,\n teamEdit: undefined,\n};\n","import { createReducer, on } from '@ngrx/store';\nimport { sortComparer } from '../../../utils/array.helper';\nimport { IClassWithUsers, IUserPermissionWithSelected, ITeamEdit } from './interfaces/team-edit.interface';\nimport * as LoungeActions from './lounge.actions';\nimport { initialLoungeState } from './lounge.state';\n\nexport const loungeFeatureKey = 'loungeState';\n\nexport const loungeReducer = createReducer(\n initialLoungeState,\n on(LoungeActions.levelLoadLevelsSuccess, (state, action) => {\n return {\n ...state,\n fullLevel: action.fullLevel,\n };\n }),\n on(LoungeActions.markTeacherForSelectionSuccess, (state, action) => {\n const newlist = JSON.parse(JSON.stringify(state.dlpTeachersList)) as IUserPermissionWithSelected[];\n\n const _teacher = newlist.find((t) => t.user.id === action.teacherId);\n\n if (_teacher) {\n _teacher.user.selected = action.selected;\n if (action.selected) {\n _teacher.permission = action.permission;\n } else {\n _teacher.permission = {\n canCreateSubTeam: false,\n canDeleteSubTeam: false,\n canDeleteTeam: false,\n canEditSubTeam: false,\n canEditTeam: false,\n canViewSubTeam: false,\n isOwner: false,\n };\n }\n }\n\n return { ...state, dlpTeachersList: newlist };\n }),\n on(LoungeActions.markClassForSelectionSuccess, (state, action) => {\n const newlist = JSON.parse(JSON.stringify(state.dlpClassWithStudentsList)) as IClassWithUsers[];\n\n const classWithUsers = newlist.find((c) => c.class.id === action.classId);\n\n if (classWithUsers) {\n classWithUsers.class.selected = action.selected;\n classWithUsers.users.forEach((s) => {\n if (!action.searchTerm) {\n s.selected = action.selected;\n } else if (s.name.toLocaleLowerCase().includes(action.searchTerm.toLocaleLowerCase())) {\n s.selected = action.selected;\n }\n });\n }\n\n return { ...state, dlpClassWithStudentsList: newlist };\n }),\n on(LoungeActions.markStudentForSelectionSuccess, (state, action) => {\n const newlist = JSON.parse(JSON.stringify(state.dlpClassWithStudentsList)) as IClassWithUsers[];\n\n const _class = newlist.find((c) => c.class.id === action.classId)?.class;\n\n if (_class) {\n const user = newlist.find((c) => c.class.id === action.classId)?.users.find((s) => s.id === action.userId);\n\n if (user) {\n user.selected = action.selected;\n\n if (!action.selected) {\n _class.selected = action.selected;\n } else {\n const notAllUsersSelected = newlist\n .find((c) => c.class.id === action.classId)\n ?.users.find((s) => s.selected === false);\n\n _class.selected = notAllUsersSelected ? false : true;\n }\n }\n }\n\n return { ...state, dlpClassWithStudentsList: newlist };\n }),\n on(LoungeActions.removeSelectionsFromStudentsSuccess, (state) => {\n let newList: IClassWithUsers[] | undefined = undefined;\n\n if (state.dlpClassWithStudentsList) {\n newList = JSON.parse(JSON.stringify(state.dlpClassWithStudentsList)) as IClassWithUsers[];\n\n newList.forEach((x) => {\n x.class.selected = false;\n x.users.forEach((x) => (x.selected = false));\n });\n }\n\n return { ...state, dlpClassWithStudentsList: newList };\n }),\n on(LoungeActions.removeSelectionsFromTeachersSuccess, (state) => {\n let newList: IUserPermissionWithSelected[] | undefined = undefined;\n\n if (state.dlpTeachersList) {\n newList = JSON.parse(JSON.stringify(state.dlpTeachersList)) as IUserPermissionWithSelected[];\n\n newList.forEach((x) => {\n x.user.selected = false;\n });\n }\n\n return { ...state, dlpTeachersList: newList };\n }),\n on(LoungeActions.dlpLoadTeachersSuccess, (state, action) => {\n const teachersSorted: IUserPermissionWithSelected[] = [...action.teachers];\n\n teachersSorted.sort((a, b) => sortComparer(a.user.name.toLowerCase(), b.user.name.toLowerCase(), true));\n return {\n ...state,\n dlpTeachersList: teachersSorted,\n };\n }),\n on(LoungeActions.dlpLoadClassesWithStudentsSuccess, (state, action) => {\n return {\n ...state,\n dlpClassWithStudentsList: action.classes,\n };\n }),\n on(LoungeActions.teamLoadTeamsSuccess, (state, action) => {\n return {\n ...state,\n teamWithTeachersList: action.teamList,\n };\n }),\n on(LoungeActions.teamEditTeam, (state, action) => {\n const teamEdit: ITeamEdit = { ...action.team, students: [] };\n\n return {\n ...state,\n teamEdit: teamEdit,\n };\n }),\n on(LoungeActions.teamEditTeamCancel, (state) => {\n return {\n ...state,\n teamEdit: undefined,\n };\n }),\n on(LoungeActions.teamEditAssignTeachersSuccess, (state, action) => {\n return {\n ...state,\n dlpTeachersList: action.teachers,\n };\n }),\n on(LoungeActions.teamEditAssignStudentsSuccess, (state, action) => {\n return {\n ...state,\n dlpClassWithStudentsList: action.classWithSelectedUsersList,\n };\n }),\n on(LoungeActions.teamLoadStudentsSuccess, (state, action) => {\n const teamEdit = state.teamEdit ? { ...state.teamEdit, students: action.studentList } : undefined;\n\n return {\n ...state,\n teamEdit: teamEdit,\n };\n }),\n on(LoungeActions.teamDeleteTeam, (state, action) => {\n const newTeamList = state.teamWithTeachersList?.filter((x) => x.id !== action.teamId);\n\n return {\n ...state,\n teamWithTeachersList: newTeamList,\n };\n }),\n on(LoungeActions.teamRemoveTeacherSelfSuccess, (state, action) => {\n const newTeamWithTeachersList = state.teamWithTeachersList?.filter((team) => team.id !== action.team.id);\n\n return {\n ...state,\n teamWithTeachersList: newTeamWithTeachersList,\n };\n })\n);\n","import { createFeatureSelector, createSelector, DefaultProjectorFn, MemoizedSelector } from '@ngrx/store';\nimport { TeamWithTeachersDto } from '../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { IClassWithUsers, IUserPermissionWithSelected, IUserWithSelected } from './interfaces/team-edit.interface';\nimport { loungeFeatureKey } from './lounge.reducers';\nimport { LoungeState } from './lounge.state';\n\nexport const selectLoungeState = createFeatureSelector<LoungeState>(loungeFeatureKey);\n\nexport const selectFullLevel = createSelector(selectLoungeState, (state) => state.fullLevel);\n\nexport const selectDlpTeachersList = createSelector(selectLoungeState, (state) => state.dlpTeachersList);\n\nexport const selectSelectedTeachersList = createSelector(selectLoungeState, (state) => {\n const teachers: IUserPermissionWithSelected[] = [];\n\n state.dlpTeachersList?.forEach((x) => (x.user.selected ? teachers.push(x) : null));\n return teachers;\n});\n\nexport const selectDlpClassWithUsersList = createSelector(selectLoungeState, (state) => state.dlpClassWithStudentsList);\n\nexport const selectSelectedUsersList = createSelector(selectLoungeState, (state) => {\n const users: IUserWithSelected[] = [];\n\n state.dlpClassWithStudentsList?.forEach((x) => x.users.forEach((x) => (x.selected ? users.push(x) : null)));\n return users;\n});\n\nexport const selectDlpClassWithStudents = (\n classId: string\n): MemoizedSelector<object, IClassWithUsers | undefined, DefaultProjectorFn<IClassWithUsers | undefined>> =>\n createSelector(selectLoungeState, (state) => state.dlpClassWithStudentsList?.find((x) => x.class.id === classId));\n\nexport const selectTeamWithTeachersList = createSelector(selectLoungeState, (state) => state.teamWithTeachersList);\n\nexport const selectTeamEdit = createSelector(selectLoungeState, (state) => state.teamEdit);\n\nexport const selectTeamWithTeachers = (\n id: string\n): MemoizedSelector<object, TeamWithTeachersDto | undefined, DefaultProjectorFn<TeamWithTeachersDto | undefined>> =>\n createSelector(selectLoungeState, (state) => state.teamWithTeachersList?.find((x) => x.id === id));\n","import { combineLatest, distinctUntilKeyChanged, Observable, Unsubscribable } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\nimport { ServerInteractionStateType } from '../services/core/enums/server-interaction-state-type.enum';\nimport { serverInteractionStateLoading } from '../services/core/fixtures/server-interaction-state.fixtures';\nimport {\n initialServerInteractionState,\n ServerInteractionState,\n} from '../services/core/interfaces/server-interaction-state.interface';\n\n/**\n * Returns the current value from an observable instantly\n */\nexport function getObservableValueSync<T>(observable: Observable<T>): T {\n let returnValue: T | undefined = undefined;\n\n observable.pipe(take(1)).subscribe((data: T) => (returnValue = data));\n\n return <T>(<unknown>returnValue);\n}\n\n/**\n * Combines the given server interaction state observables to a single observable representing their collective state.\n *\n * Any error takes precedence over everything else.\n * Loading is returned if anything is loading OR some items have been loaded and some haven't yet started loaded.\n * Success is only returned once everything is loaded.\n */\nexport function combineServerInteractionStateObservables(\n observables: Observable<ServerInteractionState>[]\n): Observable<ServerInteractionState> {\n return combineLatest(observables).pipe(\n map((serverInteractionStates) => {\n const filtered = serverInteractionStates.filter((serverInteractionState) => serverInteractionState);\n const initial = filtered.filter(\n (serverInteractionState) => serverInteractionState.state === ServerInteractionStateType.INITIAL\n );\n const loading = filtered.filter(\n (serverInteractionState) => serverInteractionState.state === ServerInteractionStateType.LOADING\n );\n const success = filtered.filter(\n (serverInteractionState) => serverInteractionState.state === ServerInteractionStateType.SUCCESS\n );\n const error = filtered.filter(\n (serverInteractionState) => serverInteractionState.state === ServerInteractionStateType.ERROR\n );\n\n if (error.length > 0) {\n return error[0];\n }\n\n if (loading.length > 0) {\n return loading[0];\n }\n\n if (initial.length > 0 && success.length > 0) {\n // Fake loading state, since some items have loaded and some haven't yet started loading\n return serverInteractionStateLoading;\n }\n\n if (success.length === filtered.length) {\n return success[0];\n }\n\n return initialServerInteractionState;\n }),\n distinctUntilKeyChanged('state')\n );\n}\n\n/**\n * Unsubscribe array of Unsubscribable\n * @param args Array of Unsubscribable\n */\nexport function unsubscribe(...args: (Unsubscribable | undefined)[]): void {\n if (args) {\n args.forEach((subscription) => subscription?.unsubscribe());\n }\n}\n","import { isDevMode } from '@angular/core';\n\nexport interface IBackendUrlConfig {\n internalBackendUrlFallBack?: Function;\n loginUsingMvcDotNet?: boolean;\n internalBackendUrl?: string;\n}\n\n/** Config for API and login logic */\nexport class BackendUrlConfig implements IBackendUrlConfig {\n /** Determines the url for the backend of the project\n * @param loginUsingMvcDotNet should we use C# MVC for login or Node server?\n * @returns Url to use for API backend */\n internalBackendUrlFallBack = (loginUsingMvcDotNet?: boolean): string => {\n /** Møller made this.\n * He is unsure why typeof loginUsingMvcDotNet === 'boolean' is there */\n let loginDotNet = typeof loginUsingMvcDotNet === 'boolean' ? loginUsingMvcDotNet : this.loginUsingMvcDotNet;\n\n return isDevMode()\n ? loginDotNet\n ? 'https://localhost:44375/'\n : 'https://localhost:8081/'\n : `${window.location.origin}/`;\n };\n\n /** default is that C# MVC is used as backend */\n loginUsingMvcDotNet = true;\n\n /** default url for backend */\n internalBackendUrl = '';\n}\n","import { BackendUrlConfig } from '../../interfaces/backend-url-config.interface';\nimport { IApiServiceConfig } from './api-service-config.interface';\n\n/**\n * Urls for API's the project uses\n */\nexport class ApiServiceConfig extends BackendUrlConfig implements IApiServiceConfig {\n /** Local hostname for when contacting Umbraco */\n localHostname = '';\n\n /** Umbraco */\n apiUmbracoBaseUrl = 'https://lri-mitalineaumb-dev.azurewebsites.net/api/';\n\n /** Next */\n apiNextBaseUrl = 'https://web-next-api-dev.azurewebsites.net/api/';\n\n /** Next search */\n apiNextSearchBaseUrl = 'https://nextsearch-dev.azurewebsites.net/api/';\n\n /** Lounge */\n apiLoungeBaseUrl = 'https://lounge.dev.alineadigital.dk/api/';\n\n /** Matematikfessor BFF gateway */\n apiBFFGatewayBaseUrl = 'https://bffgateway.dev.alineadigital.dk/api/';\n}\n","export enum UserTypeEnum {\n NOT_LOGGED_IN = 'NotLoggedIn',\n LOGGED_IN = 'LoggedIn',\n ALL = 'All',\n STUDENTS = 'Student',\n TEACHERS = 'Teacher',\n}\n","import { Injectable, Optional } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { getObservableValueSync } from '../../../utils/observables';\nimport { ApiServiceConfig } from '../api/config/api-service-config';\nimport { UserTypeEnum } from '../enums/user-type.enum';\nimport { IIsbn } from './interfaces/isbn.interface';\nimport { INextToken } from './interfaces/next-token.interface';\nimport { IUser } from './interfaces/user.interface';\n\n/** Service for handling the user and user data (login, logout, status etc.) */\n@Injectable({ providedIn: 'root' })\nexport class UserService {\n /** A {@link BehaviorSubject} for handling the status of {@link loginStatus$} */\n private _loginStatus = new BehaviorSubject<boolean>(false);\n\n /** Observable for getting the login status of the user. If user is logged in returns true otherwise returns false */\n loginStatus$ = this._loginStatus.asObservable();\n\n /** A {@link BehaviorSubject} for handling the status of {@link user$} */\n private _user = new BehaviorSubject<IUser | undefined>(undefined);\n\n /** Observable for getting the logged in user. If not logged in returns undefined */\n user$ = this._user.asObservable();\n\n /** The URL for the internal backend */\n private _internalBackendUrl?: string;\n\n /** Whether or not to login using C# MVC */\n private _loginUsingMvcDotNet?: boolean;\n\n /** Handles normal DependencyInjection but also for {@link UserServiceConfig}.\n * If no config is supplied in the providers field in the module we use the default config. */\n constructor(@Optional() apiServiceConfig?: ApiServiceConfig) {\n const defaultUserServiceConfig = new ApiServiceConfig();\n\n this._loginUsingMvcDotNet =\n typeof apiServiceConfig?.loginUsingMvcDotNet === 'boolean'\n ? apiServiceConfig?.loginUsingMvcDotNet\n : defaultUserServiceConfig.loginUsingMvcDotNet;\n this._internalBackendUrl =\n apiServiceConfig?.internalBackendUrl ||\n (defaultUserServiceConfig.internalBackendUrl !== ''\n ? defaultUserServiceConfig.internalBackendUrl\n : defaultUserServiceConfig.internalBackendUrlFallBack(apiServiceConfig?.loginUsingMvcDotNet));\n }\n\n /** The userLogin method will perform a user login through the MVC project login controller. */\n login(isbn: string = ''): void {\n const href = this._loginUsingMvcDotNet\n ? `${this._internalBackendUrl}login/login?returnUrl=${this.returnUrl}`\n : `${this._internalBackendUrl}auth/login?returnUrl=${this.returnUrl}&isbn=${isbn}`;\n\n window.location.replace(href);\n }\n\n /** The userLogin method will perform a user logout through the MVC project login controller. */\n logout(): void {\n localStorage.removeItem('token');\n const href = this._loginUsingMvcDotNet\n ? `${this._internalBackendUrl}login/beginlogout?returnUrl=${this.returnUrl}`\n : `${this._internalBackendUrl}authorize/logoff?returnUrl=${this.returnUrl}`;\n\n window.location.replace(href);\n }\n\n /** Will set the user as undefined */\n removeUser(): void {\n this._user.next(undefined);\n this._loginStatus.next(false);\n }\n\n /** Sets the user if input is correct otherwise removes user */\n setUser(user: IUser): void {\n if (user?.userId && user.userId !== '00000000-0000-0000-0000-000000000000') {\n this._user.next(user);\n this._loginStatus.next(true);\n } else {\n this.removeUser();\n this._loginStatus.next(false);\n }\n }\n\n /** Sets the ISBNs if user is logged in */\n setISBNs(isbns: IIsbn[]): void {\n if (this.user) {\n this.user.isbns = isbns;\n this._user.next(this.user);\n }\n }\n\n /** Sets the {@link INextToken} and applies values to {@link IUser.accessToken} and {@link IUser.expiresAt} */\n setToken(token: INextToken): void {\n if (this.user) {\n this.user.accessToken = token.AccessToken;\n this.user.expiresAt = token.AccessTokenExpiresAt;\n this._user.next(this.user);\n }\n }\n\n /* get helpers */\n\n /** Retrieves the user and returns undefined if not logged in */\n get user(): IUser | undefined {\n return getObservableValueSync(this.user$);\n }\n\n /** Retrieves the user type\n * @example\n * UserTypeEnum.TEACHERS\n * UserTypeEnum.STUDENTS\n * UserTypeEnum.NOT_LOGGED_IN */\n get userType(): string {\n if (this.user) {\n if (this.user.isTeacher) {\n return UserTypeEnum.TEACHERS;\n } else {\n return UserTypeEnum.STUDENTS;\n }\n } else {\n return UserTypeEnum.NOT_LOGGED_IN;\n }\n }\n\n /** Retrieves if we shouldn't track the user if logged in */\n get doNotTrack(): boolean {\n if (this.user) {\n return this.user?.doNotTrack;\n } else {\n return false;\n }\n }\n\n /** Checks if user is logged in */\n get isLoggedIn(): boolean {\n return this.user ? true : false;\n }\n\n /** Checks if user is a student if logged in */\n get isStudent(): boolean {\n return this.userType === UserTypeEnum.STUDENTS;\n }\n\n /** Checks if user is a teacher if logged in */\n get isTeacher(): boolean {\n return this.userType === UserTypeEnum.TEACHERS;\n }\n\n /** Checks if user is an Alinea user if logged in */\n get isAlineaUser(): boolean {\n if (this.user) {\n return this.user.isAlineaUser ? true : false;\n } else {\n return false;\n }\n }\n\n /** Retrieves the authentication token from the user if logged in */\n get authenticationToken(): string | undefined {\n if (this.user) {\n return this.user.authenticationToken;\n } else {\n return;\n }\n }\n\n /** Retrieves the access token from the user if logged in */\n get accessToken(): string | undefined {\n if (this.user) {\n return this.user.accessToken;\n } else {\n return;\n }\n }\n\n /** Retrieves the expires at from the user if logged in */\n get expiresAt(): string | undefined | number {\n if (this.user) {\n return this.user.expiresAt;\n } else {\n return;\n }\n }\n\n /** Retrieves the context identifier from the user if logged in */\n get contextIdentifier(): string | undefined {\n if (this.user) {\n return this.user.contextIdentifier;\n } else {\n return;\n }\n }\n\n /** Retrieves the institution number from the user if logged in */\n get institutionNumber(): string | undefined {\n if (this.user) {\n return this.user.institutionNumber;\n } else {\n return;\n }\n }\n\n /** Retrieves the user id from the user if logged in */\n get userId(): string | undefined {\n if (this.user) {\n return this.user.userId;\n } else {\n return;\n }\n }\n\n /** Retrieves the display name from the user if logged in */\n get displayName(): string | undefined {\n if (this.user) {\n return this.user.displayName;\n } else {\n return;\n }\n }\n\n /** Retrieves the institution name from the user if logged in */\n get institutionName(): string | undefined {\n if (this.user) {\n return this.user.institutionName;\n } else {\n return;\n }\n }\n\n /** Retrieves the initials from the user if logged in */\n get initials(): string | undefined {\n if (this.user) {\n return this.user.initials;\n } else {\n return;\n }\n }\n\n /** Retrieves the isbns from the user if logged in */\n get isbns(): IIsbn[] | undefined {\n if (this.user) {\n return this.user.isbns;\n } else {\n return [];\n }\n }\n\n /** Retrieves the institution id from the user if logged in */\n get institutionId(): string | undefined {\n if (this.user) {\n return this.user.institutionId;\n } else {\n return;\n }\n }\n\n /** Retrieves the url to return to after redirecting after login or logout */\n private get returnUrl(): string {\n const querystring = new URLSearchParams(window.location.search);\n\n querystring.delete('returnUrl');\n const q = querystring.toString() !== '' ? '?' + querystring.toString() : '';\n\n return `${window.location.origin}${window.location.pathname}${q}`;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { debounce } from 'throttle-debounce';\nimport { UserService } from '../core/user/user.service';\nimport { GTMJS } from './gtm-events.const';\nimport { GTMProperties } from './gtm-properties.interface';\nimport { GTMTag } from './gtm-tag.interface';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class GoogleTagManagerService {\n private id?: string;\n private isLoaded = false;\n private debouncedFunc = debounce(1500, (event: string, properties?: GTMProperties) =>\n this.pushTagWithUserType(event, properties)\n );\n\n constructor(private userService: UserService) {}\n\n pushTagWithUserType(event: string, properties?: GTMProperties): void {\n let obj = {\n event: event,\n visitorType: this.userService.userType,\n };\n\n if (properties) {\n obj = { ...obj, ...properties };\n }\n\n this.pushTag(obj);\n }\n\n pushDebouncedTagWithUserType(event: string, properties?: GTMProperties): void {\n this.debouncedFunc(event, properties);\n }\n\n setId(id: string): void {\n this.id = id;\n }\n\n addToDOM(): void {\n if (this.isLoaded || !this.id) {\n return;\n }\n\n const doc = this.browserGlobals.documentRef();\n\n this.pushOnDataLayer({\n 'gtm.start': new Date().getTime(),\n event: GTMJS,\n });\n\n const script = doc.createElement('script');\n\n script.id = 'GTMscript';\n script.async = true;\n script.src = `https://www.googletagmanager.com/gtm.js?id=${this.id}`;\n\n doc.head.insertBefore(script, doc.head.firstChild);\n this.isLoaded = true;\n }\n\n pushTag(tag: GTMTag): void {\n if (!this.isLoaded) {\n this.addToDOM();\n }\n\n this.pushOnDataLayer(tag);\n }\n\n private pushOnDataLayer(obj: GTMTag): void {\n const dataLayer = this.getDataLayer();\n\n dataLayer.push(obj);\n }\n\n private browserGlobals = {\n windowRef() {\n return window;\n },\n documentRef() {\n return document;\n },\n };\n\n private getDataLayer(): object[] {\n const window = this.browserGlobals.windowRef();\n\n window.dataLayer = window.dataLayer || [];\n return window.dataLayer;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Store } from '@ngrx/store';\nimport { distinctUntilChanged, map, Observable, share, tap, withLatestFrom } from 'rxjs';\nimport { UserService } from '../../../services/core/user/user.service';\nimport { GoogleTagManagerService } from '../../../services/gtm/google-tag-manager.service';\nimport { LoungeEditTeacher } from '../../../services/gtm/gtm-events.const';\nimport { SharedLoadingKeys } from '../../../services/loading/shared-loading-keys.enums';\nimport { FullLevelDto } from '../interfaces/endpoint/dtos/dto-level.interface';\nimport { TeamWithTeachersDto } from '../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { AddTeacher, ILoungePostBodyTeam_CreateTeam } from '../interfaces/endpoint/team.interface';\nimport { IClassWithUsers, ITeamEdit, IUserPermissionWithSelected } from '../store/interfaces/team-edit.interface';\nimport * as LoungeActions from '../store/lounge.actions';\nimport * as LoungeSelectors from '../store/lounge.selectors';\nimport { LoungeState } from '../store/lounge.state';\n\n/** Service for handling data between application and Lounge API */\n@Injectable({ providedIn: 'root' })\nexport class LoungeService {\n /** Retrieve full level from the store and if nothing is found send a request to retrieve it from API */\n fullLevel$: Observable<FullLevelDto | undefined> = this.loungeStore.select(LoungeSelectors.selectFullLevel).pipe(\n share(),\n distinctUntilChanged(),\n tap((x) => {\n if (!x) {\n this.loungeStore.dispatch(LoungeActions.levelLoadLevels({ loadingKey: SharedLoadingKeys.fullLevel }));\n }\n })\n );\n\n /** Retrieve selected teachers from the store */\n selectedTeachersList$ = this.loungeStore.select(LoungeSelectors.selectSelectedTeachersList);\n\n /** Retrieve teachers from the store without current user and if nothing is found send a request to retrieve it from the API */\n dlpTeachersListWithoutCurrentUser$: Observable<IUserPermissionWithSelected[] | undefined> = this.loungeStore\n .select(LoungeSelectors.selectDlpTeachersList)\n .pipe(\n share(),\n distinctUntilChanged(),\n tap((x) => {\n if (!x) {\n this.dlpLoadTeachers(SharedLoadingKeys.teachers);\n }\n }),\n withLatestFrom(this.userService.user$),\n map(([data, user]) => data?.filter((t) => t.user.id !== user?.userId))\n );\n\n /** Retrieve selected users from the store */\n selectedUsersList$ = this.loungeStore.select(LoungeSelectors.selectSelectedUsersList);\n\n /** Retrieve classes with students from the store and if nothing is found send a request to retrieve it from the API */\n dlpClassWithStudentsList$: Observable<IClassWithUsers[] | undefined> = this.loungeStore\n .select(LoungeSelectors.selectDlpClassWithUsersList)\n .pipe(\n share(),\n distinctUntilChanged(),\n tap((x) => {\n if (!x) {\n this.dlpLoadClassesWithStudents(SharedLoadingKeys.dlpClasses);\n }\n })\n );\n\n /** Retrieve teams with teachers from the store and if nothing is found send a request to retrieve it from the API */\n teamTeamWithTeachersList$: Observable<TeamWithTeachersDto[] | undefined> = this.loungeStore\n .select(LoungeSelectors.selectTeamWithTeachersList)\n .pipe(\n share(),\n distinctUntilChanged(),\n tap((x) => {\n if (!x) {\n this.teamLoadTeams(SharedLoadingKeys.teams);\n }\n })\n );\n\n /** Retrieve the current team under edit mode from the store */\n teamEdit$: Observable<ITeamEdit | undefined> = this.loungeStore.select(LoungeSelectors.selectTeamEdit);\n\n /** Dispatch an action to load classes with students from the API to the store\n * @param loadingKey */\n private dlpLoadClassesWithStudents(loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.dlpLoadClassesWithStudents({ loadingKey }));\n }\n\n /** Dispatch an action to load teachers from the API to the store\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n dlpLoadTeachers(loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.dlpLoadTeachers({ loadingKey }));\n }\n\n /** Dispatch an action to mark the student for selection in the store\n * @param classId The id of the student's class\n * @param studentId The id of the student to mark\n * @param checked The checked status of the selection */\n markStudentForSelection(classId: string, studentId: string, checked: boolean): void {\n this.loungeStore.dispatch(LoungeActions.markStudentForSelection({ classId, userId: studentId, selected: checked }));\n }\n\n /** Dispatch an action to mark the class (and all students that are valid according to the searchTerm) for selection in the store\n * @param classId The id of the class to mark\n * @param checked The checked status of the selection\n * @param searchTerm The searchTerm from the user input so only students that apply to the searchTerm will be checked */\n markClassForSelection(classId: string, checked: boolean, searchTerm: string): void {\n this.loungeStore.dispatch(LoungeActions.markClassForSelection({ classId, selected: checked, searchTerm }));\n }\n\n /** Dispatch an action to mark the teacher for selection in the store\n * @param teacherId The id of the teacher to mark\n * @param checked The checked status of the selection */\n markTeacherForSelection(teacherId: string, checked: boolean): void {\n this.loungeStore.dispatch(LoungeActions.markTeacherForSelection({ teacherId, selected: checked }));\n }\n\n /** Unmark all selected students in the store */\n removeStudentsFromSelection(): void {\n this.loungeStore.dispatch(LoungeActions.removeSelectionsFromStudents());\n }\n\n /** Unmark all selected teachers in the store */\n removeTeachersFromSelection(): void {\n this.loungeStore.dispatch(LoungeActions.removeSelectionsFromTeachers());\n }\n\n /** Dispatch an action to save teachers to a team\n * @param teamId The id of the team to add the teachers to\n * @param teachers List of one or more teachers to add to the team\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamSaveTeachersToTeam(teamId: string, teachers: AddTeacher[], loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamAddTeachers({ teamId, teachers, loadingKey }));\n }\n\n /** Dispatch an action to save students to a team\n * @param teamId The id of the team to add the students to\n * @param studentIds List of one or more student ids to add to the team\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamSaveStudentsToTeam(teamId: string, studentIds: string[], loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamSaveStudentsToTeam({ teamId, studentIds, loadingKey }));\n }\n\n /** Dispatch an action to save details to a team\n * @param teamId The id of the team to save the details to\n * @param title The new title to add to the team\n * @param levelIds Combined list of ids from all the levels that should be on the team.\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamSaveDetailsToTeam(teamId: string, title: string, levelIds: string[], loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamSaveDetailsToTeam({ teamId, title, levelIds, loadingKey }));\n }\n\n /** Dispatch an action to load all teams from the API\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamLoadTeams(loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamLoadTeams({ loadingKey }));\n }\n\n /** Navigates by adding '?edit=' + the team id to the end of the URL.\n * @param team The team to navigate to */\n teamEditNavigate(team: TeamWithTeachersDto): void {\n this.router.navigateByUrl(window.location.pathname + '?edit=' + team.id);\n }\n\n /** Dispatch an action to cancel the editing of the team */\n teamEditCancel(): void {\n this.loungeStore.dispatch(LoungeActions.teamEditTeamCancel());\n }\n\n /** Dispatch an action to load and fill the store with already selected students from the team so we're ready to display them in the UI */\n teamEditAssignStudents(): void {\n this.loungeStore.dispatch(LoungeActions.teamEditAssignStudents());\n }\n\n /** Dispatch an action to load and fill the store with already selected teachers from the team so we're ready to display them in the UI\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamEditAssignTeachers(loadingKey: string): void {\n this.gtmService.pushTagWithUserType(LoungeEditTeacher);\n this.loungeStore.dispatch(LoungeActions.teamEditAssignTeachers({ loadingKey }));\n }\n\n /** Dispatch an action to display the delete team modal */\n teamDeleteModal(): void {\n this.loungeStore.dispatch(LoungeActions.teamDeleteModal());\n }\n\n /** Dispatch an action to delete the team\n * @param teamId id of the team to delete\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamDelete(teamId: string, loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamDeleteTeam({ teamId, loadingKey }));\n }\n\n /** Dispatch an action to create a team\n * @param team the team to create\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamCreate(team: ILoungePostBodyTeam_CreateTeam, loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamCreateTeam({ team, loadingKey }));\n }\n\n /** Dispatch an action to open the edit details of team modal */\n teamEditDetailsModal(): void {\n this.loungeStore.dispatch(LoungeActions.teamEditDetailsModal());\n }\n\n /** Dispatch an action to open the remove yourself from the team modal */\n teamRemoveTeacherSelfModal(): void {\n this.loungeStore.dispatch(LoungeActions.teamRemoveTeacherSelfModal());\n }\n\n /** Dispatch an action to remove the current user from the team\n * @param team the team to remove the current user from\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamRemoveTeacherSelf(team: TeamWithTeachersDto, loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamRemoveTeacherSelf({ team, loadingKey }));\n }\n\n /** Dispatch an action to add a single teacher to a team\n * @param teamId the id of the team to add the teacher to\n * @param teacher the teacher to add to the team\n * @param loadingKey The key used for checking and changing status of the UI loading component\n * @deprecated Should probably be removed and be replaced by just using the {@link teamSaveTeachersToTeam} */\n teamAddTeacher(teamId: string, teacher: AddTeacher, loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamAddTeacher({ teamId, teacher, loadingKey }));\n }\n\n /** Dispatch an action to load a team for editing\n * @param teamId id of the team to load\n * @param loadingKey The key used for checking and changing status of the UI loading component */\n teamLoadSingleTeamForEdit(teamId: string, loadingKey: string): void {\n this.loungeStore.dispatch(LoungeActions.teamLoadSingleTeamForEdit({ teamId, loadingKey }));\n }\n\n /** @ignore */\n constructor(\n private loungeStore: Store<LoungeState>,\n private router: Router,\n private userService: UserService,\n private gtmService: GoogleTagManagerService\n ) {}\n}\n","import { createAction, props } from '@ngrx/store';\n\nexport interface ErrorWithLoadingKey {\n error: Error;\n loadingKey: string;\n}\n\nconst modulePrefix = '[LoadingModule]';\n\nexport const startLoading = createAction(`${modulePrefix} Start load`, props<{ loadingKey: string }>());\n\nexport const finishLoading = createAction(`${modulePrefix} Stop load`, props<{ loadingKey: string }>());\n\nexport const loadFailed = createAction(`${modulePrefix} Load failed`, props<ErrorWithLoadingKey>());\n","import { createReducer, on } from '@ngrx/store';\nimport {\n levelLoadLevels,\n levelLoadLevelsSuccess,\n levelLoadLevelsFailure,\n dlpLoadClassesWithStudentsFailure,\n dlpLoadTeachersFailure,\n teamAddTeacherFailure,\n teamAddTeachersFailure,\n teamCreateTeamFailure,\n teamDeleteTeamFailure,\n teamEditDetailsFailure,\n teamLoadSingleTeamForEditFailure,\n teamLoadStudentsFailure,\n teamLoadTeamsFailure,\n teamRemoveTeacherSelfFailure,\n teamSaveDetailsToTeamFailure,\n teamSaveStudentsToTeamFailure,\n teamLoadTeams,\n teamLoadTeamsSuccess,\n dlpLoadClassesWithStudents,\n dlpLoadClassesWithStudentsSuccess,\n teamCreateTeam,\n teamCreateTeamSuccess,\n teamEditAssignTeachers,\n teamEditAssignTeachersSuccess,\n teamAddTeachers,\n teamAddTeachersSuccess,\n teamLoadStudents,\n teamLoadStudentsSuccess,\n teamSaveDetailsToTeam,\n teamSaveDetailsToTeamSuccess,\n teamLoadSingleTeamForEdit,\n teamEditTeam,\n teamSaveStudentsToTeam,\n teamSaveStudentsToTeamSuccess,\n} from '../../../modules/lounge/store/lounge.actions';\nimport { startLoading, finishLoading, loadFailed } from './loading.actions';\n\nimport { initialLoadingState, LoadingState, LoadStateEnum } from './loading.state';\n\nexport const loadingFeatureKey = 'loadingState';\n\n// Add actions to this list that should automatically start loading. Actions needs to have \"loadingKey: string\" in their props.\nconst actionsThatStartLoad = [\n levelLoadLevels,\n teamLoadTeams,\n dlpLoadClassesWithStudents,\n teamCreateTeam,\n teamEditAssignTeachers,\n teamAddTeachers,\n teamLoadStudents,\n teamSaveDetailsToTeam,\n teamLoadSingleTeamForEdit,\n teamSaveStudentsToTeam,\n];\n\n// Add actions to this list that should automatically finish loading. Actions needs to have \"loadingKey: string\" in their props.\nconst actionsThatFinishLoad = [\n levelLoadLevelsSuccess,\n teamLoadTeamsSuccess,\n dlpLoadClassesWithStudentsSuccess,\n teamCreateTeamSuccess,\n teamEditAssignTeachersSuccess,\n teamAddTeachersSuccess,\n teamLoadStudentsSuccess,\n teamSaveDetailsToTeamSuccess,\n teamEditTeam,\n teamSaveStudentsToTeamSuccess,\n];\n\n// Add actions to this list that should automatically add the returned error to the store. Actions needs to have \"loadingKey: string\" and \"error: Error\" in their props.\nexport const actionsThatError = [\n levelLoadLevelsFailure,\n dlpLoadTeachersFailure,\n dlpLoadClassesWithStudentsFailure,\n teamLoadTeamsFailure,\n teamCreateTeamFailure,\n teamLoadStudentsFailure,\n teamSaveStudentsToTeamFailure,\n teamDeleteTeamFailure,\n teamEditDetailsFailure,\n teamSaveDetailsToTeamFailure,\n teamRemoveTeacherSelfFailure,\n teamAddTeacherFailure,\n teamAddTeachersFailure,\n teamLoadSingleTeamForEditFailure,\n];\n\nexport const loadingReducer = createReducer(\n initialLoadingState,\n on(startLoading, ...actionsThatStartLoad, (state, action) =>\n assignCallStateToState(state, action.loadingKey, LoadStateEnum.LOADING)\n ),\n on(finishLoading, ...actionsThatFinishLoad, (state, action) =>\n assignCallStateToState(state, action.loadingKey, LoadStateEnum.LOADED)\n ),\n on(loadFailed, ...actionsThatError, (state, action) => assignCallStateToState(state, action.loadingKey, action.error))\n);\n\nfunction assignCallStateToState(\n state: LoadingState,\n loadingKey: string,\n callState: LoadStateEnum | Error\n): LoadingState {\n const newCallStates = state.callStates.filter((x) => x.loadingKey !== loadingKey);\n\n return {\n ...state,\n callStates: [...newCallStates, { loadingKey, callState }],\n };\n}\n","/**\n * loading store\n */\nexport interface LoadingState {\n callStates: CallStateWithInstance[];\n}\n\n/**\n * loading store\n */\nexport const initialLoadingState: LoadingState = {\n callStates: [],\n};\n\n/**\n * loading store\n */\nexport interface CallStateWithInstance {\n loadingKey: string;\n callState: LoadStateEnum | Error;\n}\n\n/**\n * loading store\n */\nexport const enum LoadStateEnum {\n INIT = 'INIT',\n LOADING = 'LOADING',\n LOADED = 'LOADED',\n}\n","import { createFeatureSelector, createSelector, DefaultProjectorFn, MemoizedSelector } from '@ngrx/store';\nimport { loadingFeatureKey } from './loading.reducers';\nimport { LoadingState, LoadStateEnum } from './loading.state';\n\nconst selectLoadingState = createFeatureSelector<LoadingState>(loadingFeatureKey);\n\nconst selectLoadState = (\n loadingKey: string\n): MemoizedSelector<object, LoadStateEnum | undefined, DefaultProjectorFn<LoadStateEnum | undefined>> =>\n createSelector(selectLoadingState, (state) => {\n const callState = state.callStates.find((x) => x.loadingKey === loadingKey)?.callState;\n\n if (!callState || (callState as Error).message !== undefined) {\n return undefined;\n }\n\n return callState as LoadStateEnum;\n });\n\nexport const selectInit = (loadingKey: string): MemoizedSelector<object, boolean, DefaultProjectorFn<boolean>> =>\n createSelector(selectLoadState(loadingKey), (state) => state === LoadStateEnum.INIT);\n\nexport const selectLoading = (loadingKey: string): MemoizedSelector<object, boolean, DefaultProjectorFn<boolean>> =>\n createSelector(selectLoadState(loadingKey), (state) => state === LoadStateEnum.LOADING);\n\nexport const selectLoaded = (loadingKey: string): MemoizedSelector<object, boolean, DefaultProjectorFn<boolean>> =>\n createSelector(selectLoadState(loadingKey), (state) => state === LoadStateEnum.LOADED);\n\nexport const selectError = (\n loadingKey: string\n): MemoizedSelector<object, string | undefined, DefaultProjectorFn<string | undefined>> =>\n createSelector(selectLoadingState, (state) => {\n const callState = state.callStates.find((x) => x.loadingKey === loadingKey)?.callState;\n\n if ((callState as Error)?.message !== undefined) {\n return (callState as Error).message;\n }\n\n return undefined;\n });\n","import { Injectable } from '@angular/core';\nimport { Store } from '@ngrx/store';\nimport { Observable } from 'rxjs';\nimport { startLoading, finishLoading } from './store/loading.actions';\nimport { selectError, selectInit, selectLoaded, selectLoading } from './store/loading.selectors';\nimport { LoadingState } from './store/loading.state';\n\n/** Service for handling loading and check state of specific loading. */\n@Injectable({\n providedIn: 'root',\n})\nexport class LoadingService {\n /**\n * @ignore\n */\n constructor(private store: Store<LoadingState>) {}\n\n /** Check if loading is in initialization state.\n * @param loadingKey Key that is used for saving and retrieving the specific loading state.\n * @returns true if loading is in the status of initialization, false if not. */\n init$ = (loadingKey: string): Observable<boolean> => this.store.select(selectInit(loadingKey));\n /** Check if loading is in loading state.\n * @param loadingKey Key that is used for saving and retrieving the specific loading state.\n * @returns true if loading is in the status of loading, false if not. */\n loading$ = (loadingKey: string): Observable<boolean> => this.store.select(selectLoading(loadingKey));\n /** Check if loaded is in loaded state.\n * @param loadingKey Key that is used for saving and retrieving the specific loading state.\n * @returns true if loading is in the status of loaded, false if not. */\n loaded$ = (loadingKey: string): Observable<boolean> => this.store.select(selectLoaded(loadingKey));\n /** Retrieve error if loading has failed\n * @param loadingKey Key that is used for saving and retrieving the specific loading state.\n * @returns a string with the error. If loading hasn't failed then it will return undefined. */\n error$ = (loadingKey: string): Observable<string | undefined> => this.store.select(selectError(loadingKey));\n\n /** Starts the specific loading and sets the status to loading state.\n * @param loadingKey Key that is used for saving and retrieving the specific loading state. */\n start(loadingKey: string): void {\n this.store.dispatch(startLoading({ loadingKey }));\n }\n\n /** Stops the specific loading and sets the status to loaded state.\n * @param loadingKey Key that is used for saving and retrieving the specific loading state. */\n stop(loadingKey: string): void {\n this.store.dispatch(finishLoading({ loadingKey }));\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\n\ntype theme = 'primary-student' | 'primary-teacher';\n\n/** Lounge box */\n@Component({\n selector: 'lru-box',\n templateUrl: './box.component.html',\n styleUrls: ['./box.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BoxComponent {\n /** what kind of box should it be? Different colors for teacher/student */\n @Input() theme: theme = 'primary-teacher';\n\n /** If hollow then the color is applied to a border instead of the background of the box */\n @Input() hollow: boolean = false;\n}\n","<div class=\"box\" [attr.data-theme]=\"theme\" [attr.data-hollow]=\"hollow\">\n <div class=\"box__header\">\n <ng-content select=\"[header]\"></ng-content>\n </div>\n <div class=\"box__content\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n</div>\n","/** Enum for different pages of the Lounge modal */\nexport enum LoungeModalPages {\n none,\n studentPicker,\n detailsInput,\n shareWithTeachers,\n deleteTeam,\n removeTeacherSelf,\n}\n","/**\n * counter ensures that each id becomes unique since the same number wont be used twice\n */\nlet counter = 0;\n\n/**\n * generates a custom unique id\n * @param prefix id prefix\n * @returns custom unique id\n */\nexport function createUniqueId(prefix?: string): string {\n return `${prefix || 'uuid'}-${counter++}`;\n}\n","import { createAction, props } from '@ngrx/store';\nimport { ToastMessageInstance } from '../interfaces/toast-message-instance.interface';\nimport { IToastConfig } from '../toast-config.interface';\n\nconst modulePrefix = '[ToastModule]';\n\nexport const addMessage = createAction(`${modulePrefix} Add message`, props<{ message: ToastMessageInstance }>());\n\nexport const updateMessage = createAction(\n `${modulePrefix} Update message`,\n props<{ message: ToastMessageInstance; ignoreTiming?: boolean }>()\n);\n\nexport const removeMessage = createAction(`${modulePrefix} Remove message`, props<{ id: string }>());\n\nexport const pauseMessageExpiration = createAction(`${modulePrefix} Pause message expiration`);\n\nexport const continueMessageExpiration = createAction(`${modulePrefix} Continue message expiration`);\n\nexport const initializeMessageTimeout = createAction(\n `${modulePrefix} Initialize message timeout`,\n props<{ message: ToastMessageInstance }>()\n);\n\nexport const clearMessageTimeout = createAction(\n `${modulePrefix} Clear message timeout`,\n props<{ message: ToastMessageInstance }>()\n);\n\nexport const setConfig = createAction(`${modulePrefix} Set config`, props<{ config: IToastConfig }>());\n","import { createReducer, on } from '@ngrx/store';\nimport { addMessage, removeMessage, setConfig, updateMessage } from './toast.actions';\nimport { initialToastState } from './toast.state';\n\nexport const toastFeatureKey = 'toastState';\n\nexport const toastReducer = createReducer(\n initialToastState,\n on(addMessage, (state, action) => {\n return {\n ...state,\n messages: [...state.messages, action.message],\n };\n }),\n on(updateMessage, (state, action) => {\n const messages = [...state.messages];\n const currentIndex = messages.findIndex((message) => message.id === action.message.id);\n\n if (currentIndex !== -1) {\n messages[currentIndex] = { ...action.message };\n }\n\n return {\n ...state,\n messages,\n };\n }),\n on(removeMessage, (state, action) => {\n const messages = state.messages.filter((message) => message.id !== action.id);\n\n return { ...state, messages: messages };\n }),\n on(setConfig, (state, action) => {\n return {\n ...state,\n config: action.config,\n };\n })\n);\n","import { ToastMessageInstance } from '../interfaces/toast-message-instance.interface';\nimport { IToastConfig } from '../toast-config.interface';\n\nexport interface ToastState {\n config: IToastConfig;\n messages: ToastMessageInstance[];\n}\n\nexport const initialToastState: ToastState = {\n // The messages are stored in an array and new messages are always added to\n // the end of the array to maintain consistency when displaying them.\n messages: [],\n config: {},\n};\n","import { createFeatureSelector, createSelector } from '@ngrx/store';\nimport { toastFeatureKey } from './toast.reducers';\nimport { ToastState } from './toast.state';\n\nexport const selectToastState = createFeatureSelector<ToastState>(toastFeatureKey);\n\nexport const selectAllMessages = createSelector(selectToastState, (state) => state.messages);\n\nexport const selectConfig = createSelector(selectToastState, (state) => state.config);\n","import { IToastConfig } from './toast-config.interface';\nimport { toastHorizontalPosition, toastVerticalPosition } from './toast-types';\n\n/**\n * Settings for toast popups\n */\nexport class ToastConfig implements IToastConfig {\n /** Where on the horizontal line of the window should toasts be displayed? */\n horizontalPosition: toastHorizontalPosition = 'right';\n\n /** Where on the vertical line of the window should toasts be displayed? */\n verticalPosition: toastVerticalPosition = 'bottom';\n\n /** When should toast messages go away? */\n durationInMilliseconds = 5000;\n\n /** How many pixels space should there be between toast messages? */\n spacingBetweenToasts = 20;\n\n /** How many pixels space should there be from toasts to the browser window? */\n spacingFromWindow = 20;\n\n /** Data-attribute to make it easier to add custom styling */\n variant = undefined;\n}\n","import { Injectable, Optional } from '@angular/core';\nimport { Store } from '@ngrx/store';\nimport { getObservableValueSync } from '../../../utils/observables';\nimport { createUniqueId } from '../../../utils/uuid';\nimport { ZIndexService } from '../../z-index/services/z-index.service';\nimport { ToastMessageInstance } from '../interfaces/toast-message-instance.interface';\nimport { ToastMessage } from '../interfaces/toast-message.interface';\nimport * as ToastActions from '../store/toast.actions';\nimport { addMessage, continueMessageExpiration, pauseMessageExpiration, removeMessage } from '../store/toast.actions';\nimport { selectAllMessages, selectConfig } from '../store/toast.selectors';\nimport { ToastState } from '../store/toast.state';\nimport { ToastConfig } from '../toast-config';\n\n/** A service for handling toast messages */\n@Injectable({ providedIn: 'root' })\nexport class ToastService {\n /** Observable of all toast messages */\n public messages$ = this.toastStore.select(selectAllMessages);\n /** Observable of ToastConfig */\n public config$ = this.toastStore.select(selectConfig);\n\n /** Handles DependencyInjection and dispatching of either incoming or default config */\n constructor(\n private toastStore: Store<ToastState>,\n private zIndexService: ZIndexService,\n @Optional() private config?: ToastConfig\n ) {\n const defaultConfig = new ToastConfig();\n\n this.toastStore.dispatch(\n ToastActions.setConfig({\n config: {\n horizontalPosition: this.config?.horizontalPosition ?? defaultConfig.horizontalPosition,\n verticalPosition: this.config?.verticalPosition ?? defaultConfig.verticalPosition,\n durationInMilliseconds: this.config?.durationInMilliseconds ?? defaultConfig.durationInMilliseconds,\n spacingBetweenToasts: this.config?.spacingBetweenToasts ?? defaultConfig.spacingBetweenToasts,\n spacingFromWindow: this.config?.spacingFromWindow ?? defaultConfig.spacingFromWindow,\n variant: this.config?.variant ?? defaultConfig.variant,\n },\n })\n );\n }\n\n /** Displays the given toast message and returns the ID created to represent the message.\n * @param message either a string or configured {@link ToastMessage} object\n * @returns ID that represent the created message */\n public displayMessage(message: string | ToastMessage): string {\n this.zIndexService.setItem('felib-toast');\n if (typeof message === 'string') {\n message = { message: message, type: 'info', canDismiss: true };\n }\n\n const preparedMessage = this.prepareMessageForStore(message);\n\n this.toastStore.dispatch(addMessage({ message: preparedMessage }));\n\n return preparedMessage.id;\n }\n\n /** Dispatches an action to remove the specific message\n * @param id the id of the specific message to remove */\n public removeMessage(id: string): void {\n this.toastStore.dispatch(removeMessage({ id }));\n }\n\n /** Dispatches an action to pause all message expirations */\n public pause(): void {\n this.toastStore.dispatch(pauseMessageExpiration());\n }\n\n /** Dispatches an action to continue all message expirations */\n public continue(): void {\n this.toastStore.dispatch(continueMessageExpiration());\n }\n\n /** Prepares the message for the store by adding specific icons and colors dependent on the specific type of message\n * @param message The message to prepare for the store\n * @returns A {@link ToastMessageInstance} object created from the param. */\n private prepareMessageForStore(message: ToastMessage): ToastMessageInstance {\n const id = createUniqueId('toast-message');\n\n if (!message.icon) {\n if (message.type === 'success') {\n message.icon = {\n path: 'felib-validation-true-icon',\n colors: {\n color: 'white',\n },\n };\n } else if (message.type === 'info') {\n message.icon = {\n path: 'felib-check',\n };\n } else if (message.type === 'warning') {\n message.icon = {\n path: 'felib-check',\n };\n } else if (message.type === 'error') {\n message.icon = {\n path: 'felib-validation-false-icon',\n colors: {\n color: 'white',\n },\n };\n }\n }\n\n let messageInstance: ToastMessageInstance = { ...message, id: id, icon: message.icon };\n\n if (messageInstance.duration === undefined) {\n messageInstance.duration = getObservableValueSync(this.config$).durationInMilliseconds!;\n }\n\n return messageInstance;\n }\n}\n","import { Injectable } from '@angular/core';\nimport {\n BehaviorSubject,\n combineLatest,\n distinctUntilChanged,\n filter,\n firstValueFrom,\n share,\n Subject,\n tap,\n} from 'rxjs';\nimport { UserService } from '../../../services/core/user/user.service';\nimport { ToastService } from '../../toast/services/toast.service';\nimport { LoungeModalPages } from '../enums/lounge-modal-pages.enum';\nimport { LoungeService } from './lounge.service';\n\n/** Service for handling modals like page, active status and the height of the modal */\n@Injectable({ providedIn: 'root' })\nexport class LoungeModalService {\n /** Property used for checking if the modal should be visible */\n modalActive = false;\n\n /** {@link BehaviorSubject} used for storing the current page that should be shown in the modal */\n private page = new BehaviorSubject<LoungeModalPages>(LoungeModalPages.none);\n\n /** Used for getting the current {@link LoungeModalPages} page of the team create / edit flow.\n * Also handles changing the modal height so it matches page and clearing students and teacher selections */\n page$ = this.page.pipe(\n distinctUntilChanged(),\n tap((page) => {\n this.modalHeight.next(this.pageToModalHeight(page));\n\n if (page === LoungeModalPages.none) {\n this.loungeService.removeStudentsFromSelection();\n this.loungeService.removeTeachersFromSelection();\n\n this.modalActive = false;\n } else {\n this.modalActive = true;\n }\n }),\n share({ resetOnRefCountZero: true })\n );\n\n /** {@link Subject} used for storing values for {@link modalHeight$} */\n private modalHeight = new Subject<string>();\n\n /** Used for getting the height for the modal. Calculated from {@link LoungeModalPages} */\n modalHeight$ = this.modalHeight.pipe(share({ resetOnRefCountZero: true }));\n\n /** Changes page. */\n async setPage(page: LoungeModalPages): Promise<void> {\n if (page === LoungeModalPages.removeTeacherSelf) {\n (await this.allowRemoveYourself()) ? this.page.next(page) : null;\n } else {\n this.page.next(page);\n }\n }\n\n /** Method for setting {@link page$} to {@link LoungeModalPages.none} */\n setPageToNone(): void {\n this.page.next(LoungeModalPages.none);\n }\n\n /** @ignore */\n constructor(\n private loungeService: LoungeService,\n private toastService: ToastService,\n private userService: UserService\n ) {}\n\n /** Converts a specific page to a string containing the specific height that is ideal for a modal window containing that specific page\n * @param page The page to convert to height\n * @returns String containing a height in pixels */\n private pageToModalHeight(page: LoungeModalPages): string {\n switch (page) {\n case LoungeModalPages.deleteTeam:\n case LoungeModalPages.removeTeacherSelf:\n return '250px';\n case LoungeModalPages.detailsInput:\n return '480px';\n default:\n return '900px';\n }\n }\n\n /** Checks if user is allowed to remove themself from the team. If user is forbidden we output a toast message explaining why.\n * @returns true if allowed, false if not */\n private async allowRemoveYourself(): Promise<boolean> {\n const [teamEdit, user] = await firstValueFrom(\n combineLatest([\n this.loungeService.teamEdit$.pipe(filter((x) => !!x)),\n this.userService.user$.pipe(filter((x) => !!x)),\n ])\n );\n\n if (!teamEdit) {\n this.toastService.displayMessage('Der er ikke noget hold i edit mode.');\n return false;\n }\n\n const userFound = teamEdit.teachers.find((t) => t.user.id === user?.userId);\n\n if (!userFound) {\n this.toastService.displayMessage('Du blev ikke fundet som lærer på holdet.');\n return false;\n }\n\n if (teamEdit.teachers.filter((t) => t.permission.canEditTeam).length < 2) {\n this.toastService.displayMessage(\n 'Du kan ikke fjerne dig selv fra holdet, da det ikke er delt med en anden lærer.'\n );\n return false;\n }\n\n return true;\n }\n}\n","import { IModalConfig } from './modal-config.interface';\n\n/**\n * Settings for modals\n */\nexport class ModalConfig implements IModalConfig {\n /** Width of modal if its available .. if not it will just fill as much as possible */\n width = undefined;\n\n /** Height of modal if its available .. if not it will just fill as much as possible */\n height = undefined;\n\n /** Data-attribute to make it easier to add custom styling */\n variant = undefined;\n\n /** should there be a transition when modal opens/closes or should it be instantly? */\n useTransition = true;\n\n /** should there be a overlay on the entire browser window to give more focus to the modal? */\n showBackgroundOverLay = true;\n\n /** Spacing from modal to browser window */\n spacingFromWindow = '20px';\n}\n","import { animate, style, transition, trigger } from '@angular/animations';\nimport { softBezier } from '../../animations/beziers';\n\nconst transitionTiming = `.3s ${softBezier}`;\nconst modalHiddenStyle = style({\n transform: 'scale(.7)',\n opacity: 0,\n});\nconst modalVisibleStyle = style({\n transform: 'scale(1)',\n opacity: 1,\n});\nconst overlayHiddenStyle = style({ opacity: 0 });\nconst overlayVisibleStyle = style({ opacity: 1 });\n\nexport const modalEnterLeaveAnimation = trigger('modal-enter-leave', [\n transition(':enter', [modalHiddenStyle, animate(transitionTiming, modalVisibleStyle)]),\n transition(':leave', [animate(transitionTiming, modalHiddenStyle)]),\n]);\n\nexport const modalOverlayEnterLeaveAnimation = trigger('modal-overlay-enter-leave', [\n transition(':enter', [overlayHiddenStyle, animate(transitionTiming, overlayVisibleStyle)]),\n transition(':leave', [animate(transitionTiming, overlayHiddenStyle)]),\n]);\n","import { DomPortalOutlet } from '@angular/cdk/portal';\nimport { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { distinctUntilChanged } from 'rxjs/operators';\nimport { getLastItemFromArray, removeFromArray } from '../../utils/array';\nimport { ModalComponent } from './components/modal/modal.component';\n\n/** Handles all modals and makes sure we're only displaying a single modal at a time.\n * Modals are created using the <lru-modal> component in any template and displayed using the <lru-modal-outlet> component in the app component. */\n@Injectable({\n providedIn: 'root',\n})\nexport class ModalService {\n /** A Portal Outlet for attaching the modal components to */\n private outlet?: DomPortalOutlet;\n\n /** Property for storing the modal to attach to the outlet when it is ready */\n private modalToAttachWhenReady?: ModalComponent;\n\n /** List of all visible modals */\n private visibleModals: ModalComponent[] = [];\n\n /** @see {@link displayOverlay$} */\n private displayOverlaySubject = new BehaviorSubject(false);\n\n /** Make sure we're only emitting to the outside world when a real change happens by using `distinctUntilChanged` */\n displayOverlay$ = this.displayOverlaySubject.pipe(distinctUntilChanged());\n\n /** Returns the current visible {@link ModalComponent} */\n private get currentlyVisibleModal(): ModalComponent | undefined {\n return getLastItemFromArray(this.visibleModals);\n }\n\n /** Sets the portal outlet which should be used by the modals.\n * Should only be called from the <lru-modal-outlet> component. */\n setPortalOutlet(outlet: DomPortalOutlet): void {\n this.outlet = outlet;\n\n if (this.modalToAttachWhenReady) {\n this.outlet.attach(this.modalToAttachWhenReady.portal);\n this.modalToAttachWhenReady = undefined;\n }\n }\n\n /** Sets the visibility for the given modal. */\n setModalVisible(modal: ModalComponent, visible: boolean): void {\n modal.setVisibility(visible);\n }\n\n /** Hides the current modal if a modal is visible. */\n hideCurrentModal(): void {\n this.currentlyVisibleModal?.setVisibility(false);\n }\n\n /** Stores the visibility of a modal in the service and reacts to it.\n * Should only be called from the <lru-modal> component.\n *\n * If a modal is hidden, the next visible modal in the stack will be displayed.\n * If a modal is shown, the previously modal in the stack will be hidden, if one exists.\n *\n * Updates the overlay subject with true if any modal is visible or false if no modal is visible. */\n storeModalVisibility(modal: ModalComponent, visible: boolean): void {\n const wasLatestVisible = this.currentlyVisibleModal === modal;\n\n // The most recent displayed modal should always be last in the array\n // To ensure no duplicate entries we always try to remove the modal before re-inserting it if necessary\n removeFromArray(this.visibleModals, modal);\n\n if (visible) {\n this.visibleModals.push(modal);\n this.attachModal(modal);\n } else if (wasLatestVisible) {\n this.detachCurrentModal();\n }\n\n const currentlyVisibleModal = this.currentlyVisibleModal;\n\n if (!visible && wasLatestVisible && currentlyVisibleModal) {\n this.setModalVisible(currentlyVisibleModal, true);\n }\n\n this.displayOverlaySubject.next(!!currentlyVisibleModal);\n }\n\n /** Method for checking if the modal is in the visible stack\n * @returns true if the given modal is or should be visible. */\n isModalInVisibleStack(modal: ModalComponent): boolean {\n return this.visibleModals.includes(modal);\n }\n\n /** Attaches the given modal to the outlet and removes any old modal from the outlet. */\n private attachModal(modal: ModalComponent): void {\n if (!this.outlet) {\n // Queue the modal if the outlet hasn't yet been set\n this.modalToAttachWhenReady = modal;\n return;\n }\n\n this.detachCurrentModal();\n this.outlet.attach(modal.portal);\n }\n\n /** Detaches the current modal from the outlet. */\n private detachCurrentModal(): void {\n this.outlet?.detach();\n }\n\n /** Relays focus events from the <lru-modal-outlet> component to the current <lru-modal> component. */\n handleFocus(event: FocusEvent): void {\n if (this.currentlyVisibleModal && event.target) {\n this.currentlyVisibleModal.trapFocus(event.target);\n }\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { StoreModule } from '@ngrx/store';\nimport { ZIndexService } from './services/z-index.service';\nimport { zIndexFeatureKey, zIndexReducer } from './store/z-index.reducers';\nimport { ZIndexConfig } from './z-index-config';\nimport { IZIndexConfig } from './z-index-config.interface';\n\n@NgModule({\n declarations: [],\n imports: [CommonModule, StoreModule.forFeature(zIndexFeatureKey, zIndexReducer)],\n providers: [ZIndexService],\n})\nexport class ZIndexModule {\n static forRoot(config: IZIndexConfig): ModuleWithProviders<ZIndexModule> {\n return {\n ngModule: ZIndexModule,\n providers: [{ provide: ZIndexConfig, useValue: config }],\n };\n }\n\n static forChild(config: IZIndexConfig): ModuleWithProviders<ZIndexModule> {\n return {\n ngModule: ZIndexModule,\n providers: [{ provide: ZIndexConfig, useValue: config }],\n };\n }\n}\n","import { AnimationEvent } from '@angular/animations';\nimport { CdkPortal } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Inject,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n ViewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { v4 as uuidv4 } from 'uuid';\nimport { getLastItemFromArray } from '../../../../utils/array';\nimport { focusableElements } from '../../../../utils/query-selectors';\nimport { ZIndexService } from '../../../z-index/public-api';\nimport { ModalConfig } from '../../modal-config';\nimport { modalEnterLeaveAnimation, modalOverlayEnterLeaveAnimation } from '../../modal.animations';\nimport { ModalService } from '../../modal.service';\n\n/**\n * A component for displaying modals.\n * The content passed will be the content of the modal.\n * The visibility is controlled by the `isVisible` attribute.\n * If the modal is hidden (or displayed) by user interaction an `isVisibleChange` event will be fired.\n * The component isn't rendered in place, but moved to the <lru-modal-outlet> component automatically to prevent issues with semantics and style bleeding.\n */\n@Component({\n selector: 'lru-modal',\n templateUrl: './modal.component.html',\n styleUrls: ['./modal.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [modalEnterLeaveAnimation, modalOverlayEnterLeaveAnimation],\n})\nexport class ModalComponent implements AfterViewInit, OnDestroy, OnChanges {\n /**\n * Hides scrollbar when false\n * Used to ensure scrollbars isnt shown while it plays transition when showing/hiding modal\n */\n overflowVisible = false;\n\n /** Enforce spacingFromWindow different from what is specified in the config {@link ModalConfig} */\n @Input() spacingFromWindow?: string;\n\n /** Enforce width different from what is specified in the config {@link ModalConfig} */\n @Input() width?: string;\n\n /** Enforce height different from what is specified in the config {@link ModalConfig} */\n @Input() height?: string;\n\n /** Enforce variant different from what is specified in the config {@link ModalConfig} */\n @Input() variant?: string;\n\n /** Enforce useTransition different from what is specified in the config {@link ModalConfig} */\n @Input() useTransition: boolean;\n\n /** Enforce showBackgroundOverLay different from what is specified in the config {@link ModalConfig} */\n @Input() showBackgroundOverLay: boolean;\n\n /**\n * Should the modal be visible to begin with?\n * This is to make it possible to show modal without user interaction\n */\n @Input() isVisible = false;\n\n /**\n * Emits modal visibility changes so the place that contains the modal can run custom logic when it happens\n */\n @Output() isVisibleChange = new EventEmitter<boolean>();\n\n /**\n * Emits when modal is fully shown or hidden so the place that contains the modal can run custom locic when it happens\n */\n @Output() animationEnded = new EventEmitter<boolean>();\n\n /**\n * Used by the modal service to get a reference of the internal modal portal.\n */\n @ViewChild(CdkPortal) public readonly portal?: CdkPortal;\n\n /**\n * Used to trap focus logic\n */\n @ViewChild('modalContent') private modalContent: ElementRef | undefined;\n\n /**\n * A reference to the element in focus when the modal was displayed.\n * Used to restore focus when the modal is hidden.\n */\n private previouslyFocusedElement: Element | null = null;\n\n /**\n * A reference to the last value we reacted to.\n */\n private lastReactionValue: boolean = false;\n\n /**\n * A reference to the last focus event target. Used to prevent unnecessary focus jumps.\n */\n private lastFocusEventTarget: EventTarget | null = null;\n\n /** unique id for this component */\n private uuid = uuidv4();\n\n /** z-index for dropdown content */\n public readonly zIndex$ = this.zIndexService.item$(this.uuid);\n\n /**\n * @ignore\n */\n constructor(\n private window: Window,\n @Inject(DOCUMENT) private document: Document,\n private modalService: ModalService,\n private cdr: ChangeDetectorRef,\n private zIndexService: ZIndexService,\n private config?: ModalConfig\n ) {\n const defaultConfig = new ModalConfig();\n\n this.width = this.config?.width ?? defaultConfig.width;\n this.height = this.config?.height ?? defaultConfig.height;\n this.variant = this.config?.variant ?? defaultConfig.variant;\n this.useTransition = this.config?.useTransition ?? defaultConfig.useTransition;\n this.showBackgroundOverLay = this.config?.showBackgroundOverLay ?? defaultConfig.showBackgroundOverLay;\n this.spacingFromWindow = this.config?.spacingFromWindow ?? defaultConfig.spacingFromWindow;\n }\n\n ngAfterViewInit(): void {\n // Make sure the correct state is reflected in the modal service\n this.reactOnVisibilityChange(this.isVisible);\n }\n\n ngOnDestroy(): void {\n // Hide the modal to prevent it from getting stuck in the modal outlet\n this.setVisibility(false);\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes.isVisible) {\n if (changes.isVisible.currentValue !== changes.isVisible.previousValue) {\n // this.isVisibleChange.emit(changes.isVisible.currentValue);\n\n // The portal doesn't yet exist when ngOnChanges is called the first time\n if (this.portal) {\n this.reactOnVisibilityChange(changes.isVisible.currentValue);\n }\n }\n }\n }\n\n /**\n * Hides the modal when the wrapper is clicked\n */\n public onWrapperClick(event: MouseEvent): void {\n // Only react to clicks on the actual wrapper to prevent clicks inside the modal from bubbling through\n if (event.target === event.currentTarget) {\n this.overflowVisible = false;\n this.cdr.detectChanges();\n this.setVisibility(false);\n }\n }\n\n /**\n * Sets a new visibility and emits a change event if necessary.\n */\n public setVisibility(visible: boolean): void {\n const wasAlreadyVisible = this.isVisible === visible;\n\n this.isVisible = visible;\n if (!wasAlreadyVisible) {\n this.isVisibleChange.emit(visible);\n }\n\n this.reactOnVisibilityChange(visible);\n }\n\n /**\n * Traps focus within the modal as long as it's visible.\n * Called from the modal service.\n */\n public trapFocus(eventTarget: EventTarget): void {\n const dropdownOutlet = document.getElementsByTagName('lru-dropdown-outlet');\n const isValidFocusElement =\n this.modalContent?.nativeElement.contains(eventTarget) ||\n (dropdownOutlet.length && dropdownOutlet[0].contains(eventTarget as HTMLElement));\n\n if (!isValidFocusElement) {\n if (eventTarget instanceof HTMLElement && eventTarget.classList.contains('focus-trap')) {\n if (eventTarget.classList.contains('focus-trap-begin')) {\n // If no timeout is set, we're constantly brought back to the last focus item for some strange reason\n setTimeout(() => {\n this.focusOnLastDescendant();\n });\n } else if (eventTarget.classList.contains('focus-trap-end')) {\n this.focusOnFirstDescendant();\n }\n } else if (this.lastFocusEventTarget === eventTarget) {\n return;\n }\n\n this.lastFocusEventTarget = eventTarget;\n this.focusOnModal();\n }\n }\n\n /**\n * Function will get triggered when modal is fully shown or hidden\n * It will get called regardless of whether transitions are enabled or not\n * @param event event with info about the animation\n */\n public animationDone(event: AnimationEvent): void {\n this.overflowVisible = this.isVisible;\n if (!this.isVisible) {\n this.unlockScroll();\n }\n\n this.cdr.detectChanges();\n this.animationEnded.emit(event.toState === null);\n }\n\n /**\n * Inspired by https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/\n */\n private unlockScroll(): void {\n const scrollY = this.document.body.dataset.scrolly;\n\n this.document.documentElement.style.overflowY = '';\n\n this.document.body.style.paddingRight = '';\n this.document.body.style.position = '';\n this.document.body.style.top = '';\n this.document.body.style.left = '';\n this.document.body.style.right = '';\n this.document.body.style.bottom = '';\n this.document.body.style.overflowY = '';\n this.document.body.removeAttribute('data-scrollY');\n this.window.scrollTo(0, parseInt(scrollY || '0'));\n this.document.documentElement.removeAttribute('data-scroll-locked');\n }\n\n /**\n * Reacts on all visibility changes:\n * - Relays the current state to the modal service.\n * - Sets focus on the correct element.\n */\n private reactOnVisibilityChange(visible: boolean): void {\n const inStack = this.modalService.isModalInVisibleStack(this);\n\n if (visible) {\n this.zIndexService.setItem(this.uuid);\n }\n\n this.modalService.storeModalVisibility(this, visible);\n\n if (visible === this.lastReactionValue) {\n return;\n }\n\n this.lastReactionValue = visible;\n\n if (visible) {\n this.previouslyFocusedElement = this.document.activeElement;\n }\n\n if (inStack && !visible) {\n setTimeout(() => {\n this.focusOnPreviousElement();\n });\n } else if (!inStack && visible) {\n setTimeout(() => {\n this.focusOnModal();\n });\n }\n }\n\n /**\n * Sets focus on the element that had focus when the modal was displayed.\n */\n private focusOnPreviousElement(): void {\n if (this.previouslyFocusedElement instanceof HTMLElement) {\n this.previouslyFocusedElement.focus();\n }\n }\n\n /**\n * Sets focus on the most relevant element in the modal.\n */\n private focusOnModal(): void {\n const modalElement = this.modalContent?.nativeElement;\n\n if (!modalElement) {\n return;\n }\n\n // Try to find an element with the autofocus attribute\n const autofocusElement = modalElement.querySelector('[autofocus]');\n\n if (autofocusElement) {\n autofocusElement.focus();\n return;\n }\n\n // Try to find any focusable element\n modalElement.querySelector(focusableElements)?.focus();\n }\n\n /**\n * Sets focus on the first focusable element in the modal.\n */\n private focusOnFirstDescendant(): void {\n this.modalContent?.nativeElement.querySelector(focusableElements)?.focus();\n }\n\n /**\n * Sets focus on the last focusable element in the modal.\n */\n private focusOnLastDescendant(): void {\n const lastElement = getLastItemFromArray(\n this.modalContent?.nativeElement.querySelectorAll(focusableElements) || []\n );\n\n if (lastElement instanceof HTMLElement) {\n lastElement.focus();\n }\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { LevelDto } from '../../../../interfaces/endpoint/dtos/dto-level.interface';\nimport { IClassWithUsers } from '../../../../store/interfaces/team-edit.interface';\n\n/** Find classes that contains users that includes the searchTerm in their name\n * or find classes that is a level in searchLevels */\n@Pipe({ name: 'searchClassWithUsers' })\nexport class SearchClassWithUsersPipe implements PipeTransform {\n /** Takes a list of IClassWithUsers and filters them by searchTerm and searchLevels and then output a filtered list of IClassWithUsers\n * @param values List of classes with users\n * @param searchTerm User name query\n * @param searchLevels Class level query\n * @returns List of classes */\n transform(values: IClassWithUsers[], searchTerm: string, searchLevels: LevelDto[]): IClassWithUsers[] {\n if (!searchTerm && searchLevels.length === 0) {\n return values;\n }\n\n let classWithUsersList: IClassWithUsers[] = [];\n\n if (searchLevels.length > 0) {\n const classesToAdd = values.filter((x) => searchLevels.some((y) => y.id === x.class.levelId));\n\n if (classesToAdd.length > 0) {\n classWithUsersList.push(...classesToAdd);\n }\n }\n\n const valuesToSearchIn = searchLevels.length > 0 ? classWithUsersList : values;\n\n if (searchTerm) {\n classWithUsersList = [];\n valuesToSearchIn.forEach((element) => {\n const users = element.users.filter((x) => x.name.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n\n if (users.length > 0) {\n if (!classWithUsersList.some((x) => x.class.id === element.class.id)) {\n classWithUsersList.push({ class: element.class, users: users });\n }\n }\n });\n }\n\n return classWithUsersList;\n }\n}\n","import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { LoadingService } from '../../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../../services/loading/shared-loading-keys.enums';\nimport { LevelDto } from '../../../interfaces/endpoint/dtos/dto-level.interface';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { IClassWithUsers } from '../../../store/interfaces/team-edit.interface';\n\n/** A component for being able to select classes and students for teams */\n@Component({\n selector: 'lru-team-picker',\n templateUrl: './team-picker.component.html',\n styleUrls: ['./team-picker.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamPickerComponent {\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** Property for storing the levels the user has selected */\n selectedLevels: LevelDto[] = [];\n\n /** Property for storing the inputted search term */\n searchTerm: string = '';\n\n /** @ignore */\n constructor(public loungeService: LoungeService, public loadingService: LoadingService) {}\n\n /** Asks {@link LoungeService} to mark the student for selection.\n * @param classId the id of the class the student belongs in\n * @param studentId the id of the student to mark\n * @param checked whether to mark or unmark the student */\n onClickUser(classId: string, studentId: string, checked: boolean): void {\n this.loungeService.markStudentForSelection(classId, studentId, checked);\n }\n\n /** Asks {@link LoungeService} to mark the whole class for selection. Take into account the searchTerm so it only marks the students in the class that matches the searchTerm.\n * @param classId the id of the class to select\n * @param checked whether to mark or unmark the class */\n onClickClass(classId: string, checked: boolean): void {\n this.loungeService.markClassForSelection(classId, checked, this.searchTerm);\n }\n\n /** Method for marking or unmarking levels from user input\n * @param level the level to mark\n * @param checked whether to mark or unmark the level */\n onClickLevel(level: LevelDto, checked: boolean): void {\n if (checked) {\n this.selectedLevels = [...this.selectedLevels, level];\n } else {\n this.selectedLevels = this.selectedLevels.filter((elem) => elem.id !== level.id);\n }\n }\n\n /** Method for getting strings for the UI to show the levels\n * @returns string with name of level */\n getLevelsLabel(): string {\n if (this.selectedLevels?.length) {\n return this.selectedLevels.map((item) => item.mediumForm).join(', ');\n } else {\n return 'Vælg klassetrin';\n }\n }\n\n /** Method used by level checkboxes indicating whether the level is selected or not\n * @param id the id of the level\n * @returns a boolean value wheter a level is selected */\n isLevelSelected(id: string): boolean {\n return this.selectedLevels.find((item) => item.id === id) ? true : false;\n }\n\n /** Returns a value indicating if the level is semi / indeterminate selected which means only some of the subitems are selected and not all\n * @param classWithUsers The class that needs to be checked if it is semichecked\n * @returns a boolean value whether a level is indeterminate selected */\n isClassSemiSelected(classWithUsers: IClassWithUsers): boolean {\n return !classWithUsers.class.selected && classWithUsers.users.some((classWithUsers) => classWithUsers.selected);\n }\n\n /** Tracker for loaded data so it doesn't need to recalculate and redraw already existing classes in the UI */\n classTrackBy(index: number, item: IClassWithUsers): string {\n return item.class.id;\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\n\n/**\n * Headline component for lounge team modals\n */\n@Component({\n selector: 'lru-team-header',\n templateUrl: './team-header.component.html',\n styleUrls: ['./team-header.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamHeaderComponent {\n /** Optional primary headline.\n * If not specified then primary headline will not be displayed. */\n @Input() header?: string;\n\n /** Optional secondary headline.\n * If not specified then secondary headline will not be displayed. */\n @Input() subHeader?: string;\n\n /** Optional function that should be executed when clicking close button.\n * If not specified then close button will not be displayed. */\n @Input() closeFunc?: Function;\n\n /** Optional function that should be executed when clicking back button.\n * If not specified then back button will not be displayed. */\n @Input() backFunc?: Function;\n\n /** Click on back button. Will execute {@link backFunc} input if supplied */\n onClickBack(): void {\n if (this.backFunc) {\n this.backFunc();\n }\n }\n\n /** Click on close button. Will execute {@link closeFunc} input if supplied */\n onClickClose(): void {\n if (this.closeFunc) {\n this.closeFunc();\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { firstValueFrom, withLatestFrom } from 'rxjs';\nimport { LoadingService } from '.././../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '.././../../../../services/loading/shared-loading-keys.enums';\nimport { LoadingAnimationVariant } from '../../../../../components/loading-animation/enum/loading-animation-variant.enum';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\n\n/** A component for assigning students to a team */\n@Component({\n selector: 'lru-team-edit-assign-students',\n templateUrl: './team-edit-assign-students.component.html',\n styleUrls: ['./team-edit-assign-students.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditAssignStudentsComponent {\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** @see {@link LoadingAnimationVariant} */\n loadingAnimationVariants = LoadingAnimationVariant;\n\n /** @ignore */\n constructor(\n public loungeService: LoungeService,\n public loadingService: LoadingService,\n private loungeModalService: LoungeModalService\n ) {}\n\n /** Saves selected students to the team */\n async onClickSave(): Promise<void> {\n const [selectedUsers, teamEdit] = await firstValueFrom(\n this.loungeService.selectedUsersList$.pipe(withLatestFrom(this.loungeService.teamEdit$))\n );\n\n if (selectedUsers && teamEdit) {\n this.loungeService.teamSaveStudentsToTeam(\n teamEdit.id,\n selectedUsers.map((x) => x.id),\n SharedLoadingKeys.teamSaveStudentsToTeam\n );\n }\n }\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { SharedLoadingKeys } from '.././../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { ITeamEdit } from '../../../store/interfaces/team-edit.interface';\n\n/** A component for deleting a team */\n@Component({\n selector: 'lru-team-edit-delete[teamEdit]',\n templateUrl: './team-edit-delete.component.html',\n styleUrls: ['./team-edit-delete.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditDeleteComponent {\n /** The team to delete */\n @Input() teamEdit!: ITeamEdit;\n\n /** @ignore */\n constructor(private loungeService: LoungeService, private loungeModalService: LoungeModalService) {}\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n\n /** Asks {@link LoungeService} to delete the {@link teamEdit} input */\n onClickDelete(): void {\n this.loungeService.teamDelete(this.teamEdit.id, SharedLoadingKeys.teamDelete);\n }\n}\n","<div class=\"main\">\n <p>Hold og data vil ikke være tilgængeligt for dig eller andre lærere.</p>\n</div>\n<div class=\"footer\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\" [hollow]=\"true\" (click)=\"onClickClose()()\">Annuller</lru-button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickDelete()\">Ja, slet hold</lru-button>\n</div>\n<lru-team-header [closeFunc]=\"onClickClose()\" [header]=\"'Slet ' + teamEdit.title\"></lru-team-header>\n","import { ChangeDetectorRef, Component, Input, OnInit, ViewEncapsulation } from '@angular/core';\nimport { AbstractControl, FormGroup } from '@angular/forms';\nimport { filter, firstValueFrom } from 'rxjs';\n\nimport { LevelDto } from '../../../interfaces/endpoint/dtos/dto-level.interface';\nimport { LoungeService } from './../../../services/lounge.service';\n\n/** A component for showing a form for team details */\n@Component({\n selector: 'lru-team-details-form[form]',\n templateUrl: './team-details-form.component.html',\n styleUrls: ['./team-details-form.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n})\nexport class TeamDetailsFormComponent implements OnInit {\n /** The FormGroup consisting of title and level */\n @Input() form!: FormGroup;\n\n /** the selected level */\n selectedLevel?: { text: string; id: string };\n\n /** @ignore */\n constructor(public loungeService: LoungeService, private changeDetector: ChangeDetectorRef) {}\n\n /** Retrieve all levels and if the level formcontrol already contains a level mark it. Used for when editing teams so the level from the team is already prefilled in the form */\n async ngOnInit(): Promise<void> {\n const level = (await firstValueFrom(this.loungeService.fullLevel$.pipe(filter((x) => !!x))))?.levels.find(\n (x) => x.id === this.level?.value\n );\n\n if (level) {\n this.onClickLevel(level);\n this.changeDetector.markForCheck();\n }\n }\n\n /** Method for selecting the level\n * @param level the level to select */\n onClickLevel(level: LevelDto): void {\n this.selectedLevel = {\n text: level.mediumForm,\n id: level.id,\n };\n\n this.level?.setValue(level.id);\n }\n\n /** Getter for retrieving the FormControl for title from the FormGroup */\n get title(): AbstractControl | null {\n return this.form.get('title');\n }\n\n /** Getter for retrieving the FormControl for level from the FormGroup */\n get level(): AbstractControl | null {\n return this.form.get('level');\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';\nimport { FormControl, FormGroup, Validators } from '@angular/forms';\nimport { firstValueFrom } from 'rxjs';\nimport { LoadingAnimationVariant } from '../../../../../components/loading-animation/enum/loading-animation-variant.enum';\nimport { LoadingService } from '../../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\n\n/** A component used for editing team details */\n@Component({\n selector: 'lru-team-edit-details',\n templateUrl: './team-edit-details.component.html',\n styleUrls: ['./team-edit-details.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditDetailsComponent implements OnInit {\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** @see {@link LoadingAnimationVariant} */\n loadingAnimationVariants = LoadingAnimationVariant;\n\n /** FormControl used for handling title of team */\n private title = new FormControl('', {\n validators: [Validators.required, Validators.minLength(2), Validators.maxLength(25)],\n updateOn: 'blur',\n });\n\n /** FormControl used for handling level of team */\n private level = new FormControl('', { validators: [Validators.required], updateOn: 'blur' });\n\n /** FormGroup consisting of {@link title} and {@link level}. Used for validating and handling values. */\n form: FormGroup = new FormGroup({\n title: this.title,\n level: this.level,\n });\n\n /** @ignore */\n constructor(\n public loungeService: LoungeService,\n public loadingService: LoadingService,\n private loungeModalService: LoungeModalService\n ) {}\n\n /** Retrieve the team to edit from the store and set values from the team in the forms */\n async ngOnInit(): Promise<void> {\n const teamEdit = await firstValueFrom(this.loungeService.teamEdit$);\n\n if (teamEdit) {\n this.title.setValue(teamEdit.title);\n this.level.setValue(teamEdit.levelIds[0]);\n }\n }\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n\n /** Checks validity of forms and asks {@LoungeService} to save details to the team. If forms aren't valid mark forms as touched and therefore show error messages.\n * @param teamId The id of the team to save the details to */\n onClickSave(teamId: string): void {\n if (this.form.valid && this.title.value && this.level.value) {\n this.loungeService.teamSaveDetailsToTeam(\n teamId,\n this.title.value,\n [this.level.value],\n SharedLoadingKeys.saveDetailsToTeam\n );\n } else {\n this.form.markAllAsTouched();\n }\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { SharedLoadingKeys } from '../../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { ITeamEdit } from '../../../store/interfaces/team-edit.interface';\n\n/** Component for being able to remove yourself from the team */\n@Component({\n selector: 'lru-team-edit-remove-teacher-self[teamEdit]',\n templateUrl: './team-edit-remove-teacher-self.component.html',\n styleUrls: ['./team-edit-remove-teacher-self.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditRemoveTeacherSelfComponent {\n /** A team with teachers and students */\n @Input() teamEdit!: ITeamEdit;\n\n /** @ignore */\n constructor(private loungeModalService: LoungeModalService, private loungeService: LoungeService) {}\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n\n /** Ask {@link LoungeService} to remove the user themself from the team */\n onClickRemoveTeacherSelf(): void {\n this.loungeService.teamRemoveTeacherSelf(this.teamEdit, SharedLoadingKeys.teamRemoveTeacherSelf);\n }\n}\n","<div class=\"main\">\n <p>Hold og data vil ikke være tilgængeligt for dig.</p>\n</div>\n<div class=\"footer\">\n <lru-button [variant]=\"'lounge'\" [theme]=\"'white'\" [hollow]=\"true\" (click)=\"onClickClose()()\">Annuller</lru-button>\n <lru-button [variant]=\"'lounge'\" [theme]=\"'primary-teacher'\" (click)=\"onClickRemoveTeacherSelf()\"\n >Ja, fjern mig fra holdet</lru-button\n >\n</div>\n<lru-team-header [closeFunc]=\"onClickClose()\" [header]=\"'Fjern dig fra ' + teamEdit.title\"></lru-team-header>\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { IUserPermissionWithSelected } from '../../modules/lounge/store/interfaces/team-edit.interface';\n\n/**\n * Filter users that includes the searchTerm in their name\n */\n@Pipe({\n name: 'searchUserPermissionWithSelectedList',\n})\nexport class SearchUserPermissionWithSelectedListPipe implements PipeTransform {\n /**\n *\n * @param values List of users\n * @param searchTerm Query\n * @returns List of users with names that includes the query\n */\n transform(values: IUserPermissionWithSelected[], searchTerm: string): IUserPermissionWithSelected[] {\n if (!searchTerm) {\n return values;\n }\n\n return values.filter((x) => x.user.name.toLocaleLowerCase().includes(searchTerm.toLocaleLowerCase()));\n }\n}\n","import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\nimport { LoadingService } from '../../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { IUserPermissionWithSelected } from '../../../store/interfaces/team-edit.interface';\n\n/** A component for being able to select teachers for teams */\n@Component({\n selector: 'lru-team-picker-teacher',\n templateUrl: './team-picker-teacher.component.html',\n styleUrls: ['./team-picker-teacher.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamPickerTeacherComponent {\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** Property for storing the inputted search term */\n searchTerm = '';\n\n /** @ignore */\n constructor(public loungeService: LoungeService, public loadingService: LoadingService) {}\n\n // onClickPermission(teacherId: string, permissionId: string, checked: boolean): void {\n // // not sure why we add this to store, but since we do I wont make it into a formcontrol\n // // this.loungeService.markPermissionForSelection(teacherId, permissionId, checked);\n // console.log(`onClickPermission(${teacherId}: string, ${permissionId}: string, ${checked}: boolean)`);\n // }\n\n /** Asks {@link LoungeService} to mark the teacher for selection in the store */\n onClickTeacher(teacherId: string, checked: boolean): void {\n this.loungeService.markTeacherForSelection(teacherId, checked);\n }\n\n /** Tracker for loaded data so it doesn't need to recalculate and redraw already existing teachers in the UI */\n teacherTrackBy(index: number, item: IUserPermissionWithSelected): string {\n return item.user.id;\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { firstValueFrom, withLatestFrom } from 'rxjs';\nimport { LoadingService } from '.././../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '.././../../../../services/loading/shared-loading-keys.enums';\nimport { LoadingAnimationVariant } from '../../../../../components/loading-animation/enum/loading-animation-variant.enum';\nimport { UserService } from '../../../../../services/core/user/user.service';\nimport { AddTeacher } from '../../../interfaces/endpoint/team.interface';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { ITeamEdit } from '../../../store/interfaces/team-edit.interface';\n\n/** A component for assigning teachers to a team */\n@Component({\n selector: 'lru-team-edit-assign-teachers[teamEdit]',\n templateUrl: './team-edit-assign-teachers.component.html',\n styleUrls: ['./team-edit-assign-teachers.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditAssignTeachersComponent {\n /** The team to assign teachers to */\n @Input() teamEdit!: ITeamEdit;\n\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** @see {@link LoadingAnimationVariant} */\n loadingAnimationVariants = LoadingAnimationVariant;\n\n /** @ignore */\n constructor(\n public loungeService: LoungeService,\n private userService: UserService,\n public loadingService: LoadingService,\n private loungeModalService: LoungeModalService\n ) {}\n\n /** Saves selected teachers to the team */\n async onClickSave(): Promise<void> {\n const [selectedTeachers, teamEdit, currentUser] = await firstValueFrom(\n this.loungeService.selectedTeachersList$.pipe(\n withLatestFrom(this.loungeService.teamEdit$, this.userService.user$)\n )\n );\n\n if (selectedTeachers && teamEdit && currentUser) {\n const currentTeacher = teamEdit.teachers.find((t) => t.user.id === currentUser.userId);\n\n if (!currentTeacher) {\n // TODO\n alert('hovsa...current teacher findes ikke');\n return;\n }\n\n const teachers: AddTeacher[] = selectedTeachers.map((x) => {\n return { ...currentTeacher?.permission, userId: x.user.id } as AddTeacher;\n });\n\n teachers.push({ ...currentTeacher?.permission, userId: currentTeacher?.user.id });\n\n this.loungeService.teamSaveTeachersToTeam(teamEdit.id, teachers, SharedLoadingKeys.teamSaveTeachersToTeam);\n }\n }\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { SharedLoadingKeys } from '../../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeModalPages } from '../../../enums/lounge-modal-pages.enum';\nimport { LoungeModalService } from '../../../services/lounge-modal.service';\nimport { LoungeService } from '../../../services/lounge.service';\nimport { ITeamEdit } from '../../../store/interfaces/team-edit.interface';\n\n/** A component for supplying CRUD for Lounge teams */\n@Component({\n selector: 'lru-team-edit-dropdown[team]',\n templateUrl: './team-edit-dropdown.component.html',\n styleUrls: ['./team-edit-dropdown.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditDropdownComponent {\n /** The team to edit */\n @Input() team!: ITeamEdit;\n\n /** @see {@link LoungeModalPages} */\n pageEnum = LoungeModalPages;\n\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** Method linked to event emitter from the modal.\n * @param showModal whether or not to show the team creation modal */\n onModalVisibilityChange(showModal: boolean): void {\n if (!showModal) {\n this.loungeModalService.setPageToNone();\n }\n }\n\n /** @ignore */\n constructor(public loungeService: LoungeService, public loungeModalService: LoungeModalService) {}\n}\n","import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport { UserService } from '../../../../services/core/user/user.service';\nimport { LoadingService } from '../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeService } from '../../services/lounge.service';\n\n/** A component for showing a team in the edit status */\n@Component({\n selector: 'lru-team-edit[id]',\n templateUrl: './team-edit.component.html',\n styleUrls: ['./team-edit.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamEditComponent implements OnInit, OnDestroy {\n /** Id of the team */\n @Input() id!: string;\n\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** @ignore */\n constructor(\n public loungeService: LoungeService,\n public userService: UserService,\n public loadingService: LoadingService,\n private route: ActivatedRoute\n ) {}\n\n /** Finds the id of the team either from the input {@link id} or from the query parameters. Tells {@link LoungeService} to start loading the team */\n ngOnInit(): void {\n const id: string = this.id || this.route.snapshot.queryParams.edit;\n\n this.loungeService.teamLoadSingleTeamForEdit(id, SharedLoadingKeys.editTeam);\n }\n\n /** On component destroy we want to ask {@link LoungeService} to cancel the edit of th team */\n ngOnDestroy(): void {\n this.loungeService.teamEditCancel();\n }\n}\n","/** Enum for choosing sorting mode */\nexport enum SortMode {\n alphabetically = 'alphabetically',\n creationDate = 'creationDate',\n updatedDate = 'updatedDate',\n}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { share, Subject } from 'rxjs';\n\n/** A service for interacting with the localstorage in the browser */\n@Injectable({ providedIn: 'root' })\nexport class StorageService implements OnDestroy {\n /** {@link Subject} that is used for sending emitted events from the localstorage eventlistener to */\n private localStorageChanged = new Subject<StorageEvent>();\n /** Observable that will emit a {@link StorageEvent} when the localstorage has changed */\n localStorageChanged$ = this.localStorageChanged.pipe(share({ resetOnRefCountZero: true }));\n\n /** In the constructor we adds an event listener to the window that listens to changes to the local storage. If storage changes we emit value to our {@link localStorageChanged} */\n constructor() {\n window.addEventListener('storage', (event) => this.localStorageChanged.next(event), true);\n }\n\n /** Retrieves a string with the value from the localstorage.\n * @param key The key of the key/value pair to retrieve\n * @use {@link getObject} for returning a JSON object\n * @returns Will return undefined if key doesn't exist */\n get(key: string): string | undefined {\n return localStorage.getItem(key) || undefined;\n }\n\n /** Retrieve object from local storage. Keep in mind that this method will not return a true class with access to methods etc.\n * @param key The key of the key/value pair to retrieve\n * @returns Returns the object from the localstorage. Will return undefined if key doesn't exist */\n getObject<T>(key: string): T | undefined {\n const jsonString = localStorage.getItem(key);\n\n if (jsonString == null) {\n return;\n }\n\n return <T>JSON.parse(jsonString);\n }\n\n /** Create / set the key/value pair with strings as values in the local storage\n * @param key The key to save the string under in the storage\n * @param value The string to store\n * @use {@link setObject} for objects */\n set(key: string, value: string): void {\n localStorage.setItem(key, value);\n }\n\n /** Create / set the key/value pair with objects as values in the local storage\n * @param key The key to save the object under in the storage\n * @param value The object to store\n * @use {@link set} for simple strings */\n setObject(key: string, value: object): void {\n localStorage.setItem(key, JSON.stringify(value));\n }\n\n /** Delete a key/value pair from the local storage\n * @param key The key of the key/value pair to delete */\n delete(key: string): void {\n localStorage.removeItem(key);\n }\n\n /** Clear all key/value pairs in the local storage\n *\n * Warning: this will clear the whole localstorage\n * @use {@link delete} for removing single key/value pairs */\n deleteAll(): void {\n localStorage.clear();\n }\n\n /** Unsubscribes from the event listener we put on the window */\n ngOnDestroy(): void {\n window.removeEventListener('storage', (event) => this.localStorageChanged.next(event), false);\n }\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { TeamWithTeachersDto } from '../../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { LoungeService } from '../../services/lounge.service';\n\n/** Component for showing a team with few details */\n@Component({\n selector: 'lru-team-box[model]',\n templateUrl: './team-box.component.html',\n styleUrls: ['./team-box.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamBoxComponent {\n /** A team with teachers used for displaying */\n @Input() model!: TeamWithTeachersDto;\n\n /** @ignore */\n constructor(private loungeService: LoungeService) {}\n\n /** Tells {@link LoungeService} that we want to navigate to edit a specific team */\n onClickEdit(team: TeamWithTeachersDto): void {\n this.loungeService.teamEditNavigate(team);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { ISiteConfiguration } from './interfaces/site-configuration.interface';\n\n/** Service for storing the site configuration and retrieving values from the configuration */\n@Injectable({ providedIn: 'root' })\nexport class UmbracoService {\n /** Site configuration coming from Umbraco */\n private _siteconfiguration?: ISiteConfiguration;\n\n /** Set the site configuration */\n setConfiguration(config: ISiteConfiguration): void {\n this._siteconfiguration = config;\n }\n\n /** Retrieve the {@link ISiteConfiguration.productId} from the site configuration */\n get productId(): string {\n if (this._siteconfiguration) {\n return this._siteconfiguration.productId || '';\n } else {\n return '';\n }\n }\n}\n","import { Injectable } from '@angular/core';\nimport { firstValueFrom } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { SharedLoadingKeys } from '.././../../../../services/loading/shared-loading-keys.enums';\nimport { UmbracoService } from '../../../../../services/core/umbraco/umbraco.service';\nimport { ILoungePostBodyTeam_CreateTeam } from '../../../interfaces/endpoint/team.interface';\nimport { LoungeService } from '../../../services/lounge.service';\n\n/** Service mainly for creating a team but also handles active and step status of the team creation flow page / modal */\n@Injectable({ providedIn: 'root' })\nexport class TeamCreationService {\n /** @ignore */\n constructor(private loungeService: LoungeService, private umbracoService: UmbracoService) {}\n\n /** Method for creating a lounge team. Users to add to the team are automatically retrieved from {@link LoungeService}'s selectedUsersList$\n * @param title Title of the team\n * @param levelIds The ids of the levels to add the team to */\n async createTeam(title: string, levelIds?: string[]): Promise<void> {\n const users = await firstValueFrom(this.loungeService.selectedUsersList$.pipe(filter((x) => !!x)));\n\n const team: ILoungePostBodyTeam_CreateTeam = {\n title,\n description: '',\n isPublic: true,\n studentIds: users.map((x) => x.id),\n productIds: [this.umbracoService.productId],\n levelIds: levelIds,\n };\n\n this.loungeService.teamCreate(team, SharedLoadingKeys.createTeam);\n }\n}\n","import { ChangeDetectionStrategy, Component, OnDestroy, ViewEncapsulation } from '@angular/core';\nimport { FormControl, FormGroup, Validators } from '@angular/forms';\nimport { tap } from 'rxjs';\nimport { LoadingAnimationVariant } from '../../../../components/loading-animation/enum/loading-animation-variant.enum';\nimport { LoadingService } from '../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../services/loading/shared-loading-keys.enums';\nimport { LoungeModalPages } from '../../enums/lounge-modal-pages.enum';\nimport { LoungeModalService } from '../../services/lounge-modal.service';\nimport { LoungeService } from '../../services/lounge.service';\nimport { TeamCreationService } from './services/team-creation.service';\n\n/** A component for team creation */\n@Component({\n selector: 'lru-team-creation',\n templateUrl: './team-creation.component.html',\n styleUrls: ['./team-creation.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamCreationComponent implements OnDestroy {\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** @see {@link LoadingAnimationVariant} */\n loadingAnimationVariants = LoadingAnimationVariant;\n\n /** @see {@link LoungeModalPages} */\n pageEnum = LoungeModalPages;\n\n /** FormControl used for handling title of team */\n title = new FormControl('', {\n validators: [Validators.required, Validators.minLength(2), Validators.maxLength(25)],\n updateOn: 'blur',\n });\n\n /** FormControl used for handling level of team */\n level = new FormControl('', {\n validators: [Validators.required],\n updateOn: 'blur',\n });\n\n /** FormGroup consisting of {@link title} and {@link level}. Used for validating and handling values. */\n form: FormGroup = new FormGroup({\n title: this.title,\n level: this.level,\n });\n\n /** Page subscription that resets the forms when the modal closes */\n private pageSubscription = this.loungeModalService.page$\n .pipe(tap((page) => (page === LoungeModalPages.none ? this.resetForm() : null)))\n .subscribe();\n\n /** @ignore */\n constructor(\n public teamCreationService: TeamCreationService,\n public loungeService: LoungeService,\n public loadingService: LoadingService,\n public loungeModalService: LoungeModalService\n ) {}\n\n /** Method that asks {@link LoungeModalService} to set page to none and also calls {@link resetForm} */\n onClickCancel(): void {\n this.loungeModalService.setPageToNone();\n this.resetForm();\n }\n\n /** Function that asks {@link LoungeModalService} to set modal page to none.\n * @returns A function that is used for inputting to the header and called from there. */\n onClickClose(): Function {\n return () => this.loungeModalService.setPageToNone();\n }\n\n /** Function that changes {@link step} to 'studentPicker'\n * @returns A function that is used for inputting to the header and called from there. */\n onClickBack(): Function {\n return () => this.loungeModalService.setPage(LoungeModalPages.studentPicker);\n }\n\n /** Changes {@link step} to 'detailsInput' */\n goToDetailsPage(): void {\n this.loungeModalService.setPage(LoungeModalPages.detailsInput);\n }\n\n /** Checks validity of forms and asks {@TeamCreationService} to create the team. If forms aren't valid mark forms as touched and therefore show error messages. */\n async onClickSubmit(): Promise<void> {\n if (this.form.valid && this.title.value) {\n const levelIds = this.level.value ? [this.level.value] : undefined;\n\n await this.teamCreationService.createTeam(this.title.value, levelIds);\n } else {\n this.form.markAllAsTouched();\n }\n }\n\n /** Unsubscribes from subscriptions */\n ngOnDestroy(): void {\n this.pageSubscription?.unsubscribe();\n }\n\n /** Reset all form controls and form groups. Method is needed since component is not destroyed when modal is closed. */\n private resetForm(): void {\n this.title.setValue('');\n this.level.setValue('');\n this.form.markAsUntouched();\n this.form.markAsPristine();\n }\n}\n","import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';\nimport { BehaviorSubject, combineLatest, map } from 'rxjs';\nimport { GoogleTagManagerService } from '../../../../services/gtm/google-tag-manager.service';\nimport { LoungeCreateTeam, LoungeSort } from '../../../../services/gtm/gtm-events.const';\nimport { LoadingService } from '../../../../services/loading/loading.service';\nimport { SharedLoadingKeys } from '../../../../services/loading/shared-loading-keys.enums';\nimport { StorageService } from '../../../../services/storage/storage.service';\nimport { sortComparer } from '../../../../utils/array.helper';\nimport { LoungeModalPages } from '../../enums/lounge-modal-pages.enum';\nimport { SortMode } from '../../enums/sort-mode.enum';\nimport { TeamWithTeachersDto } from '../../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { LoungeModalService } from '../../services/lounge-modal.service';\nimport { LoungeService } from '../../services/lounge.service';\n\n/** A component to give an overview over all teams */\n@Component({\n selector: 'lru-team-overview',\n templateUrl: './team-overview.component.html',\n styleUrls: ['./team-overview.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TeamOverviewComponent implements OnInit {\n /** @see {@link SortMode} */\n sortModeEnum = SortMode;\n\n /** {@link BehaviorSubject} for handling sorting mode of the loaded teams */\n sortMode$ = new BehaviorSubject<SortMode>(SortMode.alphabetically);\n\n /** @see {@link SharedLoadingKeys} */\n sharedLoadingKeys = SharedLoadingKeys;\n\n /** Teams from the store sorted according to the sorting mode */\n teams$ = combineLatest([this.loungeService.teamTeamWithTeachersList$, this.sortMode$]).pipe(\n map(([data, sortMode]) => this.sort(sortMode, data))\n );\n\n /** local storage key for saving sorting mode */\n private teamOverviewSort = 'teamOverviewSort';\n\n /** @ignore */\n constructor(\n private storageService: StorageService,\n public loungeService: LoungeService,\n public loadingService: LoadingService,\n public loungeModalService: LoungeModalService,\n private gtmService: GoogleTagManagerService\n ) {}\n\n /** Retrieves the sort mode from the localstorage if it exists and if not use creationDate and applies it to {@link sortMode$} */\n ngOnInit(): void {\n this.sortMode$.next((this.storageService.get(this.teamOverviewSort) as SortMode) || SortMode.creationDate);\n }\n\n onClickCreateTeam(): void {\n this.loungeModalService.setPage(LoungeModalPages.studentPicker);\n this.gtmService.pushTagWithUserType(LoungeCreateTeam);\n }\n\n /** Applies the selected sort mode to {@link sortMode$} and saves the value in the localstorage */\n onClickSort(sortMode: SortMode): void {\n this.sortMode$.next(sortMode);\n this.storageService.set(this.teamOverviewSort, sortMode.toString());\n this.gtmService.pushTagWithUserType(LoungeSort, { sort: sortMode });\n }\n\n /** Method linked to event emitter from the modal.\n * @param showModal whether or not to show the team creation modal */\n onModalVisibilityChange(showModal: boolean): void {\n if (!showModal) {\n this.loungeModalService.setPageToNone();\n }\n }\n\n /** Sorting method for team with teachers\n * @param sortMode The sorting mode to sort the teams in\n * @param input The teams to sort\n * @returns The teams now sorted according to the sorting mode */\n private sort(sortMode: SortMode, input?: TeamWithTeachersDto[]): TeamWithTeachersDto[] | undefined {\n if (!input) {\n return undefined;\n }\n\n const models = [...input];\n\n if (sortMode) {\n if (sortMode === SortMode.alphabetically) {\n models.sort((a, b) => sortComparer(a.title.toLowerCase(), b.title.toLowerCase(), true));\n } else if (sortMode === SortMode.creationDate) {\n models.sort((a, b) => sortComparer(a.created, b.created));\n } else if (sortMode === SortMode.updatedDate) {\n models.sort((a, b) => sortComparer(a.updated, b.updated));\n }\n }\n\n return models;\n }\n}\n","import { DomPortalOutlet } from '@angular/cdk/portal';\nimport { DOCUMENT } from '@angular/common';\nimport {\n AfterViewInit,\n ApplicationRef,\n ChangeDetectionStrategy,\n Component,\n ComponentFactoryResolver,\n ElementRef,\n HostListener,\n Inject,\n Injector,\n OnDestroy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { getScrollbarWidth } from '../../../../utils/scrollbar';\nimport { modalOverlayEnterLeaveAnimation } from '../../modal.animations';\nimport { ModalService } from '../../modal.service';\n\n/**\n * The outlet for modals.\n * This component is controlled by the modal service and relays global keypress\n * and focus events back to the service for further processing.\n */\n@Component({\n selector: 'lru-modal-outlet',\n template: '',\n styleUrls: ['./modal-outlet.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [modalOverlayEnterLeaveAnimation],\n})\nexport class ModalOutletComponent implements AfterViewInit, OnDestroy {\n /**\n * @ignore\n */\n constructor(\n private window: Window,\n @Inject(DOCUMENT) private document: Document,\n private componentFactoryResolver: ComponentFactoryResolver,\n private appRef: ApplicationRef,\n private injector: Injector,\n private modalService: ModalService,\n private elementRef: ElementRef\n ) {\n modalService.displayOverlay$.subscribe((displayOverlay) => {\n if (displayOverlay) {\n this.lockScroll();\n this.setUpFocusHandler();\n } else {\n this.destroyFocusHandler();\n }\n });\n }\n\n ngAfterViewInit(): void {\n // Set up a dom portal outlet and pass it on to the modal service\n const outlet = new DomPortalOutlet(\n this.elementRef.nativeElement,\n this.componentFactoryResolver,\n this.appRef,\n this.injector\n );\n\n this.modalService.setPortalOutlet(outlet);\n }\n\n ngOnDestroy(): void {\n // Stop any focus handling\n this.destroyFocusHandler();\n }\n\n /**\n * Inspired by https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/\n */\n private lockScroll(): void {\n const scrollY = this.window.scrollY;\n\n // When the modal is shown, we want a fixed body\n this.document.documentElement.style.overflowY = 'hidden';\n\n this.document.body.style.setProperty('padding-right', `${getScrollbarWidth()}px`, 'important');\n this.document.body.style.position = 'fixed';\n this.document.body.style.top = '0';\n this.document.body.style.left = '0';\n this.document.body.style.right = '0';\n this.document.body.style.bottom = '0';\n this.document.body.style.overflow = 'hidden';\n this.document.body.setAttribute('data-scrollY', scrollY.toString());\n\n this.document.body.scroll({\n left: 0,\n top: scrollY,\n });\n this.document.documentElement.setAttribute('data-scroll-locked', 'true');\n }\n\n /**\n * Add event listener that traps focus\n */\n private setUpFocusHandler(): void {\n // It would be nicer to use Angular host bindings for the event handling, but angular doesn't support capture instead of bubbling\n this.document.addEventListener('focus', this.focusHandler, true);\n }\n\n /**\n * Removes event listener that traps focus\n */\n private destroyFocusHandler(): void {\n this.document.removeEventListener('focus', this.focusHandler, true);\n }\n\n /**\n * Relays focus event on to the modal service.\n */\n private focusHandler = (event: FocusEvent): void => {\n this.modalService.handleFocus(event);\n };\n\n /**\n * Hides the current modal if the escape button is pressed.\n */\n @HostListener('document:keydown', ['$event'])\n onKeydown(event: KeyboardEvent): void {\n const dropdownOutlet = document.getElementsByTagName('lru-dropdown-outlet');\n const dropdownFocus = dropdownOutlet.length && dropdownOutlet[0].matches(':focus-within');\n\n if (event.code === 'Escape' && !dropdownFocus) {\n this.modalService.hideCurrentModal();\n }\n }\n\n /**\n * Hides the current modal if the outlet element is clicked outside of the modal content.\n */\n @HostListener('click', ['$event.target'])\n onClick(element: HTMLElement): void {\n if (element === this.elementRef.nativeElement) {\n this.modalService.hideCurrentModal();\n }\n }\n}\n","/**\n * Calculates browser width in pixels.\n * It generates a DOM element with a scrollbar to measure it, since the body might not have scrollbar.\n * @returns Width of scrollbar in pixels.\n */\nexport function getScrollbarWidth(): number {\n // Creating invisible container\n const outer = document.createElement('div');\n\n outer.style.visibility = 'hidden';\n outer.style.overflow = 'scroll'; // forcing scrollbar to appear\n document.body.appendChild(outer);\n\n // Creating inner element and placing it in the container\n const inner = document.createElement('div');\n\n outer.appendChild(inner);\n\n // Calculating difference between container's full width and the child width\n const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\n\n // Removing temporary elements from the DOM\n outer.parentNode?.removeChild(outer);\n return scrollbarWidth;\n}\n","import { PortalModule } from '@angular/cdk/portal';\nimport { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { ModalComponent } from './components/modal/modal.component';\nimport { ModalOutletComponent } from './components/modal-outlet/modal-outlet.component';\nimport { ModalConfig } from './modal-config';\nimport { IModalConfig } from './modal-config.interface';\n\n@NgModule({\n declarations: [ModalComponent, ModalOutletComponent],\n imports: [CommonModule, PortalModule],\n exports: [ModalComponent, ModalOutletComponent],\n providers: [{ provide: Window, useValue: window }],\n})\nexport class ModalModule {\n static forRoot(config: IModalConfig): ModuleWithProviders<ModalModule> {\n return {\n ngModule: ModalModule,\n providers: [{ provide: ModalConfig, useValue: config }],\n };\n }\n\n static forChild(config: IModalConfig): ModuleWithProviders<ModalModule> {\n return {\n ngModule: ModalModule,\n providers: [{ provide: ModalConfig, useValue: config }],\n };\n }\n}\n","import { ChangeDetectionStrategy, Component, HostBinding, Input, ViewEncapsulation } from '@angular/core';\nimport { ToastMessageInstance } from '../../interfaces/toast-message-instance.interface';\nimport { ToastService } from '../../services/toast.service';\n\n/** Individual toast message */\n@Component({\n selector: 'lru-toast-message[message]',\n templateUrl: './toast-message.component.html',\n styleUrls: ['./toast-message.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ToastMessageComponent {\n /** Toast message instance */\n @Input() message!: ToastMessageInstance;\n\n /** Makes it possible to add styling for different states like for example \"success\" | \"info\" */\n @HostBinding('attr.data-type')\n public get toastType(): string {\n return this.message.type;\n }\n\n /** @ignore */\n constructor(private toastService: ToastService) {}\n\n /** Close toast popup */\n public onDismissClick(): void {\n this.toastService.removeMessage(this.message.id);\n }\n}\n","import { animate, query, stagger, style, transition, trigger } from '@angular/animations';\nimport { softBezier } from '../../animations/beziers';\n\nconst transitionTiming = `.3s ${softBezier}`;\nconst animationMarginOut = '-80px';\nconst animationMarginIn = '0px';\n\nexport const toastAnimateInOut = trigger('animateInOut', [\n transition('* => *', [\n query(\n ':leave',\n [\n stagger(100, [\n animate(\n transitionTiming,\n style({ opacity: 0, transform: 'translateY(-66.67%) scale(0)', marginBottom: animationMarginOut })\n ),\n ]),\n ],\n { optional: true }\n ),\n query(\n ':enter',\n [\n style({ opacity: 0, marginBottom: animationMarginOut }),\n stagger(100, [animate(transitionTiming, style({ opacity: 1, marginBottom: animationMarginIn }))]),\n ],\n {\n optional: true,\n }\n ),\n ]),\n]);\n","import { ChangeDetectionStrategy, Component, OnDestroy, ViewEncapsulation } from '@angular/core';\nimport { ZIndexService } from '../../../z-index/services/z-index.service';\nimport { ToastService } from '../../public-api';\nimport { toastHorizontalPosition, toastVerticalPosition } from '../../toast-types';\nimport { toastAnimateInOut } from '../../toast.animations';\n\n/**\n * Toast messages\n */\n@Component({\n selector: 'lru-toast-message-list',\n templateUrl: './toast-message-list.component.html',\n styleUrls: ['./toast-message-list.component.scss'],\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [toastAnimateInOut],\n})\nexport class ToastMessageListComponent implements OnDestroy {\n /** style.gap */\n appliedSpacingBetweenToasts?: string;\n\n /** style.padding */\n appliedSpacingFromWindow?: string;\n\n /** attr.data-horizontal-position.\n * Used to make it possible to add specific styling for this. */\n appliedHorizontalPosition?: toastHorizontalPosition;\n\n /** attr.data-vertical-position.\n * Used to make it possible to add specific styling for this. */\n appliedVerticalPosition?: toastVerticalPosition;\n\n /** attr.data-variant.\n * Used to make it possible to add specific styling for this. */\n appliedVariant?: string;\n\n /** Array of toast messages to display */\n public readonly messages$ = this.toastService.messages$;\n\n /** z-index for toasts container */\n public readonly zIndex$ = this.zIndexService.item$('felib-toast');\n\n /** Get toast config */\n private toastConfigSubscription = this.toastService.config$.subscribe((data) => {\n this.appliedHorizontalPosition = data.horizontalPosition;\n this.appliedVerticalPosition = data.verticalPosition;\n this.appliedSpacingBetweenToasts = data.spacingBetweenToasts ? `${data.spacingBetweenToasts}px` : undefined;\n this.appliedSpacingFromWindow = data.spacingFromWindow ? `${data.spacingFromWindow}px` : undefined;\n this.appliedVariant = data.variant;\n });\n\n /**\n * @ignore\n */\n constructor(private toastService: ToastService, private zIndexService: ZIndexService) {}\n\n /** pause countdown for toast to go away when hovering it with cursor */\n public onMouseenter(event: MouseEvent): void {\n // Only pause the toast messages if we're not animating.\n // The mouseenter event is sometimes fired when animating elements pass the cursor, but the mouseleave event isn't.\n if (!(<Element>event.target).classList.contains('ng-animating')) {\n this.toastService.pause();\n }\n }\n\n /** resume countdown for toast to go away when removing cursor from it */\n public onMouseleave(): void {\n this.toastService.continue();\n }\n\n ngOnDestroy(): void {\n this.toastConfigSubscription.unsubscribe();\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects';\nimport { Store } from '@ngrx/store';\nimport { exhaustMap, map } from 'rxjs/operators';\nimport {\n addMessage,\n clearMessageTimeout,\n continueMessageExpiration,\n initializeMessageTimeout,\n pauseMessageExpiration,\n removeMessage,\n updateMessage,\n} from './toast.actions';\nimport { selectAllMessages } from './toast.selectors';\nimport { ToastState } from './toast.state';\n\n/** Effects that are related to ToastMessages */\n@Injectable()\nexport class ToastEffects {\n /** An effect that maps the message to an InitializeMessageTimeout action */\n addMessage$ = createEffect(() => {\n return this.actions$.pipe(\n ofType(addMessage),\n map(({ message }) => initializeMessageTimeout({ message }))\n );\n });\n\n /** Change a toast message timeout */\n updateMessage$ = createEffect(() => {\n return this.actions$.pipe(\n ofType(updateMessage),\n exhaustMap(({ message, ignoreTiming }) => {\n if (ignoreTiming) {\n /** FNI COMMENT :: Why? */\n return [];\n }\n\n if (message.expirationTimestamp) {\n message.duration = Date.now() - message.expirationTimestamp;\n delete message.expirationTimestamp;\n }\n\n return [clearMessageTimeout({ message }), initializeMessageTimeout({ message })];\n })\n );\n });\n\n /** If message has a duration we start a timeout with the message's duration. After the timeout we dispatch an action to clear the message */\n initializeMessageTimeout$ = createEffect(\n () => {\n return this.actions$.pipe(\n ofType(initializeMessageTimeout),\n map(({ message }) => {\n if (message.duration) {\n const expirationTimestamp = Date.now() + message.duration;\n\n const timeoutId = window.setTimeout(() => {\n this.toastStore.dispatch(removeMessage({ id: message.id }));\n }, message.duration);\n\n /** FNI COMMENT :: Why? */\n this.toastStore.dispatch(\n updateMessage({\n message: { ...message, timeoutId, expirationTimestamp },\n ignoreTiming: true,\n })\n );\n }\n })\n );\n },\n { dispatch: false }\n );\n\n /**\n * Clears timeout for specific toast message.\n * This is needed since timeout can be paused.\n */\n clearMessageTimeout$ = createEffect(() => {\n return this.actions$.pipe(\n ofType(clearMessageTimeout),\n exhaustMap((action) => {\n window.clearTimeout(action.message.timeoutId);\n const message = { ...action.message };\n\n delete message.timeoutId;\n\n return [updateMessage({ message })];\n })\n );\n });\n\n /** Pause the countdown for toast messages to go away */\n pauseMessageExpiration$ = createEffect(() => {\n return this.actions$.pipe(\n ofType(pauseMessageExpiration),\n concatLatestFrom(() => [this.toastStore.select(selectAllMessages)]),\n exhaustMap(([_, messages]) => {\n const now = Date.now();\n\n return messages\n .filter((message) => message.expirationTimestamp)\n .map((message) => {\n clearTimeout(message.timeoutId);\n const newMessage = {\n ...message,\n // Update the duration to match the remaining time\n duration: message.expirationTimestamp! - now,\n };\n\n // Remove expiration timestamp since it's now invalid\n delete newMessage.expirationTimestamp;\n\n return updateMessage({ message: newMessage, ignoreTiming: true });\n });\n })\n );\n });\n\n /** Continue the countdown for toast messages to go away */\n continueMessageExpiration$ = createEffect(() => {\n return this.actions$.pipe(\n ofType(continueMessageExpiration),\n concatLatestFrom(() => [this.toastStore.select(selectAllMessages)]),\n exhaustMap(([_, messages]) => messages.map((message) => initializeMessageTimeout({ message })))\n );\n });\n\n /** @ignore */\n constructor(private actions$: Actions, private toastStore: Store<ToastState>) {}\n}\n","import { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { EffectsModule } from '@ngrx/effects';\nimport { StoreModule } from '@ngrx/store';\nimport { ButtonModule } from '../button/button.module';\nimport { IconModule } from '../icon/icon.module';\nimport { ToastMessageComponent } from './components/toast-message/toast-message.component';\nimport { ToastMessageListComponent } from './components/toast-message-list/toast-message-list.component';\nimport { ToastService } from './services/toast.service';\nimport { ToastEffects } from './store/toast.effects';\nimport { toastFeatureKey, toastReducer } from './store/toast.reducers';\nimport { ToastConfig } from './toast-config';\nimport { IToastConfig } from './toast-config.interface';\n\n@NgModule({\n declarations: [ToastMessageComponent, ToastMessageListComponent],\n imports: [\n CommonModule,\n StoreModule.forFeature(toastFeatureKey, toastReducer),\n EffectsModule.forFeature([ToastEffects]),\n ButtonModule,\n IconModule,\n ],\n exports: [ToastMessageComponent, ToastMessageListComponent],\n providers: [ToastService],\n})\nexport class ToastModule {\n static forRoot(config: IToastConfig): ModuleWithProviders<ToastModule> {\n return {\n ngModule: ToastModule,\n providers: [{ provide: ToastConfig, useValue: config }],\n };\n }\n\n static forChild(config: IToastConfig): ModuleWithProviders<ToastModule> {\n return {\n ngModule: ToastModule,\n providers: [{ provide: ToastConfig, useValue: config }],\n };\n }\n}\n","import { HttpClient, HttpContext, HttpContextToken, HttpParams } from '@angular/common/http';\nimport { Injectable, Optional } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { ApiServiceConfig } from './config/api-service-config';\n\n/** Service that supplies access to the {@link HttpClient} but handles basic stuff as prefixing right baseURL and adding credentials. */\n@Injectable({ providedIn: 'root' })\nexport class ApiService {\n /** The URL for the internal backend */\n private _internalBackendUrl: string;\n /** The URL for Umbraco API */\n private _apiUmbracoBaseUrl: string;\n /** The URL for Next API */\n private _apiNextBaseUrl: string;\n /** The URL for NextSearch API */\n private _apiNextSearchBaseUrl: string;\n /** The URL for Lounge API */\n private _apiLoungeBaseUrl: string;\n /** The URL for Matematikfessor gateway */\n private _apiBFFGatewayBaseUrl: string;\n\n /** Handles normal DependencyInjection but also for {@link ApiServiceConfig}.\n * If no config is supplied in the providers field in the module we use the default config. */\n constructor(private httpClient: HttpClient, @Optional() config?: ApiServiceConfig) {\n const defaultConfig = new ApiServiceConfig();\n\n this._apiLoungeBaseUrl = config?.apiLoungeBaseUrl || defaultConfig.apiLoungeBaseUrl;\n this._apiNextBaseUrl = config?.apiNextBaseUrl || defaultConfig.apiNextBaseUrl;\n this._apiBFFGatewayBaseUrl = config?.apiBFFGatewayBaseUrl || defaultConfig.apiBFFGatewayBaseUrl;\n this._apiNextSearchBaseUrl = config?.apiNextSearchBaseUrl || defaultConfig.apiNextSearchBaseUrl;\n this._apiUmbracoBaseUrl = config?.apiUmbracoBaseUrl || defaultConfig.apiUmbracoBaseUrl;\n this._internalBackendUrl =\n config?.internalBackendUrl || defaultConfig.internalBackendUrlFallBack(config?.loginUsingMvcDotNet);\n }\n\n /** Used for sending a GET request to Lounge\n * @param url the url to append to the {@link _apiLoungeBaseUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getLounge<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.get<T>(this._apiLoungeBaseUrl, url, httpParams);\n }\n\n /** Used for sending a GET request to Next\n * @param url the url to append to the {@link _apiNextBaseUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getNext<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.get<T>(this._apiNextBaseUrl, url, httpParams);\n }\n\n /** Used for sending a GET request to NextSearch\n * @param url the url to append to the {@link _apiNextSearchBaseUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getNextSearch<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.get<T>(this._apiNextSearchBaseUrl, url, httpParams);\n }\n\n /** Used for sending a GET request to Umbraco\n * @param url the url to append to the {@link _apiUmbracoBaseUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getUmbraco<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.get<T>(this._apiUmbracoBaseUrl, url, httpParams);\n }\n\n /** Used for sending a GET request to the InternalBackend\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getInternalBackend<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.get<T>(this._internalBackendUrl, url, httpParams);\n }\n\n /** Used for sending a GET request to the InternalBackend with the header withCredentials set as true\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n public getInternalBackendWithCredentials<T>(url: string, httpParams?: HttpParams): Observable<T> {\n return this.httpClient.get<T>(this._internalBackendUrl + url, {\n params: httpParams,\n withCredentials: true,\n });\n }\n\n /** Used for sending a POST request to Matematikfessor BFF gateway\n * @param url the url to append to the {@link _apiBFFGatewayBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postBFFGateway<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._apiBFFGatewayBaseUrl, url, body, wwwForm);\n }\n\n /** Used for sending a POST request to Lounge\n * @param url the url to append to the {@link _apiLoungeBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postLounge<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._apiLoungeBaseUrl, url, body, wwwForm);\n }\n\n /** Used for sending a POST request to Next\n * @param url the url to append to the {@link _apiNextBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postNext<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._apiNextBaseUrl, url, body, wwwForm);\n }\n\n /** Used for sending a POST request to NextSearch\n * @param url the url to append to the {@link _apiNextSearchBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postNextSearch<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._apiNextSearchBaseUrl, url, body, wwwForm);\n }\n\n /** Used for sending a POST request to Umbraco\n * @param url the url to append to the {@link _apiUmbracoBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postUmbraco<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._apiUmbracoBaseUrl, url, body, wwwForm);\n }\n\n /** Used for sending a POST request to the InternalBackend\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n public postInternalBackend<T>(url: string, body?: any, wwwForm?: boolean): Observable<T> {\n return this.post<T>(this._internalBackendUrl, url, body, wwwForm);\n }\n\n /** Used for sending a PUT request to Lounge\n * @param url the url to append to the {@link _apiLoungeBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PUT request in the form of the ContentType\n * @returns The response from the PUT request */\n public putLounge<T>(url: string, body?: any): Observable<T> {\n return this.put<T>(this._apiLoungeBaseUrl, url, body);\n }\n\n /** Used for sending a PUT request to Next\n * @param url the url to append to the {@link _apiNextBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PUT request in the form of the ContentType\n * @returns The response from the PUT request */\n public putNext<T>(url: string, body?: any): Observable<T> {\n return this.put<T>(this._apiNextBaseUrl, url, body);\n }\n\n /** Used for sending a PUT request to NextSearch\n * @param url the url to append to the {@link _apiNextSearchBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PUT request in the form of the ContentType\n * @returns The response from the PUT request */\n public putNextSearch<T>(url: string, body?: any): Observable<T> {\n return this.put<T>(this._apiNextSearchBaseUrl, url, body);\n }\n\n /** Used for sending a PUT request to Umbraco\n * @param url the url to append to the {@link _apiUmbracoBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PUT request in the form of the ContentType\n * @returns The response from the PUT request */\n public putUmbraco<T>(url: string, body?: any): Observable<T> {\n return this.put<T>(this._apiUmbracoBaseUrl, url, body);\n }\n\n /** Used for sending a PUT request to the InternalBackend\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PUT request in the form of the ContentType\n * @returns The response from the PUT request */\n public putInternalBackend<T>(url: string, body?: any): Observable<T> {\n return this.put<T>(this._internalBackendUrl, url, body);\n }\n\n /** Used for sending a PATCH request to Lounge\n * @param url the url to append to the {@link _apiLoungeBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n public patchLounge<T>(url: string, body?: any): Observable<T> {\n return this.patch<T>(this._apiLoungeBaseUrl, url, body);\n }\n\n /** Used for sending a PATCH request to Next\n * @param url the url to append to the {@link _apiNextBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n public patchNext<T>(url: string, body?: any): Observable<T> {\n return this.patch<T>(this._apiNextBaseUrl, url, body);\n }\n\n /** Used for sending a PATCH request to NextSearch\n * @param url the url to append to the {@link _apiNextSearchBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n public patchNextSearch<T>(url: string, body?: any): Observable<T> {\n return this.patch<T>(this._apiNextSearchBaseUrl, url, body);\n }\n\n /** Used for sending a PATCH request to Umbraco\n * @param url the url to append to the {@link _apiUmbracoBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n public patchUmbraco<T>(url: string, body?: any): Observable<T> {\n return this.patch<T>(this._apiUmbracoBaseUrl, url, body);\n }\n\n /** Used for sending a PATCH request to the InternalBackend\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n public patchInternalBackend<T>(url: string, body?: any): Observable<T> {\n return this.patch<T>(this._internalBackendUrl, url, body);\n }\n\n /** Used for sending a DELETE request to Lounge\n * @param url the url to append to the {@link _apiLoungeBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n public deleteLounge<T>(url: string, body?: any): Observable<T> {\n return this.delete<T>(this._apiLoungeBaseUrl, url, body);\n }\n\n /** Used for sending a DELETE request to Next\n * @param url the url to append to the {@link _apiNextBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n public deleteNext<T>(url: string, body?: any): Observable<T> {\n return this.delete<T>(this._apiNextBaseUrl, url, body);\n }\n\n /** Used for sending a DELETE request to NextSearch\n * @param url the url to append to the {@link _apiNextSearchBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n public deleteNextSearch<T>(url: string, body?: any): Observable<T> {\n return this.delete<T>(this._apiNextSearchBaseUrl, url, body);\n }\n\n /** Used for sending a DELETE request to Umbraco\n * @param url the url to append to the {@link _apiUmbracoBaseUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n public deleteUmbraco<T>(url: string, body?: any): Observable<T> {\n return this.delete<T>(this._apiUmbracoBaseUrl, url, body);\n }\n\n /** Used for sending a DELETE request to the InternalBackend\n * @param url the url to append to the {@link _internalBackendUrl} coming from the {@link ApiServiceConfig}\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n public deleteInternalBackend<T>(url: string, body?: any): Observable<T> {\n return this.delete<T>(this._internalBackendUrl, url, body);\n }\n\n /** Used for sending POST requests\n * @param apiBaseUrl The url for the specific API you want to send the request to\n * @param url The appended url for the specific REST controller you want to send the request to\n * @param body the data to attach to the POST request in the form of the ContentType\n * @param wwwForm Whether to set ContentType to wwwForm or keep it as JSON\n * @returns The response from the POST request */\n private post<T>(apiBaseUrl: string, url: string, body?: any, wwwForm?: boolean): Observable<T> {\n const context = new HttpContext();\n\n context.set(\n new HttpContextToken(() => 'test'),\n wwwForm ? 'application/x-www-form-urlencoded; charset=utf-8' : 'application/json; charset=utf-8'\n );\n\n return this.httpClient.post<T>(apiBaseUrl + url, body, {\n context: context,\n });\n }\n\n /** Used for sending GET requests\n * @param apiBaseUrl The url for the specific API you want to send the request to\n * @param url The appended url for the specific REST controller you want to send the request to\n * @param httpParams can be used for attaching {@link HttpParams} to the request\n * @returns The response from the GET request */\n private get<T>(apiBaseUrl: string, url: string, httpParams?: HttpParams): Observable<T> {\n return this.httpClient.get<T>(apiBaseUrl + url, {\n params: httpParams,\n });\n }\n\n /** Used for sending PUT requests\n * @param apiBaseUrl The url for the specific API you want to send the request to\n * @param url The appended url for the specific REST controller you want to send the request to\n * @param body the data to attach to the POST request in the form of the ContentType\n * @returns The response from the PUT request */\n private put<T>(apiBaseUrl: string, url: string, body?: any): Observable<T> {\n return this.httpClient.put<T>(apiBaseUrl + url, body);\n }\n\n /** Used for sending DELETE requests\n * @param apiBaseUrl The url for the specific API you want to send the request to\n * @param url The appended url for the specific REST controller you want to send the request to\n * @param body the data to attach to the DELETE request in the form of the ContentType\n * @returns The response from the DELETE request */\n private delete<T>(apiBaseUrl: string, url: string, body?: any): Observable<T> {\n const httpOptions = {\n body: body,\n };\n\n return this.httpClient.delete<T>(apiBaseUrl + url, httpOptions);\n }\n\n /** Used for sending PATCH requests\n * @param apiBaseUrl The url for the specific API you want to send the request to\n * @param url The appended url for the specific REST controller you want to send the request to\n * @param body the data to attach to the PATCH request in the form of the ContentType\n * @returns The response from the PATCH request */\n private patch<T>(apiBaseUrl: string, url: string, body?: any): Observable<T> {\n return this.httpClient.patch<T>(apiBaseUrl + url, body);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { ApiService } from '../../../services/core/api/api.service';\nimport {\n ILoungePostBodyContentSearch_Status,\n ILoungeResponseContentSearch_Status,\n} from '../interfaces/endpoint/content-search-status.interface';\nimport {\n ILoungePostBodyDlp_UsersInClasses,\n ILoungeResponseDlp_Classes,\n ILoungeResponseDlp_CurrentUser,\n ILoungeResponseDlp_TeachersInInstitution,\n ILoungeResponseDlp_UsersInClass,\n ILoungeResponseDlp_UsersInClasses,\n} from '../interfaces/endpoint/dlp.interface';\nimport { ILoungeResponseLevel_GetListOfLevelsLevelGroupsAndEducationGroups } from '../interfaces/endpoint/level.interface';\nimport { ILoungeResponseTemplate } from '../interfaces/endpoint/response-template.interface';\nimport {\n ILoungePostBodySubTeam_CreateSubTeam,\n ILoungePostBodySubTeam_SaveStudentsToSubTeam,\n ILoungePutBodySubTeam_UpdateSubTeam,\n ILoungeResponseSubTeam_CreateSubTeam,\n ILoungeResponseSubTeam_GetAllSubTeamsInTeam,\n ILoungeResponseSubTeam_GetIconsAvailableToSubTeams,\n ILoungeResponseSubTeam_GetSingleSubTeam,\n ILoungeResponseSubTeam_SaveStudentsToSubTeam,\n ILoungeResponseSubTeam_UpdateSubTeam,\n} from '../interfaces/endpoint/sub-team.interface';\nimport {\n ILoungePostBodyTeam_AddTeachersToTeam,\n ILoungePostBodyTeam_AddTeacherToTeam,\n ILoungePostBodyTeam_CreateTeam,\n ILoungePostBodyTeam_SaveStudentsToTeam,\n ILoungePutBodyTeam_UpdateTeam,\n ILoungeResponseTeam_AddTeachersToTeam,\n ILoungeResponseTeam_AddTeacherToTeam,\n ILoungeResponseTeam_CreateTeam,\n ILoungeResponseTeam_GetSingleTeam,\n ILoungeResponseTeam_GetStudentsInTeam,\n ILoungeResponseTeam_GetTeamsAndClassesAvailableToUser,\n ILoungeResponseTeam_GetTeamsAvailableToUser,\n ILoungeResponseTeam_GetTeamsWhereUserIsStudent,\n ILoungeResponseTeam_SaveStudentsToTeam,\n ILoungeResponseTeam_StudentsInSubTeams,\n ILoungeResponseTeam_UpdateTeam,\n} from '../interfaces/endpoint/team.interface';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class LoungeApiService {\n /** @ignore */\n constructor(private apiService: ApiService) {}\n\n //#region DLP (classes, teachers, students) ########################################################\n dlpGetCurrentUser(): Observable<ILoungeResponseDlp_CurrentUser> {\n return this.apiService.getLounge<ILoungeResponseDlp_CurrentUser>(`v1/dlp/user`);\n }\n\n dlpGetClasses(): Observable<ILoungeResponseDlp_Classes> {\n return this.apiService.getLounge<ILoungeResponseDlp_Classes>(`v1/dlp/classes`);\n }\n\n dlpGetStudentsInClass(classId: string): Observable<ILoungeResponseDlp_UsersInClass> {\n return this.apiService.getLounge<ILoungeResponseDlp_UsersInClass>(`v1/dlp/class/${classId}/students`);\n }\n\n dlpGetClassesWithStudents(): Observable<ILoungeResponseDlp_UsersInClasses> {\n return this.apiService.getLounge<ILoungeResponseDlp_UsersInClasses>(`v1/dlp/classes/users`);\n }\n\n dlpGetStudentsInClasses(classIds: string[]): Observable<ILoungeResponseDlp_UsersInClasses> {\n const postBody: ILoungePostBodyDlp_UsersInClasses = {\n dlpClassIds: classIds,\n };\n\n return this.apiService.postLounge<ILoungeResponseDlp_UsersInClasses>(`v1/dlp/classes/students`, postBody);\n }\n\n dlpGetAllTeachersInInstitution(): Observable<ILoungeResponseDlp_TeachersInInstitution> {\n return this.apiService.getLounge<ILoungeResponseDlp_TeachersInInstitution>(`v1/dlp/teachers`);\n }\n //#endregion DLP (classes, teachers, students) ########################################################\n\n //#region LEVEL ########################################################\n levelGetListOfLevelsLevelGroupsAndEducationGroups(): Observable<ILoungeResponseLevel_GetListOfLevelsLevelGroupsAndEducationGroups> {\n return this.apiService.getLounge<ILoungeResponseLevel_GetListOfLevelsLevelGroupsAndEducationGroups>(`v1/level`);\n }\n //#endregion LEVEL ########################################################\n\n //#region SUBTEAM ########################################################\n subTeamGetSingleSubTeam(subTeamId: string): Observable<ILoungeResponseSubTeam_GetSingleSubTeam> {\n return this.apiService.getLounge<ILoungeResponseSubTeam_GetSingleSubTeam>(`v1/subteam/${subTeamId}`);\n }\n\n subTeamGetAllSubTeamsInTeam(teamId: string): Observable<ILoungeResponseSubTeam_GetAllSubTeamsInTeam> {\n return this.apiService.getLounge<ILoungeResponseSubTeam_GetAllSubTeamsInTeam>(`v1/subteam/${teamId}/list`);\n }\n\n subTeamCreateSubTeam(\n teamId: string,\n postBody: ILoungePostBodySubTeam_CreateSubTeam\n ): Observable<ILoungeResponseSubTeam_CreateSubTeam> {\n return this.apiService.postLounge<ILoungeResponseSubTeam_CreateSubTeam>(`v1/subteam/${teamId}`, postBody);\n }\n\n subTeamUpdateSubTeam(\n teamId: string,\n subTeamId: string,\n putBody: ILoungePutBodySubTeam_UpdateSubTeam\n ): Observable<ILoungeResponseSubTeam_UpdateSubTeam> {\n return this.apiService.putLounge<ILoungeResponseSubTeam_UpdateSubTeam>(\n `v1/subteam/${teamId}/${subTeamId}`,\n putBody\n );\n }\n\n subTeamDeleteSubTeam(teamId: string, subTeamId: string): Observable<ILoungeResponseTemplate> {\n return this.apiService.deleteLounge<ILoungeResponseTemplate>(`v1/subteam/${teamId}/${subTeamId}`);\n }\n\n subTeamSaveStudentsToSubTeam(\n teamId: string,\n subTeamId: string,\n postBody: ILoungePostBodySubTeam_SaveStudentsToSubTeam\n ): Observable<ILoungeResponseSubTeam_SaveStudentsToSubTeam> {\n return this.apiService.postLounge<ILoungeResponseSubTeam_SaveStudentsToSubTeam>(\n `v1/subteam/${teamId}/${subTeamId}/students`,\n postBody\n );\n }\n\n subTeamGetIconsAvailableToSubTeams(): Observable<ILoungeResponseSubTeam_GetIconsAvailableToSubTeams> {\n return this.apiService.getLounge<ILoungeResponseSubTeam_GetIconsAvailableToSubTeams>(`v1/subteam/icons`);\n }\n //#endregion SUBTEAM ########################################################\n\n //#region TEAM ########################################################\n teamGetSingleTeam(teamId: string): Observable<ILoungeResponseTeam_GetSingleTeam> {\n return this.apiService.getLounge<ILoungeResponseTeam_GetSingleTeam>(`v1/team/${teamId}`);\n }\n\n teamUpdateTeam(teamId: string, putBody: ILoungePutBodyTeam_UpdateTeam): Observable<ILoungeResponseTeam_UpdateTeam> {\n return this.apiService.putLounge<ILoungeResponseTeam_UpdateTeam>(`v1/team/${teamId}`, putBody);\n }\n\n teamDeleteTeam(teamId: string): Observable<ILoungeResponseTemplate> {\n return this.apiService.deleteLounge<ILoungeResponseTemplate>(`v1/team/${teamId}`);\n }\n\n teamGetTeamsAvailableToUser(productId: string): Observable<ILoungeResponseTeam_GetTeamsAvailableToUser> {\n return this.apiService.getLounge<ILoungeResponseTeam_GetTeamsAvailableToUser>(\n `v1/team/list?productId=${productId}`\n );\n }\n\n teamGetTeamsAndDlpClassesAvailableToUser(\n productId: string\n ): Observable<ILoungeResponseTeam_GetTeamsAndClassesAvailableToUser> {\n return this.apiService.getLounge<ILoungeResponseTeam_GetTeamsAndClassesAvailableToUser>(\n `v1/team/listwithclasses?productId=${productId}`\n );\n }\n\n teamGetTeamsWhereUserIsStudent(productId: string): Observable<ILoungeResponseTeam_GetTeamsWhereUserIsStudent> {\n return this.apiService.getLounge<ILoungeResponseTeam_GetTeamsWhereUserIsStudent>(\n `v1/team/student-in/list?productId=${productId}`\n );\n }\n\n teamCreateTeam(postBody: ILoungePostBodyTeam_CreateTeam): Observable<ILoungeResponseTeam_CreateTeam> {\n return this.apiService.postLounge<ILoungeResponseTeam_CreateTeam>(`v1/team`, postBody);\n }\n\n teamSaveStudentsToTeam(\n teamId: string,\n postBody: ILoungePostBodyTeam_SaveStudentsToTeam\n ): Observable<ILoungeResponseTeam_SaveStudentsToTeam> {\n return this.apiService.postLounge<ILoungeResponseTeam_SaveStudentsToTeam>(`v1/team/${teamId}/students`, postBody);\n }\n\n teamGetStudentsInTeam(teamId: string): Observable<ILoungeResponseTeam_GetStudentsInTeam> {\n return this.apiService.getLounge<ILoungeResponseTeam_GetStudentsInTeam>(`v1/team/${teamId}/students`);\n }\n\n teamGetStudentsInSubTeams(teamId: string): Observable<ILoungeResponseTeam_StudentsInSubTeams> {\n return this.apiService.getLounge<ILoungeResponseTeam_StudentsInSubTeams>(`v1/team/${teamId}/students-in-subteams`);\n }\n\n teamAddTeacher(\n teamId: string,\n postBody: ILoungePostBodyTeam_AddTeacherToTeam\n ): Observable<ILoungeResponseTeam_AddTeacherToTeam> {\n return this.apiService.postLounge<ILoungeResponseTeam_AddTeacherToTeam>(`v1/team/${teamId}/teacher`, postBody);\n }\n\n teamRemoveTeacher(teamId: string, userId: string): Observable<ILoungeResponseTemplate> {\n return this.apiService.deleteLounge<ILoungeResponseTemplate>(`v1/team/${teamId}/teacher/${userId}`);\n }\n\n teamRemoveSelf(teamId: string): Observable<ILoungeResponseTemplate> {\n return this.apiService.deleteLounge<ILoungeResponseTemplate>(`v1/team/${teamId}/teacher/self`);\n }\n\n teamAddTeachers(\n teamId: string,\n postBody: ILoungePostBodyTeam_AddTeachersToTeam\n ): Observable<ILoungeResponseTeam_AddTeachersToTeam> {\n return this.apiService.postLounge<ILoungeResponseTeam_AddTeachersToTeam>(`v1/team/${teamId}/teachers`, postBody);\n }\n //#endregion TEAM ########################################################\n\n //#region CONTENT SEARCH STATUS ########################################################\n\n /**\n * content search status\n * @param postBody\n * @returns\n */\n contentSearchStatus(postBody: ILoungePostBodyContentSearch_Status): Observable<ILoungeResponseContentSearch_Status> {\n return this.apiService.postLounge<ILoungeResponseContentSearch_Status>(`v1/contentsearchstatus`, postBody);\n }\n\n //#endregion TEAM ########################################################\n}\n","import { Injectable } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Actions, createEffect, ofType } from '@ngrx/effects';\nimport { Store } from '@ngrx/store';\nimport { combineLatest, of } from 'rxjs';\nimport { catchError, exhaustMap, filter, map, mergeMap, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';\nimport { UmbracoService } from '../../../services/core/umbraco/umbraco.service';\nimport { UserService } from '../../../services/core/user/user.service';\nimport { GoogleTagManagerService } from '../../../services/gtm/google-tag-manager.service';\nimport {\n LoungeCreateTeamDone,\n LoungeDeleteTeamDone,\n LoungeEditTeacherDone,\n LoungeEditTeam,\n LoungeEditTeamDone,\n LoungeEditTeamSettingsDone,\n LoungeRemoveTeacherDone,\n} from '../../../services/gtm/gtm-events.const';\nimport { SharedLoadingKeys } from '../../../services/loading/shared-loading-keys.enums';\nimport { ToastService } from '../../toast/services/toast.service';\nimport { LoungeModalPages } from '../enums/lounge-modal-pages.enum';\nimport { PermissionDto } from '../interfaces/endpoint/dtos/dto-permission.interface';\nimport { TeamWithTeachersDto } from '../interfaces/endpoint/dtos/dto-team-with-teachers.interface';\nimport { ILoungePostBodyTeam_AddTeachersToTeam } from '../interfaces/endpoint/team.interface';\nimport { LoungeApiService } from '../services/lounge-api.service';\nimport { LoungeModalService } from '../services/lounge-modal.service';\nimport { LoungeService } from '../services/lounge.service';\n\nimport {\n IClassWithSelected,\n IClassWithUsers,\n IUserPermissionWithSelected,\n IUserWithSelected,\n} from './interfaces/team-edit.interface';\nimport * as LoungeActions from './lounge.actions';\nimport { LoungeState } from './lounge.state';\n\n@Injectable()\nexport class LoungeEffects {\n levelLoadLevels$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.levelLoadLevels),\n exhaustMap((action) =>\n this.loungeApiService.levelGetListOfLevelsLevelGroupsAndEducationGroups().pipe(\n map((response) =>\n LoungeActions.levelLoadLevelsSuccess({\n fullLevel: response.result,\n loadingKey: action.loadingKey,\n })\n ),\n catchError((error) => of(LoungeActions.levelLoadLevelsFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n dlpLoadTeachers$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.dlpLoadTeachers),\n exhaustMap((action) =>\n this.loungeApiService.dlpGetAllTeachersInInstitution().pipe(\n map((data) => {\n const teacherList: IUserPermissionWithSelected[] = [];\n\n data.result.forEach((x) => {\n const teacher: IUserPermissionWithSelected = {\n permission: {\n canCreateSubTeam: false,\n canDeleteSubTeam: false,\n canDeleteTeam: false,\n canEditSubTeam: false,\n canEditTeam: false,\n canViewSubTeam: false,\n isOwner: false,\n },\n user: {\n firstName: x.firstName,\n id: x.id,\n lastName: x.lastName,\n name: x.name,\n role: x.role,\n selected: false,\n },\n };\n\n teacherList.push(teacher);\n });\n return teacherList;\n }),\n map((data) =>\n LoungeActions.dlpLoadTeachersSuccess({\n teachers: data,\n })\n ),\n catchError((error) => of(LoungeActions.dlpLoadTeachersFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n dlpLoadClassesWithStudents$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.dlpLoadClassesWithStudents),\n mergeMap((action) =>\n this.loungeApiService.dlpGetClassesWithStudents().pipe(\n map((data) => {\n const classWithUsersList: IClassWithUsers[] = data.result\n .filter((x) => x.users.length > 0)\n .map((x) => {\n const _class: IClassWithSelected = {\n id: x.class.id,\n levelId: x.class.levelId,\n name: x.class.name,\n selected: false,\n };\n const classWithUsers: IClassWithUsers = {\n class: _class,\n users: x.users.map((x) => {\n const user: IUserWithSelected = {\n id: x.id,\n firstName: x.firstName,\n lastName: x.lastName,\n name: x.name,\n role: x.role,\n selected: false,\n };\n\n return user;\n }),\n };\n\n return classWithUsers;\n });\n\n return classWithUsersList;\n }),\n map((data) =>\n LoungeActions.dlpLoadClassesWithStudentsSuccess({\n loadingKey: action.loadingKey,\n classes: data,\n })\n ),\n catchError((error) =>\n of(LoungeActions.dlpLoadClassesWithStudentsFailure({ error, loadingKey: action.loadingKey }))\n )\n )\n )\n )\n );\n\n markTeacherForSelection$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.markTeacherForSelection),\n withLatestFrom(this.loungeService.teamEdit$, this.userService.user$),\n map(([action, teamEdit, currentUser]) => {\n const _currentTeacher = teamEdit?.teachers.find((t) => t.user.id === currentUser?.userId);\n const _permission: PermissionDto = JSON.parse(JSON.stringify(_currentTeacher?.permission));\n\n return LoungeActions.markTeacherForSelectionSuccess({\n teacherId: action.teacherId,\n selected: action.selected,\n permission: _permission,\n });\n })\n )\n );\n\n markClassForSelection$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.markClassForSelection),\n map((action) =>\n LoungeActions.markClassForSelectionSuccess({\n classId: action.classId,\n selected: action.selected,\n searchTerm: action.searchTerm,\n })\n )\n )\n );\n\n markStudentForSelection$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.markStudentForSelection),\n map((action) =>\n LoungeActions.markStudentForSelectionSuccess({\n classId: action.classId,\n userId: action.userId,\n selected: action.selected,\n })\n )\n )\n );\n\n removeSelectionsForStudents$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.removeSelectionsFromStudents),\n map((_) => LoungeActions.removeSelectionsFromStudentsSuccess())\n )\n );\n\n removeSelectionsFromTeachers$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.removeSelectionsFromTeachers),\n map((_) => LoungeActions.removeSelectionsFromTeachersSuccess())\n )\n );\n\n teamLoadTeams$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamLoadTeams),\n mergeMap((action) =>\n this.loungeApiService.teamGetTeamsAvailableToUser(this.umbracoService.productId).pipe(\n map((response) =>\n LoungeActions.teamLoadTeamsSuccess({ loadingKey: action.loadingKey, teamList: response.result })\n ),\n catchError((error) => of(LoungeActions.teamLoadTeamsFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n teamSaveStudentsToTeam$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamSaveStudentsToTeam),\n mergeMap((action) =>\n this.loungeApiService.teamSaveStudentsToTeam(action.teamId, { studentIds: action.studentIds }).pipe(\n tap((_) => {\n this.toastService.displayMessage('Elever gemt til holdet');\n this.loungeModalService.setPageToNone();\n this.loungeStore.dispatch(\n LoungeActions.teamLoadSingleTeamForEdit({ loadingKey: action.loadingKey, teamId: action.teamId })\n );\n }),\n map((_) =>\n LoungeActions.teamSaveStudentsToTeamSuccess({ loadingKey: action.loadingKey, teamId: action.teamId })\n ),\n catchError((error) =>\n of(LoungeActions.teamSaveStudentsToTeamFailure({ error, loadingKey: action.loadingKey }))\n )\n )\n )\n )\n );\n\n teamSaveStudentsToTeamSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamSaveStudentsToTeamSuccess),\n tap(() => this.gtmService.pushTagWithUserType(LoungeEditTeamDone)),\n map(() => LoungeActions.teamLoadTeams({ loadingKey: SharedLoadingKeys.teams }))\n )\n );\n\n removeTeam$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamDeleteTeam),\n mergeMap((action) =>\n this.loungeApiService.teamDeleteTeam(action.teamId).pipe(\n map(() => LoungeActions.teamDeleteTeamSuccess({ teamId: action.teamId })),\n catchError((error) => of(LoungeActions.teamDeleteTeamFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n removeTeamSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamDeleteTeamSuccess),\n tap((_) => {\n this.toastService.displayMessage('Holdet er slettet');\n this.gtmService.pushTagWithUserType(LoungeDeleteTeamDone);\n }),\n map((_) => LoungeActions.teamEditTeamCancel())\n )\n );\n\n editTeamDetails$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamSaveDetailsToTeam),\n mergeMap((action) =>\n this.loungeApiService\n .teamUpdateTeam(action.teamId, {\n title: action.title,\n levelIds: action.levelIds,\n })\n .pipe(\n map((_) =>\n LoungeActions.teamSaveDetailsToTeamSuccess({ loadingKey: action.loadingKey, teamId: action.teamId })\n ),\n catchError((error) =>\n of(LoungeActions.teamSaveDetailsToTeamFailure({ error, loadingKey: action.loadingKey }))\n )\n )\n )\n )\n );\n\n editTeamDetailsSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamSaveDetailsToTeamSuccess),\n tap((action) => {\n this.loungeModalService.setPageToNone();\n this.toastService.displayMessage('Ændringer gemt');\n this.loungeStore.dispatch(\n LoungeActions.teamLoadSingleTeamForEdit({ loadingKey: action.loadingKey, teamId: action.teamId })\n );\n this.gtmService.pushTagWithUserType(LoungeEditTeamSettingsDone);\n }),\n map((_) => LoungeActions.teamLoadTeams({ loadingKey: SharedLoadingKeys.teams }))\n )\n );\n\n teamCreateTeam$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamCreateTeam),\n mergeMap((action) =>\n this.loungeApiService.teamCreateTeam(action.team).pipe(\n map((response) =>\n LoungeActions.teamCreateTeamSuccess({ loadingKey: action.loadingKey, teamId: response.result })\n ),\n catchError((error) => of(LoungeActions.teamCreateTeamFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n teamCreateTeamSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamCreateTeamSuccess),\n tap((_) => {\n this.toastService.displayMessage('Hold oprettet');\n this.loungeModalService.setPageToNone();\n this.gtmService.pushTagWithUserType(LoungeCreateTeamDone);\n }),\n map((_) => LoungeActions.teamLoadTeams({ loadingKey: SharedLoadingKeys.teams }))\n )\n );\n\n teamEditTeam$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamEditTeam),\n map((action) =>\n LoungeActions.teamLoadStudents({ loadingKey: SharedLoadingKeys.teamStudents, teamId: action.team.id })\n )\n )\n );\n\n teamEditTeamCancel$ = createEffect(\n () =>\n this.actions$.pipe(\n ofType(LoungeActions.teamEditTeamCancel),\n tap((_) => {\n this.router.navigateByUrl(window.location.pathname);\n this.loungeModalService.setPageToNone();\n })\n ),\n { dispatch: false }\n );\n\n teamEditAssignTeachers$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamEditAssignTeachers),\n tap(() => this.loungeModalService.setPage(LoungeModalPages.shareWithTeachers)),\n switchMap((action) =>\n combineLatest([\n of(action),\n this.loungeService.dlpTeachersListWithoutCurrentUser$.pipe(\n filter((x) => !!x),\n take(1)\n ),\n this.loungeService.teamEdit$.pipe(\n filter((x) => !!x),\n take(1)\n ),\n ])\n ),\n map(([action, teachersList, teamEdit]) => {\n const clone = JSON.parse(JSON.stringify(teachersList)) as IUserPermissionWithSelected[];\n\n teamEdit?.teachers.forEach((selectedTeacher) => {\n const selectedUser = clone.find((teacher) => teacher.user.id === selectedTeacher.user.id);\n\n if (selectedUser) {\n selectedUser.user.selected = true;\n }\n });\n return LoungeActions.teamEditAssignTeachersSuccess({\n teachers: clone,\n loadingKey: action.loadingKey,\n });\n })\n )\n );\n\n teamEditAssignStudents$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamEditAssignStudents),\n tap(() => {\n this.gtmService.pushTagWithUserType(LoungeEditTeam);\n this.loungeModalService.setPage(LoungeModalPages.studentPicker);\n }),\n switchMap((_) =>\n combineLatest([\n this.loungeService.dlpClassWithStudentsList$.pipe(\n filter((x) => !!x),\n take(1)\n ),\n this.loungeService.teamEdit$.pipe(\n filter((x) => !!x),\n take(1)\n ),\n ])\n ),\n map(([classWithStudentsList, teamEdit]) => {\n const clone = JSON.parse(JSON.stringify(classWithStudentsList)) as IClassWithUsers[];\n\n teamEdit?.students.forEach((selectedStudent) => {\n const selectedUser = clone\n .find((classDto) => classDto.users.find((users) => users.id === selectedStudent.id))\n ?.users.find((x) => x.id === selectedStudent.id);\n\n if (selectedUser) {\n selectedUser.selected = true;\n }\n });\n\n clone.forEach((x) => {\n if (!x.users.find((u) => u.selected === false)) {\n x.class.selected = true;\n }\n });\n\n return LoungeActions.teamEditAssignStudentsSuccess({\n classWithSelectedUsersList: clone,\n });\n })\n )\n );\n\n teamLoadStudents$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamLoadStudents),\n mergeMap((action) =>\n this.loungeApiService.teamGetStudentsInTeam(action.teamId).pipe(\n map((response) => {\n return LoungeActions.teamLoadStudentsSuccess({\n loadingKey: action.loadingKey,\n studentList: response.result,\n });\n }),\n catchError((error) => of(LoungeActions.teamLoadStudentsFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n teamDeleteModal$ = createEffect(\n () =>\n this.actions$.pipe(\n ofType(LoungeActions.teamDeleteModal),\n tap(() => this.loungeModalService.setPage(LoungeModalPages.deleteTeam))\n ),\n { dispatch: false }\n );\n\n teamEditDetailsModal = createEffect(\n () =>\n this.actions$.pipe(\n ofType(LoungeActions.teamEditDetailsModal),\n tap(() => this.loungeModalService.setPage(LoungeModalPages.detailsInput))\n ),\n { dispatch: false }\n );\n\n teamRemoveTeacherSelfModal$ = createEffect(\n () =>\n this.actions$.pipe(\n ofType(LoungeActions.teamRemoveTeacherSelfModal),\n tap(() => this.loungeModalService.setPage(LoungeModalPages.removeTeacherSelf))\n ),\n { dispatch: false }\n );\n\n teamRemoveTeacherSelf$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamRemoveTeacherSelf),\n mergeMap((action) =>\n this.loungeApiService.teamRemoveSelf(action.team.id).pipe(\n map((_) => LoungeActions.teamRemoveTeacherSelfSuccess({ team: action.team })),\n catchError((error) =>\n of(LoungeActions.teamRemoveTeacherSelfFailure({ error, loadingKey: action.loadingKey }))\n )\n )\n )\n )\n );\n\n teamRemoveTeacherSelfSuccess$ = createEffect(\n () =>\n this.actions$.pipe(\n ofType(LoungeActions.teamRemoveTeacherSelfSuccess),\n tap((_) => {\n this.loungeModalService.setPageToNone();\n this.router.navigateByUrl(window.location.pathname);\n this.gtmService.pushTagWithUserType(LoungeRemoveTeacherDone);\n })\n ),\n { dispatch: false }\n );\n\n teamAddTeachers$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamAddTeachers),\n mergeMap((action) => {\n const postBody: ILoungePostBodyTeam_AddTeachersToTeam = {\n teachers: action.teachers,\n };\n\n return this.loungeApiService.teamAddTeachers(action.teamId, postBody).pipe(\n tap((_) => {\n this.toastService.displayMessage('Lærere opdateret');\n this.loungeModalService.setPageToNone();\n }),\n map((_) => LoungeActions.teamAddTeachersSuccess({ loadingKey: action.loadingKey, teamId: action.teamId })),\n catchError((error) => of(LoungeActions.teamAddTeachersFailure({ error, loadingKey: action.loadingKey })))\n );\n })\n )\n );\n\n teamAddTeachersSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamAddTeachersSuccess),\n tap(() => this.gtmService.pushTagWithUserType(LoungeEditTeacherDone)),\n map((action) => LoungeActions.teamLoadSingleTeamForEdit({ loadingKey: action.loadingKey, teamId: action.teamId }))\n )\n );\n\n teamAddTeachersSuccessLoadTeams$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamAddTeachersSuccess),\n map(() => LoungeActions.teamLoadTeams({ loadingKey: SharedLoadingKeys.teams }))\n )\n );\n\n teamAddTeacher$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamAddTeacher),\n mergeMap((action) => {\n return this.loungeApiService.teamAddTeacher(action.teamId, action.teacher).pipe(\n switchMap((_) => [\n LoungeActions.teamAddTeacherSuccess({ loadingKey: action.loadingKey, teamId: action.teamId }),\n ]),\n catchError((error) => of(LoungeActions.teamAddTeacherFailure({ error, loadingKey: action.loadingKey })))\n );\n })\n )\n );\n\n teamAddTeacherSuccess$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamAddTeacherSuccess),\n switchMap((action) =>\n this.loungeApiService.teamGetTeamsAvailableToUser(this.umbracoService.productId).pipe(\n map((response) => {\n this.loungeStore.dispatch(\n LoungeActions.teamEditTeam({\n loadingKey: action.loadingKey,\n team: response.result.find((t) => t.id === action.teamId) || ({} as TeamWithTeachersDto),\n })\n );\n return LoungeActions.teamLoadTeamsSuccess({ loadingKey: action.loadingKey, teamList: response.result });\n }),\n catchError((error) => of(LoungeActions.teamLoadTeamsFailure({ error, loadingKey: action.loadingKey })))\n )\n )\n )\n );\n\n teamLoadSingleTeamForEdit$ = createEffect(() =>\n this.actions$.pipe(\n ofType(LoungeActions.teamLoadSingleTeamForEdit),\n mergeMap((action) =>\n this.loungeApiService.teamGetSingleTeam(action.teamId).pipe(\n map((response) => LoungeActions.teamEditTeam({ loadingKey: action.loadingKey, team: response.result })),\n catchError((error) => {\n this.router.navigateByUrl(window.location.pathname);\n return of(LoungeActions.teamLoadSingleTeamForEditFailure({ error, loadingKey: action.loadingKey }));\n })\n )\n )\n )\n );\n\n /** @ignore */\n constructor(\n private actions$: Actions,\n private loungeApiService: LoungeApiService,\n private loungeStore: Store<LoungeState>,\n private loungeService: LoungeService,\n private router: Router,\n private toastService: ToastService,\n private umbracoService: UmbracoService,\n private userService: UserService,\n private loungeModalService: LoungeModalService,\n private gtmService: GoogleTagManagerService\n ) {}\n}\n","import { CommonModule } from '@angular/common';\nimport { ModuleWithProviders, NgModule } from '@angular/core';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { MatExpansionModule } from '@angular/material/expansion';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field';\nimport { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu';\nimport { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select';\nimport { EffectsModule } from '@ngrx/effects';\nimport { StoreModule } from '@ngrx/store';\nimport { LoadingAnimationModule } from '../../components/loading-animation/loading-animation.module';\nimport { SearchUserPermissionWithSelectedListPipe } from '../../utils/pipes/search-user-permission-with-selected-list.pipe';\nimport { ButtonModule } from '../button/button.module';\nimport { CheckboxModule } from '../checkbox/checkbox.module';\nimport { DropdownModule } from '../dropdown/dropdown.module';\nimport { IconModule } from '../icon/icon.module';\nimport { ModalModule } from '../modal/modal.module';\nimport { ToastModule } from '../toast/toast.module';\nimport { BoxComponent } from './components/__shared/box/box.component';\nimport { TeamHeaderComponent } from './components/__shared/team-header/team-header.component';\nimport { TeamBoxComponent } from './components/team-box/team-box.component';\nimport { TeamCreationComponent } from './components/team-creation/team-creation.component';\nimport { TeamDetailsFormComponent } from './components/team-creation/team-details-form/team-details-form.component';\nimport { SearchClassWithUsersPipe } from './components/team-creation/team-picker/pipes/search-class-with-users.pipe';\nimport { TeamPickerComponent } from './components/team-creation/team-picker/team-picker.component';\nimport { TeamEditAssignStudentsComponent } from './components/team-edit/team-edit-assign-students/team-edit-assign-students.component';\nimport { TeamEditAssignTeachersComponent } from './components/team-edit/team-edit-assign-teachers/team-edit-assign-teachers.component';\nimport { TeamEditDeleteComponent } from './components/team-edit/team-edit-delete/team-edit-delete.component';\nimport { TeamEditDetailsComponent } from './components/team-edit/team-edit-details/team-edit-details.component';\nimport { TeamEditDropdownComponent } from './components/team-edit/team-edit-dropdown/team-edit-dropdown.component';\nimport { TeamEditRemoveTeacherSelfComponent } from './components/team-edit/team-edit-remove-teacher-self/team-edit-remove-teacher-self.component';\nimport { TeamEditComponent } from './components/team-edit/team-edit.component';\nimport { TeamPickerTeacherComponent } from './components/team-edit/team-picker-teacher/team-picker-teacher.component';\nimport { TeamOverviewComponent } from './components/team-overview/team-overview.component';\nimport { LoungeConfig } from './lounge-config';\nimport { ILoungeConfig } from './lounge-config.interface';\nimport { LoungeEffects } from './store/lounge.effects';\nimport { loungeFeatureKey, loungeReducer } from './store/lounge.reducers';\n\n@NgModule({\n declarations: [\n TeamOverviewComponent,\n TeamBoxComponent,\n TeamCreationComponent,\n TeamPickerComponent,\n TeamDetailsFormComponent,\n TeamEditComponent,\n BoxComponent,\n TeamEditDropdownComponent,\n TeamEditAssignStudentsComponent,\n TeamHeaderComponent,\n TeamEditDeleteComponent,\n TeamEditDetailsComponent,\n SearchClassWithUsersPipe,\n SearchUserPermissionWithSelectedListPipe,\n TeamEditRemoveTeacherSelfComponent,\n TeamEditAssignTeachersComponent,\n TeamPickerTeacherComponent,\n ],\n imports: [\n IconModule,\n CommonModule,\n MatMenuModule,\n MatIconModule,\n MatFormFieldModule,\n MatSelectModule,\n MatExpansionModule,\n ModalModule,\n StoreModule.forFeature(loungeFeatureKey, loungeReducer),\n EffectsModule.forFeature([LoungeEffects]),\n FormsModule,\n ReactiveFormsModule,\n DropdownModule,\n ToastModule,\n CheckboxModule,\n ButtonModule,\n LoadingAnimationModule,\n ],\n exports: [TeamOverviewComponent, TeamEditComponent],\n})\nexport class LoungeModule {\n static forRoot(config?: ILoungeConfig): ModuleWithProviders<LoungeModule> {\n return {\n ngModule: LoungeModule,\n providers: [{ provide: LoungeConfig, useValue: config }],\n };\n }\n\n static forChild(config?: ILoungeConfig): ModuleWithProviders<LoungeModule> {\n return {\n ngModule: LoungeModule,\n providers: [{ provide: LoungeConfig, useValue: config }],\n };\n }\n}\n","import { HttpEvent, HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { Observable, of, throwError } from 'rxjs';\nimport { catchError, mergeMap, switchMap } from 'rxjs/operators';\nimport { UserService } from '../../user/user.service';\n\n/** Interceptor that catches all HTTP requests and add authentication headers to the request. */\n@Injectable()\nexport class AuthInterceptor implements HttpInterceptor {\n /** @ignore */\n constructor(private userService: UserService) {}\n\n /** @ignore */\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<any>> {\n return this.addAuth(request).pipe(\n mergeMap((request) => next.handle(request)),\n catchError((x) => throwError(() => x))\n );\n }\n\n /** Adds authentication headers on the HTTP request.\n * @param request The intercepted request\n * @returns The intercepted request with the added authentication headers */\n private addAuth(request: HttpRequest<unknown>): Observable<HttpRequest<unknown>> {\n return this.userService.user$.pipe(\n switchMap((user) => {\n request = request.clone({\n setHeaders: {\n 'Content-Type': 'application/json; charset=utf-8',\n },\n });\n if (user) {\n const headers = new HttpHeaders({\n Authorization: `Bearer ${user.accessToken}`,\n AuthenticationToken: user.authenticationToken,\n ContextIdentifier: user.contextIdentifier,\n InstitutionNumber: user.institutionNumber,\n });\n\n request = request.clone({ headers });\n }\n\n return of(request);\n })\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Actions, createEffect, ofType } from '@ngrx/effects';\nimport { tap } from 'rxjs';\nimport { ToastService } from '../../../modules/toast/services/toast.service';\nimport { actionsThatError } from './loading.reducers';\n\n/** Effects for loading.state.ts */\n@Injectable()\nexport class LoadingEffects {\n /** When error occur in one of specified functions show error toast */\n showErrorMessagesAsToasts$ = createEffect(\n () => {\n return this.actions$.pipe(\n ofType(...actionsThatError),\n tap((action) => this.toastService.displayMessage(`Fejlbesked: ${action.error.message}`))\n );\n },\n { dispatch: false }\n );\n\n /** @ignore */\n constructor(private actions$: Actions, private toastService: ToastService) {}\n}\n","import { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\nimport { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';\nimport { EffectsModule } from '@ngrx/effects';\nimport { StoreModule } from '@ngrx/store';\nimport { LoadingAnimationModule } from '../../components/loading-animation/loading-animation.module';\nimport { LoadingEffects } from '../loading/store/loading.effects';\nimport { loadingFeatureKey, loadingReducer } from '../loading/store/loading.reducers';\nimport { MouseKeyboardService } from '../mouse-keyboard/mouse-keyboard.service';\nimport { ApiServiceConfig } from './api/config/api-service-config';\nimport { IServicesModuleConfiguration } from './interfaces/service-module-configuration.interface';\n\n@NgModule({\n declarations: [],\n imports: [\n CommonModule,\n HttpClientModule,\n StoreModule.forFeature(loadingFeatureKey, loadingReducer),\n EffectsModule.forFeature([LoadingEffects]),\n LoadingAnimationModule,\n ],\n})\nexport class CoreModule {\n /** Ensures CoreModule is only loaded once. Also loads MouseKeyboardService so even if the depending projects aren't DependencyInjecting it, it will still load and add functionality for FELIB. */\n constructor(public mouseKeyboardService: MouseKeyboardService, @Optional() @SkipSelf() parentModule?: CoreModule) {\n if (parentModule) {\n throw new Error('CoreModule is already loaded. Import it in the AppModule only');\n }\n }\n\n static forRoot(config?: IServicesModuleConfiguration): ModuleWithProviders<CoreModule> {\n return {\n ngModule: CoreModule,\n providers: [{ provide: ApiServiceConfig, useValue: config?.apiConfig }],\n };\n }\n}\n","import { Injectable, Optional } from '@angular/core';\nimport { ApiServiceConfig } from '../api/config/api-service-config';\n\n@Injectable({ providedIn: 'root' })\nexport class LocalService {\n /** The local hostname for contacting Umbraco */\n private _localHostname: string;\n\n /** @ignore */\n constructor(@Optional() config?: ApiServiceConfig) {\n const defaultConfig = new ApiServiceConfig();\n\n this._localHostname = config?.localHostname ?? defaultConfig.localHostname;\n }\n\n /** Returns the hostname. If we're on localhost it returns the hardcoded domain.\n * @example 'superbog.dev.alineadigital.dk' */\n get hostName(): string {\n return this.isLocalhost() ? this._localHostname : window.location.hostname;\n }\n\n /** Determines if {@link Window.location} is localhost.\n * @returns A boolean value indicating if the current location is localhost */\n isLocalhost(): boolean {\n return window.location.hostname === 'localhost';\n }\n}\n","import { HttpErrorResponse } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { EMPTY, catchError, firstValueFrom, map } from 'rxjs';\nimport { LocalService } from '../local/local.service';\nimport { IUmbSiteConfiguration } from '../umbraco/interfaces/configuration/umb-site-configuration.interface';\nimport { ISiteConfiguration } from '../umbraco/interfaces/site-configuration.interface';\nimport { UmbracoService } from '../umbraco/umbraco.service';\nimport { IUser } from '../user/interfaces/user.interface';\nimport { UserService } from '../user/user.service';\nimport { ApiService } from './../api/api.service';\n\n/** A service for initializing the web application */\n@Injectable({ providedIn: 'root' })\nexport class InitService {\n /** @ignore */\n constructor(\n private apiService: ApiService,\n private userService: UserService,\n private umbracoService: UmbracoService,\n private localService: LocalService\n ) {}\n\n /** A method that initializes the login by retrieving the user from the internal backend. Furthermore it handles differences between MF and Fagportal response which is not identical.\n *\n * The method also retrieves and stores the configuration from Umbraco. */\n async initializeLogin(): Promise<void> {\n const user = await this.retrieveUser();\n\n if (user) {\n this.userService.setUser(user);\n }\n\n const siteConfiguration = await this.retrieveConfig();\n\n if (siteConfiguration) {\n this.umbracoService.setConfiguration(siteConfiguration);\n }\n }\n\n /** Retrieves the site configuration from Umbraco and maps it */\n private async retrieveConfig(): Promise<ISiteConfiguration | undefined> {\n return await firstValueFrom(\n this.apiService\n .getUmbraco<IUmbSiteConfiguration>(\n `alineaportal/getportal/${this.localService.hostName}/${this.userService.userType}`\n )\n .pipe(\n catchError((error: HttpErrorResponse) => {\n console.error(`%cThere was a problem fetching siteconfig.`, 'background: red; color: white', error.message);\n return EMPTY;\n }),\n map((json) => {\n if (!json) {\n return;\n }\n\n const siteConfig: ISiteConfiguration = {\n productId: json.id.toString(),\n };\n\n return siteConfig;\n })\n )\n );\n }\n\n /** Retrieves the user model from the internal backend. Maps it correctly to the IUser interface according to what internal backend is used */\n private async retrieveUser(): Promise<IUser | undefined> {\n return await firstValueFrom(\n this.apiService.getInternalBackendWithCredentials('Home/GetUserModel').pipe(\n catchError((error: HttpErrorResponse) => {\n console.error(\n `%cWhen you run the project on localhost, you need to start the express server. User model data could not be loaded and it's nessesary to perform login.`,\n 'background: red; color: white',\n error.message\n );\n return EMPTY;\n }),\n map((json: any) => {\n if (!json) {\n return;\n }\n\n // MF returns camelCase properties\n if (json?.userId) {\n return json as IUser;\n }\n\n // Fagportal returns PascalCase properties\n const user: IUser = {\n userId: json.UserId,\n contextIdentifier: json.ContextIdentifier,\n accessToken: json.AccessToken,\n initials: json.Initials,\n hasAccess: json.HasAccess,\n userName: json.UserName,\n isTeacher: json.IsTeacher,\n isAlineaUser: json.IsAlineaUser,\n displayName: json.DisplayName,\n authenticationToken: json.AuthenticationToken,\n buildKey: json.BuildKey,\n institutionName: json.InstitutionName,\n institutionId: json.InstitutionId,\n institutionShortId: json.InstitutionShortId,\n institutionNumber: json.InstitutionNumber,\n expiresAt: json.ExpiresAt,\n idToken: json.IdToken,\n doNotTrack: json.DoNotTrack,\n };\n\n return user;\n })\n )\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { ICssColors } from './css-color.interfaces';\nimport { cssColorVariant } from './css-color.types';\n\n/** Service used to add css variables and their variations to the site */\n@Injectable({\n providedIn: 'root',\n})\nexport class CssColorService {\n /** Adds CSS variables to the sites HTML element\n * @param colors array of colors that should be added as CSS variables */\n setCssColors(colors: ICssColors): void {\n colors.items.forEach((color) => {\n const rgb = this.hexToRgb(color.hex100);\n\n if (rgb) {\n document.documentElement.style.setProperty(\n `--${colors.prefix ? colors.prefix + '-' : ''}${color.name}${color.add100Suffix ? '-100' : ''}`,\n rgb\n );\n }\n\n color.variants?.forEach((variant) => {\n const variantHex = this.lightenDarkenHexColor(color.hex100, this.convertCssColorVariantToPercentage(variant));\n const variantRgb = this.hexToRgb(variantHex);\n\n if (variantRgb) {\n document.documentElement.style.setProperty(\n `--${colors.prefix ? colors.prefix + '-' : ''}${color.name}-${variant}`,\n variantRgb\n );\n }\n });\n });\n }\n\n /** Converts HEX value to RGB value\n * @param hex A HEX value to convert to RGB\n * @returns a string consisting of RGB values */\n hexToRgb(hex?: string): string | undefined {\n if (!hex) {\n return;\n }\n\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\n return result ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : undefined;\n }\n\n /**\n * ligten or darken a HEX color\n * @param color hex value like \"#ff0000\" or \"ff0000\"\n * @param percent plus percentage makes it lighter. minus percentage makes it darker.\n * @returns hex color\n */\n private lightenDarkenHexColor(color: string, percent: number): string {\n const num = parseInt(color.replace('#', ''), 16);\n const amt = Math.round(2.55 * percent);\n\n /* eslint-disable no-bitwise */\n const r = (num >> 16) + amt;\n const b = ((num >> 8) & 0x00ff) + amt;\n const g = (num & 0x0000ff) + amt;\n /* eslint-enable no-bitwise */\n\n return (\n '#' +\n (\n 0x1000000 +\n (r < 255 ? (r < 1 ? 0 : r) : 255) * 0x10000 +\n (b < 255 ? (b < 1 ? 0 : b) : 255) * 0x100 +\n (g < 255 ? (g < 1 ? 0 : g) : 255)\n )\n .toString(16)\n .slice(1)\n );\n }\n\n /**\n * Convert variant into a value that lightenDarkenHexColor() can understand\n * @param variant naming based on naming standard for color themíng\n * @returns percent value. 10 = 10% ligther. -10 = 10% darker.\n */\n private convertCssColorVariantToPercentage(variant: cssColorVariant): number {\n return 100 - variant;\n }\n}\n","import { Observable } from '../Observable';\nimport { innerFrom } from './innerFrom';\nimport { Subscription } from '../Subscription';\nimport { ObservableInput, ObservableInputTuple } from '../types';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { createOperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { Subscriber } from '../Subscriber';\n\nexport function race<T extends readonly unknown[]>(inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\nexport function race<T extends readonly unknown[]>(...inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\n\n/**\n * Returns an observable that mirrors the first source observable to emit an item.\n *\n * ![](race.png)\n *\n * `race` returns an observable, that when subscribed to, subscribes to all source observables immediately.\n * As soon as one of the source observables emits a value, the result unsubscribes from the other sources.\n * The resulting observable will forward all notifications, including error and completion, from the \"winning\"\n * source observable.\n *\n * If one of the used source observable throws an errors before a first notification\n * the race operator will also throw an error, no matter if another source observable\n * could potentially win the race.\n *\n * `race` can be useful for selecting the response from the fastest network connection for\n * HTTP or WebSockets. `race` can also be useful for switching observable context based on user\n * input.\n *\n * ## Example\n *\n * Subscribes to the observable that was the first to start emitting.\n *\n * ```ts\n * import { interval, map, race } from 'rxjs';\n *\n * const obs1 = interval(7000).pipe(map(() => 'slow one'));\n * const obs2 = interval(3000).pipe(map(() => 'fast one'));\n * const obs3 = interval(5000).pipe(map(() => 'medium one'));\n *\n * race(obs1, obs2, obs3)\n * .subscribe(winner => console.log(winner));\n *\n * // Outputs\n * // a series of 'fast one'\n * ```\n *\n * @param {...Observables} ...observables sources used to race for which Observable emits first.\n * @return {Observable} an Observable that mirrors the output of the first Observable to emit an item.\n */\nexport function race<T>(...sources: (ObservableInput<T> | ObservableInput<T>[])[]): Observable<any> {\n sources = argsOrArgArray(sources);\n // If only one source was passed, just return it. Otherwise return the race.\n return sources.length === 1 ? innerFrom(sources[0] as ObservableInput<T>) : new Observable<T>(raceInit(sources as ObservableInput<T>[]));\n}\n\n/**\n * An observable initializer function for both the static version and the\n * operator version of race.\n * @param sources The sources to race\n */\nexport function raceInit<T>(sources: ObservableInput<T>[]) {\n return (subscriber: Subscriber<T>) => {\n let subscriptions: Subscription[] = [];\n\n // Subscribe to all of the sources. Note that we are checking `subscriptions` here\n // Is is an array of all actively \"racing\" subscriptions, and it is `null` after the\n // race has been won. So, if we have racer that synchronously \"wins\", this loop will\n // stop before it subscribes to any more.\n for (let i = 0; subscriptions && !subscriber.closed && i < sources.length; i++) {\n subscriptions.push(\n innerFrom(sources[i] as ObservableInput<T>).subscribe(\n createOperatorSubscriber(subscriber, (value) => {\n if (subscriptions) {\n // We're still racing, but we won! So unsubscribe\n // all other subscriptions that we have, except this one.\n for (let s = 0; s < subscriptions.length; s++) {\n s !== i && subscriptions[s].unsubscribe();\n }\n subscriptions = null!;\n }\n subscriber.next(value);\n })\n )\n );\n }\n };\n}\n","var hash = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nexport default function getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}","import { auto } from \"../enums.js\";\nexport default function getBasePlacement(placement) {\n return placement.split('-')[0];\n}","var hash = {\n start: 'end',\n end: 'start'\n};\nexport default function getOppositeVariationPlacement(placement) {\n return placement.replace(/start|end/g, function (matched) {\n return hash[matched];\n });\n}","export var top = 'top';\nexport var bottom = 'bottom';\nexport var right = 'right';\nexport var left = 'left';\nexport var auto = 'auto';\nexport var basePlacements = [top, bottom, right, left];\nexport var start = 'start';\nexport var end = 'end';\nexport var clippingParents = 'clippingParents';\nexport var viewport = 'viewport';\nexport var popper = 'popper';\nexport var reference = 'reference';\nexport var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) {\n return acc.concat([placement + \"-\" + start, placement + \"-\" + end]);\n}, []);\nexport var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) {\n return acc.concat([placement, placement + \"-\" + start, placement + \"-\" + end]);\n}, []); // modifiers that need to read the DOM\n\nexport var beforeRead = 'beforeRead';\nexport var read = 'read';\nexport var afterRead = 'afterRead'; // pure-logic modifiers\n\nexport var beforeMain = 'beforeMain';\nexport var main = 'main';\nexport var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)\n\nexport var beforeWrite = 'beforeWrite';\nexport var write = 'write';\nexport var afterWrite = 'afterWrite';\nexport var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];","export default function getWindow(node) {\n if (node == null) {\n return window;\n }\n\n if (node.toString() !== '[object Window]') {\n var ownerDocument = node.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView || window : window;\n }\n\n return node;\n}","import getWindow from \"./getWindow.js\";\n\nfunction isElement(node) {\n var OwnElement = getWindow(node).Element;\n return node instanceof OwnElement || node instanceof Element;\n}\n\nfunction isHTMLElement(node) {\n var OwnElement = getWindow(node).HTMLElement;\n return node instanceof OwnElement || node instanceof HTMLElement;\n}\n\nfunction isShadowRoot(node) {\n // IE 11 has no ShadowRoot\n if (typeof ShadowRoot === 'undefined') {\n return false;\n }\n\n var OwnElement = getWindow(node).ShadowRoot;\n return node instanceof OwnElement || node instanceof ShadowRoot;\n}\n\nexport { isElement, isHTMLElement, isShadowRoot };","import { isElement } from \"./instanceOf.js\";\nexport default function getDocumentElement(element) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]\n element.document) || window.document).documentElement;\n}","export var max = Math.max;\nexport var min = Math.min;\nexport var round = Math.round;","export default function getUAString() {\n var uaData = navigator.userAgentData;\n\n if (uaData != null && uaData.brands) {\n return uaData.brands.map(function (item) {\n return item.brand + \"/\" + item.version;\n }).join(' ');\n }\n\n return navigator.userAgent;\n}","import getUAString from \"../utils/userAgent.js\";\nexport default function isLayoutViewport() {\n return !/^((?!chrome|android).)*safari/i.test(getUAString());\n}","import { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport { round } from \"../utils/math.js\";\nimport getWindow from \"./getWindow.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getBoundingClientRect(element, includeScale, isFixedStrategy) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n\n var clientRect = element.getBoundingClientRect();\n var scaleX = 1;\n var scaleY = 1;\n\n if (includeScale && isHTMLElement(element)) {\n scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;\n scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;\n }\n\n var _ref = isElement(element) ? getWindow(element) : window,\n visualViewport = _ref.visualViewport;\n\n var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;\n var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;\n var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;\n var width = clientRect.width / scaleX;\n var height = clientRect.height / scaleY;\n return {\n width: width,\n height: height,\n top: y,\n right: x + width,\n bottom: y + height,\n left: x,\n x: x,\n y: y\n };\n}","import getWindow from \"./getWindow.js\";\nexport default function getWindowScroll(node) {\n var win = getWindow(node);\n var scrollLeft = win.pageXOffset;\n var scrollTop = win.pageYOffset;\n return {\n scrollLeft: scrollLeft,\n scrollTop: scrollTop\n };\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nexport default function getWindowScrollBarX(element) {\n // If <html> has a CSS width greater than the viewport, then this will be\n // incorrect for RTL.\n // Popper 1 is broken in this case and never had a bug report so let's assume\n // it's not an issue. I don't think anyone ever specifies width on <html>\n // anyway.\n // Browsers where the left scrollbar doesn't cause an issue report `0` for\n // this (e.g. Edge 2019, IE11, Safari)\n return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;\n}","import getWindow from \"./getWindow.js\";\nexport default function getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}","export default function getNodeName(element) {\n return element ? (element.nodeName || '').toLowerCase() : null;\n}","import getNodeName from \"./getNodeName.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport { isShadowRoot } from \"./instanceOf.js\";\nexport default function getParentNode(element) {\n if (getNodeName(element) === 'html') {\n return element;\n }\n\n return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle\n // $FlowFixMe[incompatible-return]\n // $FlowFixMe[prop-missing]\n element.assignedSlot || // step into the shadow DOM of the parent of a slotted node\n element.parentNode || ( // DOM Element detected\n isShadowRoot(element) ? element.host : null) || // ShadowRoot detected\n // $FlowFixMe[incompatible-call]: HTMLElement is a Node\n getDocumentElement(element) // fallback\n\n );\n}","import getComputedStyle from \"./getComputedStyle.js\";\nexport default function isScrollParent(element) {\n // Firefox wants us to check `-x` and `-y` variations as well\n var _getComputedStyle = getComputedStyle(element),\n overflow = _getComputedStyle.overflow,\n overflowX = _getComputedStyle.overflowX,\n overflowY = _getComputedStyle.overflowY;\n\n return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);\n}","import getParentNode from \"./getParentNode.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nexport default function getScrollParent(node) {\n if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {\n // $FlowFixMe[incompatible-return]: assume body is always available\n return node.ownerDocument.body;\n }\n\n if (isHTMLElement(node) && isScrollParent(node)) {\n return node;\n }\n\n return getScrollParent(getParentNode(node));\n}","import getScrollParent from \"./getScrollParent.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getWindow from \"./getWindow.js\";\nimport isScrollParent from \"./isScrollParent.js\";\n/*\ngiven a DOM element, return the list of all scroll parents, up the list of ancesors\nuntil we get to the top window object. This list is what we attach scroll listeners\nto, because if any of these parent elements scroll, we'll need to re-calculate the\nreference element's position.\n*/\n\nexport default function listScrollParents(element, list) {\n var _element$ownerDocumen;\n\n if (list === void 0) {\n list = [];\n }\n\n var scrollParent = getScrollParent(element);\n var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);\n var win = getWindow(scrollParent);\n var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;\n var updatedList = list.concat(target);\n return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here\n updatedList.concat(listScrollParents(getParentNode(target)));\n}","import getNodeName from \"./getNodeName.js\";\nexport default function isTableElement(element) {\n return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;\n}","import getWindow from \"./getWindow.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isHTMLElement, isShadowRoot } from \"./instanceOf.js\";\nimport isTableElement from \"./isTableElement.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport getUAString from \"../utils/userAgent.js\";\n\nfunction getTrueOffsetParent(element) {\n if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837\n getComputedStyle(element).position === 'fixed') {\n return null;\n }\n\n return element.offsetParent;\n} // `.offsetParent` reports `null` for fixed elements, while absolute elements\n// return the containing block\n\n\nfunction getContainingBlock(element) {\n var isFirefox = /firefox/i.test(getUAString());\n var isIE = /Trident/i.test(getUAString());\n\n if (isIE && isHTMLElement(element)) {\n // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport\n var elementCss = getComputedStyle(element);\n\n if (elementCss.position === 'fixed') {\n return null;\n }\n }\n\n var currentNode = getParentNode(element);\n\n if (isShadowRoot(currentNode)) {\n currentNode = currentNode.host;\n }\n\n while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {\n var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that\n // create a containing block.\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n\n if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {\n return currentNode;\n } else {\n currentNode = currentNode.parentNode;\n }\n }\n\n return null;\n} // Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\n\n\nexport default function getOffsetParent(element) {\n var window = getWindow(element);\n var offsetParent = getTrueOffsetParent(element);\n\n while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {\n offsetParent = getTrueOffsetParent(offsetParent);\n }\n\n if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {\n return window;\n }\n\n return offsetParent || getContainingBlock(element) || window;\n}","import { isShadowRoot } from \"./instanceOf.js\";\nexport default function contains(parent, child) {\n var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method\n\n if (parent.contains(child)) {\n return true;\n } // then fallback to custom implementation with Shadow DOM support\n else if (rootNode && isShadowRoot(rootNode)) {\n var next = child;\n\n do {\n if (next && parent.isSameNode(next)) {\n return true;\n } // $FlowFixMe[prop-missing]: need a better way to handle this...\n\n\n next = next.parentNode || next.host;\n } while (next);\n } // Give up, the result is false\n\n\n return false;\n}","export default function rectToClientRect(rect) {\n return Object.assign({}, rect, {\n left: rect.x,\n top: rect.y,\n right: rect.x + rect.width,\n bottom: rect.y + rect.height\n });\n}","import { viewport } from \"../enums.js\";\nimport getViewportRect from \"./getViewportRect.js\";\nimport getDocumentRect from \"./getDocumentRect.js\";\nimport listScrollParents from \"./listScrollParents.js\";\nimport getOffsetParent from \"./getOffsetParent.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport { isElement, isHTMLElement } from \"./instanceOf.js\";\nimport getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getParentNode from \"./getParentNode.js\";\nimport contains from \"./contains.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport rectToClientRect from \"../utils/rectToClientRect.js\";\nimport { max, min } from \"../utils/math.js\";\n\nfunction getInnerBoundingClientRect(element, strategy) {\n var rect = getBoundingClientRect(element, false, strategy === 'fixed');\n rect.top = rect.top + element.clientTop;\n rect.left = rect.left + element.clientLeft;\n rect.bottom = rect.top + element.clientHeight;\n rect.right = rect.left + element.clientWidth;\n rect.width = element.clientWidth;\n rect.height = element.clientHeight;\n rect.x = rect.left;\n rect.y = rect.top;\n return rect;\n}\n\nfunction getClientRectFromMixedType(element, clippingParent, strategy) {\n return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));\n} // A \"clipping parent\" is an overflowable container with the characteristic of\n// clipping (or hiding) overflowing elements with a position different from\n// `initial`\n\n\nfunction getClippingParents(element) {\n var clippingParents = listScrollParents(getParentNode(element));\n var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;\n var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;\n\n if (!isElement(clipperElement)) {\n return [];\n } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414\n\n\n return clippingParents.filter(function (clippingParent) {\n return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';\n });\n} // Gets the maximum area that the element is visible in due to any number of\n// clipping parents\n\n\nexport default function getClippingRect(element, boundary, rootBoundary, strategy) {\n var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);\n var clippingParents = [].concat(mainClippingParents, [rootBoundary]);\n var firstClippingParent = clippingParents[0];\n var clippingRect = clippingParents.reduce(function (accRect, clippingParent) {\n var rect = getClientRectFromMixedType(element, clippingParent, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromMixedType(element, firstClippingParent, strategy));\n clippingRect.width = clippingRect.right - clippingRect.left;\n clippingRect.height = clippingRect.bottom - clippingRect.top;\n clippingRect.x = clippingRect.left;\n clippingRect.y = clippingRect.top;\n return clippingRect;\n}","import getWindow from \"./getWindow.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport isLayoutViewport from \"./isLayoutViewport.js\";\nexport default function getViewportRect(element, strategy) {\n var win = getWindow(element);\n var html = getDocumentElement(element);\n var visualViewport = win.visualViewport;\n var width = html.clientWidth;\n var height = html.clientHeight;\n var x = 0;\n var y = 0;\n\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n var layoutViewport = isLayoutViewport();\n\n if (layoutViewport || !layoutViewport && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n\n return {\n width: width,\n height: height,\n x: x + getWindowScrollBarX(element),\n y: y\n };\n}","import getDocumentElement from \"./getDocumentElement.js\";\nimport getComputedStyle from \"./getComputedStyle.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getWindowScroll from \"./getWindowScroll.js\";\nimport { max } from \"../utils/math.js\"; // Gets the entire size of the scrollable document area, even extending outside\n// of the `<html>` and `<body>` rect bounds if horizontally scrollable\n\nexport default function getDocumentRect(element) {\n var _element$ownerDocumen;\n\n var html = getDocumentElement(element);\n var winScroll = getWindowScroll(element);\n var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;\n var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);\n var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);\n var x = -winScroll.scrollLeft + getWindowScrollBarX(element);\n var y = -winScroll.scrollTop;\n\n if (getComputedStyle(body || html).direction === 'rtl') {\n x += max(html.clientWidth, body ? body.clientWidth : 0) - width;\n }\n\n return {\n width: width,\n height: height,\n x: x,\n y: y\n };\n}","export default function getVariation(placement) {\n return placement.split('-')[1];\n}","export default function getMainAxisFromPlacement(placement) {\n return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';\n}","import getBasePlacement from \"./getBasePlacement.js\";\nimport getVariation from \"./getVariation.js\";\nimport getMainAxisFromPlacement from \"./getMainAxisFromPlacement.js\";\nimport { top, right, bottom, left, start, end } from \"../enums.js\";\nexport default function computeOffsets(_ref) {\n var reference = _ref.reference,\n element = _ref.element,\n placement = _ref.placement;\n var basePlacement = placement ? getBasePlacement(placement) : null;\n var variation = placement ? getVariation(placement) : null;\n var commonX = reference.x + reference.width / 2 - element.width / 2;\n var commonY = reference.y + reference.height / 2 - element.height / 2;\n var offsets;\n\n switch (basePlacement) {\n case top:\n offsets = {\n x: commonX,\n y: reference.y - element.height\n };\n break;\n\n case bottom:\n offsets = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n\n case right:\n offsets = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n\n case left:\n offsets = {\n x: reference.x - element.width,\n y: commonY\n };\n break;\n\n default:\n offsets = {\n x: reference.x,\n y: reference.y\n };\n }\n\n var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;\n\n if (mainAxis != null) {\n var len = mainAxis === 'y' ? 'height' : 'width';\n\n switch (variation) {\n case start:\n offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);\n break;\n\n case end:\n offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);\n break;\n\n default:\n }\n }\n\n return offsets;\n}","import getFreshSideObject from \"./getFreshSideObject.js\";\nexport default function mergePaddingObject(paddingObject) {\n return Object.assign({}, getFreshSideObject(), paddingObject);\n}","export default function getFreshSideObject() {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n };\n}","export default function expandToHashMap(value, keys) {\n return keys.reduce(function (hashMap, key) {\n hashMap[key] = value;\n return hashMap;\n }, {});\n}","import getClippingRect from \"../dom-utils/getClippingRect.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getBoundingClientRect from \"../dom-utils/getBoundingClientRect.js\";\nimport computeOffsets from \"./computeOffsets.js\";\nimport rectToClientRect from \"./rectToClientRect.js\";\nimport { clippingParents, reference, popper, bottom, top, right, basePlacements, viewport } from \"../enums.js\";\nimport { isElement } from \"../dom-utils/instanceOf.js\";\nimport mergePaddingObject from \"./mergePaddingObject.js\";\nimport expandToHashMap from \"./expandToHashMap.js\"; // eslint-disable-next-line import/no-unused-modules\n\nexport default function detectOverflow(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n _options$placement = _options.placement,\n placement = _options$placement === void 0 ? state.placement : _options$placement,\n _options$strategy = _options.strategy,\n strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,\n _options$boundary = _options.boundary,\n boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,\n _options$rootBoundary = _options.rootBoundary,\n rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,\n _options$elementConte = _options.elementContext,\n elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,\n _options$altBoundary = _options.altBoundary,\n altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,\n _options$padding = _options.padding,\n padding = _options$padding === void 0 ? 0 : _options$padding;\n var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n var altContext = elementContext === popper ? reference : popper;\n var popperRect = state.rects.popper;\n var element = state.elements[altBoundary ? altContext : elementContext];\n var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);\n var referenceClientRect = getBoundingClientRect(state.elements.reference);\n var popperOffsets = computeOffsets({\n reference: referenceClientRect,\n element: popperRect,\n strategy: 'absolute',\n placement: placement\n });\n var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));\n var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect\n // 0 or negative = within the clipping rect\n\n var overflowOffsets = {\n top: clippingClientRect.top - elementClientRect.top + paddingObject.top,\n bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,\n left: clippingClientRect.left - elementClientRect.left + paddingObject.left,\n right: elementClientRect.right - clippingClientRect.right + paddingObject.right\n };\n var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element\n\n if (elementContext === popper && offsetData) {\n var offset = offsetData[placement];\n Object.keys(overflowOffsets).forEach(function (key) {\n var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;\n var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';\n overflowOffsets[key] += offset[axis] * multiply;\n });\n }\n\n return overflowOffsets;\n}","import getOppositePlacement from \"../utils/getOppositePlacement.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getOppositeVariationPlacement from \"../utils/getOppositeVariationPlacement.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport computeAutoPlacement from \"../utils/computeAutoPlacement.js\";\nimport { bottom, top, start, right, left, auto } from \"../enums.js\";\nimport getVariation from \"../utils/getVariation.js\"; // eslint-disable-next-line import/no-unused-modules\n\nfunction getExpandedFallbackPlacements(placement) {\n if (getBasePlacement(placement) === auto) {\n return [];\n }\n\n var oppositePlacement = getOppositePlacement(placement);\n return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];\n}\n\nfunction flip(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n\n if (state.modifiersData[name]._skip) {\n return;\n }\n\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,\n specifiedFallbackPlacements = options.fallbackPlacements,\n padding = options.padding,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n _options$flipVariatio = options.flipVariations,\n flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,\n allowedAutoPlacements = options.allowedAutoPlacements;\n var preferredPlacement = state.options.placement;\n var basePlacement = getBasePlacement(preferredPlacement);\n var isBasePlacement = basePlacement === preferredPlacement;\n var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));\n var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) {\n return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n flipVariations: flipVariations,\n allowedAutoPlacements: allowedAutoPlacements\n }) : placement);\n }, []);\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var checksMap = new Map();\n var makeFallbackChecks = true;\n var firstFittingPlacement = placements[0];\n\n for (var i = 0; i < placements.length; i++) {\n var placement = placements[i];\n\n var _basePlacement = getBasePlacement(placement);\n\n var isStartVariation = getVariation(placement) === start;\n var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;\n var len = isVertical ? 'width' : 'height';\n var overflow = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n altBoundary: altBoundary,\n padding: padding\n });\n var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;\n\n if (referenceRect[len] > popperRect[len]) {\n mainVariationSide = getOppositePlacement(mainVariationSide);\n }\n\n var altVariationSide = getOppositePlacement(mainVariationSide);\n var checks = [];\n\n if (checkMainAxis) {\n checks.push(overflow[_basePlacement] <= 0);\n }\n\n if (checkAltAxis) {\n checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);\n }\n\n if (checks.every(function (check) {\n return check;\n })) {\n firstFittingPlacement = placement;\n makeFallbackChecks = false;\n break;\n }\n\n checksMap.set(placement, checks);\n }\n\n if (makeFallbackChecks) {\n // `2` may be desired in some cases – research later\n var numberOfChecks = flipVariations ? 3 : 1;\n\n var _loop = function _loop(_i) {\n var fittingPlacement = placements.find(function (placement) {\n var checks = checksMap.get(placement);\n\n if (checks) {\n return checks.slice(0, _i).every(function (check) {\n return check;\n });\n }\n });\n\n if (fittingPlacement) {\n firstFittingPlacement = fittingPlacement;\n return \"break\";\n }\n };\n\n for (var _i = numberOfChecks; _i > 0; _i--) {\n var _ret = _loop(_i);\n\n if (_ret === \"break\") break;\n }\n }\n\n if (state.placement !== firstFittingPlacement) {\n state.modifiersData[name]._skip = true;\n state.placement = firstFittingPlacement;\n state.reset = true;\n }\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'flip',\n enabled: true,\n phase: 'main',\n fn: flip,\n requiresIfExists: ['offset'],\n data: {\n _skip: false\n }\n};","import getVariation from \"./getVariation.js\";\nimport { variationPlacements, basePlacements, placements as allPlacements } from \"../enums.js\";\nimport detectOverflow from \"./detectOverflow.js\";\nimport getBasePlacement from \"./getBasePlacement.js\";\nexport default function computeAutoPlacement(state, options) {\n if (options === void 0) {\n options = {};\n }\n\n var _options = options,\n placement = _options.placement,\n boundary = _options.boundary,\n rootBoundary = _options.rootBoundary,\n padding = _options.padding,\n flipVariations = _options.flipVariations,\n _options$allowedAutoP = _options.allowedAutoPlacements,\n allowedAutoPlacements = _options$allowedAutoP === void 0 ? allPlacements : _options$allowedAutoP;\n var variation = getVariation(placement);\n var placements = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) {\n return getVariation(placement) === variation;\n }) : basePlacements;\n var allowedPlacements = placements.filter(function (placement) {\n return allowedAutoPlacements.indexOf(placement) >= 0;\n });\n\n if (allowedPlacements.length === 0) {\n allowedPlacements = placements;\n\n if (process.env.NODE_ENV !== \"production\") {\n console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, \"auto\" cannot be used to allow \"bottom-start\".', 'Use \"auto-start\" instead.'].join(' '));\n }\n } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...\n\n\n var overflows = allowedPlacements.reduce(function (acc, placement) {\n acc[placement] = detectOverflow(state, {\n placement: placement,\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding\n })[getBasePlacement(placement)];\n return acc;\n }, {});\n return Object.keys(overflows).sort(function (a, b) {\n return overflows[a] - overflows[b];\n });\n}","import { max as mathMax, min as mathMin } from \"./math.js\";\nexport function within(min, value, max) {\n return mathMax(min, mathMin(value, max));\n}\nexport function withinMaxClamp(min, value, max) {\n var v = within(min, value, max);\n return v > max ? max : v;\n}","import getBoundingClientRect from \"./getBoundingClientRect.js\"; // Returns the layout rect of an element relative to its offsetParent. Layout\n// means it doesn't take into account transforms.\n\nexport default function getLayoutRect(element) {\n var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.\n // Fixes https://github.com/popperjs/popper-core/issues/1223\n\n var width = element.offsetWidth;\n var height = element.offsetHeight;\n\n if (Math.abs(clientRect.width - width) <= 1) {\n width = clientRect.width;\n }\n\n if (Math.abs(clientRect.height - height) <= 1) {\n height = clientRect.height;\n }\n\n return {\n x: element.offsetLeft,\n y: element.offsetTop,\n width: width,\n height: height\n };\n}","import { top, left, right, bottom, start } from \"../enums.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport getAltAxis from \"../utils/getAltAxis.js\";\nimport { within, withinMaxClamp } from \"../utils/within.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport detectOverflow from \"../utils/detectOverflow.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport getFreshSideObject from \"../utils/getFreshSideObject.js\";\nimport { min as mathMin, max as mathMax } from \"../utils/math.js\";\n\nfunction preventOverflow(_ref) {\n var state = _ref.state,\n options = _ref.options,\n name = _ref.name;\n var _options$mainAxis = options.mainAxis,\n checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,\n _options$altAxis = options.altAxis,\n checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,\n boundary = options.boundary,\n rootBoundary = options.rootBoundary,\n altBoundary = options.altBoundary,\n padding = options.padding,\n _options$tether = options.tether,\n tether = _options$tether === void 0 ? true : _options$tether,\n _options$tetherOffset = options.tetherOffset,\n tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;\n var overflow = detectOverflow(state, {\n boundary: boundary,\n rootBoundary: rootBoundary,\n padding: padding,\n altBoundary: altBoundary\n });\n var basePlacement = getBasePlacement(state.placement);\n var variation = getVariation(state.placement);\n var isBasePlacement = !variation;\n var mainAxis = getMainAxisFromPlacement(basePlacement);\n var altAxis = getAltAxis(mainAxis);\n var popperOffsets = state.modifiersData.popperOffsets;\n var referenceRect = state.rects.reference;\n var popperRect = state.rects.popper;\n var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {\n placement: state.placement\n })) : tetherOffset;\n var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {\n mainAxis: tetherOffsetValue,\n altAxis: tetherOffsetValue\n } : Object.assign({\n mainAxis: 0,\n altAxis: 0\n }, tetherOffsetValue);\n var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;\n var data = {\n x: 0,\n y: 0\n };\n\n if (!popperOffsets) {\n return;\n }\n\n if (checkMainAxis) {\n var _offsetModifierState$;\n\n var mainSide = mainAxis === 'y' ? top : left;\n var altSide = mainAxis === 'y' ? bottom : right;\n var len = mainAxis === 'y' ? 'height' : 'width';\n var offset = popperOffsets[mainAxis];\n var min = offset + overflow[mainSide];\n var max = offset - overflow[altSide];\n var additive = tether ? -popperRect[len] / 2 : 0;\n var minLen = variation === start ? referenceRect[len] : popperRect[len];\n var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go\n // outside the reference bounds\n\n var arrowElement = state.elements.arrow;\n var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {\n width: 0,\n height: 0\n };\n var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();\n var arrowPaddingMin = arrowPaddingObject[mainSide];\n var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want\n // to include its full size in the calculation. If the reference is small\n // and near the edge of a boundary, the popper can overflow even if the\n // reference is not overflowing as well (e.g. virtual elements with no\n // width or height)\n\n var arrowLen = within(0, referenceRect[len], arrowRect[len]);\n var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;\n var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;\n var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);\n var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;\n var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;\n var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;\n var tetherMax = offset + maxOffset - offsetModifierValue;\n var preventedOffset = within(tether ? mathMin(min, tetherMin) : min, offset, tether ? mathMax(max, tetherMax) : max);\n popperOffsets[mainAxis] = preventedOffset;\n data[mainAxis] = preventedOffset - offset;\n }\n\n if (checkAltAxis) {\n var _offsetModifierState$2;\n\n var _mainSide = mainAxis === 'x' ? top : left;\n\n var _altSide = mainAxis === 'x' ? bottom : right;\n\n var _offset = popperOffsets[altAxis];\n\n var _len = altAxis === 'y' ? 'height' : 'width';\n\n var _min = _offset + overflow[_mainSide];\n\n var _max = _offset - overflow[_altSide];\n\n var isOriginSide = [top, left].indexOf(basePlacement) !== -1;\n\n var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;\n\n var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;\n\n var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;\n\n var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);\n\n popperOffsets[altAxis] = _preventedOffset;\n data[altAxis] = _preventedOffset - _offset;\n }\n\n state.modifiersData[name] = data;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'preventOverflow',\n enabled: true,\n phase: 'main',\n fn: preventOverflow,\n requiresIfExists: ['offset']\n};","export default function getAltAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}","import getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getLayoutRect from \"../dom-utils/getLayoutRect.js\";\nimport contains from \"../dom-utils/contains.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getMainAxisFromPlacement from \"../utils/getMainAxisFromPlacement.js\";\nimport { within } from \"../utils/within.js\";\nimport mergePaddingObject from \"../utils/mergePaddingObject.js\";\nimport expandToHashMap from \"../utils/expandToHashMap.js\";\nimport { left, right, basePlacements, top, bottom } from \"../enums.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar toPaddingObject = function toPaddingObject(padding, state) {\n padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {\n placement: state.placement\n })) : padding;\n return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));\n};\n\nfunction arrow(_ref) {\n var _state$modifiersData$;\n\n var state = _ref.state,\n name = _ref.name,\n options = _ref.options;\n var arrowElement = state.elements.arrow;\n var popperOffsets = state.modifiersData.popperOffsets;\n var basePlacement = getBasePlacement(state.placement);\n var axis = getMainAxisFromPlacement(basePlacement);\n var isVertical = [left, right].indexOf(basePlacement) >= 0;\n var len = isVertical ? 'height' : 'width';\n\n if (!arrowElement || !popperOffsets) {\n return;\n }\n\n var paddingObject = toPaddingObject(options.padding, state);\n var arrowRect = getLayoutRect(arrowElement);\n var minProp = axis === 'y' ? top : left;\n var maxProp = axis === 'y' ? bottom : right;\n var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];\n var startDiff = popperOffsets[axis] - state.rects.reference[axis];\n var arrowOffsetParent = getOffsetParent(arrowElement);\n var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;\n var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is\n // outside of the popper bounds\n\n var min = paddingObject[minProp];\n var max = clientSize - arrowRect[len] - paddingObject[maxProp];\n var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;\n var offset = within(min, center, max); // Prevents breaking syntax highlighting...\n\n var axisProp = axis;\n state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state,\n options = _ref2.options;\n var _options$element = options.element,\n arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;\n\n if (arrowElement == null) {\n return;\n } // CSS selector\n\n\n if (typeof arrowElement === 'string') {\n arrowElement = state.elements.popper.querySelector(arrowElement);\n\n if (!arrowElement) {\n return;\n }\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!isHTMLElement(arrowElement)) {\n console.error(['Popper: \"arrow\" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' '));\n }\n }\n\n if (!contains(state.elements.popper, arrowElement)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(['Popper: \"arrow\" modifier\\'s `element` must be a child of the popper', 'element.'].join(' '));\n }\n\n return;\n }\n\n state.elements.arrow = arrowElement;\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'arrow',\n enabled: true,\n phase: 'main',\n fn: arrow,\n effect: effect,\n requires: ['popperOffsets'],\n requiresIfExists: ['preventOverflow']\n};","import getBoundingClientRect from \"./getBoundingClientRect.js\";\nimport getNodeScroll from \"./getNodeScroll.js\";\nimport getNodeName from \"./getNodeName.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getWindowScrollBarX from \"./getWindowScrollBarX.js\";\nimport getDocumentElement from \"./getDocumentElement.js\";\nimport isScrollParent from \"./isScrollParent.js\";\nimport { round } from \"../utils/math.js\";\n\nfunction isElementScaled(element) {\n var rect = element.getBoundingClientRect();\n var scaleX = round(rect.width) / element.offsetWidth || 1;\n var scaleY = round(rect.height) / element.offsetHeight || 1;\n return scaleX !== 1 || scaleY !== 1;\n} // Returns the composite rect of an element relative to its offsetParent.\n// Composite means it takes into account transforms as well as layout.\n\n\nexport default function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n\n var isOffsetParentAnElement = isHTMLElement(offsetParent);\n var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);\n var documentElement = getDocumentElement(offsetParent);\n var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);\n var scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n var offsets = {\n x: 0,\n y: 0\n };\n\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078\n isScrollParent(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n\n if (isHTMLElement(offsetParent)) {\n offsets = getBoundingClientRect(offsetParent, true);\n offsets.x += offsetParent.clientLeft;\n offsets.y += offsetParent.clientTop;\n } else if (documentElement) {\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n\n return {\n x: rect.left + scroll.scrollLeft - offsets.x,\n y: rect.top + scroll.scrollTop - offsets.y,\n width: rect.width,\n height: rect.height\n };\n}","import getWindowScroll from \"./getWindowScroll.js\";\nimport getWindow from \"./getWindow.js\";\nimport { isHTMLElement } from \"./instanceOf.js\";\nimport getHTMLElementScroll from \"./getHTMLElementScroll.js\";\nexport default function getNodeScroll(node) {\n if (node === getWindow(node) || !isHTMLElement(node)) {\n return getWindowScroll(node);\n } else {\n return getHTMLElementScroll(node);\n }\n}","export default function getHTMLElementScroll(element) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n}","import { modifierPhases } from \"../enums.js\"; // source: https://stackoverflow.com/questions/49875255\n\nfunction order(modifiers) {\n var map = new Map();\n var visited = new Set();\n var result = [];\n modifiers.forEach(function (modifier) {\n map.set(modifier.name, modifier);\n }); // On visiting object, check for its dependencies and visit them recursively\n\n function sort(modifier) {\n visited.add(modifier.name);\n var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);\n requires.forEach(function (dep) {\n if (!visited.has(dep)) {\n var depModifier = map.get(dep);\n\n if (depModifier) {\n sort(depModifier);\n }\n }\n });\n result.push(modifier);\n }\n\n modifiers.forEach(function (modifier) {\n if (!visited.has(modifier.name)) {\n // check for visited object\n sort(modifier);\n }\n });\n return result;\n}\n\nexport default function orderModifiers(modifiers) {\n // order based on dependencies\n var orderedModifiers = order(modifiers); // order based on phase\n\n return modifierPhases.reduce(function (acc, phase) {\n return acc.concat(orderedModifiers.filter(function (modifier) {\n return modifier.phase === phase;\n }));\n }, []);\n}","export default function debounce(fn) {\n var pending;\n return function () {\n if (!pending) {\n pending = new Promise(function (resolve) {\n Promise.resolve().then(function () {\n pending = undefined;\n resolve(fn());\n });\n });\n }\n\n return pending;\n };\n}","import getCompositeRect from \"./dom-utils/getCompositeRect.js\";\nimport getLayoutRect from \"./dom-utils/getLayoutRect.js\";\nimport listScrollParents from \"./dom-utils/listScrollParents.js\";\nimport getOffsetParent from \"./dom-utils/getOffsetParent.js\";\nimport getComputedStyle from \"./dom-utils/getComputedStyle.js\";\nimport orderModifiers from \"./utils/orderModifiers.js\";\nimport debounce from \"./utils/debounce.js\";\nimport validateModifiers from \"./utils/validateModifiers.js\";\nimport uniqueBy from \"./utils/uniqueBy.js\";\nimport getBasePlacement from \"./utils/getBasePlacement.js\";\nimport mergeByName from \"./utils/mergeByName.js\";\nimport detectOverflow from \"./utils/detectOverflow.js\";\nimport { isElement } from \"./dom-utils/instanceOf.js\";\nimport { auto } from \"./enums.js\";\nvar INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.';\nvar INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.';\nvar DEFAULT_OPTIONS = {\n placement: 'bottom',\n modifiers: [],\n strategy: 'absolute'\n};\n\nfunction areValidElements() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return !args.some(function (element) {\n return !(element && typeof element.getBoundingClientRect === 'function');\n });\n}\n\nexport function popperGenerator(generatorOptions) {\n if (generatorOptions === void 0) {\n generatorOptions = {};\n }\n\n var _generatorOptions = generatorOptions,\n _generatorOptions$def = _generatorOptions.defaultModifiers,\n defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,\n _generatorOptions$def2 = _generatorOptions.defaultOptions,\n defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;\n return function createPopper(reference, popper, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n var state = {\n placement: 'bottom',\n orderedModifiers: [],\n options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),\n modifiersData: {},\n elements: {\n reference: reference,\n popper: popper\n },\n attributes: {},\n styles: {}\n };\n var effectCleanupFns = [];\n var isDestroyed = false;\n var instance = {\n state: state,\n setOptions: function setOptions(setOptionsAction) {\n var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;\n cleanupModifierEffects();\n state.options = Object.assign({}, defaultOptions, state.options, options);\n state.scrollParents = {\n reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],\n popper: listScrollParents(popper)\n }; // Orders the modifiers based on their dependencies and `phase`\n // properties\n\n var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers\n\n state.orderedModifiers = orderedModifiers.filter(function (m) {\n return m.enabled;\n }); // Validate the provided modifiers so that the consumer will get warned\n // if one of the modifiers is invalid for any reason\n\n if (process.env.NODE_ENV !== \"production\") {\n var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) {\n var name = _ref.name;\n return name;\n });\n validateModifiers(modifiers);\n\n if (getBasePlacement(state.options.placement) === auto) {\n var flipModifier = state.orderedModifiers.find(function (_ref2) {\n var name = _ref2.name;\n return name === 'flip';\n });\n\n if (!flipModifier) {\n console.error(['Popper: \"auto\" placements require the \"flip\" modifier be', 'present and enabled to work.'].join(' '));\n }\n }\n\n var _getComputedStyle = getComputedStyle(popper),\n marginTop = _getComputedStyle.marginTop,\n marginRight = _getComputedStyle.marginRight,\n marginBottom = _getComputedStyle.marginBottom,\n marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can\n // cause bugs with positioning, so we'll warn the consumer\n\n\n if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) {\n return parseFloat(margin);\n })) {\n console.warn(['Popper: CSS \"margin\" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' '));\n }\n }\n\n runModifierEffects();\n return instance.update();\n },\n // Sync update – it will always be executed, even if not necessary. This\n // is useful for low frequency updates where sync behavior simplifies the\n // logic.\n // For high frequency updates (e.g. `resize` and `scroll` events), always\n // prefer the async Popper#update method\n forceUpdate: function forceUpdate() {\n if (isDestroyed) {\n return;\n }\n\n var _state$elements = state.elements,\n reference = _state$elements.reference,\n popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements\n // anymore\n\n if (!areValidElements(reference, popper)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(INVALID_ELEMENT_ERROR);\n }\n\n return;\n } // Store the reference and popper rects to be read by modifiers\n\n\n state.rects = {\n reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),\n popper: getLayoutRect(popper)\n }; // Modifiers have the ability to reset the current update cycle. The\n // most common use case for this is the `flip` modifier changing the\n // placement, which then needs to re-run all the modifiers, because the\n // logic was previously ran for the previous placement and is therefore\n // stale/incorrect\n\n state.reset = false;\n state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier\n // is filled with the initial data specified by the modifier. This means\n // it doesn't persist and is fresh on each update.\n // To ensure persistent data, use `${name}#persistent`\n\n state.orderedModifiers.forEach(function (modifier) {\n return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);\n });\n var __debug_loops__ = 0;\n\n for (var index = 0; index < state.orderedModifiers.length; index++) {\n if (process.env.NODE_ENV !== \"production\") {\n __debug_loops__ += 1;\n\n if (__debug_loops__ > 100) {\n console.error(INFINITE_LOOP_ERROR);\n break;\n }\n }\n\n if (state.reset === true) {\n state.reset = false;\n index = -1;\n continue;\n }\n\n var _state$orderedModifie = state.orderedModifiers[index],\n fn = _state$orderedModifie.fn,\n _state$orderedModifie2 = _state$orderedModifie.options,\n _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,\n name = _state$orderedModifie.name;\n\n if (typeof fn === 'function') {\n state = fn({\n state: state,\n options: _options,\n name: name,\n instance: instance\n }) || state;\n }\n }\n },\n // Async and optimistically optimized update – it will not be executed if\n // not necessary (debounced to run at most once-per-tick)\n update: debounce(function () {\n return new Promise(function (resolve) {\n instance.forceUpdate();\n resolve(state);\n });\n }),\n destroy: function destroy() {\n cleanupModifierEffects();\n isDestroyed = true;\n }\n };\n\n if (!areValidElements(reference, popper)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(INVALID_ELEMENT_ERROR);\n }\n\n return instance;\n }\n\n instance.setOptions(options).then(function (state) {\n if (!isDestroyed && options.onFirstUpdate) {\n options.onFirstUpdate(state);\n }\n }); // Modifiers have the ability to execute arbitrary code before the first\n // update cycle runs. They will be executed in the same order as the update\n // cycle. This is useful when a modifier adds some persistent data that\n // other modifiers need to use, but the modifier is run after the dependent\n // one.\n\n function runModifierEffects() {\n state.orderedModifiers.forEach(function (_ref3) {\n var name = _ref3.name,\n _ref3$options = _ref3.options,\n options = _ref3$options === void 0 ? {} : _ref3$options,\n effect = _ref3.effect;\n\n if (typeof effect === 'function') {\n var cleanupFn = effect({\n state: state,\n name: name,\n instance: instance,\n options: options\n });\n\n var noopFn = function noopFn() {};\n\n effectCleanupFns.push(cleanupFn || noopFn);\n }\n });\n }\n\n function cleanupModifierEffects() {\n effectCleanupFns.forEach(function (fn) {\n return fn();\n });\n effectCleanupFns = [];\n }\n\n return instance;\n };\n}\nexport var createPopper = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules\n\nexport { detectOverflow };","export default function mergeByName(modifiers) {\n var merged = modifiers.reduce(function (merged, current) {\n var existing = merged[current.name];\n merged[current.name] = existing ? Object.assign({}, existing, current, {\n options: Object.assign({}, existing.options, current.options),\n data: Object.assign({}, existing.data, current.data)\n }) : current;\n return merged;\n }, {}); // IE11 does not support Object.values\n\n return Object.keys(merged).map(function (key) {\n return merged[key];\n });\n}","import getWindow from \"../dom-utils/getWindow.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar passive = {\n passive: true\n};\n\nfunction effect(_ref) {\n var state = _ref.state,\n instance = _ref.instance,\n options = _ref.options;\n var _options$scroll = options.scroll,\n scroll = _options$scroll === void 0 ? true : _options$scroll,\n _options$resize = options.resize,\n resize = _options$resize === void 0 ? true : _options$resize;\n var window = getWindow(state.elements.popper);\n var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);\n\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.addEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.addEventListener('resize', instance.update, passive);\n }\n\n return function () {\n if (scroll) {\n scrollParents.forEach(function (scrollParent) {\n scrollParent.removeEventListener('scroll', instance.update, passive);\n });\n }\n\n if (resize) {\n window.removeEventListener('resize', instance.update, passive);\n }\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'eventListeners',\n enabled: true,\n phase: 'write',\n fn: function fn() {},\n effect: effect,\n data: {}\n};","import { top, left, right, bottom, end } from \"../enums.js\";\nimport getOffsetParent from \"../dom-utils/getOffsetParent.js\";\nimport getWindow from \"../dom-utils/getWindow.js\";\nimport getDocumentElement from \"../dom-utils/getDocumentElement.js\";\nimport getComputedStyle from \"../dom-utils/getComputedStyle.js\";\nimport getBasePlacement from \"../utils/getBasePlacement.js\";\nimport getVariation from \"../utils/getVariation.js\";\nimport { round } from \"../utils/math.js\"; // eslint-disable-next-line import/no-unused-modules\n\nvar unsetSides = {\n top: 'auto',\n right: 'auto',\n bottom: 'auto',\n left: 'auto'\n}; // Round the offsets to the nearest suitable subpixel based on the DPR.\n// Zooming can change the DPR, but it seems to report a value that will\n// cleanly divide the values into the appropriate subpixels.\n\nfunction roundOffsetsByDPR(_ref) {\n var x = _ref.x,\n y = _ref.y;\n var win = window;\n var dpr = win.devicePixelRatio || 1;\n return {\n x: round(x * dpr) / dpr || 0,\n y: round(y * dpr) / dpr || 0\n };\n}\n\nexport function mapToStyles(_ref2) {\n var _Object$assign2;\n\n var popper = _ref2.popper,\n popperRect = _ref2.popperRect,\n placement = _ref2.placement,\n variation = _ref2.variation,\n offsets = _ref2.offsets,\n position = _ref2.position,\n gpuAcceleration = _ref2.gpuAcceleration,\n adaptive = _ref2.adaptive,\n roundOffsets = _ref2.roundOffsets,\n isFixed = _ref2.isFixed;\n var _offsets$x = offsets.x,\n x = _offsets$x === void 0 ? 0 : _offsets$x,\n _offsets$y = offsets.y,\n y = _offsets$y === void 0 ? 0 : _offsets$y;\n\n var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref3.x;\n y = _ref3.y;\n var hasX = offsets.hasOwnProperty('x');\n var hasY = offsets.hasOwnProperty('y');\n var sideX = left;\n var sideY = top;\n var win = window;\n\n if (adaptive) {\n var offsetParent = getOffsetParent(popper);\n var heightProp = 'clientHeight';\n var widthProp = 'clientWidth';\n\n if (offsetParent === getWindow(popper)) {\n offsetParent = getDocumentElement(popper);\n\n if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {\n heightProp = 'scrollHeight';\n widthProp = 'scrollWidth';\n }\n } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it\n\n\n offsetParent = offsetParent;\n\n if (placement === top || (placement === left || placement === right) && variation === end) {\n sideY = bottom;\n var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]\n offsetParent[heightProp];\n y -= offsetY - popperRect.height;\n y *= gpuAcceleration ? 1 : -1;\n }\n\n if (placement === left || (placement === top || placement === bottom) && variation === end) {\n sideX = right;\n var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]\n offsetParent[widthProp];\n x -= offsetX - popperRect.width;\n x *= gpuAcceleration ? 1 : -1;\n }\n }\n\n var commonStyles = Object.assign({\n position: position\n }, adaptive && unsetSides);\n\n var _ref4 = roundOffsets === true ? roundOffsetsByDPR({\n x: x,\n y: y\n }) : {\n x: x,\n y: y\n };\n\n x = _ref4.x;\n y = _ref4.y;\n\n if (gpuAcceleration) {\n var _Object$assign;\n\n return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? \"translate(\" + x + \"px, \" + y + \"px)\" : \"translate3d(\" + x + \"px, \" + y + \"px, 0)\", _Object$assign));\n }\n\n return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + \"px\" : '', _Object$assign2[sideX] = hasX ? x + \"px\" : '', _Object$assign2.transform = '', _Object$assign2));\n}\n\nfunction computeStyles(_ref5) {\n var state = _ref5.state,\n options = _ref5.options;\n var _options$gpuAccelerat = options.gpuAcceleration,\n gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,\n _options$adaptive = options.adaptive,\n adaptive = _options$adaptive === void 0 ? true : _options$adaptive,\n _options$roundOffsets = options.roundOffsets,\n roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;\n\n if (process.env.NODE_ENV !== \"production\") {\n var transitionProperty = getComputedStyle(state.elements.popper).transitionProperty || '';\n\n if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) {\n return transitionProperty.indexOf(property) >= 0;\n })) {\n console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: \"transform\", \"top\", \"right\", \"bottom\", \"left\".', '\\n\\n', 'Disable the \"computeStyles\" modifier\\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\\n\\n', 'We recommend using the popper element as a wrapper around an inner', 'element that can have any CSS property transitioned for animations.'].join(' '));\n }\n }\n\n var commonStyles = {\n placement: getBasePlacement(state.placement),\n variation: getVariation(state.placement),\n popper: state.elements.popper,\n popperRect: state.rects.popper,\n gpuAcceleration: gpuAcceleration,\n isFixed: state.options.strategy === 'fixed'\n };\n\n if (state.modifiersData.popperOffsets != null) {\n state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.popperOffsets,\n position: state.options.strategy,\n adaptive: adaptive,\n roundOffsets: roundOffsets\n })));\n }\n\n if (state.modifiersData.arrow != null) {\n state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {\n offsets: state.modifiersData.arrow,\n position: 'absolute',\n adaptive: false,\n roundOffsets: roundOffsets\n })));\n }\n\n state.attributes.popper = Object.assign({}, state.attributes.popper, {\n 'data-popper-placement': state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'computeStyles',\n enabled: true,\n phase: 'beforeWrite',\n fn: computeStyles,\n data: {}\n};","import { popperGenerator, detectOverflow } from \"./createPopper.js\";\nimport eventListeners from \"./modifiers/eventListeners.js\";\nimport popperOffsets from \"./modifiers/popperOffsets.js\";\nimport computeStyles from \"./modifiers/computeStyles.js\";\nimport applyStyles from \"./modifiers/applyStyles.js\";\nvar defaultModifiers = [eventListeners, popperOffsets, computeStyles, applyStyles];\nvar createPopper = /*#__PURE__*/popperGenerator({\n defaultModifiers: defaultModifiers\n}); // eslint-disable-next-line import/no-unused-modules\n\nexport { createPopper, popperGenerator, defaultModifiers, detectOverflow };","import computeOffsets from \"../utils/computeOffsets.js\";\n\nfunction popperOffsets(_ref) {\n var state = _ref.state,\n name = _ref.name;\n // Offsets are the actual position the popper needs to have to be\n // properly positioned near its reference element\n // This is the most basic placement, and will be adjusted by\n // the modifiers in the next step\n state.modifiersData[name] = computeOffsets({\n reference: state.rects.reference,\n element: state.rects.popper,\n strategy: 'absolute',\n placement: state.placement\n });\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'popperOffsets',\n enabled: true,\n phase: 'read',\n fn: popperOffsets,\n data: {}\n};","import getNodeName from \"../dom-utils/getNodeName.js\";\nimport { isHTMLElement } from \"../dom-utils/instanceOf.js\"; // This modifier takes the styles prepared by the `computeStyles` modifier\n// and applies them to the HTMLElements such as popper and arrow\n\nfunction applyStyles(_ref) {\n var state = _ref.state;\n Object.keys(state.elements).forEach(function (name) {\n var style = state.styles[name] || {};\n var attributes = state.attributes[name] || {};\n var element = state.elements[name]; // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n } // Flow doesn't support to extend this property, but it's the most\n // effective way to apply styles to an HTMLElement\n // $FlowFixMe[cannot-write]\n\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (name) {\n var value = attributes[name];\n\n if (value === false) {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value === true ? '' : value);\n }\n });\n });\n}\n\nfunction effect(_ref2) {\n var state = _ref2.state;\n var initialStyles = {\n popper: {\n position: state.options.strategy,\n left: '0',\n top: '0',\n margin: '0'\n },\n arrow: {\n position: 'absolute'\n },\n reference: {}\n };\n Object.assign(state.elements.popper.style, initialStyles.popper);\n state.styles = initialStyles;\n\n if (state.elements.arrow) {\n Object.assign(state.elements.arrow.style, initialStyles.arrow);\n }\n\n return function () {\n Object.keys(state.elements).forEach(function (name) {\n var element = state.elements[name];\n var attributes = state.attributes[name] || {};\n var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them\n\n var style = styleProperties.reduce(function (style, property) {\n style[property] = '';\n return style;\n }, {}); // arrow is optional + virtual elements\n\n if (!isHTMLElement(element) || !getNodeName(element)) {\n return;\n }\n\n Object.assign(element.style, style);\n Object.keys(attributes).forEach(function (attribute) {\n element.removeAttribute(attribute);\n });\n });\n };\n} // eslint-disable-next-line import/no-unused-modules\n\n\nexport default {\n name: 'applyStyles',\n enabled: true,\n phase: 'write',\n fn: applyStyles,\n effect: effect,\n requires: ['computeStyles']\n};","import { Component, Input, OnChanges, ChangeDetectionStrategy, SimpleChanges, ViewEncapsulation } from '@angular/core';\nimport { regExpEscape, toString, removeAccents } from '../util/util';\nimport { NgFor, NgIf } from '@angular/common';\n\n/**\n * A component that helps with text highlighting.\n *\n * It splits the `result` text into parts that contain the searched `term` and generates the HTML markup to simplify\n * highlighting:\n *\n * Ex. `result=\"Alaska\"` and `term=\"as\"` will produce `Al<span class=\"ngb-highlight\">as</span>ka`.\n */\n@Component({\n\tselector: 'ngb-highlight',\n\tstandalone: true,\n\timports: [NgIf, NgFor],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\ttemplate:\n\t\t`<ng-template ngFor [ngForOf]=\"parts\" let-part let-isOdd=\"odd\">` +\n\t\t`<span *ngIf=\"isOdd; else even\" [class]=\"highlightClass\">{{part}}</span><ng-template #even>{{part}}</ng-template>` +\n\t\t`</ng-template>`, // template needs to be formatted in a certain way so we don't add empty text nodes\n\tstyleUrls: ['./highlight.scss'],\n})\nexport class NgbHighlight implements OnChanges {\n\tparts: string[];\n\n\t/**\n\t * The CSS class for `<span>` elements wrapping the `term` inside the `result`.\n\t */\n\t@Input() highlightClass = 'ngb-highlight';\n\n\t/**\n\t * The text highlighting is added to.\n\t *\n\t * If the `term` is found inside this text, it will be highlighted.\n\t * If the `term` contains array then all the items from it will be highlighted inside the text.\n\t */\n\t@Input() result?: string | null;\n\n\t/**\n\t * The term or array of terms to be highlighted.\n\t * Since version `v4.2.0` term could be a `string[]`\n\t */\n\t@Input() term: string | readonly string[];\n\n\t/**\n\t * Boolean option to determine if the highlighting should be sensitive to accents or not.\n\t *\n\t * This feature is only available for browsers that implement the `String.normalize` function\n\t * (typically not Internet Explorer).\n\t * If you want to use this feature in a browser that does not implement `String.normalize`,\n\t * you will have to include a polyfill in your application (`unorm` for example).\n\t *\n\t * @since 9.1.0\n\t */\n\t@Input() accentSensitive = true;\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\tif (!this.accentSensitive && !String.prototype.normalize) {\n\t\t\tconsole.warn(\n\t\t\t\t'The `accentSensitive` input in `ngb-highlight` cannot be set to `false` in a browser ' +\n\t\t\t\t\t'that does not implement the `String.normalize` function. ' +\n\t\t\t\t\t'You will have to include a polyfill in your application to use this feature in the current browser.',\n\t\t\t);\n\t\t\tthis.accentSensitive = true;\n\t\t}\n\t\tconst result = toString(this.result);\n\n\t\tconst terms = Array.isArray(this.term) ? this.term : [this.term];\n\t\tconst prepareTerm = (term) => (this.accentSensitive ? term : removeAccents(term));\n\t\tconst escapedTerms = terms.map((term) => regExpEscape(prepareTerm(toString(term)))).filter((term) => term);\n\t\tconst toSplit = this.accentSensitive ? result : removeAccents(result);\n\n\t\tconst parts = escapedTerms.length ? toSplit.split(new RegExp(`(${escapedTerms.join('|')})`, 'gmi')) : [result];\n\n\t\tif (this.accentSensitive) {\n\t\t\tthis.parts = parts;\n\t\t} else {\n\t\t\tlet offset = 0;\n\t\t\tthis.parts = parts.map((part) => result.substring(offset, (offset += part.length)));\n\t\t}\n\t}\n}\n","import { NgZone } from '@angular/core';\nimport { Observable, OperatorFunction } from 'rxjs';\n\nexport function toInteger(value: any): number {\n\treturn parseInt(`${value}`, 10);\n}\n\nexport function toString(value: any): string {\n\treturn value !== undefined && value !== null ? `${value}` : '';\n}\n\nexport function getValueInRange(value: number, max: number, min = 0): number {\n\treturn Math.max(Math.min(value, max), min);\n}\n\nexport function isString(value: any): value is string {\n\treturn typeof value === 'string';\n}\n\nexport function isNumber(value: any): value is number {\n\treturn !isNaN(toInteger(value));\n}\n\nexport function isInteger(value: any): value is number {\n\treturn typeof value === 'number' && isFinite(value) && Math.floor(value) === value;\n}\n\nexport function isDefined(value: any): boolean {\n\treturn value !== undefined && value !== null;\n}\n\nexport function isPromise<T>(v: any): v is Promise<T> {\n\treturn v && v.then;\n}\n\nexport function padNumber(value: number) {\n\tif (isNumber(value)) {\n\t\treturn `0${value}`.slice(-2);\n\t} else {\n\t\treturn '';\n\t}\n}\n\nexport function regExpEscape(text) {\n\treturn text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n}\n\nexport function hasClassName(element: any, className: string): boolean {\n\treturn (\n\t\telement && element.className && element.className.split && element.className.split(/\\s+/).indexOf(className) >= 0\n\t);\n}\n\nexport function closest(element: HTMLElement, selector?: string): HTMLElement | null {\n\tif (!selector) {\n\t\treturn null;\n\t}\n\n\t/*\n\t * In certain browsers (e.g. Edge 44.18362.449.0) HTMLDocument does\n\t * not support `Element.prototype.closest`. To emulate the correct behaviour\n\t * we return null when the method is missing.\n\t *\n\t * Note that in evergreen browsers `closest(document.documentElement, 'html')`\n\t * will return the document element whilst in Edge null will be returned. This\n\t * compromise was deemed good enough.\n\t */\n\tif (typeof element.closest === 'undefined') {\n\t\treturn null;\n\t}\n\n\treturn element.closest(selector);\n}\n\n/**\n * Force a browser reflow\n * @param element element where to apply the reflow\n */\nexport function reflow(element: HTMLElement) {\n\treturn (element || document.body).getBoundingClientRect();\n}\n\n/**\n * Creates an observable where all callbacks are executed inside a given zone\n *\n * @param zone\n */\nexport function runInZone<T>(zone: NgZone): OperatorFunction<T, T> {\n\treturn (source) => {\n\t\treturn new Observable((observer) => {\n\t\t\tconst next = (value: T) => zone.run(() => observer.next(value));\n\t\t\tconst error = (e: any) => zone.run(() => observer.error(e));\n\t\t\tconst complete = () => zone.run(() => observer.complete());\n\t\t\treturn source.subscribe({ next, error, complete });\n\t\t});\n\t};\n}\n\nexport function removeAccents(str: string): string {\n\treturn str.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n}\n","export const environment = {\n\tanimation: true,\n\ttransitionTimerDelayMs: 5,\n};\n","import { NgZone } from '@angular/core';\nimport { EMPTY, fromEvent, Observable, of, race, Subject, timer } from 'rxjs';\nimport { endWith, filter, takeUntil } from 'rxjs/operators';\nimport { getTransitionDurationMs } from './util';\nimport { environment } from '../../environment';\nimport { runInZone } from '../util';\n\nexport type NgbTransitionStartFn<T = any> = (\n\telement: HTMLElement,\n\tanimation: boolean,\n\tcontext: T,\n) => NgbTransitionEndFn | void;\nexport type NgbTransitionEndFn = () => void;\n\nexport interface NgbTransitionOptions<T> {\n\tanimation: boolean;\n\trunningTransition: 'continue' | 'stop';\n\tcontext?: T;\n}\n\nexport interface NgbTransitionCtx<T> {\n\ttransition$: Subject<any>;\n\tcomplete: () => void;\n\tcontext: T;\n}\n\nconst noopFn: NgbTransitionEndFn = () => {};\n\nconst { transitionTimerDelayMs } = environment;\nconst runningTransitions = new Map<HTMLElement, NgbTransitionCtx<any>>();\n\nexport const ngbRunTransition = <T>(\n\tzone: NgZone,\n\telement: HTMLElement,\n\tstartFn: NgbTransitionStartFn<T>,\n\toptions: NgbTransitionOptions<T>,\n): Observable<void> => {\n\t// Getting initial context from options\n\tlet context = options.context || <T>{};\n\n\t// Checking if there are already running transitions on the given element.\n\tconst running = runningTransitions.get(element);\n\tif (running) {\n\t\tswitch (options.runningTransition) {\n\t\t\t// If there is one running and we want for it to 'continue' to run, we have to cancel the new one.\n\t\t\t// We're not emitting any values, but simply completing the observable (EMPTY).\n\t\t\tcase 'continue':\n\t\t\t\treturn EMPTY;\n\t\t\t// If there is one running and we want for it to 'stop', we have to complete the running one.\n\t\t\t// We're simply completing the running one and not emitting any values and merging newly provided context\n\t\t\t// with the one coming from currently running transition.\n\t\t\tcase 'stop':\n\t\t\t\tzone.run(() => running.transition$.complete());\n\t\t\t\tcontext = Object.assign(running.context, context);\n\t\t\t\trunningTransitions.delete(element);\n\t\t}\n\t}\n\n\t// Running the start function\n\tconst endFn = startFn(element, options.animation, context) || noopFn;\n\n\t// If 'prefer-reduced-motion' is enabled, the 'transition' will be set to 'none'.\n\t// If animations are disabled, we have to emit a value and complete the observable\n\t// In this case we have to call the end function, but can finish immediately by emitting a value,\n\t// completing the observable and executing end functions synchronously.\n\tif (!options.animation || window.getComputedStyle(element).transitionProperty === 'none') {\n\t\tzone.run(() => endFn());\n\t\treturn of(undefined).pipe(runInZone(zone));\n\t}\n\n\t// Starting a new transition\n\tconst transition$ = new Subject<void>();\n\tconst finishTransition$ = new Subject<void>();\n\tconst stop$ = transition$.pipe(endWith(true));\n\trunningTransitions.set(element, {\n\t\ttransition$,\n\t\tcomplete: () => {\n\t\t\tfinishTransition$.next();\n\t\t\tfinishTransition$.complete();\n\t\t},\n\t\tcontext,\n\t});\n\n\tconst transitionDurationMs = getTransitionDurationMs(element);\n\n\t// 1. We have to both listen for the 'transitionend' event and have a 'just-in-case' timer,\n\t// because 'transitionend' event might not be fired in some browsers, if the transitioning\n\t// element becomes invisible (ex. when scrolling, making browser tab inactive, etc.). The timer\n\t// guarantees, that we'll release the DOM element and complete 'ngbRunTransition'.\n\t// 2. We need to filter transition end events, because they might bubble from shorter transitions\n\t// on inner DOM elements. We're only interested in the transition on the 'element' itself.\n\tzone.runOutsideAngular(() => {\n\t\tconst transitionEnd$ = fromEvent(element, 'transitionend').pipe(\n\t\t\ttakeUntil(stop$),\n\t\t\tfilter(({ target }) => target === element),\n\t\t);\n\t\tconst timer$ = timer(transitionDurationMs + transitionTimerDelayMs).pipe(takeUntil(stop$));\n\n\t\trace(timer$, transitionEnd$, finishTransition$)\n\t\t\t.pipe(takeUntil(stop$))\n\t\t\t.subscribe(() => {\n\t\t\t\trunningTransitions.delete(element);\n\t\t\t\tzone.run(() => {\n\t\t\t\t\tendFn();\n\t\t\t\t\ttransition$.next();\n\t\t\t\t\ttransition$.complete();\n\t\t\t\t});\n\t\t\t});\n\t});\n\n\treturn transition$.asObservable();\n};\n\nexport const ngbCompleteTransition = (element: HTMLElement) => {\n\trunningTransitions.get(element)?.complete();\n};\n","/** prettier */\nimport { Observable } from '../Observable';\nimport { concat } from '../observable/concat';\nimport { of } from '../observable/of';\nimport { MonoTypeOperatorFunction, SchedulerLike, OperatorFunction, ValueFromArray } from '../types';\n\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `concatAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function endWith<T>(scheduler: SchedulerLike): MonoTypeOperatorFunction<T>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `concatAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function endWith<T, A extends unknown[] = T[]>(\n ...valuesAndScheduler: [...A, SchedulerLike]\n): OperatorFunction<T, T | ValueFromArray<A>>;\n\nexport function endWith<T, A extends unknown[] = T[]>(...values: A): OperatorFunction<T, T | ValueFromArray<A>>;\n\n/**\n * Returns an observable that will emit all values from the source, then synchronously emit\n * the provided value(s) immediately after the source completes.\n *\n * NOTE: Passing a last argument of a Scheduler is _deprecated_, and may result in incorrect\n * types in TypeScript.\n *\n * This is useful for knowing when an observable ends. Particularly when paired with an\n * operator like {@link takeUntil}\n *\n * ![](endWith.png)\n *\n * ## Example\n *\n * Emit values to know when an interval starts and stops. The interval will\n * stop when a user clicks anywhere on the document.\n *\n * ```ts\n * import { interval, map, fromEvent, startWith, takeUntil, endWith } from 'rxjs';\n *\n * const ticker$ = interval(5000).pipe(\n * map(() => 'tick')\n * );\n *\n * const documentClicks$ = fromEvent(document, 'click');\n *\n * ticker$.pipe(\n * startWith('interval started'),\n * takeUntil(documentClicks$),\n * endWith('interval ended by click')\n * )\n * .subscribe(x => console.log(x));\n *\n * // Result (assuming a user clicks after 15 seconds)\n * // 'interval started'\n * // 'tick'\n * // 'tick'\n * // 'tick'\n * // 'interval ended by click'\n * ```\n *\n * @see {@link startWith}\n * @see {@link concat}\n * @see {@link takeUntil}\n *\n * @param values Items you want the modified Observable to emit last.\n * @return A function that returns an Observable that emits all values from the\n * source, then synchronously emits the provided value(s) immediately after the\n * source completes.\n */\nexport function endWith<T>(...values: Array<T | SchedulerLike>): MonoTypeOperatorFunction<T> {\n return (source: Observable<T>) => concat(source, of(...values)) as Observable<T>;\n}\n","export function getTransitionDurationMs(element: HTMLElement) {\n\tconst { transitionDelay, transitionDuration } = window.getComputedStyle(element);\n\tconst transitionDelaySec = parseFloat(transitionDelay);\n\tconst transitionDurationSec = parseFloat(transitionDuration);\n\n\treturn (transitionDelaySec + transitionDurationSec) * 1000;\n}\n","import { NgbTransitionStartFn } from './ngbTransition';\nimport { reflow } from '../util';\n\nexport interface NgbCollapseCtx {\n\tdirection: 'show' | 'hide';\n\tdimension: 'width' | 'height';\n\tmaxSize?: string;\n}\n\nfunction measureCollapsingElementDimensionPx(element: HTMLElement, dimension: 'width' | 'height'): string {\n\t// SSR fix for without injecting the PlatformId\n\tif (typeof navigator === 'undefined') {\n\t\treturn '0px';\n\t}\n\n\tconst { classList } = element;\n\tconst hasShownClass = classList.contains('show');\n\tif (!hasShownClass) {\n\t\tclassList.add('show');\n\t}\n\n\telement.style[dimension] = '';\n\tconst dimensionSize = element.getBoundingClientRect()[dimension] + 'px';\n\n\tif (!hasShownClass) {\n\t\tclassList.remove('show');\n\t}\n\n\treturn dimensionSize;\n}\n\nexport const ngbCollapsingTransition: NgbTransitionStartFn<NgbCollapseCtx> = (\n\telement: HTMLElement,\n\tanimation: boolean,\n\tcontext: NgbCollapseCtx,\n) => {\n\tlet { direction, maxSize, dimension } = context;\n\tconst { classList } = element;\n\n\tfunction setInitialClasses() {\n\t\tclassList.add('collapse');\n\t\tif (direction === 'show') {\n\t\t\tclassList.add('show');\n\t\t} else {\n\t\t\tclassList.remove('show');\n\t\t}\n\t}\n\n\t// without animations we just need to set initial classes\n\tif (!animation) {\n\t\tsetInitialClasses();\n\t\treturn;\n\t}\n\n\t// No maxHeight -> running the transition for the first time\n\tif (!maxSize) {\n\t\tmaxSize = measureCollapsingElementDimensionPx(element, dimension);\n\t\tcontext.maxSize = maxSize;\n\n\t\t// Fix the height before starting the animation\n\t\telement.style[dimension] = direction !== 'show' ? maxSize : '0px';\n\n\t\tclassList.remove('collapse');\n\t\tclassList.remove('collapsing');\n\t\tclassList.remove('show');\n\n\t\treflow(element);\n\n\t\t// Start the animation\n\t\tclassList.add('collapsing');\n\t}\n\n\t// Start or revert the animation\n\telement.style[dimension] = direction === 'show' ? maxSize : '0px';\n\n\treturn () => {\n\t\tsetInitialClasses();\n\t\tclassList.remove('collapsing');\n\t\telement.style[dimension] = '';\n\t};\n};\n","import { Injectable } from '@angular/core';\nimport { environment } from './environment';\n\n/**\n * Global ng-bootstrap config\n *\n * @since 8.0.0\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbConfig {\n\tanimation = environment.animation;\n}\n","import { Injectable } from '@angular/core';\nimport { NgbConfig } from '../ngb-config';\n\n/**\n * A configuration service for the [`NgbAccordionDirective`](#/components/accordion/api#NgbAccordionDirective).\n *\n * You can inject this service, typically in your root component, and customize its properties\n * to provide default values for all accordions used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbAccordionConfig {\n\tcloseOthers = false;\n\t/**\n\t * @deprecated 14.1.0\n\t */\n\ttype: string;\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","/* eslint-disable deprecation/deprecation */\nimport {\n\tAfterContentChecked,\n\tChangeDetectorRef,\n\tComponent,\n\tContentChildren,\n\tDirective,\n\tElementRef,\n\tEventEmitter,\n\tHost,\n\tInput,\n\tOptional,\n\tOutput,\n\tQueryList,\n\tTemplateRef,\n\tViewEncapsulation,\n\tNgZone,\n\tOnInit,\n\tOnDestroy,\n\tInject,\n\tforwardRef,\n} from '@angular/core';\n\nimport { isString } from '../util/util';\n\nimport { NgbAccordionConfig } from './accordion-config';\nimport { ngbRunTransition } from '../util/transition/ngbTransition';\nimport { ngbCollapsingTransition } from '../util/transition/ngbCollapseTransition';\nimport { take } from 'rxjs/operators';\nimport { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';\n\nlet nextId = 0;\n\n/**\n * The context for the [NgbPanelHeader](#/components/accordion/api#NgbPanelHeader) template\n *\n * @since 4.1.0\n * @deprecated 14.1.0\n */\nexport interface NgbPanelHeaderContext {\n\t/**\n\t * `True` if current panel is opened\n\t */\n\topened: boolean;\n}\n\n/**\n * A directive that wraps an accordion panel header with any HTML markup and a toggling button\n * marked with [`NgbPanelToggle`](#/components/accordion/api#NgbPanelToggle).\n * See the [header customization demo](#/components/accordion/examples#header) for more details.\n *\n * You can also use [`NgbPanelTitle`](#/components/accordion/api#NgbPanelTitle) to customize only the panel title.\n *\n * @since 4.1.0\n * @deprecated 14.1.0\n */\n@Directive({ selector: 'ng-template[ngbPanelHeader]', standalone: true })\nexport class NgbPanelHeader {\n\tconstructor(public templateRef: TemplateRef<any>) {}\n}\n\n/**\n * A directive that wraps only the panel title with HTML markup inside.\n *\n * You can also use [`NgbPanelHeader`](#/components/accordion/api#NgbPanelHeader) to customize the full panel header.\n *\n * @deprecated 14.1.0\n */\n@Directive({ selector: 'ng-template[ngbPanelTitle]', standalone: true })\nexport class NgbPanelTitle {\n\tconstructor(public templateRef: TemplateRef<any>) {}\n}\n\n/**\n * A directive that wraps the accordion panel content.\n *\n * @deprecated 14.1.0\n */\n@Directive({ selector: 'ng-template[ngbPanelContent]', standalone: true })\nexport class NgbPanelContent {\n\tconstructor(public templateRef: TemplateRef<any>) {}\n}\n\n/**\n * A directive that wraps an individual accordion panel with title and collapsible content.\n *\n * @deprecated 14.1.0\n */\n@Directive({ selector: 'ngb-panel', standalone: true })\nexport class NgbPanel implements AfterContentChecked {\n\t/**\n\t * If `true`, the panel is disabled an can't be toggled.\n\t */\n\t@Input() disabled = false;\n\n\t/**\n\t * An optional id for the panel that must be unique on the page.\n\t *\n\t * If not provided, it will be auto-generated in the `ngb-panel-xxx` format.\n\t */\n\t@Input() id = `ngb-panel-${nextId++}`;\n\n\tisOpen = false;\n\n\t/* A flag to specified that the transition panel classes have been initialized */\n\tinitClassDone = false;\n\n\t/* A flag to specified if the panel is currently being animated, to ensure its presence in the dom */\n\ttransitionRunning = false;\n\n\t/**\n\t * The panel title.\n\t *\n\t * You can alternatively use [`NgbPanelTitle`](#/components/accordion/api#NgbPanelTitle) to set panel title.\n\t */\n\t@Input() title: string;\n\n\t/**\n\t * Type of the current panel.\n\t *\n\t * Bootstrap provides styles for the following types: `'success'`, `'info'`, `'warning'`, `'danger'`, `'primary'`,\n\t * `'secondary'`, `'light'` and `'dark'`.\n\t */\n\t@Input() type: string;\n\n\t/**\n\t * An optional class applied to the accordion card element that wraps both panel title and content.\n\t *\n\t * @since 5.3.0\n\t */\n\t@Input() cardClass: string;\n\n\t/**\n\t * An event emitted when the panel is shown, after the transition. It has no payload.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() shown = new EventEmitter<void>();\n\n\t/**\n\t * An event emitted when the panel is hidden, after the transition. It has no payload.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() hidden = new EventEmitter<void>();\n\n\ttitleTpl?: NgbPanelTitle;\n\theaderTpl?: NgbPanelHeader;\n\tcontentTpl?: NgbPanelContent;\n\tpanelDiv: HTMLElement | null;\n\n\t@ContentChildren(NgbPanelTitle, { descendants: false }) titleTpls: QueryList<NgbPanelTitle>;\n\t@ContentChildren(NgbPanelHeader, { descendants: false }) headerTpls: QueryList<NgbPanelHeader>;\n\t@ContentChildren(NgbPanelContent, { descendants: false }) contentTpls: QueryList<NgbPanelContent>;\n\n\tngAfterContentChecked() {\n\t\t// We are using @ContentChildren instead of @ContentChild as in the Angular version being used\n\t\t// only @ContentChildren allows us to specify the {descendants: false} option.\n\t\t// Without {descendants: false} we are hitting bugs described in:\n\t\t// https://github.com/ng-bootstrap/ng-bootstrap/issues/2240\n\t\tthis.titleTpl = this.titleTpls.first;\n\t\tthis.headerTpl = this.headerTpls.first;\n\t\tthis.contentTpl = this.contentTpls.first;\n\t}\n}\n\n/**\n * An event emitted right before toggling an accordion panel.\n *\n * @deprecated 14.1.0\n */\nexport interface NgbPanelChangeEvent {\n\t/**\n\t * The id of the accordion panel being toggled.\n\t */\n\tpanelId: string;\n\n\t/**\n\t * The next state of the panel.\n\t *\n\t * `true` if it will be opened, `false` if closed.\n\t */\n\tnextState: boolean;\n\n\t/**\n\t * Calling this function will prevent panel toggling.\n\t */\n\tpreventDefault: () => void;\n}\n\n@Directive({ selector: '[ngbRef]', standalone: true })\nexport class NgbRefDirective implements OnInit, OnDestroy {\n\t@Output() ngbRef = new EventEmitter<HTMLElement | null>();\n\tconstructor(private _El: ElementRef) {}\n\n\tngOnInit() {\n\t\tthis.ngbRef.emit(this._El.nativeElement);\n\t}\n\n\tngOnDestroy() {\n\t\tthis.ngbRef.emit(null);\n\t}\n}\n\n/**\n * A directive to put on a button that toggles panel opening and closing.\n *\n * To be used inside the [`NgbPanelHeader`](#/components/accordion/api#NgbPanelHeader)\n *\n * @since 4.1.0\n * @deprecated 14.1.0\n */\n@Directive({\n\tselector: 'button[ngbPanelToggle]',\n\tstandalone: true,\n\thost: {\n\t\ttype: 'button',\n\t\t'[disabled]': 'panel.disabled',\n\t\t'[class.collapsed]': '!panel.isOpen',\n\t\t'[attr.aria-expanded]': 'panel.isOpen',\n\t\t'[attr.aria-controls]': 'panel.id',\n\t\t'(click)': 'accordion.toggle(panel.id)',\n\t},\n})\nexport class NgbPanelToggle {\n\tstatic ngAcceptInputType_ngbPanelToggle: NgbPanel | '';\n\n\t@Input()\n\tset ngbPanelToggle(panel: NgbPanel) {\n\t\tif (panel) {\n\t\t\tthis.panel = panel;\n\t\t}\n\t}\n\n\tconstructor(\n\t\t@Inject(forwardRef(() => NgbAccordion)) public accordion: NgbAccordion,\n\t\t@Optional() @Host() public panel: NgbPanel,\n\t) {}\n}\n\n/**\n * Accordion is a collection of collapsible panels (bootstrap cards).\n *\n * It can ensure only one panel is opened at a time and allows to customize panel\n * headers.\n *\n * @deprecated 14.1.0\n */\n@Component({\n\tselector: 'ngb-accordion',\n\texportAs: 'ngbAccordion',\n\tstandalone: true,\n\timports: [NgFor, NgTemplateOutlet, NgbPanelToggle, NgbRefDirective, NgbPanelHeader, NgIf],\n\tencapsulation: ViewEncapsulation.None,\n\thost: { class: 'accordion', role: 'tablist', '[attr.aria-multiselectable]': '!closeOtherPanels' },\n\ttemplate: `\n\t\t<ng-template #t ngbPanelHeader let-panel>\n\t\t\t<button class=\"accordion-button\" [ngbPanelToggle]=\"panel\">\n\t\t\t\t{{ panel.title }}\n\t\t\t\t<ng-template [ngTemplateOutlet]=\"panel.titleTpl?.templateRef\"></ng-template>\n\t\t\t</button>\n\t\t</ng-template>\n\t\t<ng-template ngFor let-panel [ngForOf]=\"panels\">\n\t\t\t<div [class]=\"'accordion-item ' + (panel.cardClass || '')\">\n\t\t\t\t<div\n\t\t\t\t\trole=\"tab\"\n\t\t\t\t\tid=\"{{ panel.id }}-header\"\n\t\t\t\t\t[class]=\"'accordion-header ' + (panel.type ? 'bg-' + panel.type : type ? 'bg-' + type : '')\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"panel.headerTpl?.templateRef || t\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: panel, opened: panel.isOpen }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tid=\"{{ panel.id }}\"\n\t\t\t\t\t(ngbRef)=\"panel.panelDiv = $event\"\n\t\t\t\t\trole=\"tabpanel\"\n\t\t\t\t\t[attr.aria-labelledby]=\"panel.id + '-header'\"\n\t\t\t\t\t*ngIf=\"!destroyOnHide || panel.isOpen || panel.transitionRunning\"\n\t\t\t\t>\n\t\t\t\t\t<div class=\"accordion-body\">\n\t\t\t\t\t\t<ng-template [ngTemplateOutlet]=\"panel.contentTpl?.templateRef || null\"></ng-template>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</ng-template>\n\t`,\n})\nexport class NgbAccordion implements AfterContentChecked {\n\t@ContentChildren(NgbPanel) panels: QueryList<NgbPanel>;\n\n\t/**\n\t * If `true`, accordion will be animated.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Input() animation;\n\n\t/**\n\t * An array or comma separated strings of panel ids that should be opened **initially**.\n\t *\n\t * For subsequent changes use methods like `expand()`, `collapse()`, etc. and\n\t * the `(panelChange)` event.\n\t */\n\t@Input() activeIds: string | readonly string[] = [];\n\n\t/**\n\t * If `true`, only one panel could be opened at a time.\n\t *\n\t * Opening a new panel will close others.\n\t */\n\t@Input('closeOthers') closeOtherPanels: boolean;\n\n\t/**\n\t * If `true`, panel content will be detached from DOM and not simply hidden when the panel is collapsed.\n\t */\n\t@Input() destroyOnHide = true;\n\n\t/**\n\t * Type of panels.\n\t *\n\t * Bootstrap provides styles for the following types: `'success'`, `'info'`, `'warning'`, `'danger'`, `'primary'`,\n\t * `'secondary'`, `'light'` and `'dark'`.\n\t */\n\t@Input() type: string;\n\n\t/**\n\t * Event emitted right before the panel toggle happens.\n\t *\n\t * See [NgbPanelChangeEvent](#/components/accordion/api#NgbPanelChangeEvent) for payload details.\n\t */\n\t@Output() panelChange = new EventEmitter<NgbPanelChangeEvent>();\n\n\t/**\n\t * An event emitted when the expanding animation is finished on the panel. The payload is the panel id.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() shown = new EventEmitter<string>();\n\n\t/**\n\t * An event emitted when the collapsing animation is finished on the panel, and before the panel element is removed.\n\t * The payload is the panel id.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() hidden = new EventEmitter<string>();\n\n\tconstructor(config: NgbAccordionConfig, private _ngZone: NgZone, private _changeDetector: ChangeDetectorRef) {\n\t\tthis.animation = config.animation;\n\t\tthis.type = config.type;\n\t\tthis.closeOtherPanels = config.closeOthers;\n\t}\n\n\t/**\n\t * Checks if a panel with a given id is expanded.\n\t */\n\tisExpanded(panelId: string): boolean {\n\t\treturn this.activeIds.indexOf(panelId) > -1;\n\t}\n\n\t/**\n\t * Expands a panel with a given id.\n\t *\n\t * Has no effect if the panel is already expanded or disabled.\n\t */\n\texpand(panelId: string): void {\n\t\tthis._changeOpenState(this._findPanelById(panelId), true);\n\t}\n\n\t/**\n\t * Expands all panels, if `[closeOthers]` is `false`.\n\t *\n\t * If `[closeOthers]` is `true`, it will expand the first panel, unless there is already a panel opened.\n\t */\n\texpandAll(): void {\n\t\tif (this.closeOtherPanels) {\n\t\t\tif (this.activeIds.length === 0 && this.panels.length) {\n\t\t\t\tthis._changeOpenState(this.panels.first, true);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.panels.forEach((panel) => this._changeOpenState(panel, true));\n\t\t}\n\t}\n\n\t/**\n\t * Collapses a panel with the given id.\n\t *\n\t * Has no effect if the panel is already collapsed or disabled.\n\t */\n\tcollapse(panelId: string) {\n\t\tthis._changeOpenState(this._findPanelById(panelId), false);\n\t}\n\n\t/**\n\t * Collapses all opened panels.\n\t */\n\tcollapseAll() {\n\t\tthis.panels.forEach((panel) => {\n\t\t\tthis._changeOpenState(panel, false);\n\t\t});\n\t}\n\n\t/**\n\t * Toggles a panel with the given id.\n\t *\n\t * Has no effect if the panel is disabled.\n\t */\n\ttoggle(panelId: string) {\n\t\tconst panel = this._findPanelById(panelId);\n\t\tif (panel) {\n\t\t\tthis._changeOpenState(panel, !panel.isOpen);\n\t\t}\n\t}\n\n\tngAfterContentChecked() {\n\t\t// active id updates\n\t\tif (isString(this.activeIds)) {\n\t\t\tthis.activeIds = this.activeIds.split(/\\s*,\\s*/);\n\t\t}\n\n\t\t// update panels open states\n\t\tthis.panels.forEach((panel) => {\n\t\t\tpanel.isOpen = !panel.disabled && this.activeIds.indexOf(panel.id) > -1;\n\t\t});\n\n\t\t// closeOthers updates\n\t\tif (this.activeIds.length > 1 && this.closeOtherPanels) {\n\t\t\tthis._closeOthers(this.activeIds[0], false);\n\t\t\tthis._updateActiveIds();\n\t\t}\n\n\t\t// Setup the initial classes here\n\t\tthis._ngZone.onStable.pipe(take(1)).subscribe(() => {\n\t\t\tthis.panels.forEach((panel) => {\n\t\t\t\tconst panelElement = panel.panelDiv;\n\t\t\t\tif (panelElement) {\n\t\t\t\t\tif (!panel.initClassDone) {\n\t\t\t\t\t\tpanel.initClassDone = true;\n\t\t\t\t\t\tngbRunTransition(this._ngZone, panelElement, ngbCollapsingTransition, {\n\t\t\t\t\t\t\tanimation: false,\n\t\t\t\t\t\t\trunningTransition: 'continue',\n\t\t\t\t\t\t\tcontext: { direction: panel.isOpen ? 'show' : 'hide', dimension: 'height' },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Classes must be initialized next time it will be in the dom\n\t\t\t\t\tpanel.initClassDone = false;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _changeOpenState(panel: NgbPanel | null, nextState: boolean) {\n\t\tif (panel != null && !panel.disabled && panel.isOpen !== nextState) {\n\t\t\tlet defaultPrevented = false;\n\n\t\t\tthis.panelChange.emit({\n\t\t\t\tpanelId: panel.id,\n\t\t\t\tnextState: nextState,\n\t\t\t\tpreventDefault: () => {\n\t\t\t\t\tdefaultPrevented = true;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!defaultPrevented) {\n\t\t\t\tpanel.isOpen = nextState;\n\t\t\t\tpanel.transitionRunning = true;\n\n\t\t\t\tif (nextState && this.closeOtherPanels) {\n\t\t\t\t\tthis._closeOthers(panel.id);\n\t\t\t\t}\n\t\t\t\tthis._updateActiveIds();\n\t\t\t\tthis._runTransitions(this.animation);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _closeOthers(panelId: string, enableTransition = true) {\n\t\tthis.panels.forEach((panel) => {\n\t\t\tif (panel.id !== panelId && panel.isOpen) {\n\t\t\t\tpanel.isOpen = false;\n\t\t\t\tpanel.transitionRunning = enableTransition;\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate _findPanelById(panelId: string): NgbPanel | null {\n\t\treturn this.panels.find((p) => p.id === panelId) || null;\n\t}\n\n\tprivate _updateActiveIds() {\n\t\tthis.activeIds = this.panels.filter((panel) => panel.isOpen && !panel.disabled).map((panel) => panel.id);\n\t}\n\n\tprivate _runTransitions(animation: boolean) {\n\t\t// detectChanges is performed to ensure that all panels are in the dom (via transitionRunning = true)\n\t\t// before starting the animation\n\t\tthis._changeDetector.detectChanges();\n\n\t\tthis.panels.forEach((panel) => {\n\t\t\t// When panel.transitionRunning is true, the transition needs to be started OR reversed,\n\t\t\t// The direction (show or hide) is choosen by each panel.isOpen state\n\t\t\tif (panel.transitionRunning) {\n\t\t\t\tconst panelElement = panel.panelDiv;\n\t\t\t\tngbRunTransition(this._ngZone, panelElement!, ngbCollapsingTransition, {\n\t\t\t\t\tanimation,\n\t\t\t\t\trunningTransition: 'stop',\n\t\t\t\t\tcontext: { direction: panel.isOpen ? 'show' : 'hide', dimension: 'height' },\n\t\t\t\t}).subscribe(() => {\n\t\t\t\t\tpanel.transitionRunning = false;\n\t\t\t\t\tconst { id } = panel;\n\t\t\t\t\tif (panel.isOpen) {\n\t\t\t\t\t\tpanel.shown.emit();\n\t\t\t\t\t\tthis.shown.emit(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpanel.hidden.emit();\n\t\t\t\t\t\tthis.hidden.emit(id);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n}\n","/* eslint-disable deprecation/deprecation */\nimport { NgModule } from '@angular/core';\n\nimport { NgbAccordion, NgbPanel, NgbPanelContent, NgbPanelHeader, NgbPanelTitle, NgbPanelToggle } from './accordion';\nimport {\n\tNgbAccordionDirective,\n\tNgbAccordionItem,\n\tNgbAccordionHeader,\n\tNgbAccordionToggle,\n\tNgbAccordionBody,\n\tNgbAccordionCollapse,\n\tNgbAccordionButton,\n} from './accordion.directive';\n\nexport {\n\tNgbAccordion,\n\tNgbPanel,\n\tNgbPanelTitle,\n\tNgbPanelContent,\n\tNgbPanelChangeEvent,\n\tNgbPanelHeader,\n\tNgbPanelHeaderContext,\n\tNgbPanelToggle,\n} from './accordion';\n\nexport {\n\tNgbAccordionButton,\n\tNgbAccordionDirective,\n\tNgbAccordionItem,\n\tNgbAccordionHeader,\n\tNgbAccordionToggle,\n\tNgbAccordionBody,\n\tNgbAccordionCollapse,\n} from './accordion.directive';\nexport { NgbAccordionConfig } from './accordion-config';\n\nconst NGB_ACCORDION_DIRECTIVES = [\n\tNgbAccordion,\n\tNgbPanel,\n\tNgbPanelTitle,\n\tNgbPanelContent,\n\tNgbPanelHeader,\n\tNgbPanelToggle,\n\tNgbAccordionButton,\n\tNgbAccordionDirective,\n\tNgbAccordionItem,\n\tNgbAccordionHeader,\n\tNgbAccordionToggle,\n\tNgbAccordionBody,\n\tNgbAccordionCollapse,\n];\n\n@NgModule({\n\timports: NGB_ACCORDION_DIRECTIVES,\n\texports: NGB_ACCORDION_DIRECTIVES,\n})\nexport class NgbAccordionModule {}\n","import { NgbTransitionStartFn } from '../util/transition/ngbTransition';\n\nexport const ngbAlertFadingTransition: NgbTransitionStartFn = ({ classList }: HTMLElement) => {\n\tclassList.remove('show');\n};\n","import { Injectable } from '@angular/core';\nimport { NgbConfig } from '../ngb-config';\n\n/**\n * A configuration service for the [NgbAlert](#/components/alert/api#NgbAlert) component.\n *\n * You can inject this service, typically in your root component, and customize its properties\n * to provide default values for all alerts used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbAlertConfig {\n\tdismissible = true;\n\ttype = 'warning';\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import {\n\tComponent,\n\tInput,\n\tOutput,\n\tEventEmitter,\n\tChangeDetectionStrategy,\n\tRenderer2,\n\tElementRef,\n\tOnChanges,\n\tOnInit,\n\tSimpleChanges,\n\tViewEncapsulation,\n\tNgZone,\n} from '@angular/core';\n\nimport { Observable } from 'rxjs';\n\nimport { NgbAlertConfig } from './alert-config';\nimport { ngbRunTransition } from '../util/transition/ngbTransition';\nimport { ngbAlertFadingTransition } from './alert-transition';\nimport { NgIf } from '@angular/common';\n\n/**\n * Alert is a component to provide contextual feedback messages for user.\n *\n * It supports several alert types and can be dismissed.\n */\n@Component({\n\tselector: 'ngb-alert',\n\texportAs: 'ngbAlert',\n\tstandalone: true,\n\timports: [NgIf],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\thost: { role: 'alert', class: 'alert show', '[class.fade]': 'animation', '[class.alert-dismissible]': 'dismissible' },\n\ttemplate: `\n\t\t<ng-content></ng-content>\n\t\t<button\n\t\t\t*ngIf=\"dismissible\"\n\t\t\ttype=\"button\"\n\t\t\tclass=\"btn-close\"\n\t\t\taria-label=\"Close\"\n\t\t\ti18n-aria-label=\"@@ngb.alert.close\"\n\t\t\t(click)=\"close()\"\n\t\t>\n\t\t</button>\n\t`,\n\tstyleUrls: ['./alert.scss'],\n})\nexport class NgbAlert implements OnInit, OnChanges {\n\t/**\n\t * If `true`, alert closing will be animated.\n\t *\n\t * Animation is triggered only when clicked on the close button (×)\n\t * or via the `.close()` function\n\t *\n\t * @since 8.0.0\n\t */\n\t@Input() animation: boolean;\n\n\t/**\n\t * If `true`, alert can be dismissed by the user.\n\t *\n\t * The close button (×) will be displayed and you can be notified\n\t * of the event with the `(close)` output.\n\t */\n\t@Input() dismissible: boolean;\n\n\t/**\n\t * Type of the alert.\n\t *\n\t * Bootstrap provides styles for the following types: `'success'`, `'info'`, `'warning'`, `'danger'`, `'primary'`,\n\t * `'secondary'`, `'light'` and `'dark'`.\n\t */\n\t@Input() type: string;\n\n\t/**\n\t * An event emitted when the close button is clicked. It has no payload and only relevant for dismissible alerts.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() closed = new EventEmitter<void>();\n\n\tconstructor(\n\t\tconfig: NgbAlertConfig,\n\t\tprivate _renderer: Renderer2,\n\t\tprivate _element: ElementRef,\n\t\tprivate _zone: NgZone,\n\t) {\n\t\tthis.dismissible = config.dismissible;\n\t\tthis.type = config.type;\n\t\tthis.animation = config.animation;\n\t}\n\n\t/**\n\t * Triggers alert closing programmatically (same as clicking on the close button (×)).\n\t *\n\t * The returned observable will emit and be completed once the closing transition has finished.\n\t * If the animations are turned off this happens synchronously.\n\t *\n\t * Alternatively you could listen or subscribe to the `(closed)` output\n\t *\n\t * @since 8.0.0\n\t */\n\tclose(): Observable<void> {\n\t\tconst transition = ngbRunTransition(this._zone, this._element.nativeElement, ngbAlertFadingTransition, {\n\t\t\tanimation: this.animation,\n\t\t\trunningTransition: 'continue',\n\t\t});\n\t\ttransition.subscribe(() => this.closed.emit());\n\t\treturn transition;\n\t}\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\tconst typeChange = changes['type'];\n\t\tif (typeChange && !typeChange.firstChange) {\n\t\t\tthis._renderer.removeClass(this._element.nativeElement, `alert-${typeChange.previousValue}`);\n\t\t\tthis._renderer.addClass(this._element.nativeElement, `alert-${typeChange.currentValue}`);\n\t\t}\n\t}\n\n\tngOnInit() {\n\t\tthis._renderer.addClass(this._element.nativeElement, `alert-${this.type}`);\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbAlert } from './alert';\n\nexport { NgbAlert } from './alert';\nexport { NgbAlertConfig } from './alert-config';\n\n@NgModule({\n\timports: [NgbAlert],\n\texports: [NgbAlert],\n})\nexport class NgbAlertModule {}\n","import { NgbTransitionStartFn } from '../util/transition/ngbTransition';\nimport { reflow } from '../util/util';\n\n/**\n * Defines the carousel slide transition direction.\n */\nexport enum NgbSlideEventDirection {\n\tSTART = 'start',\n\tEND = 'end',\n}\n\nexport interface NgbCarouselCtx {\n\t/**\n\t * <span class=\"badge bg-info text-dark\">since 12.0.0</span> Possible values are `'start' | 'end'`.\n\t *\n\t * <span class=\"badge bg-secondary\">before 12.0.0</span> Possible values were `'left' | 'right'`.\n\t */\n\tdirection: 'start' | 'end';\n}\n\nconst isBeingAnimated = ({ classList }: HTMLElement) => {\n\treturn classList.contains('carousel-item-start') || classList.contains('carousel-item-end');\n};\n\nconst removeDirectionClasses = (classList: DOMTokenList) => {\n\tclassList.remove('carousel-item-start');\n\tclassList.remove('carousel-item-end');\n};\n\nconst removeClasses = (classList: DOMTokenList) => {\n\tremoveDirectionClasses(classList);\n\tclassList.remove('carousel-item-prev');\n\tclassList.remove('carousel-item-next');\n};\n\nexport const ngbCarouselTransitionIn: NgbTransitionStartFn<NgbCarouselCtx> = (\n\telement: HTMLElement,\n\tanimation: boolean,\n\t{ direction }: NgbCarouselCtx,\n) => {\n\tconst { classList } = element;\n\n\tif (!animation) {\n\t\tremoveDirectionClasses(classList);\n\t\tremoveClasses(classList);\n\t\tclassList.add('active');\n\t\treturn;\n\t}\n\n\tif (isBeingAnimated(element)) {\n\t\t// Revert the transition\n\t\tremoveDirectionClasses(classList);\n\t} else {\n\t\t// For the 'in' transition, a 'pre-class' is applied to the element to ensure its visibility\n\t\tclassList.add('carousel-item-' + (direction === NgbSlideEventDirection.START ? 'next' : 'prev'));\n\t\treflow(element);\n\t\tclassList.add('carousel-item-' + direction);\n\t}\n\n\treturn () => {\n\t\tremoveClasses(classList);\n\t\tclassList.add('active');\n\t};\n};\n\nexport const ngbCarouselTransitionOut: NgbTransitionStartFn<NgbCarouselCtx> = (\n\telement: HTMLElement,\n\tanimation: boolean,\n\t{ direction }: NgbCarouselCtx,\n) => {\n\tconst { classList } = element;\n\n\tif (!animation) {\n\t\tremoveDirectionClasses(classList);\n\t\tremoveClasses(classList);\n\t\tclassList.remove('active');\n\t\treturn;\n\t}\n\n\t// direction is left or right, depending on the way the slide goes out.\n\tif (isBeingAnimated(element)) {\n\t\t// Revert the transition\n\t\tremoveDirectionClasses(classList);\n\t} else {\n\t\tclassList.add('carousel-item-' + direction);\n\t}\n\n\treturn () => {\n\t\tremoveClasses(classList);\n\t\tclassList.remove('active');\n\t};\n};\n","import { Injectable } from '@angular/core';\nimport { NgbConfig } from '../ngb-config';\n\n/**\n * A configuration service for the [NgbCarousel](#/components/carousel/api#NgbCarousel) component.\n *\n * You can inject this service, typically in your root component, and customize its properties\n * to provide default values for all carousels used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbCarouselConfig {\n\tinterval = 5000;\n\twrap = true;\n\tkeyboard = true;\n\tpauseOnHover = true;\n\tpauseOnFocus = true;\n\tshowNavigationArrows = true;\n\tshowNavigationIndicators = true;\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import {\n\tAfterContentChecked,\n\tAfterContentInit,\n\tChangeDetectionStrategy,\n\tChangeDetectorRef,\n\tComponent,\n\tContentChildren,\n\tDirective,\n\tElementRef,\n\tEventEmitter,\n\tInject,\n\tInput,\n\tNgZone,\n\tOnDestroy,\n\tOutput,\n\tPLATFORM_ID,\n\tQueryList,\n\tTemplateRef,\n\tViewEncapsulation,\n\tAfterViewInit,\n} from '@angular/core';\nimport { isPlatformBrowser, NgFor, NgIf, NgTemplateOutlet } from '@angular/common';\n\nimport { NgbCarouselConfig } from './carousel-config';\n\nimport { BehaviorSubject, combineLatest, NEVER, Observable, Subject, timer, zip } from 'rxjs';\nimport { distinctUntilChanged, map, startWith, switchMap, take, takeUntil } from 'rxjs/operators';\nimport { ngbCompleteTransition, ngbRunTransition, NgbTransitionOptions } from '../util/transition/ngbTransition';\nimport {\n\tngbCarouselTransitionIn,\n\tngbCarouselTransitionOut,\n\tNgbSlideEventDirection,\n\tNgbCarouselCtx,\n} from './carousel-transition';\n\nlet nextId = 0;\n\n/**\n * A directive that wraps the individual carousel slide.\n */\n@Directive({ selector: 'ng-template[ngbSlide]', standalone: true })\nexport class NgbSlide {\n\t/**\n\t * Slide id that must be unique for the entire document.\n\t *\n\t * If not provided, will be generated in the `ngb-slide-xx` format.\n\t */\n\t@Input() id = `ngb-slide-${nextId++}`;\n\n\t/**\n\t * An event emitted when the slide transition is finished\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() slid = new EventEmitter<NgbSingleSlideEvent>();\n\n\tconstructor(public tplRef: TemplateRef<any>) {}\n}\n\n/**\n * Carousel is a component to easily create and control slideshows.\n *\n * Allows to set intervals, change the way user interacts with the slides and provides a programmatic API.\n */\n@Component({\n\tselector: 'ngb-carousel',\n\texportAs: 'ngbCarousel',\n\tstandalone: true,\n\timports: [NgFor, NgTemplateOutlet, NgIf],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'carousel slide',\n\t\t'[style.display]': '\"block\"',\n\t\ttabIndex: '0',\n\t\t'(keydown.arrowLeft)': 'keyboard && arrowLeft()',\n\t\t'(keydown.arrowRight)': 'keyboard && arrowRight()',\n\t\t'(mouseenter)': 'mouseHover = true',\n\t\t'(mouseleave)': 'mouseHover = false',\n\t\t'(focusin)': 'focused = true',\n\t\t'(focusout)': 'focused = false',\n\t\t'[attr.aria-activedescendant]': `'slide-' + activeId`,\n\t},\n\ttemplate: `\n\t\t<div class=\"carousel-indicators\" [class.visually-hidden]=\"!showNavigationIndicators\" role=\"tablist\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdata-bs-target\n\t\t\t\t*ngFor=\"let slide of slides\"\n\t\t\t\t[class.active]=\"slide.id === activeId\"\n\t\t\t\trole=\"tab\"\n\t\t\t\t[attr.aria-labelledby]=\"'slide-' + slide.id\"\n\t\t\t\t[attr.aria-controls]=\"'slide-' + slide.id\"\n\t\t\t\t[attr.aria-selected]=\"slide.id === activeId\"\n\t\t\t\t(click)=\"focus(); select(slide.id, NgbSlideEventSource.INDICATOR)\"\n\t\t\t></button>\n\t\t</div>\n\t\t<div class=\"carousel-inner\">\n\t\t\t<div\n\t\t\t\t*ngFor=\"let slide of slides; index as i; count as c\"\n\t\t\t\tclass=\"carousel-item\"\n\t\t\t\t[id]=\"'slide-' + slide.id\"\n\t\t\t\trole=\"tabpanel\"\n\t\t\t>\n\t\t\t\t<span\n\t\t\t\t\tclass=\"visually-hidden\"\n\t\t\t\t\ti18n=\"Currently selected slide number read by screen reader@@ngb.carousel.slide-number\"\n\t\t\t\t>\n\t\t\t\t\tSlide {{ i + 1 }} of {{ c }}\n\t\t\t\t</span>\n\t\t\t\t<ng-template [ngTemplateOutlet]=\"slide.tplRef\"></ng-template>\n\t\t\t</div>\n\t\t</div>\n\t\t<button class=\"carousel-control-prev\" type=\"button\" (click)=\"arrowLeft()\" *ngIf=\"showNavigationArrows\">\n\t\t\t<span class=\"carousel-control-prev-icon\" aria-hidden=\"true\"></span>\n\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.carousel.previous\">Previous</span>\n\t\t</button>\n\t\t<button class=\"carousel-control-next\" type=\"button\" (click)=\"arrowRight()\" *ngIf=\"showNavigationArrows\">\n\t\t\t<span class=\"carousel-control-next-icon\" aria-hidden=\"true\"></span>\n\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.carousel.next\">Next</span>\n\t\t</button>\n\t`,\n})\nexport class NgbCarousel implements AfterContentChecked, AfterContentInit, AfterViewInit, OnDestroy {\n\t@ContentChildren(NgbSlide) slides: QueryList<NgbSlide>;\n\n\tpublic NgbSlideEventSource = NgbSlideEventSource;\n\n\tprivate _destroy$ = new Subject<void>();\n\tprivate _interval$ = new BehaviorSubject(0);\n\tprivate _mouseHover$ = new BehaviorSubject(false);\n\tprivate _focused$ = new BehaviorSubject(false);\n\tprivate _pauseOnHover$ = new BehaviorSubject(false);\n\tprivate _pauseOnFocus$ = new BehaviorSubject(false);\n\tprivate _pause$ = new BehaviorSubject(false);\n\tprivate _wrap$ = new BehaviorSubject(false);\n\n\t/**\n\t * A flag to enable/disable the animations.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Input() animation: boolean;\n\n\t/**\n\t * The slide id that should be displayed **initially**.\n\t *\n\t * For subsequent interactions use methods `select()`, `next()`, etc. and the `(slide)` output.\n\t */\n\t@Input() activeId: string;\n\n\t/**\n\t * Time in milliseconds before the next slide is shown.\n\t */\n\t@Input()\n\tset interval(value: number) {\n\t\tthis._interval$.next(value);\n\t}\n\n\tget interval() {\n\t\treturn this._interval$.value;\n\t}\n\n\t/**\n\t * If `true`, will 'wrap' the carousel by switching from the last slide back to the first.\n\t */\n\t@Input()\n\tset wrap(value: boolean) {\n\t\tthis._wrap$.next(value);\n\t}\n\n\tget wrap() {\n\t\treturn this._wrap$.value;\n\t}\n\n\t/**\n\t * If `true`, allows to interact with carousel using keyboard 'arrow left' and 'arrow right'.\n\t */\n\t@Input() keyboard: boolean;\n\n\t/**\n\t * If `true`, will pause slide switching when mouse cursor hovers the slide.\n\t *\n\t * @since 2.2.0\n\t */\n\t@Input()\n\tset pauseOnHover(value: boolean) {\n\t\tthis._pauseOnHover$.next(value);\n\t}\n\n\tget pauseOnHover() {\n\t\treturn this._pauseOnHover$.value;\n\t}\n\n\t/**\n\t * If `true`, will pause slide switching when the focus is inside the carousel.\n\t */\n\t@Input()\n\tset pauseOnFocus(value: boolean) {\n\t\tthis._pauseOnFocus$.next(value);\n\t}\n\n\tget pauseOnFocus() {\n\t\treturn this._pauseOnFocus$.value;\n\t}\n\n\t/**\n\t * If `true`, 'previous' and 'next' navigation arrows will be visible on the slide.\n\t *\n\t * @since 2.2.0\n\t */\n\t@Input() showNavigationArrows: boolean;\n\n\t/**\n\t * If `true`, navigation indicators at the bottom of the slide will be visible.\n\t *\n\t * @since 2.2.0\n\t */\n\t@Input() showNavigationIndicators: boolean;\n\n\t/**\n\t * An event emitted just before the slide transition starts.\n\t *\n\t * See [`NgbSlideEvent`](#/components/carousel/api#NgbSlideEvent) for payload details.\n\t */\n\t@Output() slide = new EventEmitter<NgbSlideEvent>();\n\n\t/**\n\t * An event emitted right after the slide transition is completed.\n\t *\n\t * See [`NgbSlideEvent`](#/components/carousel/api#NgbSlideEvent) for payload details.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() slid = new EventEmitter<NgbSlideEvent>();\n\n\t/*\n\t * Keep the ids of the panels currently transitionning\n\t * in order to allow only the transition revertion\n\t */\n\tprivate _transitionIds: [string, string] | null = null;\n\n\tset mouseHover(value: boolean) {\n\t\tthis._mouseHover$.next(value);\n\t}\n\n\tget mouseHover() {\n\t\treturn this._mouseHover$.value;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused$.next(value);\n\t}\n\n\tget focused() {\n\t\treturn this._focused$.value;\n\t}\n\n\tconstructor(\n\t\tconfig: NgbCarouselConfig,\n\t\t@Inject(PLATFORM_ID) private _platformId,\n\t\tprivate _ngZone: NgZone,\n\t\tprivate _cd: ChangeDetectorRef,\n\t\tprivate _container: ElementRef,\n\t) {\n\t\tthis.animation = config.animation;\n\t\tthis.interval = config.interval;\n\t\tthis.wrap = config.wrap;\n\t\tthis.keyboard = config.keyboard;\n\t\tthis.pauseOnHover = config.pauseOnHover;\n\t\tthis.pauseOnFocus = config.pauseOnFocus;\n\t\tthis.showNavigationArrows = config.showNavigationArrows;\n\t\tthis.showNavigationIndicators = config.showNavigationIndicators;\n\t}\n\n\tarrowLeft() {\n\t\tthis.focus();\n\t\tthis.prev(NgbSlideEventSource.ARROW_LEFT);\n\t}\n\n\tarrowRight() {\n\t\tthis.focus();\n\t\tthis.next(NgbSlideEventSource.ARROW_RIGHT);\n\t}\n\n\tngAfterContentInit() {\n\t\t// setInterval() doesn't play well with SSR and protractor,\n\t\t// so we should run it in the browser and outside Angular\n\t\tif (isPlatformBrowser(this._platformId)) {\n\t\t\tthis._ngZone.runOutsideAngular(() => {\n\t\t\t\tconst hasNextSlide$ = combineLatest([\n\t\t\t\t\tthis.slide.pipe(\n\t\t\t\t\t\tmap((slideEvent) => slideEvent.current),\n\t\t\t\t\t\tstartWith(this.activeId),\n\t\t\t\t\t),\n\t\t\t\t\tthis._wrap$,\n\t\t\t\t\tthis.slides.changes.pipe(startWith(null)),\n\t\t\t\t]).pipe(\n\t\t\t\t\tmap(([currentSlideId, wrap]) => {\n\t\t\t\t\t\tconst slideArr = this.slides.toArray();\n\t\t\t\t\t\tconst currentSlideIdx = this._getSlideIdxById(currentSlideId);\n\t\t\t\t\t\treturn wrap ? slideArr.length > 1 : currentSlideIdx < slideArr.length - 1;\n\t\t\t\t\t}),\n\t\t\t\t\tdistinctUntilChanged(),\n\t\t\t\t);\n\t\t\t\tcombineLatest([\n\t\t\t\t\tthis._pause$,\n\t\t\t\t\tthis._pauseOnHover$,\n\t\t\t\t\tthis._mouseHover$,\n\t\t\t\t\tthis._pauseOnFocus$,\n\t\t\t\t\tthis._focused$,\n\t\t\t\t\tthis._interval$,\n\t\t\t\t\thasNextSlide$,\n\t\t\t\t])\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tmap(\n\t\t\t\t\t\t\t([pause, pauseOnHover, mouseHover, pauseOnFocus, focused, interval, hasNextSlide]: [\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t\tnumber,\n\t\t\t\t\t\t\t\tboolean,\n\t\t\t\t\t\t\t]) =>\n\t\t\t\t\t\t\t\tpause || (pauseOnHover && mouseHover) || (pauseOnFocus && focused) || !hasNextSlide ? 0 : interval,\n\t\t\t\t\t\t),\n\n\t\t\t\t\t\tdistinctUntilChanged(),\n\t\t\t\t\t\tswitchMap((interval) => (interval > 0 ? timer(interval, interval) : NEVER)),\n\t\t\t\t\t\ttakeUntil(this._destroy$),\n\t\t\t\t\t)\n\t\t\t\t\t.subscribe(() => this._ngZone.run(() => this.next(NgbSlideEventSource.TIMER)));\n\t\t\t});\n\t\t}\n\n\t\tthis.slides.changes.pipe(takeUntil(this._destroy$)).subscribe(() => {\n\t\t\tthis._transitionIds?.forEach((id) => ngbCompleteTransition(this._getSlideElement(id)));\n\t\t\tthis._transitionIds = null;\n\n\t\t\tthis._cd.markForCheck();\n\n\t\t\t// The following code need to be done asynchronously, after the dom becomes stable,\n\t\t\t// otherwise all changes will be undone.\n\t\t\tthis._ngZone.onStable.pipe(take(1)).subscribe(() => {\n\t\t\t\tfor (const { id } of this.slides) {\n\t\t\t\t\tconst element = this._getSlideElement(id);\n\t\t\t\t\tif (id === this.activeId) {\n\t\t\t\t\t\telement.classList.add('active');\n\t\t\t\t\t} else {\n\t\t\t\t\t\telement.classList.remove('active');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\tngAfterContentChecked() {\n\t\tlet activeSlide = this._getSlideById(this.activeId);\n\t\tthis.activeId = activeSlide ? activeSlide.id : this.slides.length ? this.slides.first.id : '';\n\t}\n\n\tngAfterViewInit() {\n\t\t// Initialize the 'active' class (not managed by the template)\n\t\tif (this.activeId) {\n\t\t\tconst element = this._getSlideElement(this.activeId);\n\t\t\tif (element) {\n\t\t\t\telement.classList.add('active');\n\t\t\t}\n\t\t}\n\t}\n\n\tngOnDestroy() {\n\t\tthis._destroy$.next();\n\t}\n\n\t/**\n\t * Navigates to a slide with the specified identifier.\n\t */\n\tselect(slideId: string, source?: NgbSlideEventSource) {\n\t\tthis._cycleToSelected(slideId, this._getSlideEventDirection(this.activeId, slideId), source);\n\t}\n\n\t/**\n\t * Navigates to the previous slide.\n\t */\n\tprev(source?: NgbSlideEventSource) {\n\t\tthis._cycleToSelected(this._getPrevSlide(this.activeId), NgbSlideEventDirection.END, source);\n\t}\n\n\t/**\n\t * Navigates to the next slide.\n\t */\n\tnext(source?: NgbSlideEventSource) {\n\t\tthis._cycleToSelected(this._getNextSlide(this.activeId), NgbSlideEventDirection.START, source);\n\t}\n\n\t/**\n\t * Pauses cycling through the slides.\n\t */\n\tpause() {\n\t\tthis._pause$.next(true);\n\t}\n\n\t/**\n\t * Restarts cycling through the slides from start to end.\n\t */\n\tcycle() {\n\t\tthis._pause$.next(false);\n\t}\n\n\t/**\n\t * Set the focus on the carousel.\n\t */\n\tfocus() {\n\t\tthis._container.nativeElement.focus();\n\t}\n\n\tprivate _cycleToSelected(slideIdx: string, direction: NgbSlideEventDirection, source?: NgbSlideEventSource) {\n\t\tconst transitionIds = this._transitionIds;\n\t\tif (transitionIds && (transitionIds[0] !== slideIdx || transitionIds[1] !== this.activeId)) {\n\t\t\t// Revert prevented\n\t\t\treturn;\n\t\t}\n\n\t\tlet selectedSlide = this._getSlideById(slideIdx);\n\t\tif (selectedSlide && selectedSlide.id !== this.activeId) {\n\t\t\tthis._transitionIds = [this.activeId, slideIdx];\n\t\t\tthis.slide.emit({\n\t\t\t\tprev: this.activeId,\n\t\t\t\tcurrent: selectedSlide.id,\n\t\t\t\tdirection: direction,\n\t\t\t\tpaused: this._pause$.value,\n\t\t\t\tsource,\n\t\t\t});\n\n\t\t\tconst options: NgbTransitionOptions<NgbCarouselCtx> = {\n\t\t\t\tanimation: this.animation,\n\t\t\t\trunningTransition: 'stop',\n\t\t\t\tcontext: { direction },\n\t\t\t};\n\n\t\t\tconst transitions: Array<Observable<any>> = [];\n\t\t\tconst activeSlide = this._getSlideById(this.activeId);\n\t\t\tif (activeSlide) {\n\t\t\t\tconst activeSlideTransition = ngbRunTransition(\n\t\t\t\t\tthis._ngZone,\n\t\t\t\t\tthis._getSlideElement(activeSlide.id),\n\t\t\t\t\tngbCarouselTransitionOut,\n\t\t\t\t\toptions,\n\t\t\t\t);\n\t\t\t\tactiveSlideTransition.subscribe(() => {\n\t\t\t\t\tactiveSlide.slid.emit({ isShown: false, direction, source });\n\t\t\t\t});\n\t\t\t\ttransitions.push(activeSlideTransition);\n\t\t\t}\n\n\t\t\tconst previousId = this.activeId;\n\t\t\tthis.activeId = selectedSlide.id;\n\t\t\tconst nextSlide = this._getSlideById(this.activeId);\n\t\t\tconst transition = ngbRunTransition(\n\t\t\t\tthis._ngZone,\n\t\t\t\tthis._getSlideElement(selectedSlide.id),\n\t\t\t\tngbCarouselTransitionIn,\n\t\t\t\toptions,\n\t\t\t);\n\t\t\ttransition.subscribe(() => {\n\t\t\t\tnextSlide?.slid.emit({ isShown: true, direction, source });\n\t\t\t});\n\t\t\ttransitions.push(transition);\n\n\t\t\tzip(...transitions)\n\t\t\t\t.pipe(take(1))\n\t\t\t\t.subscribe(() => {\n\t\t\t\t\tthis._transitionIds = null;\n\t\t\t\t\tthis.slid.emit({\n\t\t\t\t\t\tprev: previousId,\n\t\t\t\t\t\tcurrent: selectedSlide!.id,\n\t\t\t\t\t\tdirection: direction,\n\t\t\t\t\t\tpaused: this._pause$.value,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t}\n\n\t\t// we get here after the interval fires or any external API call like next(), prev() or select()\n\t\tthis._cd.markForCheck();\n\t}\n\n\tprivate _getSlideEventDirection(currentActiveSlideId: string, nextActiveSlideId: string): NgbSlideEventDirection {\n\t\tconst currentActiveSlideIdx = this._getSlideIdxById(currentActiveSlideId);\n\t\tconst nextActiveSlideIdx = this._getSlideIdxById(nextActiveSlideId);\n\n\t\treturn currentActiveSlideIdx > nextActiveSlideIdx ? NgbSlideEventDirection.END : NgbSlideEventDirection.START;\n\t}\n\n\tprivate _getSlideById(slideId: string): NgbSlide | null {\n\t\treturn this.slides.find((slide) => slide.id === slideId) || null;\n\t}\n\n\tprivate _getSlideIdxById(slideId: string): number {\n\t\tconst slide = this._getSlideById(slideId);\n\t\treturn slide != null ? this.slides.toArray().indexOf(slide) : -1;\n\t}\n\n\tprivate _getNextSlide(currentSlideId: string): string {\n\t\tconst slideArr = this.slides.toArray();\n\t\tconst currentSlideIdx = this._getSlideIdxById(currentSlideId);\n\t\tconst isLastSlide = currentSlideIdx === slideArr.length - 1;\n\n\t\treturn isLastSlide\n\t\t\t? this.wrap\n\t\t\t\t? slideArr[0].id\n\t\t\t\t: slideArr[slideArr.length - 1].id\n\t\t\t: slideArr[currentSlideIdx + 1].id;\n\t}\n\n\tprivate _getPrevSlide(currentSlideId: string): string {\n\t\tconst slideArr = this.slides.toArray();\n\t\tconst currentSlideIdx = this._getSlideIdxById(currentSlideId);\n\t\tconst isFirstSlide = currentSlideIdx === 0;\n\n\t\treturn isFirstSlide\n\t\t\t? this.wrap\n\t\t\t\t? slideArr[slideArr.length - 1].id\n\t\t\t\t: slideArr[0].id\n\t\t\t: slideArr[currentSlideIdx - 1].id;\n\t}\n\n\tprivate _getSlideElement(slideId: string): HTMLElement {\n\t\treturn this._container.nativeElement.querySelector(`#slide-${slideId}`);\n\t}\n}\n\n/**\n * A slide change event emitted right after the slide transition is completed.\n */\nexport interface NgbSlideEvent {\n\t/**\n\t * The previous slide id.\n\t */\n\tprev: string;\n\n\t/**\n\t * The current slide id.\n\t */\n\tcurrent: string;\n\n\t/**\n\t * The slide event direction.\n\t *\n\t * <span class=\"badge bg-info text-dark\">since 12.0.0</span> Possible values are `'start' | 'end'`.\n\t *\n\t * <span class=\"badge bg-secondary\">before 12.0.0</span> Possible values were `'left' | 'right'`.\n\t */\n\tdirection: NgbSlideEventDirection;\n\n\t/**\n\t * Whether the pause() method was called (and no cycle() call was done afterwards).\n\t *\n\t * @since 5.1.0\n\t */\n\tpaused: boolean;\n\n\t/**\n\t * Source triggering the slide change event.\n\t *\n\t * Possible values are `'timer' | 'arrowLeft' | 'arrowRight' | 'indicator'`\n\t *\n\t * @since 5.1.0\n\t */\n\tsource?: NgbSlideEventSource;\n}\n\n/**\n * A slide change event emitted right after the slide transition is completed.\n *\n * @since 8.0.0\n */\nexport interface NgbSingleSlideEvent {\n\t/**\n\t * true if the slide is shown, false otherwise\n\t */\n\tisShown: boolean;\n\n\t/**\n\t * The slide event direction.\n\t *\n\t * <span class=\"badge bg-info text-dark\">since 12.0.0</span> Possible values are `'start' | 'end'`.\n\t *\n\t * <span class=\"badge bg-secondary\">before 12.0.0</span> Possible values were `'left' | 'right'`.\n\t */\n\tdirection: NgbSlideEventDirection;\n\n\t/**\n\t * Source triggering the slide change event.\n\t *\n\t * Possible values are `'timer' | 'arrowLeft' | 'arrowRight' | 'indicator'`\n\t *\n\t */\n\tsource?: NgbSlideEventSource;\n}\n\nexport enum NgbSlideEventSource {\n\tTIMER = 'timer',\n\tARROW_LEFT = 'arrowLeft',\n\tARROW_RIGHT = 'arrowRight',\n\tINDICATOR = 'indicator',\n}\n","import { NgModule } from '@angular/core';\nimport { NgbCarousel, NgbSlide } from './carousel';\n\nexport { NgbCarousel, NgbSlide, NgbSlideEvent, NgbSlideEventSource } from './carousel';\nexport { NgbSlideEventDirection } from './carousel-transition';\nexport { NgbCarouselConfig } from './carousel-config';\n\n@NgModule({\n\timports: [NgbCarousel, NgbSlide],\n\texports: [NgbCarousel, NgbSlide],\n})\nexport class NgbCarouselModule {}\n","import { NgModule } from '@angular/core';\nimport { NgbCollapse } from './collapse';\n\nexport { NgbCollapse } from './collapse';\nexport { NgbCollapseConfig } from './collapse-config';\n\n@NgModule({\n\timports: [NgbCollapse],\n\texports: [NgbCollapse],\n})\nexport class NgbCollapseModule {}\n","import { NgbDateStruct } from './ngb-date-struct';\nimport { isInteger } from '../util/util';\n\n/**\n * A simple class that represents a date that datepicker also uses internally.\n *\n * It is the implementation of the `NgbDateStruct` interface that adds some convenience methods,\n * like `.equals()`, `.before()`, etc.\n *\n * All datepicker APIs consume `NgbDateStruct`, but return `NgbDate`.\n *\n * In many cases it is simpler to manipulate these objects together with\n * [`NgbCalendar`](#/components/datepicker/api#NgbCalendar) than native JS Dates.\n *\n * See the [date format overview](#/components/datepicker/overview#date-model) for more details.\n *\n * @since 3.0.0\n */\nexport class NgbDate implements NgbDateStruct {\n\t/**\n\t * The year, for example 2016\n\t */\n\tyear: number;\n\n\t/**\n\t * The month, for example 1=Jan ... 12=Dec as in ISO 8601\n\t */\n\tmonth: number;\n\n\t/**\n\t * The day of month, starting with 1\n\t */\n\tday: number;\n\n\t/**\n\t * A **static method** that creates a new date object from the `NgbDateStruct`,\n\t *\n\t * ex. `NgbDate.from({year: 2000, month: 5, day: 1})`.\n\t *\n\t * If the `date` is already of `NgbDate` type, the method will return the same object.\n\t */\n\tstatic from(date?: NgbDateStruct | null): NgbDate | null {\n\t\tif (date instanceof NgbDate) {\n\t\t\treturn date;\n\t\t}\n\t\treturn date ? new NgbDate(date.year, date.month, date.day) : null;\n\t}\n\n\tconstructor(year: number, month: number, day: number) {\n\t\tthis.year = isInteger(year) ? year : <any>null;\n\t\tthis.month = isInteger(month) ? month : <any>null;\n\t\tthis.day = isInteger(day) ? day : <any>null;\n\t}\n\n\t/**\n\t * Checks if the current date is equal to another date.\n\t */\n\tequals(other?: NgbDateStruct | null): boolean {\n\t\treturn other != null && this.year === other.year && this.month === other.month && this.day === other.day;\n\t}\n\n\t/**\n\t * Checks if the current date is before another date.\n\t */\n\tbefore(other?: NgbDateStruct | null): boolean {\n\t\tif (!other) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.year === other.year) {\n\t\t\tif (this.month === other.month) {\n\t\t\t\treturn this.day === other.day ? false : this.day < other.day;\n\t\t\t} else {\n\t\t\t\treturn this.month < other.month;\n\t\t\t}\n\t\t} else {\n\t\t\treturn this.year < other.year;\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the current date is after another date.\n\t */\n\tafter(other?: NgbDateStruct | null): boolean {\n\t\tif (!other) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.year === other.year) {\n\t\t\tif (this.month === other.month) {\n\t\t\t\treturn this.day === other.day ? false : this.day > other.day;\n\t\t\t} else {\n\t\t\t\treturn this.month > other.month;\n\t\t\t}\n\t\t} else {\n\t\t\treturn this.year > other.year;\n\t\t}\n\t}\n}\n","import { NgbDate } from './ngb-date';\nimport { DatepickerViewModel, DayViewModel, MonthViewModel } from './datepicker-view-model';\nimport { NgbCalendar } from './ngb-calendar';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\n\nexport function isChangedDate(prev?: NgbDate | null, next?: NgbDate | null): boolean {\n\treturn !dateComparator(prev, next);\n}\n\nexport function isChangedMonth(prev?: NgbDate | null, next?: NgbDate | null): boolean {\n\treturn !prev && !next ? false : !prev || !next ? true : prev.year !== next.year || prev.month !== next.month;\n}\n\nexport function dateComparator(prev?: NgbDate | null, next?: NgbDate | null): boolean {\n\treturn (!prev && !next) || (!!prev && !!next && prev.equals(next));\n}\n\nexport function checkMinBeforeMax(minDate?: NgbDate | null, maxDate?: NgbDate | null): void {\n\tif (maxDate && minDate && maxDate.before(minDate)) {\n\t\tthrow new Error(`'maxDate' ${maxDate} should be greater than 'minDate' ${minDate}`);\n\t}\n}\n\nexport function checkDateInRange(\n\tdate?: NgbDate | null,\n\tminDate?: NgbDate | null,\n\tmaxDate?: NgbDate | null,\n): NgbDate | null {\n\tif (date && minDate && date.before(minDate)) {\n\t\treturn minDate;\n\t}\n\tif (date && maxDate && date.after(maxDate)) {\n\t\treturn maxDate;\n\t}\n\n\treturn date || null;\n}\n\nexport function isDateSelectable(date: NgbDate | null | undefined, state: DatepickerViewModel) {\n\tconst { minDate, maxDate, disabled, markDisabled } = state;\n\treturn !(\n\t\tdate === null ||\n\t\tdate === undefined ||\n\t\tdisabled ||\n\t\t(markDisabled && markDisabled(date, { year: date.year, month: date.month })) ||\n\t\t(minDate && date.before(minDate)) ||\n\t\t(maxDate && date.after(maxDate))\n\t);\n}\n\nexport function generateSelectBoxMonths(\n\tcalendar: NgbCalendar,\n\tdate: NgbDate,\n\tminDate: NgbDate | null,\n\tmaxDate: NgbDate | null,\n) {\n\tif (!date) {\n\t\treturn [];\n\t}\n\n\tlet months = calendar.getMonths(date.year);\n\n\tif (minDate && date.year === minDate.year) {\n\t\tconst index = months.findIndex((month) => month === minDate.month);\n\t\tmonths = months.slice(index);\n\t}\n\n\tif (maxDate && date.year === maxDate.year) {\n\t\tconst index = months.findIndex((month) => month === maxDate.month);\n\t\tmonths = months.slice(0, index + 1);\n\t}\n\n\treturn months;\n}\n\nexport function generateSelectBoxYears(date: NgbDate, minDate: NgbDate | null, maxDate: NgbDate | null) {\n\tif (!date) {\n\t\treturn [];\n\t}\n\n\tconst start = minDate ? Math.max(minDate.year, date.year - 500) : date.year - 10;\n\tconst end = maxDate ? Math.min(maxDate.year, date.year + 500) : date.year + 10;\n\n\tconst length = end - start + 1;\n\tconst numbers = Array(length);\n\tfor (let i = 0; i < length; i++) {\n\t\tnumbers[i] = start + i;\n\t}\n\n\treturn numbers;\n}\n\nexport function nextMonthDisabled(calendar: NgbCalendar, date: NgbDate, maxDate: NgbDate | null) {\n\tconst nextDate = Object.assign(calendar.getNext(date, 'm'), { day: 1 });\n\treturn maxDate != null && nextDate.after(maxDate);\n}\n\nexport function prevMonthDisabled(calendar: NgbCalendar, date: NgbDate, minDate: NgbDate | null) {\n\tconst prevDate = Object.assign(calendar.getPrev(date, 'm'), { day: 1 });\n\treturn (\n\t\tminDate != null &&\n\t\t((prevDate.year === minDate.year && prevDate.month < minDate.month) ||\n\t\t\t(prevDate.year < minDate.year && minDate.month === 1))\n\t);\n}\n\nexport function buildMonths(\n\tcalendar: NgbCalendar,\n\tdate: NgbDate,\n\tstate: DatepickerViewModel,\n\ti18n: NgbDatepickerI18n,\n\tforce: boolean,\n): MonthViewModel[] {\n\tconst { displayMonths, months } = state;\n\t// move old months to a temporary array\n\tconst monthsToReuse = months.splice(0, months.length);\n\n\t// generate new first dates, nullify or reuse months\n\tconst firstDates = Array.from({ length: displayMonths }, (_, i) => {\n\t\tconst firstDate = Object.assign(calendar.getNext(date, 'm', i), { day: 1 });\n\t\tmonths[i] = <any>null;\n\n\t\tif (!force) {\n\t\t\tconst reusedIndex = monthsToReuse.findIndex((month) => month.firstDate.equals(firstDate));\n\t\t\t// move reused month back to months\n\t\t\tif (reusedIndex !== -1) {\n\t\t\t\tmonths[i] = monthsToReuse.splice(reusedIndex, 1)[0];\n\t\t\t}\n\t\t}\n\n\t\treturn firstDate;\n\t});\n\n\t// rebuild nullified months\n\tfirstDates.forEach((firstDate, i) => {\n\t\tif (months[i] === null) {\n\t\t\tmonths[i] = buildMonth(calendar, firstDate, state, i18n, monthsToReuse.shift() || ({} as MonthViewModel));\n\t\t}\n\t});\n\n\treturn months;\n}\n\nexport function buildMonth(\n\tcalendar: NgbCalendar,\n\tdate: NgbDate,\n\tstate: DatepickerViewModel,\n\ti18n: NgbDatepickerI18n,\n\tmonth: MonthViewModel = {} as MonthViewModel,\n): MonthViewModel {\n\tconst {\n\t\tdayTemplateData,\n\t\tminDate,\n\t\tmaxDate,\n\t\tfirstDayOfWeek,\n\t\tmarkDisabled,\n\t\toutsideDays,\n\t\tweekdayWidth,\n\t\tweekdaysVisible,\n\t} = state;\n\tconst calendarToday = calendar.getToday();\n\n\tmonth.firstDate = <any>null;\n\tmonth.lastDate = <any>null;\n\tmonth.number = date.month;\n\tmonth.year = date.year;\n\tmonth.weeks = month.weeks || [];\n\tmonth.weekdays = month.weekdays || [];\n\n\tdate = getFirstViewDate(calendar, date, firstDayOfWeek);\n\n\t// clearing weekdays, if not visible\n\tif (!weekdaysVisible) {\n\t\tmonth.weekdays.length = 0;\n\t}\n\n\t// month has weeks\n\tfor (let week = 0; week < calendar.getWeeksPerMonth(); week++) {\n\t\tlet weekObject = month.weeks[week];\n\t\tif (!weekObject) {\n\t\t\tweekObject = month.weeks[week] = { number: 0, days: [], collapsed: true };\n\t\t}\n\t\tconst days = weekObject.days;\n\n\t\t// week has days\n\t\tfor (let day = 0; day < calendar.getDaysPerWeek(); day++) {\n\t\t\tif (week === 0 && weekdaysVisible) {\n\t\t\t\tmonth.weekdays[day] = i18n.getWeekdayLabel(calendar.getWeekday(date), weekdayWidth);\n\t\t\t}\n\n\t\t\tconst newDate = new NgbDate(date.year, date.month, date.day);\n\t\t\tconst nextDate = calendar.getNext(newDate);\n\n\t\t\tconst ariaLabel = i18n.getDayAriaLabel(newDate);\n\n\t\t\t// marking date as disabled\n\t\t\tlet disabled = !!((minDate && newDate.before(minDate)) || (maxDate && newDate.after(maxDate)));\n\t\t\tif (!disabled && markDisabled) {\n\t\t\t\tdisabled = markDisabled(newDate, { month: month.number, year: month.year });\n\t\t\t}\n\n\t\t\t// today\n\t\t\tlet today = newDate.equals(calendarToday);\n\n\t\t\t// adding user-provided data to the context\n\t\t\tlet contextUserData = dayTemplateData\n\t\t\t\t? dayTemplateData(newDate, { month: month.number, year: month.year })\n\t\t\t\t: undefined;\n\n\t\t\t// saving first date of the month\n\t\t\tif (month.firstDate === null && newDate.month === month.number) {\n\t\t\t\tmonth.firstDate = newDate;\n\t\t\t}\n\n\t\t\t// saving last date of the month\n\t\t\tif (newDate.month === month.number && nextDate.month !== month.number) {\n\t\t\t\tmonth.lastDate = newDate;\n\t\t\t}\n\n\t\t\tlet dayObject = days[day];\n\t\t\tif (!dayObject) {\n\t\t\t\tdayObject = days[day] = {} as DayViewModel;\n\t\t\t}\n\t\t\tdayObject.date = newDate;\n\t\t\tdayObject.context = Object.assign(dayObject.context || {}, {\n\t\t\t\t$implicit: newDate,\n\t\t\t\tdate: newDate,\n\t\t\t\tdata: contextUserData,\n\t\t\t\tcurrentMonth: month.number,\n\t\t\t\tcurrentYear: month.year,\n\t\t\t\tdisabled,\n\t\t\t\tfocused: false,\n\t\t\t\tselected: false,\n\t\t\t\ttoday,\n\t\t\t});\n\t\t\tdayObject.tabindex = -1;\n\t\t\tdayObject.ariaLabel = ariaLabel;\n\t\t\tdayObject.hidden = false;\n\n\t\t\tdate = nextDate;\n\t\t}\n\n\t\tweekObject.number = calendar.getWeekNumber(\n\t\t\tdays.map((day) => day.date),\n\t\t\tfirstDayOfWeek,\n\t\t);\n\n\t\t// marking week as collapsed\n\t\tweekObject.collapsed =\n\t\t\toutsideDays === 'collapsed' &&\n\t\t\tdays[0].date.month !== month.number &&\n\t\t\tdays[days.length - 1].date.month !== month.number;\n\t}\n\n\treturn month;\n}\n\nexport function getFirstViewDate(calendar: NgbCalendar, date: NgbDate, firstDayOfWeek: number): NgbDate {\n\tconst daysPerWeek = calendar.getDaysPerWeek();\n\tconst firstMonthDate = new NgbDate(date.year, date.month, 1);\n\tconst dayOfWeek = calendar.getWeekday(firstMonthDate) % daysPerWeek;\n\treturn calendar.getPrev(firstMonthDate, 'd', (daysPerWeek + dayOfWeek - firstDayOfWeek) % daysPerWeek);\n}\n","import { NgbDate } from './ngb-date';\nimport { Injectable } from '@angular/core';\nimport { isInteger } from '../util/util';\n\nexport function fromJSDate(jsDate: Date) {\n\treturn new NgbDate(jsDate.getFullYear(), jsDate.getMonth() + 1, jsDate.getDate());\n}\nexport function toJSDate(date: NgbDate) {\n\tconst jsDate = new Date(date.year, date.month - 1, date.day, 12);\n\t// this is done avoid 30 -> 1930 conversion\n\tif (!isNaN(jsDate.getTime())) {\n\t\tjsDate.setFullYear(date.year);\n\t}\n\treturn jsDate;\n}\n\nexport type NgbPeriod = 'y' | 'm' | 'd';\n\nexport function NGB_DATEPICKER_CALENDAR_FACTORY() {\n\treturn new NgbCalendarGregorian();\n}\n\n/**\n * A service that represents the calendar used by the datepicker.\n *\n * The default implementation uses the Gregorian calendar. You can inject it in your own\n * implementations if necessary to simplify `NgbDate` calculations.\n */\n@Injectable({ providedIn: 'root', useFactory: NGB_DATEPICKER_CALENDAR_FACTORY })\nexport abstract class NgbCalendar {\n\t/**\n\t * Returns the number of days per week.\n\t */\n\tabstract getDaysPerWeek(): number;\n\n\t/**\n\t * Returns an array of months per year.\n\t *\n\t * With default calendar we use ISO 8601 and return [1, 2, ..., 12];\n\t */\n\tabstract getMonths(year?: number): number[];\n\n\t/**\n\t * Returns the number of weeks per month.\n\t */\n\tabstract getWeeksPerMonth(): number;\n\n\t/**\n\t * Returns the weekday number for a given day.\n\t *\n\t * With the default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun\n\t */\n\tabstract getWeekday(date: NgbDate): number;\n\n\t/**\n\t * Adds a number of years, months or days to a given date.\n\t *\n\t * * `period` can be `y`, `m` or `d` and defaults to day.\n\t * * `number` defaults to 1.\n\t *\n\t * Always returns a new date.\n\t */\n\tabstract getNext(date: NgbDate, period?: NgbPeriod, number?: number): NgbDate;\n\n\t/**\n\t * Subtracts a number of years, months or days from a given date.\n\t *\n\t * * `period` can be `y`, `m` or `d` and defaults to day.\n\t * * `number` defaults to 1.\n\t *\n\t * Always returns a new date.\n\t */\n\tabstract getPrev(date: NgbDate, period?: NgbPeriod, number?: number): NgbDate;\n\n\t/**\n\t * Returns the week number for a given week.\n\t */\n\tabstract getWeekNumber(week: readonly NgbDate[], firstDayOfWeek: number): number;\n\n\t/**\n\t * Returns the today's date.\n\t */\n\tabstract getToday(): NgbDate;\n\n\t/**\n\t * Checks if a date is valid in the current calendar.\n\t */\n\tabstract isValid(date?: NgbDate | null): boolean;\n}\n\n@Injectable()\nexport class NgbCalendarGregorian extends NgbCalendar {\n\tgetDaysPerWeek() {\n\t\treturn 7;\n\t}\n\n\tgetMonths() {\n\t\treturn [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];\n\t}\n\n\tgetWeeksPerMonth() {\n\t\treturn 6;\n\t}\n\n\tgetNext(date: NgbDate, period: NgbPeriod = 'd', number = 1) {\n\t\tlet jsDate = toJSDate(date);\n\t\tlet checkMonth = true;\n\t\tlet expectedMonth = jsDate.getMonth();\n\n\t\tswitch (period) {\n\t\t\tcase 'y':\n\t\t\t\tjsDate.setFullYear(jsDate.getFullYear() + number);\n\t\t\t\tbreak;\n\t\t\tcase 'm':\n\t\t\t\texpectedMonth += number;\n\t\t\t\tjsDate.setMonth(expectedMonth);\n\t\t\t\texpectedMonth = expectedMonth % 12;\n\t\t\t\tif (expectedMonth < 0) {\n\t\t\t\t\texpectedMonth = expectedMonth + 12;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'd':\n\t\t\t\tjsDate.setDate(jsDate.getDate() + number);\n\t\t\t\tcheckMonth = false;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn date;\n\t\t}\n\n\t\tif (checkMonth && jsDate.getMonth() !== expectedMonth) {\n\t\t\t// this means the destination month has less days than the initial month\n\t\t\t// let's go back to the end of the previous month:\n\t\t\tjsDate.setDate(0);\n\t\t}\n\n\t\treturn fromJSDate(jsDate);\n\t}\n\n\tgetPrev(date: NgbDate, period: NgbPeriod = 'd', number = 1) {\n\t\treturn this.getNext(date, period, -number);\n\t}\n\n\tgetWeekday(date: NgbDate) {\n\t\tlet jsDate = toJSDate(date);\n\t\tlet day = jsDate.getDay();\n\t\t// in JS Date Sun=0, in ISO 8601 Sun=7\n\t\treturn day === 0 ? 7 : day;\n\t}\n\n\tgetWeekNumber(week: readonly NgbDate[], firstDayOfWeek: number) {\n\t\t// in JS Date Sun=0, in ISO 8601 Sun=7\n\t\tif (firstDayOfWeek === 7) {\n\t\t\tfirstDayOfWeek = 0;\n\t\t}\n\n\t\tconst thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;\n\t\tlet date = week[thursdayIndex];\n\n\t\tconst jsDate = toJSDate(date);\n\t\tjsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday\n\t\tconst time = jsDate.getTime();\n\t\tjsDate.setMonth(0); // Compare with Jan 1\n\t\tjsDate.setDate(1);\n\t\treturn Math.floor(Math.round((time - jsDate.getTime()) / 86400000) / 7) + 1;\n\t}\n\n\tgetToday(): NgbDate {\n\t\treturn fromJSDate(new Date());\n\t}\n\n\tisValid(date?: NgbDate | null): boolean {\n\t\tif (!date || !isInteger(date.year) || !isInteger(date.month) || !isInteger(date.day)) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// year 0 doesn't exist in Gregorian calendar\n\t\tif (date.year === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst jsDate = toJSDate(date);\n\n\t\treturn (\n\t\t\t!isNaN(jsDate.getTime()) &&\n\t\t\tjsDate.getFullYear() === date.year &&\n\t\t\tjsDate.getMonth() + 1 === date.month &&\n\t\t\tjsDate.getDate() === date.day\n\t\t);\n\t}\n}\n","import { Inject, Injectable, LOCALE_ID } from '@angular/core';\nimport { formatDate, FormStyle, getLocaleDayNames, getLocaleMonthNames, TranslationWidth } from '@angular/common';\nimport { NgbDateStruct } from './ngb-date-struct';\n\nexport function NGB_DATEPICKER_18N_FACTORY(locale) {\n\treturn new NgbDatepickerI18nDefault(locale);\n}\n\n/**\n * A service supplying i18n data to the datepicker component.\n *\n * The default implementation of this service uses the Angular locale and registered locale data for\n * weekdays and month names (as explained in the Angular i18n guide).\n *\n * It also provides a way to i18n data that depends on calendar calculations, like aria labels, day, week and year\n * numerals. For other static labels the datepicker uses the default Angular i18n.\n *\n * See the [i18n demo](#/components/datepicker/examples#i18n) and\n * [Hebrew calendar demo](#/components/datepicker/calendars#hebrew) on how to extend this class and define\n * a custom provider for i18n.\n */\n@Injectable({ providedIn: 'root', useFactory: NGB_DATEPICKER_18N_FACTORY, deps: [LOCALE_ID] })\nexport abstract class NgbDatepickerI18n {\n\t/**\n\t * Returns the weekday label using specified width\n\t *\n\t * @since 9.1.0\n\t */\n\tabstract getWeekdayLabel(weekday: number, width?: TranslationWidth): string;\n\n\t/**\n\t * Returns the short month name to display in the date picker navigation.\n\t *\n\t * With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.\n\t */\n\tabstract getMonthShortName(month: number, year?: number): string;\n\n\t/**\n\t * Returns the full month name to display in the date picker navigation.\n\t *\n\t * With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.\n\t */\n\tabstract getMonthFullName(month: number, year?: number): string;\n\n\t/**\n\t * Returns the text label to display above the day view.\n\t *\n\t * @since 9.1.0\n\t */\n\tgetMonthLabel(date: NgbDateStruct): string {\n\t\treturn `${this.getMonthFullName(date.month, date.year)} ${this.getYearNumerals(date.year)}`;\n\t}\n\n\t/**\n\t * Returns the value of the `aria-label` attribute for a specific date.\n\t *\n\t * @since 2.0.0\n\t */\n\tabstract getDayAriaLabel(date: NgbDateStruct): string;\n\n\t/**\n\t * Returns the textual representation of a day that is rendered in a day cell.\n\t *\n\t * @since 3.0.0\n\t */\n\tgetDayNumerals(date: NgbDateStruct): string {\n\t\treturn `${date.day}`;\n\t}\n\n\t/**\n\t * Returns the textual representation of a week number rendered by datepicker.\n\t *\n\t * @since 3.0.0\n\t */\n\tgetWeekNumerals(weekNumber: number): string {\n\t\treturn `${weekNumber}`;\n\t}\n\n\t/**\n\t * Returns the textual representation of a year that is rendered in the datepicker year select box.\n\t *\n\t * @since 3.0.0\n\t */\n\tgetYearNumerals(year: number): string {\n\t\treturn `${year}`;\n\t}\n\n\t/**\n\t * Returns the week label to display in the heading of the month view.\n\t *\n\t * @since 9.1.0\n\t */\n\tgetWeekLabel(): string {\n\t\treturn '';\n\t}\n}\n\n/**\n * A service providing default implementation for the datepicker i18n.\n * It can be used as a base implementation if necessary.\n *\n * @since 9.1.0\n */\n@Injectable()\nexport class NgbDatepickerI18nDefault extends NgbDatepickerI18n {\n\tprivate _monthsShort: readonly string[];\n\tprivate _monthsFull: readonly string[];\n\n\tconstructor(@Inject(LOCALE_ID) private _locale: string) {\n\t\tsuper();\n\n\t\tthis._monthsShort = getLocaleMonthNames(_locale, FormStyle.Standalone, TranslationWidth.Abbreviated);\n\t\tthis._monthsFull = getLocaleMonthNames(_locale, FormStyle.Standalone, TranslationWidth.Wide);\n\t}\n\n\tgetWeekdayLabel(weekday: number, width?: TranslationWidth): string {\n\t\tconst weekdaysStartingOnSunday = getLocaleDayNames(\n\t\t\tthis._locale,\n\t\t\tFormStyle.Standalone,\n\t\t\twidth === undefined ? TranslationWidth.Short : width,\n\t\t);\n\t\tconst weekdays = weekdaysStartingOnSunday.map((day, index) => weekdaysStartingOnSunday[(index + 1) % 7]);\n\t\treturn weekdays[weekday - 1] || '';\n\t}\n\n\tgetMonthShortName(month: number): string {\n\t\treturn this._monthsShort[month - 1] || '';\n\t}\n\n\tgetMonthFullName(month: number): string {\n\t\treturn this._monthsFull[month - 1] || '';\n\t}\n\n\tgetDayAriaLabel(date: NgbDateStruct): string {\n\t\tconst jsDate = new Date(date.year, date.month - 1, date.day);\n\t\treturn formatDate(jsDate, 'fullDate', this._locale);\n\t}\n}\n","import { NgbCalendar } from './ngb-calendar';\nimport { NgbDate } from './ngb-date';\nimport { NgbDateStruct } from './ngb-date-struct';\nimport { DatepickerViewModel, NgbDayTemplateData, NgbMarkDisabled } from './datepicker-view-model';\nimport { Injectable } from '@angular/core';\nimport { isInteger, toInteger } from '../util/util';\nimport { Observable, Subject } from 'rxjs';\nimport {\n\tbuildMonths,\n\tcheckDateInRange,\n\tcheckMinBeforeMax,\n\tgenerateSelectBoxMonths,\n\tgenerateSelectBoxYears,\n\tisChangedDate,\n\tisChangedMonth,\n\tisDateSelectable,\n\tnextMonthDisabled,\n\tprevMonthDisabled,\n} from './datepicker-tools';\n\nimport { filter } from 'rxjs/operators';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\nimport { TranslationWidth } from '@angular/common';\n\nexport type DatepickerServiceInputs = Partial<{\n\tdayTemplateData: NgbDayTemplateData;\n\tdisplayMonths: number;\n\tdisabled: boolean;\n\tfirstDayOfWeek: number;\n\tfocusVisible: boolean;\n\tmarkDisabled: NgbMarkDisabled;\n\tmaxDate: NgbDate | null;\n\tminDate: NgbDate | null;\n\tnavigation: 'select' | 'arrows' | 'none';\n\toutsideDays: 'visible' | 'collapsed' | 'hidden';\n\tweekdays: TranslationWidth | boolean;\n}>;\n\n@Injectable()\nexport class NgbDatepickerService {\n\tprivate _VALIDATORS: {\n\t\t[K in keyof DatepickerServiceInputs]: (v: DatepickerServiceInputs[K]) => Partial<DatepickerViewModel> | void;\n\t} = {\n\t\tdayTemplateData: (dayTemplateData: NgbDayTemplateData) => {\n\t\t\tif (this._state.dayTemplateData !== dayTemplateData) {\n\t\t\t\treturn { dayTemplateData };\n\t\t\t}\n\t\t},\n\t\tdisplayMonths: (displayMonths: number) => {\n\t\t\tdisplayMonths = toInteger(displayMonths);\n\t\t\tif (isInteger(displayMonths) && displayMonths > 0 && this._state.displayMonths !== displayMonths) {\n\t\t\t\treturn { displayMonths };\n\t\t\t}\n\t\t},\n\t\tdisabled: (disabled: boolean) => {\n\t\t\tif (this._state.disabled !== disabled) {\n\t\t\t\treturn { disabled };\n\t\t\t}\n\t\t},\n\t\tfirstDayOfWeek: (firstDayOfWeek: number) => {\n\t\t\tfirstDayOfWeek = toInteger(firstDayOfWeek);\n\t\t\tif (isInteger(firstDayOfWeek) && firstDayOfWeek >= 0 && this._state.firstDayOfWeek !== firstDayOfWeek) {\n\t\t\t\treturn { firstDayOfWeek };\n\t\t\t}\n\t\t},\n\t\tfocusVisible: (focusVisible: boolean) => {\n\t\t\tif (this._state.focusVisible !== focusVisible && !this._state.disabled) {\n\t\t\t\treturn { focusVisible };\n\t\t\t}\n\t\t},\n\t\tmarkDisabled: (markDisabled: NgbMarkDisabled) => {\n\t\t\tif (this._state.markDisabled !== markDisabled) {\n\t\t\t\treturn { markDisabled };\n\t\t\t}\n\t\t},\n\t\tmaxDate: (date: NgbDate | null) => {\n\t\t\tconst maxDate = this.toValidDate(date, null);\n\t\t\tif (isChangedDate(this._state.maxDate, maxDate)) {\n\t\t\t\treturn { maxDate };\n\t\t\t}\n\t\t},\n\t\tminDate: (date: NgbDate | null) => {\n\t\t\tconst minDate = this.toValidDate(date, null);\n\t\t\tif (isChangedDate(this._state.minDate, minDate)) {\n\t\t\t\treturn { minDate };\n\t\t\t}\n\t\t},\n\t\tnavigation: (navigation: 'select' | 'arrows' | 'none') => {\n\t\t\tif (this._state.navigation !== navigation) {\n\t\t\t\treturn { navigation };\n\t\t\t}\n\t\t},\n\t\toutsideDays: (outsideDays: 'visible' | 'collapsed' | 'hidden') => {\n\t\t\tif (this._state.outsideDays !== outsideDays) {\n\t\t\t\treturn { outsideDays };\n\t\t\t}\n\t\t},\n\t\tweekdays: (weekdays: boolean | TranslationWidth) => {\n\t\t\tconst weekdayWidth = weekdays === true || weekdays === false ? TranslationWidth.Short : weekdays;\n\t\t\tconst weekdaysVisible = weekdays === true || weekdays === false ? weekdays : true;\n\t\t\tif (this._state.weekdayWidth !== weekdayWidth || this._state.weekdaysVisible !== weekdaysVisible) {\n\t\t\t\treturn { weekdayWidth, weekdaysVisible };\n\t\t\t}\n\t\t},\n\t};\n\n\tprivate _model$ = new Subject<DatepickerViewModel>();\n\n\tprivate _dateSelect$ = new Subject<NgbDate>();\n\n\tprivate _state: DatepickerViewModel = {\n\t\tdayTemplateData: null,\n\t\tmarkDisabled: null,\n\t\tmaxDate: null,\n\t\tminDate: null,\n\t\tdisabled: false,\n\t\tdisplayMonths: 1,\n\t\tfirstDate: null,\n\t\tfirstDayOfWeek: 1,\n\t\tlastDate: null,\n\t\tfocusDate: null,\n\t\tfocusVisible: false,\n\t\tmonths: [],\n\t\tnavigation: 'select',\n\t\toutsideDays: 'visible',\n\t\tprevDisabled: false,\n\t\tnextDisabled: false,\n\t\tselectedDate: null,\n\t\tselectBoxes: { years: [], months: [] },\n\t\tweekdayWidth: TranslationWidth.Short,\n\t\tweekdaysVisible: true,\n\t};\n\n\tget model$(): Observable<DatepickerViewModel> {\n\t\treturn this._model$.pipe(filter((model) => model.months.length > 0));\n\t}\n\n\tget dateSelect$(): Observable<NgbDate> {\n\t\treturn this._dateSelect$.pipe(filter((date) => date !== null));\n\t}\n\n\tset(options: DatepickerServiceInputs) {\n\t\tlet patch = Object.keys(options)\n\t\t\t.map((key) => this._VALIDATORS[key](options[key]))\n\t\t\t.reduce((obj, part) => ({ ...obj, ...part }), {});\n\n\t\tif (Object.keys(patch).length > 0) {\n\t\t\tthis._nextState(patch);\n\t\t}\n\t}\n\n\tconstructor(private _calendar: NgbCalendar, private _i18n: NgbDatepickerI18n) {}\n\n\tfocus(date?: NgbDate | null) {\n\t\tconst focusedDate = this.toValidDate(date, null);\n\t\tif (focusedDate != null && !this._state.disabled && isChangedDate(this._state.focusDate, focusedDate)) {\n\t\t\tthis._nextState({ focusDate: date });\n\t\t}\n\t}\n\n\tfocusSelect() {\n\t\tif (isDateSelectable(this._state.focusDate, this._state)) {\n\t\t\tthis.select(this._state.focusDate, { emitEvent: true });\n\t\t}\n\t}\n\n\topen(date?: NgbDate | null) {\n\t\tconst firstDate = this.toValidDate(date, this._calendar.getToday());\n\t\tif (\n\t\t\tfirstDate != null &&\n\t\t\t!this._state.disabled &&\n\t\t\t(!this._state.firstDate || isChangedMonth(this._state.firstDate, firstDate))\n\t\t) {\n\t\t\tthis._nextState({ firstDate });\n\t\t}\n\t}\n\n\tselect(date?: NgbDate | null, options: { emitEvent?: boolean } = {}) {\n\t\tconst selectedDate = this.toValidDate(date, null);\n\t\tif (selectedDate != null && !this._state.disabled) {\n\t\t\tif (isChangedDate(this._state.selectedDate, selectedDate)) {\n\t\t\t\tthis._nextState({ selectedDate });\n\t\t\t}\n\n\t\t\tif (options.emitEvent && isDateSelectable(selectedDate, this._state)) {\n\t\t\t\tthis._dateSelect$.next(selectedDate);\n\t\t\t}\n\t\t}\n\t}\n\n\ttoValidDate(date?: NgbDateStruct | null, defaultValue?: NgbDate | null): NgbDate | null {\n\t\tconst ngbDate = NgbDate.from(date);\n\t\tif (defaultValue === undefined) {\n\t\t\tdefaultValue = this._calendar.getToday();\n\t\t}\n\t\treturn this._calendar.isValid(ngbDate) ? ngbDate : defaultValue;\n\t}\n\n\tgetMonth(struct: NgbDateStruct) {\n\t\tfor (let month of this._state.months) {\n\t\t\tif (struct.month === month.number && struct.year === month.year) {\n\t\t\t\treturn month;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`month ${struct.month} of year ${struct.year} not found`);\n\t}\n\n\tprivate _nextState(patch: Partial<DatepickerViewModel>) {\n\t\tconst newState = this._updateState(patch);\n\t\tthis._patchContexts(newState);\n\t\tthis._state = newState;\n\t\tthis._model$.next(this._state);\n\t}\n\n\tprivate _patchContexts(state: DatepickerViewModel) {\n\t\tconst { months, displayMonths, selectedDate, focusDate, focusVisible, disabled, outsideDays } = state;\n\t\tstate.months.forEach((month) => {\n\t\t\tmonth.weeks.forEach((week) => {\n\t\t\t\tweek.days.forEach((day) => {\n\t\t\t\t\t// patch focus flag\n\t\t\t\t\tif (focusDate) {\n\t\t\t\t\t\tday.context.focused = focusDate.equals(day.date) && focusVisible;\n\t\t\t\t\t}\n\n\t\t\t\t\t// calculating tabindex\n\t\t\t\t\tday.tabindex =\n\t\t\t\t\t\t!disabled && focusDate && day.date.equals(focusDate) && focusDate.month === month.number ? 0 : -1;\n\n\t\t\t\t\t// override context disabled\n\t\t\t\t\tif (disabled === true) {\n\t\t\t\t\t\tday.context.disabled = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// patch selection flag\n\t\t\t\t\tif (selectedDate !== undefined) {\n\t\t\t\t\t\tday.context.selected = selectedDate !== null && selectedDate.equals(day.date);\n\t\t\t\t\t}\n\n\t\t\t\t\t// visibility\n\t\t\t\t\tif (month.number !== day.date.month) {\n\t\t\t\t\t\tday.hidden =\n\t\t\t\t\t\t\toutsideDays === 'hidden' ||\n\t\t\t\t\t\t\toutsideDays === 'collapsed' ||\n\t\t\t\t\t\t\t(displayMonths > 1 &&\n\t\t\t\t\t\t\t\tday.date.after(months[0].firstDate) &&\n\t\t\t\t\t\t\t\tday.date.before(months[displayMonths - 1].lastDate));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate _updateState(patch: Partial<DatepickerViewModel>): DatepickerViewModel {\n\t\t// patching fields\n\t\tconst state = Object.assign({}, this._state, patch);\n\n\t\tlet startDate = state.firstDate;\n\n\t\t// min/max dates changed\n\t\tif ('minDate' in patch || 'maxDate' in patch) {\n\t\t\tcheckMinBeforeMax(state.minDate, state.maxDate);\n\t\t\tstate.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);\n\t\t\tstate.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);\n\t\t\tstartDate = state.focusDate;\n\t\t}\n\n\t\t// disabled\n\t\tif ('disabled' in patch) {\n\t\t\tstate.focusVisible = false;\n\t\t}\n\n\t\t// initial rebuild via 'select()'\n\t\tif ('selectedDate' in patch && this._state.months.length === 0) {\n\t\t\tstartDate = state.selectedDate;\n\t\t}\n\n\t\t// terminate early if only focus visibility was changed\n\t\tif ('focusVisible' in patch) {\n\t\t\treturn state;\n\t\t}\n\n\t\t// focus date changed\n\t\tif ('focusDate' in patch) {\n\t\t\tstate.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);\n\t\t\tstartDate = state.focusDate;\n\n\t\t\t// nothing to rebuild if only focus changed and it is still visible\n\t\t\tif (\n\t\t\t\tstate.months.length !== 0 &&\n\t\t\t\tstate.focusDate &&\n\t\t\t\t!state.focusDate.before(state.firstDate) &&\n\t\t\t\t!state.focusDate.after(state.lastDate)\n\t\t\t) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t}\n\n\t\t// first date changed\n\t\tif ('firstDate' in patch) {\n\t\t\tstate.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);\n\t\t\tstartDate = state.firstDate;\n\t\t}\n\n\t\t// rebuilding months\n\t\tif (startDate) {\n\t\t\tconst forceRebuild =\n\t\t\t\t'dayTemplateData' in patch ||\n\t\t\t\t'firstDayOfWeek' in patch ||\n\t\t\t\t'markDisabled' in patch ||\n\t\t\t\t'minDate' in patch ||\n\t\t\t\t'maxDate' in patch ||\n\t\t\t\t'disabled' in patch ||\n\t\t\t\t'outsideDays' in patch ||\n\t\t\t\t'weekdaysVisible' in patch;\n\n\t\t\tconst months = buildMonths(this._calendar, startDate, state, this._i18n, forceRebuild);\n\n\t\t\t// updating months and boundary dates\n\t\t\tstate.months = months;\n\t\t\tstate.firstDate = months[0].firstDate;\n\t\t\tstate.lastDate = months[months.length - 1].lastDate;\n\n\t\t\t// reset selected date if 'markDisabled' returns true\n\t\t\tif ('selectedDate' in patch && !isDateSelectable(state.selectedDate, state)) {\n\t\t\t\tstate.selectedDate = null;\n\t\t\t}\n\n\t\t\t// adjusting focus after months were built\n\t\t\tif ('firstDate' in patch) {\n\t\t\t\tif (!state.focusDate || state.focusDate.before(state.firstDate) || state.focusDate.after(state.lastDate)) {\n\t\t\t\t\tstate.focusDate = startDate;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// adjusting months/years for the select box navigation\n\t\t\tconst yearChanged = !this._state.firstDate || this._state.firstDate.year !== state.firstDate.year;\n\t\t\tconst monthChanged = !this._state.firstDate || this._state.firstDate.month !== state.firstDate.month;\n\t\t\tif (state.navigation === 'select') {\n\t\t\t\t// years -> boundaries (min/max were changed)\n\t\t\t\tif ('minDate' in patch || 'maxDate' in patch || state.selectBoxes.years.length === 0 || yearChanged) {\n\t\t\t\t\tstate.selectBoxes.years = generateSelectBoxYears(state.firstDate, state.minDate, state.maxDate);\n\t\t\t\t}\n\n\t\t\t\t// months -> when current year or boundaries change\n\t\t\t\tif ('minDate' in patch || 'maxDate' in patch || state.selectBoxes.months.length === 0 || yearChanged) {\n\t\t\t\t\tstate.selectBoxes.months = generateSelectBoxMonths(\n\t\t\t\t\t\tthis._calendar,\n\t\t\t\t\t\tstate.firstDate,\n\t\t\t\t\t\tstate.minDate,\n\t\t\t\t\t\tstate.maxDate,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstate.selectBoxes = { years: [], months: [] };\n\t\t\t}\n\n\t\t\t// updating navigation arrows -> boundaries change (min/max) or month/year changes\n\t\t\tif (\n\t\t\t\t(state.navigation === 'arrows' || state.navigation === 'select') &&\n\t\t\t\t(monthChanged || yearChanged || 'minDate' in patch || 'maxDate' in patch || 'disabled' in patch)\n\t\t\t) {\n\t\t\t\tstate.prevDisabled = state.disabled || prevMonthDisabled(this._calendar, state.firstDate, state.minDate);\n\t\t\t\tstate.nextDisabled = state.disabled || nextMonthDisabled(this._calendar, state.lastDate, state.maxDate);\n\t\t\t}\n\t\t}\n\n\t\treturn state;\n\t}\n}\n","import { NgbDate } from './ngb-date';\nimport { NgbDateStruct } from './ngb-date-struct';\nimport { DayTemplateContext } from './datepicker-day-template-context';\nimport { TranslationWidth } from '@angular/common';\n\nexport type NgbMarkDisabled = (date: NgbDateStruct, current?: { year: number; month: number }) => boolean;\nexport type NgbDayTemplateData = (date: NgbDateStruct, current?: { year: number; month: number }) => any;\n\nexport type DayViewModel = {\n\tdate: NgbDate;\n\tcontext: DayTemplateContext;\n\ttabindex: number;\n\tariaLabel: string;\n\thidden: boolean;\n};\n\nexport type WeekViewModel = {\n\tnumber: number;\n\tdays: DayViewModel[];\n\tcollapsed: boolean;\n};\n\nexport type MonthViewModel = {\n\tfirstDate: NgbDate;\n\tlastDate: NgbDate;\n\tnumber: number;\n\tyear: number;\n\tweeks: WeekViewModel[];\n\tweekdays: string[];\n};\n\nexport type DatepickerViewModel = {\n\tdayTemplateData: NgbDayTemplateData | null;\n\tdisabled: boolean;\n\tdisplayMonths: number;\n\tfirstDate: NgbDate | null;\n\tfirstDayOfWeek: number;\n\tfocusDate: NgbDate | null;\n\tfocusVisible: boolean;\n\tlastDate: NgbDate | null;\n\tmarkDisabled: NgbMarkDisabled | null;\n\tmaxDate: NgbDate | null;\n\tminDate: NgbDate | null;\n\tmonths: MonthViewModel[];\n\tnavigation: 'select' | 'arrows' | 'none';\n\toutsideDays: 'visible' | 'collapsed' | 'hidden';\n\tprevDisabled: boolean;\n\tnextDisabled: boolean;\n\tselectBoxes: {\n\t\tyears: number[];\n\t\tmonths: number[];\n\t};\n\tselectedDate: NgbDate | null;\n\tweekdayWidth: TranslationWidth;\n\tweekdaysVisible: boolean;\n};\n\nexport enum NavigationEvent {\n\tPREV,\n\tNEXT,\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';\nimport { NgbDate } from './ngb-date';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\n\n@Component({\n\tselector: '[ngbDatepickerDayView]',\n\tstandalone: true,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./datepicker-day-view.scss'],\n\thost: {\n\t\tclass: 'btn-light',\n\t\t'[class.bg-primary]': 'selected',\n\t\t'[class.text-white]': 'selected',\n\t\t'[class.text-muted]': 'isMuted()',\n\t\t'[class.outside]': 'isMuted()',\n\t\t'[class.active]': 'focused',\n\t},\n\ttemplate: `{{ i18n.getDayNumerals(date) }}`,\n})\nexport class NgbDatepickerDayView {\n\t@Input() currentMonth: number;\n\t@Input() date: NgbDate;\n\t@Input() disabled: boolean;\n\t@Input() focused: boolean;\n\t@Input() selected: boolean;\n\n\tconstructor(public i18n: NgbDatepickerI18n) {}\n\n\tisMuted() {\n\t\treturn !this.selected && (this.date.month !== this.currentMonth || this.disabled);\n\t}\n}\n","import {\n\tComponent,\n\tInput,\n\tOutput,\n\tEventEmitter,\n\tChangeDetectionStrategy,\n\tViewEncapsulation,\n\tAfterViewChecked,\n\tViewChild,\n\tElementRef,\n\tRenderer2,\n} from '@angular/core';\nimport { NgbDate } from './ngb-date';\nimport { toInteger } from '../util/util';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\nimport { NgFor } from '@angular/common';\n\n@Component({\n\tselector: 'ngb-datepicker-navigation-select',\n\tstandalone: true,\n\timports: [NgFor],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./datepicker-navigation-select.scss'],\n\ttemplate: `\n\t\t<select\n\t\t\t#month\n\t\t\t[disabled]=\"disabled\"\n\t\t\tclass=\"form-select\"\n\t\t\ti18n-aria-label=\"@@ngb.datepicker.select-month\"\n\t\t\taria-label=\"Select month\"\n\t\t\ti18n-title=\"@@ngb.datepicker.select-month\"\n\t\t\ttitle=\"Select month\"\n\t\t\t(change)=\"changeMonth($any($event).target.value)\"\n\t\t>\n\t\t\t<option *ngFor=\"let m of months\" [attr.aria-label]=\"i18n.getMonthFullName(m, date.year)\" [value]=\"m\">{{\n\t\t\t\ti18n.getMonthShortName(m, date.year)\n\t\t\t}}</option> </select\n\t\t><select\n\t\t\t#year\n\t\t\t[disabled]=\"disabled\"\n\t\t\tclass=\"form-select\"\n\t\t\ti18n-aria-label=\"@@ngb.datepicker.select-year\"\n\t\t\taria-label=\"Select year\"\n\t\t\ti18n-title=\"@@ngb.datepicker.select-year\"\n\t\t\ttitle=\"Select year\"\n\t\t\t(change)=\"changeYear($any($event).target.value)\"\n\t\t>\n\t\t\t<option *ngFor=\"let y of years\" [value]=\"y\">{{ i18n.getYearNumerals(y) }}</option>\n\t\t</select>\n\t`,\n})\nexport class NgbDatepickerNavigationSelect implements AfterViewChecked {\n\t@Input() date: NgbDate;\n\t@Input() disabled: boolean;\n\t@Input() months: number[];\n\t@Input() years: number[];\n\n\t@Output() select = new EventEmitter<NgbDate>();\n\n\t@ViewChild('month', { static: true, read: ElementRef }) monthSelect: ElementRef;\n\t@ViewChild('year', { static: true, read: ElementRef }) yearSelect: ElementRef;\n\n\tprivate _month = -1;\n\tprivate _year = -1;\n\n\tconstructor(public i18n: NgbDatepickerI18n, private _renderer: Renderer2) {}\n\n\tchangeMonth(month: string) {\n\t\tthis.select.emit(new NgbDate(this.date.year, toInteger(month), 1));\n\t}\n\n\tchangeYear(year: string) {\n\t\tthis.select.emit(new NgbDate(toInteger(year), this.date.month, 1));\n\t}\n\n\tngAfterViewChecked() {\n\t\tif (this.date) {\n\t\t\tif (this.date.month !== this._month) {\n\t\t\t\tthis._month = this.date.month;\n\t\t\t\tthis._renderer.setProperty(this.monthSelect.nativeElement, 'value', this._month);\n\t\t\t}\n\t\t\tif (this.date.year !== this._year) {\n\t\t\t\tthis._year = this.date.year;\n\t\t\t\tthis._renderer.setProperty(this.yearSelect.nativeElement, 'value', this._year);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';\nimport { NavigationEvent, MonthViewModel } from './datepicker-view-model';\nimport { NgbDate } from './ngb-date';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\nimport { NgFor, NgIf } from '@angular/common';\nimport { NgbDatepickerNavigationSelect } from './datepicker-navigation-select';\n\n@Component({\n\tselector: 'ngb-datepicker-navigation',\n\tstandalone: true,\n\timports: [NgIf, NgFor, NgbDatepickerNavigationSelect],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./datepicker-navigation.scss'],\n\ttemplate: `\n\t\t<div class=\"ngb-dp-arrow\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"btn btn-link ngb-dp-arrow-btn\"\n\t\t\t\t(click)=\"onClickPrev($event)\"\n\t\t\t\t[disabled]=\"prevDisabled\"\n\t\t\t\ti18n-aria-label=\"@@ngb.datepicker.previous-month\"\n\t\t\t\taria-label=\"Previous month\"\n\t\t\t\ti18n-title=\"@@ngb.datepicker.previous-month\"\n\t\t\t\ttitle=\"Previous month\"\n\t\t\t>\n\t\t\t\t<span class=\"ngb-dp-navigation-chevron\"></span>\n\t\t\t</button>\n\t\t</div>\n\t\t<ngb-datepicker-navigation-select\n\t\t\t*ngIf=\"showSelect\"\n\t\t\tclass=\"ngb-dp-navigation-select\"\n\t\t\t[date]=\"date\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[months]=\"selectBoxes.months\"\n\t\t\t[years]=\"selectBoxes.years\"\n\t\t\t(select)=\"select.emit($event)\"\n\t\t>\n\t\t</ngb-datepicker-navigation-select>\n\n\t\t<ng-template *ngIf=\"!showSelect\" ngFor let-month [ngForOf]=\"months\" let-i=\"index\">\n\t\t\t<div class=\"ngb-dp-arrow\" *ngIf=\"i > 0\"></div>\n\t\t\t<div class=\"ngb-dp-month-name\">\n\t\t\t\t{{ i18n.getMonthLabel(month.firstDate) }}\n\t\t\t</div>\n\t\t\t<div class=\"ngb-dp-arrow\" *ngIf=\"i !== months.length - 1\"></div>\n\t\t</ng-template>\n\t\t<div class=\"ngb-dp-arrow right\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclass=\"btn btn-link ngb-dp-arrow-btn\"\n\t\t\t\t(click)=\"onClickNext($event)\"\n\t\t\t\t[disabled]=\"nextDisabled\"\n\t\t\t\ti18n-aria-label=\"@@ngb.datepicker.next-month\"\n\t\t\t\taria-label=\"Next month\"\n\t\t\t\ti18n-title=\"@@ngb.datepicker.next-month\"\n\t\t\t\ttitle=\"Next month\"\n\t\t\t>\n\t\t\t\t<span class=\"ngb-dp-navigation-chevron\"></span>\n\t\t\t</button>\n\t\t</div>\n\t`,\n})\nexport class NgbDatepickerNavigation {\n\tnavigation = NavigationEvent;\n\n\t@Input() date: NgbDate;\n\t@Input() disabled: boolean;\n\t@Input() months: MonthViewModel[] = [];\n\t@Input() showSelect: boolean;\n\t@Input() prevDisabled: boolean;\n\t@Input() nextDisabled: boolean;\n\t@Input() selectBoxes: { years: number[]; months: number[] };\n\n\t@Output() navigate = new EventEmitter<NavigationEvent>();\n\t@Output() select = new EventEmitter<NgbDate>();\n\n\tconstructor(public i18n: NgbDatepickerI18n) {}\n\n\tonClickPrev(event: MouseEvent) {\n\t\t(event.currentTarget as HTMLElement).focus();\n\t\tthis.navigate.emit(this.navigation.PREV);\n\t}\n\n\tonClickNext(event: MouseEvent) {\n\t\t(event.currentTarget as HTMLElement).focus();\n\t\tthis.navigate.emit(this.navigation.NEXT);\n\t}\n}\n","export enum Key {\n\tTab = 9,\n\tEnter = 13,\n\tEscape = 27,\n\tSpace = 32,\n\tPageUp = 33,\n\tPageDown = 34,\n\tEnd = 35,\n\tHome = 36,\n\tArrowLeft = 37,\n\tArrowUp = 38,\n\tArrowRight = 39,\n\tArrowDown = 40,\n}\n","import { Injectable } from '@angular/core';\nimport { NgbDatepicker } from './datepicker';\nimport { Key } from '../util/key';\n\n/**\n * A service that represents the keyboard navigation.\n *\n * Default keyboard shortcuts [are documented in the overview](#/components/datepicker/overview#keyboard-shortcuts)\n *\n * @since 5.2.0\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbDatepickerKeyboardService {\n\t/**\n\t * Processes a keyboard event.\n\t */\n\tprocessKey(event: KeyboardEvent, datepicker: NgbDatepicker) {\n\t\tconst { state, calendar } = datepicker;\n\t\t/* eslint-disable-next-line deprecation/deprecation */\n\t\tswitch (event.which) {\n\t\t\tcase Key.PageUp:\n\t\t\t\tdatepicker.focusDate(calendar.getPrev(state.focusedDate, event.shiftKey ? 'y' : 'm', 1));\n\t\t\t\tbreak;\n\t\t\tcase Key.PageDown:\n\t\t\t\tdatepicker.focusDate(calendar.getNext(state.focusedDate, event.shiftKey ? 'y' : 'm', 1));\n\t\t\t\tbreak;\n\t\t\tcase Key.End:\n\t\t\t\tdatepicker.focusDate(event.shiftKey ? state.maxDate : state.lastDate);\n\t\t\t\tbreak;\n\t\t\tcase Key.Home:\n\t\t\t\tdatepicker.focusDate(event.shiftKey ? state.minDate : state.firstDate);\n\t\t\t\tbreak;\n\t\t\tcase Key.ArrowLeft:\n\t\t\t\tdatepicker.focusDate(calendar.getPrev(state.focusedDate, 'd', 1));\n\t\t\t\tbreak;\n\t\t\tcase Key.ArrowUp:\n\t\t\t\tdatepicker.focusDate(calendar.getPrev(state.focusedDate, 'd', calendar.getDaysPerWeek()));\n\t\t\t\tbreak;\n\t\t\tcase Key.ArrowRight:\n\t\t\t\tdatepicker.focusDate(calendar.getNext(state.focusedDate, 'd', 1));\n\t\t\t\tbreak;\n\t\t\tcase Key.ArrowDown:\n\t\t\t\tdatepicker.focusDate(calendar.getNext(state.focusedDate, 'd', calendar.getDaysPerWeek()));\n\t\t\t\tbreak;\n\t\t\tcase Key.Enter:\n\t\t\tcase Key.Space:\n\t\t\t\tdatepicker.focusSelect();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t}\n}\n","import { Injectable, TemplateRef } from '@angular/core';\nimport { TranslationWidth } from '@angular/common';\nimport { DayTemplateContext } from './datepicker-day-template-context';\nimport { NgbDateStruct } from './ngb-date-struct';\n\n/**\n * A configuration service for the [`NgbDatepicker`](#/components/datepicker/api#NgbDatepicker) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the datepickers used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbDatepickerConfig {\n\tdayTemplate: TemplateRef<DayTemplateContext>;\n\tdayTemplateData: (date: NgbDateStruct, current?: { year: number; month: number }) => any;\n\tfooterTemplate: TemplateRef<any>;\n\tdisplayMonths = 1;\n\tfirstDayOfWeek = 1;\n\tmarkDisabled: (date: NgbDateStruct, current?: { year: number; month: number }) => boolean;\n\tminDate: NgbDateStruct;\n\tmaxDate: NgbDateStruct;\n\tnavigation: 'select' | 'arrows' | 'none' = 'select';\n\toutsideDays: 'visible' | 'collapsed' | 'hidden' = 'visible';\n\tshowWeekNumbers = false;\n\tstartDate: { year: number; month: number };\n\tweekdays: TranslationWidth | boolean = TranslationWidth.Short;\n}\n","import { Injectable } from '@angular/core';\nimport { NgbDateStruct } from '../ngb-date-struct';\nimport { isInteger } from '../../util/util';\n\nexport function NGB_DATEPICKER_DATE_ADAPTER_FACTORY() {\n\treturn new NgbDateStructAdapter();\n}\n\n/**\n * An abstract service that does the conversion between the internal datepicker `NgbDateStruct` model and\n * any provided user date model `D`, ex. a string, a native date, etc.\n *\n * The adapter is used **only** for conversion when binding datepicker to a form control,\n * ex. `[(ngModel)]=\"userDateModel\"`. Here `userDateModel` can be of any type.\n *\n * The default datepicker implementation assumes we use `NgbDateStruct` as a user model.\n *\n * See the [date format overview](#/components/datepicker/overview#date-model) for more details\n * and the [custom adapter demo](#/components/datepicker/examples#adapter) for an example.\n */\n@Injectable({ providedIn: 'root', useFactory: NGB_DATEPICKER_DATE_ADAPTER_FACTORY })\nexport abstract class NgbDateAdapter<D> {\n\t/**\n\t * Converts a user-model date of type `D` to an `NgbDateStruct` for internal use.\n\t */\n\tabstract fromModel(value: D | null): NgbDateStruct | null;\n\n\t/**\n\t * Converts an internal `NgbDateStruct` date to a user-model date of type `D`.\n\t */\n\tabstract toModel(date: NgbDateStruct | null): D | null;\n}\n\n@Injectable()\nexport class NgbDateStructAdapter extends NgbDateAdapter<NgbDateStruct> {\n\t/**\n\t * Converts a NgbDateStruct value into NgbDateStruct value\n\t */\n\tfromModel(date: NgbDateStruct | null): NgbDateStruct | null {\n\t\treturn date && isInteger(date.year) && isInteger(date.month) && isInteger(date.day)\n\t\t\t? { year: date.year, month: date.month, day: date.day }\n\t\t\t: null;\n\t}\n\n\t/**\n\t * Converts a NgbDateStruct value into NgbDateStruct value\n\t */\n\ttoModel(date: NgbDateStruct | null): NgbDateStruct | null {\n\t\treturn date && isInteger(date.year) && isInteger(date.month) && isInteger(date.day)\n\t\t\t? { year: date.year, month: date.month, day: date.day }\n\t\t\t: null;\n\t}\n}\n","import { fromEvent, merge, Subject } from 'rxjs';\nimport { filter, take, takeUntil } from 'rxjs/operators';\nimport {\n\tAfterViewInit,\n\tChangeDetectionStrategy,\n\tChangeDetectorRef,\n\tComponent,\n\tContentChild,\n\tDirective,\n\tElementRef,\n\tEventEmitter,\n\tforwardRef,\n\tinject,\n\tInject,\n\tInjector,\n\tInput,\n\tNgZone,\n\tOnChanges,\n\tOnDestroy,\n\tOnInit,\n\tOutput,\n\tSimpleChanges,\n\tTemplateRef,\n\tViewChild,\n\tViewEncapsulation,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { NgFor, NgIf, NgTemplateOutlet, TranslationWidth } from '@angular/common';\n\nimport { NgbCalendar } from './ngb-calendar';\nimport { NgbDate } from './ngb-date';\nimport { DatepickerServiceInputs, NgbDatepickerService } from './datepicker-service';\nimport { DatepickerViewModel, DayViewModel, MonthViewModel, NavigationEvent } from './datepicker-view-model';\nimport { DayTemplateContext } from './datepicker-day-template-context';\nimport { NgbDatepickerConfig } from './datepicker-config';\nimport { NgbDateAdapter } from './adapters/ngb-date-adapter';\nimport { NgbDateStruct } from './ngb-date-struct';\nimport { NgbDatepickerI18n } from './datepicker-i18n';\nimport { NgbDatepickerKeyboardService } from './datepicker-keyboard-service';\nimport { isChangedDate, isChangedMonth } from './datepicker-tools';\nimport { hasClassName } from '../util/util';\nimport { NgbDatepickerDayView } from './datepicker-day-view';\nimport { NgbDatepickerNavigation } from './datepicker-navigation';\nimport { ContentTemplateContext } from './datepicker-content-template-context';\n\n/**\n * An event emitted right before the navigation happens and the month displayed by the datepicker changes.\n */\nexport interface NgbDatepickerNavigateEvent {\n\t/**\n\t * The currently displayed month.\n\t */\n\tcurrent: { year: number; month: number } | null;\n\n\t/**\n\t * The month we're navigating to.\n\t */\n\tnext: { year: number; month: number };\n\n\t/**\n\t * Calling this function will prevent navigation from happening.\n\t *\n\t * @since 4.1.0\n\t */\n\tpreventDefault: () => void;\n}\n\n/**\n * An interface that represents the readonly public state of the datepicker.\n *\n * Accessible via the `datepicker.state` getter\n *\n * @since 5.2.0\n */\nexport interface NgbDatepickerState {\n\t/**\n\t * The earliest date that can be displayed or selected\n\t */\n\treadonly minDate: NgbDate | null;\n\n\t/**\n\t * The latest date that can be displayed or selected\n\t */\n\treadonly maxDate: NgbDate | null;\n\n\t/**\n\t * The first visible date of currently displayed months\n\t */\n\treadonly firstDate: NgbDate;\n\n\t/**\n\t * The last visible date of currently displayed months\n\t */\n\treadonly lastDate: NgbDate;\n\n\t/**\n\t * The date currently focused by the datepicker\n\t */\n\treadonly focusedDate: NgbDate;\n\n\t/**\n\t * First dates of months currently displayed by the datepicker\n\t *\n\t * @since 5.3.0\n\t */\n\treadonly months: NgbDate[];\n}\n\n/**\n * A directive that marks the content template that customizes the way datepicker months are displayed\n *\n * @since 5.3.0\n */\n@Directive({ selector: 'ng-template[ngbDatepickerContent]', standalone: true })\nexport class NgbDatepickerContent {\n\tconstructor(public templateRef: TemplateRef<any>) {}\n}\n\n/**\n * A component that renders one month including all the days, weekdays and week numbers. Can be used inside\n * the `<ng-template ngbDatepickerMonths></ng-template>` when you want to customize months layout.\n *\n * For a usage example, see [custom month layout demo](#/components/datepicker/examples#custommonth)\n *\n * @since 5.3.0\n */\n@Component({\n\tselector: 'ngb-datepicker-month',\n\tstandalone: true,\n\timports: [NgIf, NgFor, NgTemplateOutlet],\n\thost: { role: 'grid', '(keydown)': 'onKeyDown($event)' },\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./datepicker-month.scss'],\n\ttemplate: `\n\t\t<div *ngIf=\"viewModel.weekdays.length > 0\" class=\"ngb-dp-week ngb-dp-weekdays\" role=\"row\">\n\t\t\t<div *ngIf=\"datepicker.showWeekNumbers\" class=\"ngb-dp-weekday ngb-dp-showweek small\">{{\n\t\t\t\ti18n.getWeekLabel()\n\t\t\t}}</div>\n\t\t\t<div *ngFor=\"let weekday of viewModel.weekdays\" class=\"ngb-dp-weekday small\" role=\"columnheader\">{{\n\t\t\t\tweekday\n\t\t\t}}</div>\n\t\t</div>\n\t\t<ng-template ngFor let-week [ngForOf]=\"viewModel.weeks\">\n\t\t\t<div *ngIf=\"!week.collapsed\" class=\"ngb-dp-week\" role=\"row\">\n\t\t\t\t<div *ngIf=\"datepicker.showWeekNumbers\" class=\"ngb-dp-week-number small text-muted\">{{\n\t\t\t\t\ti18n.getWeekNumerals(week.number)\n\t\t\t\t}}</div>\n\t\t\t\t<div\n\t\t\t\t\t*ngFor=\"let day of week.days\"\n\t\t\t\t\t(click)=\"doSelect(day); $event.preventDefault()\"\n\t\t\t\t\tclass=\"ngb-dp-day\"\n\t\t\t\t\trole=\"gridcell\"\n\t\t\t\t\t[class.disabled]=\"day.context.disabled\"\n\t\t\t\t\t[tabindex]=\"day.tabindex\"\n\t\t\t\t\t[class.hidden]=\"day.hidden\"\n\t\t\t\t\t[class.ngb-dp-today]=\"day.context.today\"\n\t\t\t\t\t[attr.aria-label]=\"day.ariaLabel\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template [ngIf]=\"!day.hidden\">\n\t\t\t\t\t\t<ng-template\n\t\t\t\t\t\t\t[ngTemplateOutlet]=\"datepicker.dayTemplate\"\n\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"day.context\"\n\t\t\t\t\t\t></ng-template>\n\t\t\t\t\t</ng-template>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</ng-template>\n\t`,\n})\nexport class NgbDatepickerMonth {\n\t/**\n\t * The first date of month to be rendered.\n\t *\n\t * This month must one of the months present in the\n\t * [datepicker state](#/components/datepicker/api#NgbDatepickerState).\n\t */\n\t@Input()\n\tset month(month: NgbDateStruct) {\n\t\tthis.viewModel = this._service.getMonth(month);\n\t}\n\n\tviewModel: MonthViewModel;\n\n\tconstructor(\n\t\tpublic i18n: NgbDatepickerI18n,\n\t\t@Inject(forwardRef(() => NgbDatepicker)) public datepicker: NgbDatepicker,\n\t\tprivate _keyboardService: NgbDatepickerKeyboardService,\n\t\tprivate _service: NgbDatepickerService,\n\t) {}\n\n\tonKeyDown(event: KeyboardEvent) {\n\t\tthis._keyboardService.processKey(event, this.datepicker);\n\t}\n\n\tdoSelect(day: DayViewModel) {\n\t\tif (!day.context.disabled && !day.hidden) {\n\t\t\tthis.datepicker.onDateSelect(day.date);\n\t\t}\n\t}\n}\n\n/**\n * A highly configurable component that helps you with selecting calendar dates.\n *\n * `NgbDatepicker` is meant to be displayed inline on a page or put inside a popup.\n */\n@Component({\n\texportAs: 'ngbDatepicker',\n\tselector: 'ngb-datepicker',\n\tstandalone: true,\n\timports: [NgIf, NgFor, NgTemplateOutlet, NgbDatepickerDayView, NgbDatepickerMonth, NgbDatepickerNavigation],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./datepicker.scss'],\n\thost: { '[class.disabled]': 'model.disabled' },\n\ttemplate: `\n\t\t<ng-template\n\t\t\t#defaultDayTemplate\n\t\t\tlet-date=\"date\"\n\t\t\tlet-currentMonth=\"currentMonth\"\n\t\t\tlet-selected=\"selected\"\n\t\t\tlet-disabled=\"disabled\"\n\t\t\tlet-focused=\"focused\"\n\t\t>\n\t\t\t<div\n\t\t\t\tngbDatepickerDayView\n\t\t\t\t[date]=\"date\"\n\t\t\t\t[currentMonth]=\"currentMonth\"\n\t\t\t\t[selected]=\"selected\"\n\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t[focused]=\"focused\"\n\t\t\t>\n\t\t\t</div>\n\t\t</ng-template>\n\n\t\t<ng-template #defaultContentTemplate>\n\t\t\t<div *ngFor=\"let month of model.months; let i = index\" class=\"ngb-dp-month\">\n\t\t\t\t<div *ngIf=\"navigation === 'none' || (displayMonths > 1 && navigation === 'select')\" class=\"ngb-dp-month-name\">\n\t\t\t\t\t{{ i18n.getMonthLabel(month.firstDate) }}\n\t\t\t\t</div>\n\t\t\t\t<ngb-datepicker-month [month]=\"month.firstDate\"></ngb-datepicker-month>\n\t\t\t</div>\n\t\t</ng-template>\n\n\t\t<div class=\"ngb-dp-header\">\n\t\t\t<ngb-datepicker-navigation\n\t\t\t\t*ngIf=\"navigation !== 'none'\"\n\t\t\t\t[date]=\"model.firstDate!\"\n\t\t\t\t[months]=\"model.months\"\n\t\t\t\t[disabled]=\"model.disabled\"\n\t\t\t\t[showSelect]=\"model.navigation === 'select'\"\n\t\t\t\t[prevDisabled]=\"model.prevDisabled\"\n\t\t\t\t[nextDisabled]=\"model.nextDisabled\"\n\t\t\t\t[selectBoxes]=\"model.selectBoxes\"\n\t\t\t\t(navigate)=\"onNavigateEvent($event)\"\n\t\t\t\t(select)=\"onNavigateDateSelect($event)\"\n\t\t\t>\n\t\t\t</ngb-datepicker-navigation>\n\t\t</div>\n\n\t\t<div class=\"ngb-dp-content\" [class.ngb-dp-months]=\"!contentTemplate\" #content>\n\t\t\t<ng-template\n\t\t\t\t[ngTemplateOutlet]=\"contentTemplate || contentTemplateFromContent?.templateRef || defaultContentTemplate\"\n\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: this }\"\n\t\t\t\t[ngTemplateOutletInjector]=\"injector\"\n\t\t\t></ng-template>\n\t\t</div>\n\n\t\t<ng-template [ngTemplateOutlet]=\"footerTemplate\"></ng-template>\n\t`,\n\tproviders: [\n\t\t{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbDatepicker), multi: true },\n\t\tNgbDatepickerService,\n\t],\n})\nexport class NgbDatepicker implements AfterViewInit, OnDestroy, OnChanges, OnInit, ControlValueAccessor {\n\tstatic ngAcceptInputType_autoClose: boolean | string;\n\tstatic ngAcceptInputType_navigation: string;\n\tstatic ngAcceptInputType_outsideDays: string;\n\tstatic ngAcceptInputType_weekdays: boolean | number;\n\n\tmodel: DatepickerViewModel;\n\n\t@ViewChild('defaultDayTemplate', { static: true }) private _defaultDayTemplate: TemplateRef<DayTemplateContext>;\n\t@ViewChild('content', { static: true }) private _contentEl: ElementRef<HTMLElement>;\n\n\tprotected injector = inject(Injector);\n\n\tprivate _controlValue: NgbDate | null = null;\n\tprivate _destroyed$ = new Subject<void>();\n\tprivate _publicState: NgbDatepickerState = <any>{};\n\n\t/**\n\t * The reference to a custom content template.\n\t *\n\t * Allows to completely override the way datepicker displays months.\n\t *\n\t * See [`NgbDatepickerContent`](#/components/datepicker/api#NgbDatepickerContent) and\n\t * [`ContentTemplateContext`](#/components/datepicker/api#ContentTemplateContext) for more details.\n\t *\n\t * @since 14.2.0\n\t */\n\t@Input() contentTemplate: TemplateRef<ContentTemplateContext>;\n\t@ContentChild(NgbDatepickerContent, { static: true }) contentTemplateFromContent?: NgbDatepickerContent;\n\n\t/**\n\t * The reference to a custom template for the day.\n\t *\n\t * Allows to completely override the way a day 'cell' in the calendar is displayed.\n\t *\n\t * See [`DayTemplateContext`](#/components/datepicker/api#DayTemplateContext) for the data you get inside.\n\t */\n\t@Input() dayTemplate: TemplateRef<DayTemplateContext>;\n\n\t/**\n\t * The callback to pass any arbitrary data to the template cell via the\n\t * [`DayTemplateContext`](#/components/datepicker/api#DayTemplateContext)'s `data` parameter.\n\t *\n\t * `current` is the month that is currently displayed by the datepicker.\n\t *\n\t * @since 3.3.0\n\t */\n\t@Input() dayTemplateData: (date: NgbDate, current?: { year: number; month: number }) => any;\n\n\t/**\n\t * The number of months to display.\n\t */\n\t@Input() displayMonths: number;\n\n\t/**\n\t * The first day of the week.\n\t *\n\t * With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun.\n\t */\n\t@Input() firstDayOfWeek: number;\n\n\t/**\n\t * The reference to the custom template for the datepicker footer.\n\t *\n\t * @since 3.3.0\n\t */\n\t@Input() footerTemplate: TemplateRef<any>;\n\n\t/**\n\t * The callback to mark some dates as disabled.\n\t *\n\t * It is called for each new date when navigating to a different month.\n\t *\n\t * `current` is the month that is currently displayed by the datepicker.\n\t */\n\t@Input() markDisabled: (date: NgbDate, current?: { year: number; month: number }) => boolean;\n\n\t/**\n\t * The latest date that can be displayed or selected.\n\t *\n\t * If not provided, 'year' select box will display 10 years after the current month.\n\t */\n\t@Input() maxDate: NgbDateStruct;\n\n\t/**\n\t * The earliest date that can be displayed or selected.\n\t *\n\t * If not provided, 'year' select box will display 10 years before the current month.\n\t */\n\t@Input() minDate: NgbDateStruct;\n\n\t/**\n\t * Navigation type.\n\t *\n\t * * `\"select\"` - select boxes for month and navigation arrows\n\t * * `\"arrows\"` - only navigation arrows\n\t * * `\"none\"` - no navigation visible at all\n\t */\n\t@Input() navigation: 'select' | 'arrows' | 'none';\n\n\t/**\n\t * The way of displaying days that don't belong to the current month.\n\t *\n\t * * `\"visible\"` - days are visible\n\t * * `\"hidden\"` - days are hidden, white space preserved\n\t * * `\"collapsed\"` - days are collapsed, so the datepicker height might change between months\n\t *\n\t * For the 2+ months view, days in between months are never shown.\n\t */\n\t@Input() outsideDays: 'visible' | 'collapsed' | 'hidden';\n\n\t/**\n\t * If `true`, week numbers will be displayed.\n\t */\n\t@Input() showWeekNumbers: boolean;\n\n\t/**\n\t * The date to open calendar with.\n\t *\n\t * With the default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.\n\t * If nothing or invalid date is provided, calendar will open with current month.\n\t *\n\t * You could use `navigateTo(date)` method as an alternative.\n\t */\n\t@Input() startDate: { year: number; month: number; day?: number };\n\n\t/**\n\t * The way weekdays should be displayed.\n\t *\n\t * * `true` - weekdays are displayed using default width\n\t * * `false` - weekdays are not displayed\n\t * * `TranslationWidth` - weekdays are displayed using specified width\n\t *\n\t * @since 9.1.0\n\t */\n\t@Input() weekdays: TranslationWidth | boolean;\n\n\t/**\n\t * An event emitted right before the navigation happens and displayed month changes.\n\t *\n\t * See [`NgbDatepickerNavigateEvent`](#/components/datepicker/api#NgbDatepickerNavigateEvent) for the payload info.\n\t */\n\t@Output() navigate = new EventEmitter<NgbDatepickerNavigateEvent>();\n\n\t/**\n\t * An event emitted when user selects a date using keyboard or mouse.\n\t *\n\t * The payload of the event is currently selected `NgbDate`.\n\t *\n\t * @since 5.2.0\n\t */\n\t@Output() dateSelect = new EventEmitter<NgbDate>();\n\n\tonChange = (_: any) => {};\n\tonTouched = () => {};\n\n\tconstructor(\n\t\tprivate _service: NgbDatepickerService,\n\t\tprivate _calendar: NgbCalendar,\n\t\tprivate _i18n: NgbDatepickerI18n,\n\t\tconfig: NgbDatepickerConfig,\n\t\tcd: ChangeDetectorRef,\n\t\tprivate _elementRef: ElementRef<HTMLElement>,\n\t\tprivate _ngbDateAdapter: NgbDateAdapter<any>,\n\t\tprivate _ngZone: NgZone,\n\t) {\n\t\t[\n\t\t\t'contentTemplate',\n\t\t\t'dayTemplate',\n\t\t\t'dayTemplateData',\n\t\t\t'displayMonths',\n\t\t\t'firstDayOfWeek',\n\t\t\t'footerTemplate',\n\t\t\t'markDisabled',\n\t\t\t'minDate',\n\t\t\t'maxDate',\n\t\t\t'navigation',\n\t\t\t'outsideDays',\n\t\t\t'showWeekNumbers',\n\t\t\t'startDate',\n\t\t\t'weekdays',\n\t\t].forEach((input) => (this[input] = config[input]));\n\n\t\t_service.dateSelect$.pipe(takeUntil(this._destroyed$)).subscribe((date) => {\n\t\t\tthis.dateSelect.emit(date);\n\t\t});\n\n\t\t_service.model$.pipe(takeUntil(this._destroyed$)).subscribe((model) => {\n\t\t\tconst newDate = model.firstDate!;\n\t\t\tconst oldDate = this.model ? this.model.firstDate : null;\n\n\t\t\t// update public state\n\t\t\tthis._publicState = {\n\t\t\t\tmaxDate: model.maxDate,\n\t\t\t\tminDate: model.minDate,\n\t\t\t\tfirstDate: model.firstDate!,\n\t\t\t\tlastDate: model.lastDate!,\n\t\t\t\tfocusedDate: model.focusDate!,\n\t\t\t\tmonths: model.months.map((viewModel) => viewModel.firstDate),\n\t\t\t};\n\n\t\t\tlet navigationPrevented = false;\n\t\t\t// emitting navigation event if the first month changes\n\t\t\tif (!newDate.equals(oldDate)) {\n\t\t\t\tthis.navigate.emit({\n\t\t\t\t\tcurrent: oldDate ? { year: oldDate.year, month: oldDate.month } : null,\n\t\t\t\t\tnext: { year: newDate.year, month: newDate.month },\n\t\t\t\t\tpreventDefault: () => (navigationPrevented = true),\n\t\t\t\t});\n\n\t\t\t\t// can't prevent the very first navigation\n\t\t\t\tif (navigationPrevented && oldDate !== null) {\n\t\t\t\t\tthis._service.open(oldDate);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst newSelectedDate = model.selectedDate;\n\t\t\tconst newFocusedDate = model.focusDate;\n\t\t\tconst oldFocusedDate = this.model ? this.model.focusDate : null;\n\n\t\t\tthis.model = model;\n\n\t\t\t// handling selection change\n\t\t\tif (isChangedDate(newSelectedDate, this._controlValue)) {\n\t\t\t\tthis._controlValue = newSelectedDate;\n\t\t\t\tthis.onTouched();\n\t\t\t\tthis.onChange(this._ngbDateAdapter.toModel(newSelectedDate));\n\t\t\t}\n\n\t\t\t// handling focus change\n\t\t\tif (isChangedDate(newFocusedDate, oldFocusedDate) && oldFocusedDate && model.focusVisible) {\n\t\t\t\tthis.focus();\n\t\t\t}\n\n\t\t\tcd.markForCheck();\n\t\t});\n\t}\n\n\t/**\n\t * Returns the readonly public state of the datepicker\n\t *\n\t * @since 5.2.0\n\t */\n\tget state(): NgbDatepickerState {\n\t\treturn this._publicState;\n\t}\n\n\t/**\n\t * Returns the calendar service used in the specific datepicker instance.\n\t *\n\t * @since 5.3.0\n\t */\n\tget calendar(): NgbCalendar {\n\t\treturn this._calendar;\n\t}\n\n\t/**\n\t * Returns the i18n service used in the specific datepicker instance.\n\t *\n\t * @since 14.2.0\n\t */\n\tget i18n(): NgbDatepickerI18n {\n\t\treturn this._i18n;\n\t}\n\n\t/**\n\t * Focuses on given date.\n\t */\n\tfocusDate(date?: NgbDateStruct | null): void {\n\t\tthis._service.focus(NgbDate.from(date));\n\t}\n\n\t/**\n\t * Selects focused date.\n\t */\n\tfocusSelect(): void {\n\t\tthis._service.focusSelect();\n\t}\n\n\tfocus() {\n\t\tthis._ngZone.onStable\n\t\t\t.asObservable()\n\t\t\t.pipe(take(1))\n\t\t\t.subscribe(() => {\n\t\t\t\tconst elementToFocus =\n\t\t\t\t\tthis._elementRef.nativeElement.querySelector<HTMLDivElement>('div.ngb-dp-day[tabindex=\"0\"]');\n\t\t\t\tif (elementToFocus) {\n\t\t\t\t\telementToFocus.focus();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/**\n\t * Navigates to the provided date.\n\t *\n\t * With the default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.\n\t * If nothing or invalid date provided calendar will open current month.\n\t *\n\t * Use the `[startDate]` input as an alternative.\n\t */\n\tnavigateTo(date?: { year: number; month: number; day?: number }) {\n\t\tthis._service.open(NgbDate.from(date ? (date.day ? (date as NgbDateStruct) : { ...date, day: 1 }) : null));\n\t}\n\n\tngAfterViewInit() {\n\t\tthis._ngZone.runOutsideAngular(() => {\n\t\t\tconst focusIns$ = fromEvent<FocusEvent>(this._contentEl.nativeElement, 'focusin');\n\t\t\tconst focusOuts$ = fromEvent<FocusEvent>(this._contentEl.nativeElement, 'focusout');\n\t\t\tconst { nativeElement } = this._elementRef;\n\n\t\t\t// we're changing 'focusVisible' only when entering or leaving months view\n\t\t\t// and ignoring all focus events where both 'target' and 'related' target are day cells\n\t\t\tmerge(focusIns$, focusOuts$)\n\t\t\t\t.pipe(\n\t\t\t\t\tfilter(\n\t\t\t\t\t\t({ target, relatedTarget }) =>\n\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\thasClassName(target, 'ngb-dp-day') &&\n\t\t\t\t\t\t\t\thasClassName(relatedTarget, 'ngb-dp-day') &&\n\t\t\t\t\t\t\t\tnativeElement.contains(target as Node) &&\n\t\t\t\t\t\t\t\tnativeElement.contains(relatedTarget as Node)\n\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t\ttakeUntil(this._destroyed$),\n\t\t\t\t)\n\t\t\t\t.subscribe(({ type }) => this._ngZone.run(() => this._service.set({ focusVisible: type === 'focusin' })));\n\t\t});\n\t}\n\n\tngOnDestroy() {\n\t\tthis._destroyed$.next();\n\t}\n\n\tngOnInit() {\n\t\tif (this.model === undefined) {\n\t\t\tconst inputs: DatepickerServiceInputs = {};\n\t\t\t[\n\t\t\t\t'dayTemplateData',\n\t\t\t\t'displayMonths',\n\t\t\t\t'markDisabled',\n\t\t\t\t'firstDayOfWeek',\n\t\t\t\t'navigation',\n\t\t\t\t'minDate',\n\t\t\t\t'maxDate',\n\t\t\t\t'outsideDays',\n\t\t\t\t'weekdays',\n\t\t\t].forEach((name) => (inputs[name] = this[name]));\n\t\t\tthis._service.set(inputs);\n\n\t\t\tthis.navigateTo(this.startDate);\n\t\t}\n\t\tif (!this.dayTemplate) {\n\t\t\tthis.dayTemplate = this._defaultDayTemplate;\n\t\t}\n\t}\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\tconst inputs: DatepickerServiceInputs = {};\n\t\t[\n\t\t\t'dayTemplateData',\n\t\t\t'displayMonths',\n\t\t\t'markDisabled',\n\t\t\t'firstDayOfWeek',\n\t\t\t'navigation',\n\t\t\t'minDate',\n\t\t\t'maxDate',\n\t\t\t'outsideDays',\n\t\t\t'weekdays',\n\t\t]\n\t\t\t.filter((name) => name in changes)\n\t\t\t.forEach((name) => (inputs[name] = this[name]));\n\t\tthis._service.set(inputs);\n\n\t\tif ('startDate' in changes) {\n\t\t\tconst { currentValue, previousValue } = changes.startDate;\n\t\t\tif (isChangedMonth(previousValue, currentValue)) {\n\t\t\t\tthis.navigateTo(this.startDate);\n\t\t\t}\n\t\t}\n\t}\n\n\tonDateSelect(date: NgbDate) {\n\t\tthis._service.focus(date);\n\t\tthis._service.select(date, { emitEvent: true });\n\t}\n\n\tonNavigateDateSelect(date: NgbDate) {\n\t\tthis._service.open(date);\n\t}\n\n\tonNavigateEvent(event: NavigationEvent) {\n\t\tswitch (event) {\n\t\t\tcase NavigationEvent.PREV:\n\t\t\t\tthis._service.open(this._calendar.getPrev(this.model.firstDate!, 'm', 1));\n\t\t\t\tbreak;\n\t\t\tcase NavigationEvent.NEXT:\n\t\t\t\tthis._service.open(this._calendar.getNext(this.model.firstDate!, 'm', 1));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tregisterOnChange(fn: (value: any) => any): void {\n\t\tthis.onChange = fn;\n\t}\n\n\tregisterOnTouched(fn: () => any): void {\n\t\tthis.onTouched = fn;\n\t}\n\n\tsetDisabledState(disabled: boolean) {\n\t\tthis._service.set({ disabled });\n\t}\n\n\twriteValue(value) {\n\t\tthis._controlValue = NgbDate.from(this._ngbDateAdapter.fromModel(value));\n\t\tthis._service.select(this._controlValue);\n\t}\n}\n","import { NgZone } from '@angular/core';\nimport { fromEvent, Observable, race } from 'rxjs';\nimport { delay, filter, map, takeUntil, tap, withLatestFrom } from 'rxjs/operators';\nimport { Key } from './key';\nimport { closest } from './util';\n\nconst isContainedIn = (element: HTMLElement, array?: HTMLElement[]) =>\n\tarray ? array.some((item) => item.contains(element)) : false;\n\nconst matchesSelectorIfAny = (element: HTMLElement, selector?: string) =>\n\t!selector || closest(element, selector) != null;\n\n// we have to add a more significant delay to avoid re-opening when handling (click) on a toggling element\n// TODO: use proper Angular platform detection when NgbAutoClose becomes a service and we can inject PLATFORM_ID\nconst isMobile = (() => {\n\tconst isIOS = () =>\n\t\t/iPad|iPhone|iPod/.test(navigator.userAgent) ||\n\t\t(/Macintosh/.test(navigator.userAgent) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);\n\tconst isAndroid = () => /Android/.test(navigator.userAgent);\n\n\treturn typeof navigator !== 'undefined' ? !!navigator.userAgent && (isIOS() || isAndroid()) : false;\n})();\n\n// setting 'ngbAutoClose' synchronously on mobile results in immediate popup closing\n// when tapping on the triggering element\nconst wrapAsyncForMobile = (fn) => (isMobile ? () => setTimeout(() => fn(), 100) : fn);\n\nexport const enum SOURCE {\n\tESCAPE,\n\tCLICK,\n}\n\nexport function ngbAutoClose(\n\tzone: NgZone,\n\tdocument: any,\n\ttype: boolean | 'inside' | 'outside',\n\tclose: (source: SOURCE) => void,\n\tclosed$: Observable<any>,\n\tinsideElements: HTMLElement[],\n\tignoreElements?: HTMLElement[],\n\tinsideSelector?: string,\n) {\n\t// closing on ESC and outside clicks\n\tif (type) {\n\t\tzone.runOutsideAngular(\n\t\t\twrapAsyncForMobile(() => {\n\t\t\t\tconst shouldCloseOnClick = (event: MouseEvent) => {\n\t\t\t\t\tconst element = event.target as HTMLElement;\n\t\t\t\t\tif (event.button === 2 || isContainedIn(element, ignoreElements)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (type === 'inside') {\n\t\t\t\t\t\treturn isContainedIn(element, insideElements) && matchesSelectorIfAny(element, insideSelector);\n\t\t\t\t\t} else if (type === 'outside') {\n\t\t\t\t\t\treturn !isContainedIn(element, insideElements);\n\t\t\t\t\t} /* if (type === true) */ else {\n\t\t\t\t\t\treturn matchesSelectorIfAny(element, insideSelector) || !isContainedIn(element, insideElements);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst escapes$ = fromEvent<KeyboardEvent>(document, 'keydown').pipe(\n\t\t\t\t\ttakeUntil(closed$),\n\t\t\t\t\t/* eslint-disable-next-line deprecation/deprecation */\n\t\t\t\t\tfilter((e) => e.which === Key.Escape),\n\t\t\t\t\ttap((e) => e.preventDefault()),\n\t\t\t\t);\n\n\t\t\t\t// we have to pre-calculate 'shouldCloseOnClick' on 'mousedown',\n\t\t\t\t// because on 'mouseup' DOM nodes might be detached\n\t\t\t\tconst mouseDowns$ = fromEvent<MouseEvent>(document, 'mousedown').pipe(\n\t\t\t\t\tmap(shouldCloseOnClick),\n\t\t\t\t\ttakeUntil(closed$),\n\t\t\t\t);\n\n\t\t\t\tconst closeableClicks$ = fromEvent<MouseEvent>(document, 'mouseup').pipe(\n\t\t\t\t\twithLatestFrom(mouseDowns$),\n\t\t\t\t\tfilter(([_, shouldClose]) => shouldClose),\n\t\t\t\t\tdelay(0),\n\t\t\t\t\ttakeUntil(closed$),\n\t\t\t\t) as Observable<MouseEvent>;\n\n\t\t\t\trace([escapes$.pipe(map((_) => SOURCE.ESCAPE)), closeableClicks$.pipe(map((_) => SOURCE.CLICK))]).subscribe(\n\t\t\t\t\t(source: SOURCE) => zone.run(() => close(source)),\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t}\n}\n","import { NgZone } from '@angular/core';\n\nimport { fromEvent, Observable } from 'rxjs';\nimport { filter, map, takeUntil, withLatestFrom } from 'rxjs/operators';\n\nimport { Key } from './key';\n\nexport const FOCUSABLE_ELEMENTS_SELECTOR = [\n\t'a[href]',\n\t'button:not([disabled])',\n\t'input:not([disabled]):not([type=\"hidden\"])',\n\t'select:not([disabled])',\n\t'textarea:not([disabled])',\n\t'[contenteditable]',\n\t'[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\n/**\n * Returns first and last focusable elements inside of a given element based on specific CSS selector\n */\nexport function getFocusableBoundaryElements(element: HTMLElement): HTMLElement[] {\n\tconst list: HTMLElement[] = Array.from(\n\t\telement.querySelectorAll(FOCUSABLE_ELEMENTS_SELECTOR) as NodeListOf<HTMLElement>,\n\t).filter((el) => el.tabIndex !== -1);\n\treturn [list[0], list[list.length - 1]];\n}\n\n/**\n * Function that enforces browser focus to be trapped inside a DOM element.\n *\n * Works only for clicks inside the element and navigation with 'Tab', ignoring clicks outside of the element\n *\n * @param zone Angular zone\n * @param element The element around which focus will be trapped inside\n * @param stopFocusTrap$ The observable stream. When completed the focus trap will clean up listeners\n * and free internal resources\n * @param refocusOnClick Put the focus back to the last focused element whenever a click occurs on element (default to\n * false)\n */\nexport const ngbFocusTrap = (\n\tzone: NgZone,\n\telement: HTMLElement,\n\tstopFocusTrap$: Observable<any>,\n\trefocusOnClick = false,\n) => {\n\tzone.runOutsideAngular(() => {\n\t\t// last focused element\n\t\tconst lastFocusedElement$ = fromEvent<FocusEvent>(element, 'focusin').pipe(\n\t\t\ttakeUntil(stopFocusTrap$),\n\t\t\tmap((e) => e.target),\n\t\t);\n\n\t\t// 'tab' / 'shift+tab' stream\n\t\tfromEvent<KeyboardEvent>(element, 'keydown')\n\t\t\t.pipe(\n\t\t\t\ttakeUntil(stopFocusTrap$),\n\t\t\t\t/* eslint-disable-next-line deprecation/deprecation */\n\t\t\t\tfilter((e) => e.which === Key.Tab),\n\t\t\t\twithLatestFrom(lastFocusedElement$),\n\t\t\t)\n\t\t\t.subscribe(([tabEvent, focusedElement]) => {\n\t\t\t\tconst [first, last] = getFocusableBoundaryElements(element);\n\n\t\t\t\tif ((focusedElement === first || focusedElement === element) && tabEvent.shiftKey) {\n\t\t\t\t\tlast.focus();\n\t\t\t\t\ttabEvent.preventDefault();\n\t\t\t\t}\n\n\t\t\t\tif (focusedElement === last && !tabEvent.shiftKey) {\n\t\t\t\t\tfirst.focus();\n\t\t\t\t\ttabEvent.preventDefault();\n\t\t\t\t}\n\t\t\t});\n\n\t\t// inside click\n\t\tif (refocusOnClick) {\n\t\t\tfromEvent(element, 'click')\n\t\t\t\t.pipe(\n\t\t\t\t\ttakeUntil(stopFocusTrap$),\n\t\t\t\t\twithLatestFrom(lastFocusedElement$),\n\t\t\t\t\tmap((arr) => arr[1] as HTMLElement),\n\t\t\t\t)\n\t\t\t\t.subscribe((lastFocusedElement) => lastFocusedElement.focus());\n\t\t}\n\t});\n};\n","import { Injectable, Inject } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\n@Injectable({ providedIn: 'root' })\nexport class NgbRTL {\n\tprivate _element: HTMLHtmlElement;\n\n\tconstructor(@Inject(DOCUMENT) document: any) {\n\t\tthis._element = document.documentElement;\n\t}\n\n\tisRTL() {\n\t\treturn (this._element.getAttribute('dir') || '').toLowerCase() === 'rtl';\n\t}\n}\n","import {\n\tarrow,\n\tcreatePopperLite,\n\tflip,\n\tInstance,\n\tModifier,\n\tPlacement as PopperPlacement,\n\tpreventOverflow,\n\tOptions,\n} from '@popperjs/core';\nimport { NgbRTL } from './rtl';\nimport { inject } from '@angular/core';\n\nconst placementSeparator = /\\s+/;\nconst spacesRegExp = / +/gi;\n\n/**\n * Matching classes from the Bootstrap ones to the poppers ones.\n * The first index of each array is used for the left to right direction,\n * the second one is used for the right to left, defaulting to the first index (when LTR and RTL lead to the same class)\n *\n * See [Bootstrap alignments](https://getbootstrap.com/docs/5.1/components/dropdowns/#alignment-options)\n * and [Popper placements](https://popper.js.org/docs/v2/constructors/#options)\n */\nconst bootstrapPopperMatches = {\n\ttop: ['top'],\n\tbottom: ['bottom'],\n\tstart: ['left', 'right'],\n\tleft: ['left'],\n\tend: ['right', 'left'],\n\tright: ['right'],\n\t'top-start': ['top-start', 'top-end'],\n\t'top-left': ['top-start'],\n\t'top-end': ['top-end', 'top-start'],\n\t'top-right': ['top-end'],\n\t'bottom-start': ['bottom-start', 'bottom-end'],\n\t'bottom-left': ['bottom-start'],\n\t'bottom-end': ['bottom-end', 'bottom-start'],\n\t'bottom-right': ['bottom-end'],\n\t'start-top': ['left-start', 'right-start'],\n\t'left-top': ['left-start'],\n\t'start-bottom': ['left-end', 'right-end'],\n\t'left-bottom': ['left-end'],\n\t'end-top': ['right-start', 'left-start'],\n\t'right-top': ['right-start'],\n\t'end-bottom': ['right-end', 'left-end'],\n\t'right-bottom': ['right-end'],\n};\n\nexport function getPopperClassPlacement(placement: Placement, isRTL: boolean): PopperPlacement {\n\tconst [leftClass, rightClass] = bootstrapPopperMatches[placement];\n\treturn isRTL ? rightClass || leftClass : leftClass;\n}\n\nconst popperStartPrimaryPlacement = /^left/;\nconst popperEndPrimaryPlacement = /^right/;\nconst popperStartSecondaryPlacement = /^start/;\nconst popperEndSecondaryPlacement = /^end/;\nexport function getBootstrapBaseClassPlacement(baseClass: string, placement: PopperPlacement): string {\n\tlet [primary, secondary] = placement.split('-');\n\tconst newPrimary = primary.replace(popperStartPrimaryPlacement, 'start').replace(popperEndPrimaryPlacement, 'end');\n\tlet classnames = [newPrimary];\n\tif (secondary) {\n\t\tlet newSecondary = secondary;\n\t\tif (primary === 'left' || primary === 'right') {\n\t\t\tnewSecondary = newSecondary\n\t\t\t\t.replace(popperStartSecondaryPlacement, 'top')\n\t\t\t\t.replace(popperEndSecondaryPlacement, 'bottom');\n\t\t}\n\t\tclassnames.push(`${newPrimary}-${newSecondary}` as Placement);\n\t}\n\tif (baseClass) {\n\t\tclassnames = classnames.map((classname) => `${baseClass}-${classname}`);\n\t}\n\treturn classnames.join(' ');\n}\n\n/*\n * Accept the placement array and applies the appropriate placement dependent on the viewport.\n * Returns the applied placement.\n * In case of auto placement, placements are selected in order\n * 'top', 'bottom', 'start', 'end',\n * 'top-start', 'top-end',\n * 'bottom-start', 'bottom-end',\n * 'start-top', 'start-bottom',\n * 'end-top', 'end-bottom'.\n * */\nexport function getPopperOptions({ placement, baseClass }: PositioningOptions, rtl: NgbRTL): Partial<Options> {\n\tlet placementVals: Array<Placement> = Array.isArray(placement)\n\t\t? placement\n\t\t: (placement.split(placementSeparator) as Array<Placement>);\n\n\t// No need to consider left and right here, as start and end are enough, and it is used for 'auto' placement only\n\tconst allowedPlacements = [\n\t\t'top',\n\t\t'bottom',\n\t\t'start',\n\t\t'end',\n\t\t'top-start',\n\t\t'top-end',\n\t\t'bottom-start',\n\t\t'bottom-end',\n\t\t'start-top',\n\t\t'start-bottom',\n\t\t'end-top',\n\t\t'end-bottom',\n\t];\n\n\t// replace auto placement with other placements\n\tlet hasAuto = placementVals.findIndex((val) => val === 'auto');\n\tif (hasAuto >= 0) {\n\t\tallowedPlacements.forEach(function (obj) {\n\t\t\tif (placementVals.find((val) => val.search('^' + obj) !== -1) == null) {\n\t\t\t\tplacementVals.splice(hasAuto++, 1, obj as Placement);\n\t\t\t}\n\t\t});\n\t}\n\n\tconst popperPlacements = placementVals.map((_placement) => {\n\t\treturn getPopperClassPlacement(_placement, rtl.isRTL());\n\t});\n\n\tlet mainPlacement = popperPlacements.shift();\n\n\tconst bsModifier: Partial<Modifier<any, any>> = {\n\t\tname: 'bootstrapClasses',\n\t\tenabled: !!baseClass,\n\t\tphase: 'write',\n\t\tfn({ state }) {\n\t\t\tconst bsClassRegExp = new RegExp(baseClass + '(-[a-z]+)*', 'gi');\n\n\t\t\tconst popperElement: HTMLElement = state.elements.popper as HTMLElement;\n\t\t\tconst popperPlacement = state.placement;\n\n\t\t\tlet className = popperElement.className;\n\n\t\t\t// Remove old bootstrap classes\n\t\t\tclassName = className.replace(bsClassRegExp, '');\n\n\t\t\t// Add current placements\n\t\t\tclassName += ` ${getBootstrapBaseClassPlacement(baseClass!, popperPlacement)}`;\n\n\t\t\t// Remove multiple spaces\n\t\t\tclassName = className.trim().replace(spacesRegExp, ' ');\n\n\t\t\t// Reassign\n\t\t\tpopperElement.className = className;\n\t\t},\n\t};\n\n\treturn {\n\t\tplacement: mainPlacement,\n\t\tmodifiers: [\n\t\t\tbsModifier,\n\t\t\tflip,\n\t\t\tpreventOverflow,\n\t\t\tarrow,\n\t\t\t{\n\t\t\t\tenabled: true,\n\t\t\t\tname: 'flip',\n\t\t\t\toptions: {\n\t\t\t\t\tfallbackPlacements: popperPlacements,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tenabled: true,\n\t\t\t\tname: 'preventOverflow',\n\t\t\t\tphase: 'main',\n\t\t\t\tfn: function () {},\n\t\t\t},\n\t\t],\n\t};\n}\n\nexport type Placement =\n\t| 'auto'\n\t| 'top'\n\t| 'bottom'\n\t| 'start'\n\t| 'left'\n\t| 'end'\n\t| 'right'\n\t| 'top-start'\n\t| 'top-left'\n\t| 'top-end'\n\t| 'top-right'\n\t| 'bottom-start'\n\t| 'bottom-left'\n\t| 'bottom-end'\n\t| 'bottom-right'\n\t| 'start-top'\n\t| 'left-top'\n\t| 'start-bottom'\n\t| 'left-bottom'\n\t| 'end-top'\n\t| 'right-top'\n\t| 'end-bottom'\n\t| 'right-bottom';\n\nexport type PlacementArray = Placement | Array<Placement> | string;\n\ninterface PositioningOptions {\n\thostElement: HTMLElement;\n\ttargetElement: HTMLElement;\n\tplacement: string | Placement | PlacementArray;\n\tappendToBody?: boolean;\n\tbaseClass?: string;\n\tupdatePopperOptions?: (options: Partial<Options>) => Partial<Options>;\n}\n\nfunction noop(arg) {\n\treturn arg;\n}\n\nexport function ngbPositioning() {\n\tconst rtl = inject(NgbRTL);\n\tlet popperInstance: Instance | null = null;\n\n\treturn {\n\t\tcreatePopper(positioningOption: PositioningOptions) {\n\t\t\tif (!popperInstance) {\n\t\t\t\tconst updatePopperOptions = positioningOption.updatePopperOptions || noop;\n\t\t\t\tlet popperOptions = updatePopperOptions(getPopperOptions(positioningOption, rtl));\n\t\t\t\tpopperInstance = createPopperLite(\n\t\t\t\t\tpositioningOption.hostElement,\n\t\t\t\t\tpositioningOption.targetElement,\n\t\t\t\t\tpopperOptions,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\tupdate() {\n\t\t\tif (popperInstance) {\n\t\t\t\tpopperInstance.update();\n\t\t\t}\n\t\t},\n\t\tsetOptions(positioningOption: PositioningOptions) {\n\t\t\tif (popperInstance) {\n\t\t\t\tconst updatePopperOptions = positioningOption.updatePopperOptions || noop;\n\t\t\t\tlet popperOptions = updatePopperOptions(getPopperOptions(positioningOption, rtl));\n\t\t\t\tpopperInstance.setOptions(popperOptions);\n\t\t\t}\n\t\t},\n\t\tdestroy() {\n\t\t\tif (popperInstance) {\n\t\t\t\tpopperInstance.destroy();\n\t\t\t\tpopperInstance = null;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { NgbCalendarIslamicCivil } from './ngb-calendar-islamic-civil';\nimport { NgbDate } from '../ngb-date';\nimport { Injectable } from '@angular/core';\n\n/**\n * Umalqura calendar is one type of Hijri calendars used in islamic countries.\n * This Calendar is used by Saudi Arabia for administrative purpose.\n * Unlike tabular calendars, the algorithm involves astronomical calculation, but it's still deterministic.\n * http://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types\n */\n\nconst GREGORIAN_FIRST_DATE = new Date(1882, 10, 12);\nconst GREGORIAN_LAST_DATE = new Date(2174, 10, 25);\nconst HIJRI_BEGIN = 1300;\nconst HIJRI_END = 1600;\nconst ONE_DAY = 1000 * 60 * 60 * 24;\n\nconst MONTH_LENGTH = [\n\t// 1300-1304\n\t'101010101010',\n\t'110101010100',\n\t'111011001001',\n\t'011011010100',\n\t'011011101010',\n\t// 1305-1309\n\t'001101101100',\n\t'101010101101',\n\t'010101010101',\n\t'011010101001',\n\t'011110010010',\n\t// 1310-1314\n\t'101110101001',\n\t'010111010100',\n\t'101011011010',\n\t'010101011100',\n\t'110100101101',\n\t// 1315-1319\n\t'011010010101',\n\t'011101001010',\n\t'101101010100',\n\t'101101101010',\n\t'010110101101',\n\t// 1320-1324\n\t'010010101110',\n\t'101001001111',\n\t'010100010111',\n\t'011010001011',\n\t'011010100101',\n\t// 1325-1329\n\t'101011010101',\n\t'001011010110',\n\t'100101011011',\n\t'010010011101',\n\t'101001001101',\n\t// 1330-1334\n\t'110100100110',\n\t'110110010101',\n\t'010110101100',\n\t'100110110110',\n\t'001010111010',\n\t// 1335-1339\n\t'101001011011',\n\t'010100101011',\n\t'101010010101',\n\t'011011001010',\n\t'101011101001',\n\t// 1340-1344\n\t'001011110100',\n\t'100101110110',\n\t'001010110110',\n\t'100101010110',\n\t'101011001010',\n\t// 1345-1349\n\t'101110100100',\n\t'101111010010',\n\t'010111011001',\n\t'001011011100',\n\t'100101101101',\n\t// 1350-1354\n\t'010101001101',\n\t'101010100101',\n\t'101101010010',\n\t'101110100101',\n\t'010110110100',\n\t// 1355-1359\n\t'100110110110',\n\t'010101010111',\n\t'001010010111',\n\t'010101001011',\n\t'011010100011',\n\t// 1360-1364\n\t'011101010010',\n\t'101101100101',\n\t'010101101010',\n\t'101010101011',\n\t'010100101011',\n\t// 1365-1369\n\t'110010010101',\n\t'110101001010',\n\t'110110100101',\n\t'010111001010',\n\t'101011010110',\n\t// 1370-1374\n\t'100101010111',\n\t'010010101011',\n\t'100101001011',\n\t'101010100101',\n\t'101101010010',\n\t// 1375-1379\n\t'101101101010',\n\t'010101110101',\n\t'001001110110',\n\t'100010110111',\n\t'010001011011',\n\t// 1380-1384\n\t'010101010101',\n\t'010110101001',\n\t'010110110100',\n\t'100111011010',\n\t'010011011101',\n\t// 1385-1389\n\t'001001101110',\n\t'100100110110',\n\t'101010101010',\n\t'110101010100',\n\t'110110110010',\n\t// 1390-1394\n\t'010111010101',\n\t'001011011010',\n\t'100101011011',\n\t'010010101011',\n\t'101001010101',\n\t// 1395-1399\n\t'101101001001',\n\t'101101100100',\n\t'101101110001',\n\t'010110110100',\n\t'101010110101',\n\t// 1400-1404\n\t'101001010101',\n\t'110100100101',\n\t'111010010010',\n\t'111011001001',\n\t'011011010100',\n\t// 1405-1409\n\t'101011101001',\n\t'100101101011',\n\t'010010101011',\n\t'101010010011',\n\t'110101001001',\n\t// 1410-1414\n\t'110110100100',\n\t'110110110010',\n\t'101010111001',\n\t'010010111010',\n\t'101001011011',\n\t// 1415-1419\n\t'010100101011',\n\t'101010010101',\n\t'101100101010',\n\t'101101010101',\n\t'010101011100',\n\t// 1420-1424\n\t'010010111101',\n\t'001000111101',\n\t'100100011101',\n\t'101010010101',\n\t'101101001010',\n\t// 1425-1429\n\t'101101011010',\n\t'010101101101',\n\t'001010110110',\n\t'100100111011',\n\t'010010011011',\n\t// 1430-1434\n\t'011001010101',\n\t'011010101001',\n\t'011101010100',\n\t'101101101010',\n\t'010101101100',\n\t// 1435-1439\n\t'101010101101',\n\t'010101010101',\n\t'101100101001',\n\t'101110010010',\n\t'101110101001',\n\t// 1440-1444\n\t'010111010100',\n\t'101011011010',\n\t'010101011010',\n\t'101010101011',\n\t'010110010101',\n\t// 1445-1449\n\t'011101001001',\n\t'011101100100',\n\t'101110101010',\n\t'010110110101',\n\t'001010110110',\n\t// 1450-1454\n\t'101001010110',\n\t'111001001101',\n\t'101100100101',\n\t'101101010010',\n\t'101101101010',\n\t// 1455-1459\n\t'010110101101',\n\t'001010101110',\n\t'100100101111',\n\t'010010010111',\n\t'011001001011',\n\t// 1460-1464\n\t'011010100101',\n\t'011010101100',\n\t'101011010110',\n\t'010101011101',\n\t'010010011101',\n\t// 1465-1469\n\t'101001001101',\n\t'110100010110',\n\t'110110010101',\n\t'010110101010',\n\t'010110110101',\n\t// 1470-1474\n\t'001011011010',\n\t'100101011011',\n\t'010010101101',\n\t'010110010101',\n\t'011011001010',\n\t// 1475-1479\n\t'011011100100',\n\t'101011101010',\n\t'010011110101',\n\t'001010110110',\n\t'100101010110',\n\t// 1480-1484\n\t'101010101010',\n\t'101101010100',\n\t'101111010010',\n\t'010111011001',\n\t'001011101010',\n\t// 1485-1489\n\t'100101101101',\n\t'010010101101',\n\t'101010010101',\n\t'101101001010',\n\t'101110100101',\n\t// 1490-1494\n\t'010110110010',\n\t'100110110101',\n\t'010011010110',\n\t'101010010111',\n\t'010101000111',\n\t// 1495-1499\n\t'011010010011',\n\t'011101001001',\n\t'101101010101',\n\t'010101101010',\n\t'101001101011',\n\t// 1500-1504\n\t'010100101011',\n\t'101010001011',\n\t'110101000110',\n\t'110110100011',\n\t'010111001010',\n\t// 1505-1509\n\t'101011010110',\n\t'010011011011',\n\t'001001101011',\n\t'100101001011',\n\t'101010100101',\n\t// 1510-1514\n\t'101101010010',\n\t'101101101001',\n\t'010101110101',\n\t'000101110110',\n\t'100010110111',\n\t// 1515-1519\n\t'001001011011',\n\t'010100101011',\n\t'010101100101',\n\t'010110110100',\n\t'100111011010',\n\t// 1520-1524\n\t'010011101101',\n\t'000101101101',\n\t'100010110110',\n\t'101010100110',\n\t'110101010010',\n\t// 1525-1529\n\t'110110101001',\n\t'010111010100',\n\t'101011011010',\n\t'100101011011',\n\t'010010101011',\n\t// 1530-1534\n\t'011001010011',\n\t'011100101001',\n\t'011101100010',\n\t'101110101001',\n\t'010110110010',\n\t// 1535-1539\n\t'101010110101',\n\t'010101010101',\n\t'101100100101',\n\t'110110010010',\n\t'111011001001',\n\t// 1540-1544\n\t'011011010010',\n\t'101011101001',\n\t'010101101011',\n\t'010010101011',\n\t'101001010101',\n\t// 1545-1549\n\t'110100101001',\n\t'110101010100',\n\t'110110101010',\n\t'100110110101',\n\t'010010111010',\n\t// 1550-1554\n\t'101000111011',\n\t'010010011011',\n\t'101001001101',\n\t'101010101010',\n\t'101011010101',\n\t// 1555-1559\n\t'001011011010',\n\t'100101011101',\n\t'010001011110',\n\t'101000101110',\n\t'110010011010',\n\t// 1560-1564\n\t'110101010101',\n\t'011010110010',\n\t'011010111001',\n\t'010010111010',\n\t'101001011101',\n\t// 1565-1569\n\t'010100101101',\n\t'101010010101',\n\t'101101010010',\n\t'101110101000',\n\t'101110110100',\n\t// 1570-1574\n\t'010110111001',\n\t'001011011010',\n\t'100101011010',\n\t'101101001010',\n\t'110110100100',\n\t// 1575-1579\n\t'111011010001',\n\t'011011101000',\n\t'101101101010',\n\t'010101101101',\n\t'010100110101',\n\t// 1580-1584\n\t'011010010101',\n\t'110101001010',\n\t'110110101000',\n\t'110111010100',\n\t'011011011010',\n\t// 1585-1589\n\t'010101011011',\n\t'001010011101',\n\t'011000101011',\n\t'101100010101',\n\t'101101001010',\n\t// 1590-1594\n\t'101110010101',\n\t'010110101010',\n\t'101010101110',\n\t'100100101110',\n\t'110010001111',\n\t// 1595-1599\n\t'010100100111',\n\t'011010010101',\n\t'011010101010',\n\t'101011010110',\n\t'010101011101',\n\t// 1600\n\t'001010011101',\n];\n\nfunction getDaysDiff(date1: Date, date2: Date): number {\n\t// Ignores the time part in date1 and date2:\n\tconst time1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());\n\tconst time2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());\n\tconst diff = Math.abs(time1 - time2);\n\treturn Math.round(diff / ONE_DAY);\n}\n\n@Injectable()\nexport class NgbCalendarIslamicUmalqura extends NgbCalendarIslamicCivil {\n\t/**\n\t * Returns the equivalent islamic(Umalqura) date value for a give input Gregorian date.\n\t * `gdate` is s JS Date to be converted to Hijri.\n\t */\n\tfromGregorian(gDate: Date): NgbDate {\n\t\tlet hDay = 1,\n\t\t\thMonth = 0,\n\t\t\thYear = 1300;\n\t\tlet daysDiff = getDaysDiff(gDate, GREGORIAN_FIRST_DATE);\n\t\tif (gDate.getTime() - GREGORIAN_FIRST_DATE.getTime() >= 0 && gDate.getTime() - GREGORIAN_LAST_DATE.getTime() <= 0) {\n\t\t\tlet year = 1300;\n\t\t\tfor (let i = 0; i < MONTH_LENGTH.length; i++, year++) {\n\t\t\t\tfor (let j = 0; j < 12; j++) {\n\t\t\t\t\tlet numOfDays = +MONTH_LENGTH[i][j] + 29;\n\t\t\t\t\tif (daysDiff <= numOfDays) {\n\t\t\t\t\t\thDay = daysDiff + 1;\n\t\t\t\t\t\tif (hDay > numOfDays) {\n\t\t\t\t\t\t\thDay = 1;\n\t\t\t\t\t\t\tj++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (j > 11) {\n\t\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\t\tyear++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\thMonth = j;\n\t\t\t\t\t\thYear = year;\n\t\t\t\t\t\treturn new NgbDate(hYear, hMonth + 1, hDay);\n\t\t\t\t\t}\n\t\t\t\t\tdaysDiff = daysDiff - numOfDays;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null as any;\n\t\t} else {\n\t\t\treturn super.fromGregorian(gDate);\n\t\t}\n\t}\n\t/**\n\t * Converts the current Hijri date to Gregorian.\n\t */\n\ttoGregorian(hDate: NgbDate): Date {\n\t\tconst hYear = hDate.year;\n\t\tconst hMonth = hDate.month - 1;\n\t\tconst hDay = hDate.day;\n\t\tlet gDate = new Date(GREGORIAN_FIRST_DATE);\n\t\tlet dayDiff = hDay - 1;\n\t\tif (hYear >= HIJRI_BEGIN && hYear <= HIJRI_END) {\n\t\t\tfor (let y = 0; y < hYear - HIJRI_BEGIN; y++) {\n\t\t\t\tfor (let m = 0; m < 12; m++) {\n\t\t\t\t\tdayDiff += +MONTH_LENGTH[y][m] + 29;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let m = 0; m < hMonth; m++) {\n\t\t\t\tdayDiff += +MONTH_LENGTH[hYear - HIJRI_BEGIN][m] + 29;\n\t\t\t}\n\t\t\tgDate.setDate(GREGORIAN_FIRST_DATE.getDate() + dayDiff);\n\t\t} else {\n\t\t\tgDate = super.toGregorian(hDate);\n\t\t}\n\t\treturn gDate;\n\t}\n\t/**\n\t * Returns the number of days in a specific Hijri hMonth.\n\t * `hMonth` is 1 for Muharram, 2 for Safar, etc.\n\t * `hYear` is any Hijri hYear.\n\t */\n\tgetDaysPerMonth(hMonth: number, hYear: number): number {\n\t\tif (hYear >= HIJRI_BEGIN && hYear <= HIJRI_END) {\n\t\t\tconst pos = hYear - HIJRI_BEGIN;\n\t\t\treturn +MONTH_LENGTH[pos][hMonth - 1] + 29;\n\t\t}\n\t\treturn super.getDaysPerMonth(hMonth, hYear);\n\t}\n}\n","import { NgModule } from '@angular/core';\nimport { NgbDatepicker, NgbDatepickerContent } from './datepicker';\nimport { NgbDatepickerMonth } from './datepicker';\nimport { NgbInputDatepicker } from './datepicker-input';\n\nexport { NgbDatepicker, NgbDatepickerContent, NgbDatepickerNavigateEvent, NgbDatepickerState } from './datepicker';\nexport { NgbInputDatepicker } from './datepicker-input';\nexport { NgbCalendar, NgbPeriod, NgbCalendarGregorian } from './ngb-calendar';\nexport { NgbCalendarIslamicCivil } from './hijri/ngb-calendar-islamic-civil';\nexport { NgbCalendarIslamicUmalqura } from './hijri/ngb-calendar-islamic-umalqura';\nexport { NgbCalendarPersian } from './jalali/ngb-calendar-persian';\nexport { NgbCalendarHebrew } from './hebrew/ngb-calendar-hebrew';\nexport { NgbDatepickerI18nHebrew } from './hebrew/datepicker-i18n-hebrew';\nexport { NgbCalendarBuddhist } from './buddhist/ngb-calendar-buddhist';\nexport { NgbDatepickerMonth } from './datepicker';\nexport { NgbDatepickerDayView } from './datepicker-day-view';\nexport { NgbDatepickerNavigation } from './datepicker-navigation';\nexport { NgbDatepickerNavigationSelect } from './datepicker-navigation-select';\nexport { NgbDatepickerConfig } from './datepicker-config';\nexport { NgbInputDatepickerConfig } from './datepicker-input-config';\nexport { NgbDatepickerI18n, NgbDatepickerI18nDefault } from './datepicker-i18n';\nexport { NgbDateStruct } from './ngb-date-struct';\nexport { NgbDate } from './ngb-date';\nexport { NgbDateAdapter, NgbDateStructAdapter } from './adapters/ngb-date-adapter';\nexport { NgbDateNativeAdapter } from './adapters/ngb-date-native-adapter';\nexport { NgbDateNativeUTCAdapter } from './adapters/ngb-date-native-utc-adapter';\nexport { NgbDateParserFormatter } from './ngb-date-parser-formatter';\nexport { NgbDatepickerKeyboardService } from './datepicker-keyboard-service';\n\nconst NGB_DATEPICKER_DIRECTIVES = [NgbDatepicker, NgbDatepickerContent, NgbInputDatepicker, NgbDatepickerMonth];\n\n@NgModule({\n\texports: NGB_DATEPICKER_DIRECTIVES,\n\timports: NGB_DATEPICKER_DIRECTIVES,\n})\nexport class NgbDatepickerModule {}\n","import { NgModule } from '@angular/core';\nimport { NgbDropdown, NgbDropdownAnchor, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem } from './dropdown';\n\nexport {\n\tNgbDropdown,\n\tNgbDropdownAnchor,\n\tNgbDropdownToggle,\n\tNgbDropdownMenu,\n\tNgbDropdownItem,\n\t// eslint-disable-next-line deprecation/deprecation\n\tNgbNavbar,\n} from './dropdown';\nexport { NgbDropdownConfig } from './dropdown-config';\n\nconst NGB_DROPDOWN_DIRECTIVES = [NgbDropdown, NgbDropdownAnchor, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem];\n\n@NgModule({\n\timports: NGB_DROPDOWN_DIRECTIVES,\n\texports: NGB_DROPDOWN_DIRECTIVES,\n})\nexport class NgbDropdownModule {}\n","import {\n\tApplicationRef,\n\tComponentRef,\n\tInjector,\n\tNgZone,\n\tRenderer2,\n\tTemplateRef,\n\tType,\n\tViewContainerRef,\n\tViewRef,\n} from '@angular/core';\n\nimport { Observable, of } from 'rxjs';\nimport { mergeMap, take, tap } from 'rxjs/operators';\n\nimport { ngbRunTransition } from './transition/ngbTransition';\n\nexport class ContentRef {\n\tconstructor(public nodes: Node[][], public viewRef?: ViewRef, public componentRef?: ComponentRef<any>) {}\n}\n\nexport class PopupService<T> {\n\tprivate _windowRef: ComponentRef<T> | null = null;\n\tprivate _contentRef: ContentRef | null = null;\n\n\tconstructor(\n\t\tprivate _componentType: Type<any>,\n\t\tprivate _injector: Injector,\n\t\tprivate _viewContainerRef: ViewContainerRef,\n\t\tprivate _renderer: Renderer2,\n\t\tprivate _ngZone: NgZone,\n\t\tprivate _applicationRef: ApplicationRef,\n\t) {}\n\n\topen(\n\t\tcontent?: string | TemplateRef<any>,\n\t\ttemplateContext?: any,\n\t\tanimation = false,\n\t): { windowRef: ComponentRef<T>; transition$: Observable<void> } {\n\t\tif (!this._windowRef) {\n\t\t\tthis._contentRef = this._getContentRef(content, templateContext);\n\t\t\tthis._windowRef = this._viewContainerRef.createComponent(this._componentType, {\n\t\t\t\tinjector: this._injector,\n\t\t\t\tprojectableNodes: this._contentRef.nodes,\n\t\t\t});\n\t\t}\n\n\t\tconst { nativeElement } = this._windowRef.location;\n\t\tconst transition$ = this._ngZone.onStable.pipe(\n\t\t\ttake(1),\n\t\t\tmergeMap(() =>\n\t\t\t\tngbRunTransition(this._ngZone, nativeElement, ({ classList }) => classList.add('show'), {\n\t\t\t\t\tanimation,\n\t\t\t\t\trunningTransition: 'continue',\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\n\t\treturn { windowRef: this._windowRef, transition$ };\n\t}\n\n\tclose(animation = false): Observable<void> {\n\t\tif (!this._windowRef) {\n\t\t\treturn of(undefined);\n\t\t}\n\n\t\treturn ngbRunTransition(\n\t\t\tthis._ngZone,\n\t\t\tthis._windowRef.location.nativeElement,\n\t\t\t({ classList }) => classList.remove('show'),\n\t\t\t{ animation, runningTransition: 'stop' },\n\t\t).pipe(\n\t\t\ttap(() => {\n\t\t\t\tif (this._windowRef) {\n\t\t\t\t\t// this is required because of the container='body' option\n\t\t\t\t\tthis._viewContainerRef.remove(this._viewContainerRef.indexOf(this._windowRef.hostView));\n\t\t\t\t\tthis._windowRef = null;\n\t\t\t\t}\n\t\t\t\tif (this._contentRef?.viewRef) {\n\t\t\t\t\tthis._applicationRef.detachView(this._contentRef.viewRef);\n\t\t\t\t\tthis._contentRef.viewRef.destroy();\n\t\t\t\t\tthis._contentRef = null;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate _getContentRef(content?: string | TemplateRef<any>, templateContext?: any): ContentRef {\n\t\tif (!content) {\n\t\t\treturn new ContentRef([]);\n\t\t} else if (content instanceof TemplateRef) {\n\t\t\tconst viewRef = content.createEmbeddedView(templateContext);\n\t\t\tthis._applicationRef.attachView(viewRef);\n\t\t\treturn new ContentRef([viewRef.rootNodes], viewRef);\n\t\t} else {\n\t\t\treturn new ContentRef([[this._renderer.createText(`${content}`)]]);\n\t\t}\n\t}\n}\n","import { Component, ElementRef, Input, NgZone, OnInit, ViewEncapsulation } from '@angular/core';\n\nimport { Observable } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\nimport { ngbRunTransition } from '../util/transition/ngbTransition';\nimport { reflow } from '../util/util';\n\n@Component({\n\tselector: 'ngb-modal-backdrop',\n\tstandalone: true,\n\tencapsulation: ViewEncapsulation.None,\n\ttemplate: '',\n\thost: {\n\t\t'[class]': '\"modal-backdrop\" + (backdropClass ? \" \" + backdropClass : \"\")',\n\t\t'[class.show]': '!animation',\n\t\t'[class.fade]': 'animation',\n\t\tstyle: 'z-index: 1055',\n\t},\n})\nexport class NgbModalBackdrop implements OnInit {\n\t@Input() animation: boolean;\n\t@Input() backdropClass: string;\n\n\tconstructor(private _el: ElementRef<HTMLElement>, private _zone: NgZone) {}\n\n\tngOnInit() {\n\t\tthis._zone.onStable\n\t\t\t.asObservable()\n\t\t\t.pipe(take(1))\n\t\t\t.subscribe(() => {\n\t\t\t\tngbRunTransition(\n\t\t\t\t\tthis._zone,\n\t\t\t\t\tthis._el.nativeElement,\n\t\t\t\t\t(element: HTMLElement, animation: boolean) => {\n\t\t\t\t\t\tif (animation) {\n\t\t\t\t\t\t\treflow(element);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telement.classList.add('show');\n\t\t\t\t\t},\n\t\t\t\t\t{ animation: this.animation, runningTransition: 'continue' },\n\t\t\t\t);\n\t\t\t});\n\t}\n\n\thide(): Observable<void> {\n\t\treturn ngbRunTransition(this._zone, this._el.nativeElement, ({ classList }) => classList.remove('show'), {\n\t\t\tanimation: this.animation,\n\t\t\trunningTransition: 'stop',\n\t\t});\n\t}\n}\n","import { ComponentRef } from '@angular/core';\n\nimport { Observable, of, Subject, zip } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nimport { NgbModalBackdrop } from './modal-backdrop';\nimport { NgbModalWindow } from './modal-window';\nimport { NgbModalOptions, NgbModalUpdatableOptions } from './modal-config';\nimport { isDefined } from '../util/util';\n\nimport { ContentRef } from '../util/popup';\nimport { isPromise } from '../util/util';\n\n/**\n * A reference to the currently opened (active) modal.\n *\n * Instances of this class can be injected into your component passed as modal content.\n * So you can `.update()`, `.close()` or `.dismiss()` the modal window from your component.\n */\nexport class NgbActiveModal {\n\t/**\n\t * Updates options of an opened modal.\n\t *\n\t * @since 14.2.0\n\t */\n\tupdate(options: NgbModalUpdatableOptions): void {}\n\t/**\n\t * Closes the modal with an optional `result` value.\n\t *\n\t * The `NgbModalRef.result` promise will be resolved with the provided value.\n\t */\n\tclose(result?: any): void {}\n\n\t/**\n\t * Dismisses the modal with an optional `reason` value.\n\t *\n\t * The `NgbModalRef.result` promise will be rejected with the provided value.\n\t */\n\tdismiss(reason?: any): void {}\n}\n\nconst WINDOW_ATTRIBUTES: string[] = [\n\t'animation',\n\t'ariaLabelledBy',\n\t'ariaDescribedBy',\n\t'backdrop',\n\t'centered',\n\t'fullscreen',\n\t'keyboard',\n\t'scrollable',\n\t'size',\n\t'windowClass',\n\t'modalDialogClass',\n];\nconst BACKDROP_ATTRIBUTES: string[] = ['animation', 'backdropClass'];\n\n/**\n * A reference to the newly opened modal returned by the `NgbModal.open()` method.\n */\nexport class NgbModalRef {\n\tprivate _closed = new Subject<any>();\n\tprivate _dismissed = new Subject<any>();\n\tprivate _hidden = new Subject<void>();\n\tprivate _resolve: (result?: any) => void;\n\tprivate _reject: (reason?: any) => void;\n\n\tprivate _applyWindowOptions(windowInstance: NgbModalWindow, options: NgbModalOptions): void {\n\t\tWINDOW_ATTRIBUTES.forEach((optionName: string) => {\n\t\t\tif (isDefined(options[optionName])) {\n\t\t\t\twindowInstance[optionName] = options[optionName];\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate _applyBackdropOptions(backdropInstance: NgbModalBackdrop, options: NgbModalOptions): void {\n\t\tBACKDROP_ATTRIBUTES.forEach((optionName: string) => {\n\t\t\tif (isDefined(options[optionName])) {\n\t\t\t\tbackdropInstance[optionName] = options[optionName];\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Updates options of an opened modal.\n\t *\n\t * @since 14.2.0\n\t */\n\tupdate(options: NgbModalUpdatableOptions): void {\n\t\tthis._applyWindowOptions(this._windowCmptRef.instance, options);\n\t\tif (this._backdropCmptRef && this._backdropCmptRef.instance) {\n\t\t\tthis._applyBackdropOptions(this._backdropCmptRef.instance, options);\n\t\t}\n\t}\n\n\t/**\n\t * The instance of a component used for the modal content.\n\t *\n\t * When a `TemplateRef` is used as the content or when the modal is closed, will return `undefined`.\n\t */\n\tget componentInstance(): any {\n\t\tif (this._contentRef && this._contentRef.componentRef) {\n\t\t\treturn this._contentRef.componentRef.instance;\n\t\t}\n\t}\n\n\t/**\n\t * The promise that is resolved when the modal is closed and rejected when the modal is dismissed.\n\t */\n\tresult: Promise<any>;\n\n\t/**\n\t * The observable that emits when the modal is closed via the `.close()` method.\n\t *\n\t * It will emit the result passed to the `.close()` method.\n\t *\n\t * @since 8.0.0\n\t */\n\tget closed(): Observable<any> {\n\t\treturn this._closed.asObservable().pipe(takeUntil(this._hidden));\n\t}\n\n\t/**\n\t * The observable that emits when the modal is dismissed via the `.dismiss()` method.\n\t *\n\t * It will emit the reason passed to the `.dismissed()` method by the user, or one of the internal\n\t * reasons like backdrop click or ESC key press.\n\t *\n\t * @since 8.0.0\n\t */\n\tget dismissed(): Observable<any> {\n\t\treturn this._dismissed.asObservable().pipe(takeUntil(this._hidden));\n\t}\n\n\t/**\n\t * The observable that emits when both modal window and backdrop are closed and animations were finished.\n\t * At this point modal and backdrop elements will be removed from the DOM tree.\n\t *\n\t * This observable will be completed after emitting.\n\t *\n\t * @since 8.0.0\n\t */\n\tget hidden(): Observable<void> {\n\t\treturn this._hidden.asObservable();\n\t}\n\n\t/**\n\t * The observable that emits when modal is fully visible and animation was finished.\n\t * Modal DOM element is always available synchronously after calling 'modal.open()' service.\n\t *\n\t * This observable will be completed after emitting.\n\t * It will not emit, if modal is closed before open animation is finished.\n\t *\n\t * @since 8.0.0\n\t */\n\tget shown(): Observable<void> {\n\t\treturn this._windowCmptRef.instance.shown.asObservable();\n\t}\n\n\tconstructor(\n\t\tprivate _windowCmptRef: ComponentRef<NgbModalWindow>,\n\t\tprivate _contentRef: ContentRef,\n\t\tprivate _backdropCmptRef?: ComponentRef<NgbModalBackdrop>,\n\t\tprivate _beforeDismiss?: () => boolean | Promise<boolean>,\n\t) {\n\t\t_windowCmptRef.instance.dismissEvent.subscribe((reason: any) => {\n\t\t\tthis.dismiss(reason);\n\t\t});\n\n\t\tthis.result = new Promise((resolve, reject) => {\n\t\t\tthis._resolve = resolve;\n\t\t\tthis._reject = reject;\n\t\t});\n\t\tthis.result.then(null, () => {});\n\t}\n\n\t/**\n\t * Closes the modal with an optional `result` value.\n\t *\n\t * The `NgbMobalRef.result` promise will be resolved with the provided value.\n\t */\n\tclose(result?: any): void {\n\t\tif (this._windowCmptRef) {\n\t\t\tthis._closed.next(result);\n\t\t\tthis._resolve(result);\n\t\t\tthis._removeModalElements();\n\t\t}\n\t}\n\n\tprivate _dismiss(reason?: any) {\n\t\tthis._dismissed.next(reason);\n\t\tthis._reject(reason);\n\t\tthis._removeModalElements();\n\t}\n\n\t/**\n\t * Dismisses the modal with an optional `reason` value.\n\t *\n\t * The `NgbModalRef.result` promise will be rejected with the provided value.\n\t */\n\tdismiss(reason?: any): void {\n\t\tif (this._windowCmptRef) {\n\t\t\tif (!this._beforeDismiss) {\n\t\t\t\tthis._dismiss(reason);\n\t\t\t} else {\n\t\t\t\tconst dismiss = this._beforeDismiss();\n\t\t\t\tif (isPromise(dismiss)) {\n\t\t\t\t\tdismiss.then(\n\t\t\t\t\t\t(result) => {\n\t\t\t\t\t\t\tif (result !== false) {\n\t\t\t\t\t\t\t\tthis._dismiss(reason);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => {},\n\t\t\t\t\t);\n\t\t\t\t} else if (dismiss !== false) {\n\t\t\t\t\tthis._dismiss(reason);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _removeModalElements() {\n\t\tconst windowTransition$ = this._windowCmptRef.instance.hide();\n\t\tconst backdropTransition$ = this._backdropCmptRef ? this._backdropCmptRef.instance.hide() : of(undefined);\n\n\t\t// hiding window\n\t\twindowTransition$.subscribe(() => {\n\t\t\tconst { nativeElement } = this._windowCmptRef.location;\n\t\t\tnativeElement.parentNode.removeChild(nativeElement);\n\t\t\tthis._windowCmptRef.destroy();\n\n\t\t\tif (this._contentRef && this._contentRef.viewRef) {\n\t\t\t\tthis._contentRef.viewRef.destroy();\n\t\t\t}\n\n\t\t\tthis._windowCmptRef = <any>null;\n\t\t\tthis._contentRef = <any>null;\n\t\t});\n\n\t\t// hiding backdrop\n\t\tbackdropTransition$.subscribe(() => {\n\t\t\tif (this._backdropCmptRef) {\n\t\t\t\tconst { nativeElement } = this._backdropCmptRef.location;\n\t\t\t\tnativeElement.parentNode.removeChild(nativeElement);\n\t\t\t\tthis._backdropCmptRef.destroy();\n\t\t\t\tthis._backdropCmptRef = <any>null;\n\t\t\t}\n\t\t});\n\n\t\t// all done\n\t\tzip(windowTransition$, backdropTransition$).subscribe(() => {\n\t\t\tthis._hidden.next();\n\t\t\tthis._hidden.complete();\n\t\t});\n\t}\n}\n","export enum ModalDismissReasons {\n\tBACKDROP_CLICK,\n\tESC,\n}\n","import { DOCUMENT } from '@angular/common';\nimport {\n\tComponent,\n\tElementRef,\n\tEventEmitter,\n\tInject,\n\tInput,\n\tNgZone,\n\tOnDestroy,\n\tOnInit,\n\tOutput,\n\tViewChild,\n\tViewEncapsulation,\n} from '@angular/core';\n\nimport { fromEvent, Observable, Subject, zip } from 'rxjs';\nimport { filter, switchMap, take, takeUntil, tap } from 'rxjs/operators';\n\nimport { getFocusableBoundaryElements } from '../util/focus-trap';\nimport { Key } from '../util/key';\nimport { ModalDismissReasons } from './modal-dismiss-reasons';\nimport { ngbRunTransition, NgbTransitionOptions } from '../util/transition/ngbTransition';\nimport { isString, reflow } from '../util/util';\n\n@Component({\n\tselector: 'ngb-modal-window',\n\tstandalone: true,\n\thost: {\n\t\t'[class]': '\"modal d-block\" + (windowClass ? \" \" + windowClass : \"\")',\n\t\t'[class.fade]': 'animation',\n\t\trole: 'dialog',\n\t\ttabindex: '-1',\n\t\t'[attr.aria-modal]': 'true',\n\t\t'[attr.aria-labelledby]': 'ariaLabelledBy',\n\t\t'[attr.aria-describedby]': 'ariaDescribedBy',\n\t},\n\ttemplate: `\n\t\t<div\n\t\t\t#dialog\n\t\t\t[class]=\"\n\t\t\t\t'modal-dialog' +\n\t\t\t\t(size ? ' modal-' + size : '') +\n\t\t\t\t(centered ? ' modal-dialog-centered' : '') +\n\t\t\t\tfullscreenClass +\n\t\t\t\t(scrollable ? ' modal-dialog-scrollable' : '') +\n\t\t\t\t(modalDialogClass ? ' ' + modalDialogClass : '')\n\t\t\t\"\n\t\t\trole=\"document\"\n\t\t>\n\t\t\t<div class=\"modal-content\"><ng-content></ng-content></div>\n\t\t</div>\n\t`,\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./modal.scss'],\n})\nexport class NgbModalWindow implements OnInit, OnDestroy {\n\tprivate _closed$ = new Subject<void>();\n\tprivate _elWithFocus: Element | null = null; // element that is focused prior to modal opening\n\n\t@ViewChild('dialog', { static: true }) private _dialogEl: ElementRef<HTMLElement>;\n\n\t@Input() animation: boolean;\n\t@Input() ariaLabelledBy: string;\n\t@Input() ariaDescribedBy: string;\n\t@Input() backdrop: boolean | string = true;\n\t@Input() centered: string;\n\t@Input() fullscreen: string | boolean;\n\t@Input() keyboard = true;\n\t@Input() scrollable: string;\n\t@Input() size: string;\n\t@Input() windowClass: string;\n\t@Input() modalDialogClass: string;\n\n\t@Output('dismiss') dismissEvent = new EventEmitter();\n\n\tshown = new Subject<void>();\n\thidden = new Subject<void>();\n\n\tconstructor(\n\t\t@Inject(DOCUMENT) private _document: any,\n\t\tprivate _elRef: ElementRef<HTMLElement>,\n\t\tprivate _zone: NgZone,\n\t) {}\n\n\tget fullscreenClass(): string {\n\t\treturn this.fullscreen === true\n\t\t\t? ' modal-fullscreen'\n\t\t\t: isString(this.fullscreen)\n\t\t\t? ` modal-fullscreen-${this.fullscreen}-down`\n\t\t\t: '';\n\t}\n\n\tdismiss(reason): void {\n\t\tthis.dismissEvent.emit(reason);\n\t}\n\n\tngOnInit() {\n\t\tthis._elWithFocus = this._document.activeElement;\n\t\tthis._zone.onStable\n\t\t\t.asObservable()\n\t\t\t.pipe(take(1))\n\t\t\t.subscribe(() => {\n\t\t\t\tthis._show();\n\t\t\t});\n\t}\n\n\tngOnDestroy() {\n\t\tthis._disableEventHandling();\n\t}\n\n\thide(): Observable<any> {\n\t\tconst { nativeElement } = this._elRef;\n\t\tconst context: NgbTransitionOptions<any> = { animation: this.animation, runningTransition: 'stop' };\n\n\t\tconst windowTransition$ = ngbRunTransition(\n\t\t\tthis._zone,\n\t\t\tnativeElement,\n\t\t\t() => nativeElement.classList.remove('show'),\n\t\t\tcontext,\n\t\t);\n\t\tconst dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => {}, context);\n\n\t\tconst transitions$ = zip(windowTransition$, dialogTransition$);\n\t\ttransitions$.subscribe(() => {\n\t\t\tthis.hidden.next();\n\t\t\tthis.hidden.complete();\n\t\t});\n\n\t\tthis._disableEventHandling();\n\t\tthis._restoreFocus();\n\n\t\treturn transitions$;\n\t}\n\n\tprivate _show() {\n\t\tconst context: NgbTransitionOptions<any> = { animation: this.animation, runningTransition: 'continue' };\n\n\t\tconst windowTransition$ = ngbRunTransition(\n\t\t\tthis._zone,\n\t\t\tthis._elRef.nativeElement,\n\t\t\t(element: HTMLElement, animation: boolean) => {\n\t\t\t\tif (animation) {\n\t\t\t\t\treflow(element);\n\t\t\t\t}\n\t\t\t\telement.classList.add('show');\n\t\t\t},\n\t\t\tcontext,\n\t\t);\n\t\tconst dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => {}, context);\n\n\t\tzip(windowTransition$, dialogTransition$).subscribe(() => {\n\t\t\tthis.shown.next();\n\t\t\tthis.shown.complete();\n\t\t});\n\n\t\tthis._enableEventHandling();\n\t\tthis._setFocus();\n\t}\n\n\tprivate _enableEventHandling() {\n\t\tconst { nativeElement } = this._elRef;\n\t\tthis._zone.runOutsideAngular(() => {\n\t\t\tfromEvent<KeyboardEvent>(nativeElement, 'keydown')\n\t\t\t\t.pipe(\n\t\t\t\t\ttakeUntil(this._closed$),\n\t\t\t\t\t/* eslint-disable-next-line deprecation/deprecation */\n\t\t\t\t\tfilter((e) => e.which === Key.Escape),\n\t\t\t\t)\n\t\t\t\t.subscribe((event) => {\n\t\t\t\t\tif (this.keyboard) {\n\t\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\t\tif (!event.defaultPrevented) {\n\t\t\t\t\t\t\t\tthis._zone.run(() => this.dismiss(ModalDismissReasons.ESC));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (this.backdrop === 'static') {\n\t\t\t\t\t\tthis._bumpBackdrop();\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t// We're listening to 'mousedown' and 'mouseup' to prevent modal from closing when pressing the mouse\n\t\t\t// inside the modal dialog and releasing it outside\n\t\t\tlet preventClose = false;\n\t\t\tfromEvent<MouseEvent>(this._dialogEl.nativeElement, 'mousedown')\n\t\t\t\t.pipe(\n\t\t\t\t\ttakeUntil(this._closed$),\n\t\t\t\t\ttap(() => (preventClose = false)),\n\t\t\t\t\tswitchMap(() => fromEvent<MouseEvent>(nativeElement, 'mouseup').pipe(takeUntil(this._closed$), take(1))),\n\t\t\t\t\tfilter(({ target }) => nativeElement === target),\n\t\t\t\t)\n\t\t\t\t.subscribe(() => {\n\t\t\t\t\tpreventClose = true;\n\t\t\t\t});\n\n\t\t\t// We're listening to 'click' to dismiss modal on modal window click, except when:\n\t\t\t// 1. clicking on modal dialog itself\n\t\t\t// 2. closing was prevented by mousedown/up handlers\n\t\t\t// 3. clicking on scrollbar when the viewport is too small and modal doesn't fit (click is not triggered at all)\n\t\t\tfromEvent<MouseEvent>(nativeElement, 'click')\n\t\t\t\t.pipe(takeUntil(this._closed$))\n\t\t\t\t.subscribe(({ target }) => {\n\t\t\t\t\tif (nativeElement === target) {\n\t\t\t\t\t\tif (this.backdrop === 'static') {\n\t\t\t\t\t\t\tthis._bumpBackdrop();\n\t\t\t\t\t\t} else if (this.backdrop === true && !preventClose) {\n\t\t\t\t\t\t\tthis._zone.run(() => this.dismiss(ModalDismissReasons.BACKDROP_CLICK));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tpreventClose = false;\n\t\t\t\t});\n\t\t});\n\t}\n\n\tprivate _disableEventHandling() {\n\t\tthis._closed$.next();\n\t}\n\n\tprivate _setFocus() {\n\t\tconst { nativeElement } = this._elRef;\n\t\tif (!nativeElement.contains(document.activeElement)) {\n\t\t\tconst autoFocusable = nativeElement.querySelector(`[ngbAutofocus]`) as HTMLElement;\n\t\t\tconst firstFocusable = getFocusableBoundaryElements(nativeElement)[0];\n\n\t\t\tconst elementToFocus = autoFocusable || firstFocusable || nativeElement;\n\t\t\telementToFocus.focus();\n\t\t}\n\t}\n\n\tprivate _restoreFocus() {\n\t\tconst body = this._document.body;\n\t\tconst elWithFocus = this._elWithFocus;\n\n\t\tlet elementToFocus;\n\t\tif (elWithFocus && elWithFocus['focus'] && body.contains(elWithFocus)) {\n\t\t\telementToFocus = elWithFocus;\n\t\t} else {\n\t\t\telementToFocus = body;\n\t\t}\n\t\tthis._zone.runOutsideAngular(() => {\n\t\t\tsetTimeout(() => elementToFocus.focus());\n\t\t\tthis._elWithFocus = null;\n\t\t});\n\t}\n\n\tprivate _bumpBackdrop() {\n\t\tif (this.backdrop === 'static') {\n\t\t\tngbRunTransition(\n\t\t\t\tthis._zone,\n\t\t\t\tthis._elRef.nativeElement,\n\t\t\t\t({ classList }) => {\n\t\t\t\t\tclassList.add('modal-static');\n\t\t\t\t\treturn () => classList.remove('modal-static');\n\t\t\t\t},\n\t\t\t\t{ animation: this.animation, runningTransition: 'continue' },\n\t\t\t);\n\t\t}\n\t}\n}\n","import { Injectable, Inject } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\n/** Type for the callback used to revert the scrollbar. */\nexport type ScrollbarReverter = () => void;\n\n/**\n * Utility to handle the scrollbar.\n *\n * It allows to hide the scrollbar and compensate the lack of a vertical scrollbar\n * by adding an equivalent padding on the right of the body, and to revert this change.\n */\n@Injectable({ providedIn: 'root' })\nexport class ScrollBar {\n\tconstructor(@Inject(DOCUMENT) private _document: any) {}\n\n\t/**\n\t * To be called to hide a potential vertical scrollbar:\n\t * - if a scrollbar is there and has a width greater than 0, adds some compensation\n\t * padding to the body to keep the same layout as when the scrollbar is there\n\t * - adds overflow: hidden\n\t *\n\t * @return a callback used to revert the change\n\t */\n\thide(): ScrollbarReverter {\n\t\tconst scrollbarWidth = Math.abs(window.innerWidth - this._document.documentElement.clientWidth);\n\t\tconst body = this._document.body;\n\t\tconst bodyStyle = body.style;\n\t\tconst { overflow, paddingRight } = bodyStyle;\n\t\tif (scrollbarWidth > 0) {\n\t\t\tconst actualPadding = parseFloat(window.getComputedStyle(body).paddingRight);\n\t\t\tbodyStyle.paddingRight = `${actualPadding + scrollbarWidth}px`;\n\t\t}\n\t\tbodyStyle.overflow = 'hidden';\n\t\treturn () => {\n\t\t\tif (scrollbarWidth > 0) {\n\t\t\t\tbodyStyle.paddingRight = paddingRight;\n\t\t\t}\n\t\t\tbodyStyle.overflow = overflow;\n\t\t};\n\t}\n}\n","import { DOCUMENT } from '@angular/common';\nimport {\n\tApplicationRef,\n\tComponentRef,\n\tcreateComponent,\n\tEnvironmentInjector,\n\tEventEmitter,\n\tInject,\n\tInjectable,\n\tInjector,\n\tNgZone,\n\tRendererFactory2,\n\tTemplateRef,\n\tType,\n} from '@angular/core';\nimport { Subject } from 'rxjs';\n\nimport { ngbFocusTrap } from '../util/focus-trap';\nimport { ContentRef } from '../util/popup';\nimport { ScrollBar } from '../util/scrollbar';\nimport { isDefined, isString } from '../util/util';\nimport { NgbModalBackdrop } from './modal-backdrop';\nimport { NgbModalOptions, NgbModalUpdatableOptions } from './modal-config';\nimport { NgbActiveModal, NgbModalRef } from './modal-ref';\nimport { NgbModalWindow } from './modal-window';\nimport { take } from 'rxjs/operators';\n\n@Injectable({ providedIn: 'root' })\nexport class NgbModalStack {\n\tprivate _activeWindowCmptHasChanged = new Subject<void>();\n\tprivate _ariaHiddenValues: Map<Element, string | null> = new Map();\n\tprivate _scrollBarRestoreFn: null | (() => void) = null;\n\tprivate _modalRefs: NgbModalRef[] = [];\n\tprivate _windowCmpts: ComponentRef<NgbModalWindow>[] = [];\n\tprivate _activeInstances: EventEmitter<NgbModalRef[]> = new EventEmitter();\n\n\tconstructor(\n\t\tprivate _applicationRef: ApplicationRef,\n\t\tprivate _injector: Injector,\n\t\tprivate _environmentInjector: EnvironmentInjector,\n\t\t@Inject(DOCUMENT) private _document: any,\n\t\tprivate _scrollBar: ScrollBar,\n\t\tprivate _rendererFactory: RendererFactory2,\n\t\tprivate _ngZone: NgZone,\n\t) {\n\t\t// Trap focus on active WindowCmpt\n\t\tthis._activeWindowCmptHasChanged.subscribe(() => {\n\t\t\tif (this._windowCmpts.length) {\n\t\t\t\tconst activeWindowCmpt = this._windowCmpts[this._windowCmpts.length - 1];\n\t\t\t\tngbFocusTrap(this._ngZone, activeWindowCmpt.location.nativeElement, this._activeWindowCmptHasChanged);\n\t\t\t\tthis._revertAriaHidden();\n\t\t\t\tthis._setAriaHidden(activeWindowCmpt.location.nativeElement);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate _restoreScrollBar() {\n\t\tconst scrollBarRestoreFn = this._scrollBarRestoreFn;\n\t\tif (scrollBarRestoreFn) {\n\t\t\tthis._scrollBarRestoreFn = null;\n\t\t\tscrollBarRestoreFn();\n\t\t}\n\t}\n\n\tprivate _hideScrollBar() {\n\t\tif (!this._scrollBarRestoreFn) {\n\t\t\tthis._scrollBarRestoreFn = this._scrollBar.hide();\n\t\t}\n\t}\n\n\topen(contentInjector: Injector, content: any, options: NgbModalOptions): NgbModalRef {\n\t\tconst containerEl =\n\t\t\toptions.container instanceof HTMLElement\n\t\t\t\t? options.container\n\t\t\t\t: isDefined(options.container)\n\t\t\t\t? this._document.querySelector(options.container)\n\t\t\t\t: this._document.body;\n\t\tconst renderer = this._rendererFactory.createRenderer(null, null);\n\n\t\tif (!containerEl) {\n\t\t\tthrow new Error(`The specified modal container \"${options.container || 'body'}\" was not found in the DOM.`);\n\t\t}\n\n\t\tthis._hideScrollBar();\n\n\t\tconst activeModal = new NgbActiveModal();\n\n\t\tcontentInjector = options.injector || contentInjector;\n\t\tconst environmentInjector = contentInjector.get(EnvironmentInjector, null) || this._environmentInjector;\n\t\tconst contentRef = this._getContentRef(contentInjector, environmentInjector, content, activeModal, options);\n\n\t\tlet backdropCmptRef: ComponentRef<NgbModalBackdrop> | undefined =\n\t\t\toptions.backdrop !== false ? this._attachBackdrop(containerEl) : undefined;\n\t\tlet windowCmptRef: ComponentRef<NgbModalWindow> = this._attachWindowComponent(containerEl, contentRef.nodes);\n\t\tlet ngbModalRef: NgbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);\n\n\t\tthis._registerModalRef(ngbModalRef);\n\t\tthis._registerWindowCmpt(windowCmptRef);\n\n\t\t// We have to cleanup DOM after the last modal when BOTH 'hidden' was emitted and 'result' promise was resolved:\n\t\t// - with animations OFF, 'hidden' emits synchronously, then 'result' is resolved asynchronously\n\t\t// - with animations ON, 'result' is resolved asynchronously, then 'hidden' emits asynchronously\n\t\tngbModalRef.hidden.pipe(take(1)).subscribe(() =>\n\t\t\tPromise.resolve(true).then(() => {\n\t\t\t\tif (!this._modalRefs.length) {\n\t\t\t\t\trenderer.removeClass(this._document.body, 'modal-open');\n\t\t\t\t\tthis._restoreScrollBar();\n\t\t\t\t\tthis._revertAriaHidden();\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\n\t\tactiveModal.close = (result: any) => {\n\t\t\tngbModalRef.close(result);\n\t\t};\n\t\tactiveModal.dismiss = (reason: any) => {\n\t\t\tngbModalRef.dismiss(reason);\n\t\t};\n\n\t\tactiveModal.update = (options: NgbModalUpdatableOptions) => {\n\t\t\tngbModalRef.update(options);\n\t\t};\n\n\t\tngbModalRef.update(options);\n\t\tif (this._modalRefs.length === 1) {\n\t\t\trenderer.addClass(this._document.body, 'modal-open');\n\t\t}\n\n\t\tif (backdropCmptRef && backdropCmptRef.instance) {\n\t\t\tbackdropCmptRef.changeDetectorRef.detectChanges();\n\t\t}\n\t\twindowCmptRef.changeDetectorRef.detectChanges();\n\t\treturn ngbModalRef;\n\t}\n\n\tget activeInstances() {\n\t\treturn this._activeInstances;\n\t}\n\n\tdismissAll(reason?: any) {\n\t\tthis._modalRefs.forEach((ngbModalRef) => ngbModalRef.dismiss(reason));\n\t}\n\n\thasOpenModals(): boolean {\n\t\treturn this._modalRefs.length > 0;\n\t}\n\n\tprivate _attachBackdrop(containerEl: Element): ComponentRef<NgbModalBackdrop> {\n\t\tlet backdropCmptRef = createComponent(NgbModalBackdrop, {\n\t\t\tenvironmentInjector: this._applicationRef.injector,\n\t\t\telementInjector: this._injector,\n\t\t});\n\t\tthis._applicationRef.attachView(backdropCmptRef.hostView);\n\t\tcontainerEl.appendChild(backdropCmptRef.location.nativeElement);\n\t\treturn backdropCmptRef;\n\t}\n\n\tprivate _attachWindowComponent(containerEl: Element, projectableNodes: Node[][]): ComponentRef<NgbModalWindow> {\n\t\tlet windowCmptRef = createComponent(NgbModalWindow, {\n\t\t\tenvironmentInjector: this._applicationRef.injector,\n\t\t\telementInjector: this._injector,\n\t\t\tprojectableNodes,\n\t\t});\n\t\tthis._applicationRef.attachView(windowCmptRef.hostView);\n\t\tcontainerEl.appendChild(windowCmptRef.location.nativeElement);\n\t\treturn windowCmptRef;\n\t}\n\n\tprivate _getContentRef(\n\t\tcontentInjector: Injector,\n\t\tenvironmentInjector: EnvironmentInjector,\n\t\tcontent: Type<any> | TemplateRef<any> | string,\n\t\tactiveModal: NgbActiveModal,\n\t\toptions: NgbModalOptions,\n\t): ContentRef {\n\t\tif (!content) {\n\t\t\treturn new ContentRef([]);\n\t\t} else if (content instanceof TemplateRef) {\n\t\t\treturn this._createFromTemplateRef(content, activeModal);\n\t\t} else if (isString(content)) {\n\t\t\treturn this._createFromString(content);\n\t\t} else {\n\t\t\treturn this._createFromComponent(contentInjector, environmentInjector, content, activeModal, options);\n\t\t}\n\t}\n\n\tprivate _createFromTemplateRef(templateRef: TemplateRef<any>, activeModal: NgbActiveModal): ContentRef {\n\t\tconst context = {\n\t\t\t$implicit: activeModal,\n\t\t\tclose(result) {\n\t\t\t\tactiveModal.close(result);\n\t\t\t},\n\t\t\tdismiss(reason) {\n\t\t\t\tactiveModal.dismiss(reason);\n\t\t\t},\n\t\t};\n\t\tconst viewRef = templateRef.createEmbeddedView(context);\n\t\tthis._applicationRef.attachView(viewRef);\n\t\treturn new ContentRef([viewRef.rootNodes], viewRef);\n\t}\n\n\tprivate _createFromString(content: string): ContentRef {\n\t\tconst component = this._document.createTextNode(`${content}`);\n\t\treturn new ContentRef([[component]]);\n\t}\n\n\tprivate _createFromComponent(\n\t\tcontentInjector: Injector,\n\t\tenvironmentInjector: EnvironmentInjector,\n\t\tcomponentType: Type<any>,\n\t\tcontext: NgbActiveModal,\n\t\toptions: NgbModalOptions,\n\t): ContentRef {\n\t\tconst elementInjector = Injector.create({\n\t\t\tproviders: [{ provide: NgbActiveModal, useValue: context }],\n\t\t\tparent: contentInjector,\n\t\t});\n\t\tconst componentRef = createComponent(componentType, {\n\t\t\tenvironmentInjector,\n\t\t\telementInjector,\n\t\t});\n\t\tconst componentNativeEl = componentRef.location.nativeElement;\n\t\tif (options.scrollable) {\n\t\t\t(componentNativeEl as HTMLElement).classList.add('component-host-scrollable');\n\t\t}\n\t\tthis._applicationRef.attachView(componentRef.hostView);\n\t\t// FIXME: we should here get rid of the component nativeElement\n\t\t// and use `[Array.from(componentNativeEl.childNodes)]` instead and remove the above CSS class.\n\t\treturn new ContentRef([[componentNativeEl]], componentRef.hostView, componentRef);\n\t}\n\n\tprivate _setAriaHidden(element: Element) {\n\t\tconst parent = element.parentElement;\n\t\tif (parent && element !== this._document.body) {\n\t\t\tArray.from(parent.children).forEach((sibling) => {\n\t\t\t\tif (sibling !== element && sibling.nodeName !== 'SCRIPT') {\n\t\t\t\t\tthis._ariaHiddenValues.set(sibling, sibling.getAttribute('aria-hidden'));\n\t\t\t\t\tsibling.setAttribute('aria-hidden', 'true');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis._setAriaHidden(parent);\n\t\t}\n\t}\n\n\tprivate _revertAriaHidden() {\n\t\tthis._ariaHiddenValues.forEach((value, element) => {\n\t\t\tif (value) {\n\t\t\t\telement.setAttribute('aria-hidden', value);\n\t\t\t} else {\n\t\t\t\telement.removeAttribute('aria-hidden');\n\t\t\t}\n\t\t});\n\t\tthis._ariaHiddenValues.clear();\n\t}\n\n\tprivate _registerModalRef(ngbModalRef: NgbModalRef) {\n\t\tconst unregisterModalRef = () => {\n\t\t\tconst index = this._modalRefs.indexOf(ngbModalRef);\n\t\t\tif (index > -1) {\n\t\t\t\tthis._modalRefs.splice(index, 1);\n\t\t\t\tthis._activeInstances.emit(this._modalRefs);\n\t\t\t}\n\t\t};\n\t\tthis._modalRefs.push(ngbModalRef);\n\t\tthis._activeInstances.emit(this._modalRefs);\n\t\tngbModalRef.result.then(unregisterModalRef, unregisterModalRef);\n\t}\n\n\tprivate _registerWindowCmpt(ngbWindowCmpt: ComponentRef<NgbModalWindow>) {\n\t\tthis._windowCmpts.push(ngbWindowCmpt);\n\t\tthis._activeWindowCmptHasChanged.next();\n\n\t\tngbWindowCmpt.onDestroy(() => {\n\t\t\tconst index = this._windowCmpts.indexOf(ngbWindowCmpt);\n\t\t\tif (index > -1) {\n\t\t\t\tthis._windowCmpts.splice(index, 1);\n\t\t\t\tthis._activeWindowCmptHasChanged.next();\n\t\t\t}\n\t\t});\n\t}\n}\n","import { Injectable, Injector } from '@angular/core';\nimport { NgbConfig } from '../ngb-config';\n\n/**\n * Options available when opening new modal windows with `NgbModal.open()` method.\n */\nexport interface NgbModalOptions {\n\t/**\n\t * If `true`, modal opening and closing will be animated.\n\t *\n\t * @since 8.0.0\n\t */\n\tanimation?: boolean;\n\n\t/**\n\t * `aria-labelledby` attribute value to set on the modal window.\n\t *\n\t * @since 2.2.0\n\t */\n\tariaLabelledBy?: string;\n\n\t/**\n\t * `aria-describedby` attribute value to set on the modal window.\n\t *\n\t * @since 6.1.0\n\t */\n\tariaDescribedBy?: string;\n\n\t/**\n\t * If `true`, the backdrop element will be created for a given modal.\n\t *\n\t * Alternatively, specify `'static'` for a backdrop which doesn't close the modal on click.\n\t *\n\t * Default value is `true`.\n\t */\n\tbackdrop?: boolean | 'static';\n\n\t/**\n\t * Callback right before the modal will be dismissed.\n\t *\n\t * If this function returns:\n\t * * `false`\n\t * * a promise resolved with `false`\n\t * * a promise that is rejected\n\t *\n\t * then the modal won't be dismissed.\n\t */\n\tbeforeDismiss?: () => boolean | Promise<boolean>;\n\n\t/**\n\t * If `true`, the modal will be centered vertically.\n\t *\n\t * Default value is `false`.\n\t *\n\t * @since 1.1.0\n\t */\n\tcentered?: boolean;\n\n\t/**\n\t * A selector specifying the element all new modal windows should be appended to.\n\t * Since v5.3.0 it is also possible to pass the reference to an `HTMLElement`.\n\t *\n\t * If not specified, will be `body`.\n\t */\n\tcontainer?: string | HTMLElement;\n\n\t/**\n\t * If `true` modal will always be displayed in fullscreen mode.\n\t *\n\t * For values like `'md'` it means that modal will be displayed in fullscreen mode\n\t * only if the viewport width is below `'md'`. For custom strings (ex. when passing `'mysize'`)\n\t * it will add a `'modal-fullscreen-mysize-down'` class.\n\t *\n\t * If not specified will be `false`.\n\t *\n\t * @since 12.1.0\n\t */\n\tfullscreen?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string;\n\n\t/**\n\t * The `Injector` to use for modal content.\n\t */\n\tinjector?: Injector;\n\n\t/**\n\t * If `true`, the modal will be closed when `Escape` key is pressed\n\t *\n\t * Default value is `true`.\n\t */\n\tkeyboard?: boolean;\n\n\t/**\n\t * Scrollable modal content (false by default).\n\t *\n\t * @since 5.0.0\n\t */\n\tscrollable?: boolean;\n\n\t/**\n\t * Size of a new modal window.\n\t */\n\tsize?: 'sm' | 'lg' | 'xl' | string;\n\n\t/**\n\t * A custom class to append to the modal window.\n\t */\n\twindowClass?: string;\n\n\t/**\n\t * A custom class to append to the modal dialog.\n\t *\n\t * @since 9.1.0\n\t */\n\tmodalDialogClass?: string;\n\n\t/**\n\t * A custom class to append to the modal backdrop.\n\t *\n\t * @since 1.1.0\n\t */\n\tbackdropClass?: string;\n}\n\n/**\n * Options that can be changed on an opened modal with `NgbModalRef.update()` and `NgbActiveModal.update()` methods.\n *\n * @since 14.2.0\n */\nexport type NgbModalUpdatableOptions = Pick<\n\tNgbModalOptions,\n\t| 'ariaLabelledBy'\n\t| 'ariaDescribedBy'\n\t| 'centered'\n\t| 'fullscreen'\n\t| 'backdropClass'\n\t| 'size'\n\t| 'windowClass'\n\t| 'modalDialogClass'\n>;\n\n/**\n * A configuration service for the [`NgbModal`](#/components/modal/api#NgbModal) service.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all modals used in the application.\n *\n * @since 3.1.0\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbModalConfig implements Required<NgbModalOptions> {\n\tariaLabelledBy: string;\n\tariaDescribedBy: string;\n\tbackdrop: boolean | 'static' = true;\n\tbeforeDismiss: () => boolean | Promise<boolean>;\n\tcentered: boolean;\n\tcontainer: string | HTMLElement;\n\tfullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\tinjector: Injector;\n\tkeyboard = true;\n\tscrollable: boolean;\n\tsize: 'sm' | 'lg' | 'xl' | string;\n\twindowClass: string;\n\tmodalDialogClass: string;\n\tbackdropClass: string;\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import { Injectable, Injector } from '@angular/core';\n\nimport { NgbModalOptions, NgbModalConfig } from './modal-config';\nimport { NgbModalRef } from './modal-ref';\nimport { NgbModalStack } from './modal-stack';\n\n/**\n * A service for opening modal windows.\n *\n * Creating a modal is straightforward: create a component or a template and pass it as an argument to\n * the `.open()` method.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbModal {\n\tconstructor(private _injector: Injector, private _modalStack: NgbModalStack, private _config: NgbModalConfig) {}\n\n\t/**\n\t * Opens a new modal window with the specified content and supplied options.\n\t *\n\t * Content can be provided as a `TemplateRef` or a component type. If you pass a component type as content,\n\t * then instances of those components can be injected with an instance of the `NgbActiveModal` class. You can then\n\t * use `NgbActiveModal` methods to close / dismiss modals from \"inside\" of your component.\n\t *\n\t * Also see the [`NgbModalOptions`](#/components/modal/api#NgbModalOptions) for the list of supported options.\n\t */\n\topen(content: any, options: NgbModalOptions = {}): NgbModalRef {\n\t\tconst combinedOptions = { ...this._config, animation: this._config.animation, ...options };\n\t\treturn this._modalStack.open(this._injector, content, combinedOptions);\n\t}\n\n\t/**\n\t * Returns an observable that holds the active modal instances.\n\t */\n\tget activeInstances() {\n\t\treturn this._modalStack.activeInstances;\n\t}\n\n\t/**\n\t * Dismisses all currently displayed modal windows with the supplied reason.\n\t *\n\t * @since 3.1.0\n\t */\n\tdismissAll(reason?: any) {\n\t\tthis._modalStack.dismissAll(reason);\n\t}\n\n\t/**\n\t * Indicates if there are currently any open modal windows in the application.\n\t *\n\t * @since 3.3.0\n\t */\n\thasOpenModals(): boolean {\n\t\treturn this._modalStack.hasOpenModals();\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbModal } from './modal';\n\nexport { NgbModal } from './modal';\nexport { NgbModalConfig, NgbModalOptions, NgbModalUpdatableOptions } from './modal-config';\nexport { NgbModalRef, NgbActiveModal } from './modal-ref';\nexport { ModalDismissReasons } from './modal-dismiss-reasons';\n\n@NgModule({ providers: [NgbModal] })\nexport class NgbModalModule {}\n","import { NgbTransitionStartFn } from '../util/transition/ngbTransition';\nimport { reflow } from '../util/util';\n\nexport const ngbNavFadeOutTransition: NgbTransitionStartFn = ({ classList }) => {\n\tclassList.remove('show');\n\treturn () => classList.remove('active');\n};\n\nexport const ngbNavFadeInTransition: NgbTransitionStartFn = (element: HTMLElement, animation: boolean) => {\n\tif (animation) {\n\t\treflow(element);\n\t}\n\telement.classList.add('show');\n};\n","import {\n\tAfterViewInit,\n\tChangeDetectionStrategy,\n\tChangeDetectorRef,\n\tComponent,\n\tDirective,\n\tElementRef,\n\tInput,\n\tNgZone,\n\tQueryList,\n\tViewChildren,\n\tViewEncapsulation,\n} from '@angular/core';\nimport { distinctUntilChanged, skip, startWith, takeUntil } from 'rxjs/operators';\n\nimport { ngbNavFadeInTransition, ngbNavFadeOutTransition } from './nav-transition';\nimport { ngbRunTransition, NgbTransitionOptions } from '../util/transition/ngbTransition';\nimport { NgbNav, NgbNavItem } from './nav';\nimport { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';\n\n@Directive({\n\tselector: '[ngbNavPane]',\n\tstandalone: true,\n\thost: {\n\t\t'[id]': 'item.panelDomId',\n\t\tclass: 'tab-pane',\n\t\t'[class.fade]': 'nav.animation',\n\t\t'[attr.role]': 'role ? role : nav.roles ? \"tabpanel\" : undefined',\n\t\t'[attr.aria-labelledby]': 'item.domId',\n\t},\n})\nexport class NgbNavPane {\n\t@Input() item: NgbNavItem;\n\t@Input() nav: NgbNav;\n\t@Input() role: string;\n\n\tconstructor(public elRef: ElementRef<HTMLElement>) {}\n}\n\n/**\n * The outlet where currently active nav content will be displayed.\n *\n * @since 5.2.0\n */\n@Component({\n\tselector: '[ngbNavOutlet]',\n\tstandalone: true,\n\timports: [NgbNavPane, NgFor, NgIf, NgTemplateOutlet],\n\thost: { '[class.tab-content]': 'true' },\n\tencapsulation: ViewEncapsulation.None,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t<ng-template ngFor let-item [ngForOf]=\"nav.items\">\n\t\t\t<div\n\t\t\t\tngbNavPane\n\t\t\t\t*ngIf=\"item.isPanelInDom() || isPanelTransitioning(item)\"\n\t\t\t\t[item]=\"item\"\n\t\t\t\t[nav]=\"nav\"\n\t\t\t\t[role]=\"paneRole\"\n\t\t\t>\n\t\t\t\t<ng-template\n\t\t\t\t\t[ngTemplateOutlet]=\"item.contentTpl?.templateRef || null\"\n\t\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: item.active || isPanelTransitioning(item) }\"\n\t\t\t\t></ng-template>\n\t\t\t</div>\n\t\t</ng-template>\n\t`,\n})\nexport class NgbNavOutlet implements AfterViewInit {\n\tprivate _activePane: NgbNavPane | null = null;\n\n\t@ViewChildren(NgbNavPane) private _panes: QueryList<NgbNavPane>;\n\n\t/**\n\t * A role to set on the nav pane\n\t */\n\t@Input() paneRole;\n\n\t/**\n\t * Reference to the `NgbNav`\n\t */\n\t@Input('ngbNavOutlet') nav: NgbNav;\n\n\tconstructor(private _cd: ChangeDetectorRef, private _ngZone: NgZone) {}\n\n\tisPanelTransitioning(item: NgbNavItem) {\n\t\treturn this._activePane?.item === item;\n\t}\n\n\tngAfterViewInit() {\n\t\t// initial display\n\t\tthis._updateActivePane();\n\n\t\t// this will be emitted for all 3 types of nav changes: .select(), [activeId] or (click)\n\t\tthis.nav.navItemChange$\n\t\t\t.pipe(takeUntil(this.nav.destroy$), startWith(this._activePane?.item || null), distinctUntilChanged(), skip(1))\n\t\t\t.subscribe((nextItem) => {\n\t\t\t\tconst options: NgbTransitionOptions<undefined> = { animation: this.nav.animation, runningTransition: 'stop' };\n\n\t\t\t\t// next panel we're switching to will only appear in DOM after the change detection is done\n\t\t\t\t// and `this._panes` will be updated\n\t\t\t\tthis._cd.detectChanges();\n\n\t\t\t\t// fading out\n\t\t\t\tif (this._activePane) {\n\t\t\t\t\tngbRunTransition(\n\t\t\t\t\t\tthis._ngZone,\n\t\t\t\t\t\tthis._activePane.elRef.nativeElement,\n\t\t\t\t\t\tngbNavFadeOutTransition,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t).subscribe(() => {\n\t\t\t\t\t\tconst activeItem = this._activePane?.item;\n\t\t\t\t\t\tthis._activePane = this._getPaneForItem(nextItem);\n\n\t\t\t\t\t\t// mark for check when transition finishes as outlet or parent containers might be OnPush\n\t\t\t\t\t\t// without this the panes that have \"faded out\" will stay in DOM\n\t\t\t\t\t\tthis._cd.markForCheck();\n\n\t\t\t\t\t\t// fading in\n\t\t\t\t\t\tif (this._activePane) {\n\t\t\t\t\t\t\t// we have to add the '.active' class before running the transition,\n\t\t\t\t\t\t\t// because it should be in place before `ngbRunTransition` does `reflow()`\n\t\t\t\t\t\t\tthis._activePane.elRef.nativeElement.classList.add('active');\n\t\t\t\t\t\t\tngbRunTransition(\n\t\t\t\t\t\t\t\tthis._ngZone,\n\t\t\t\t\t\t\t\tthis._activePane.elRef.nativeElement,\n\t\t\t\t\t\t\t\tngbNavFadeInTransition,\n\t\t\t\t\t\t\t\toptions,\n\t\t\t\t\t\t\t).subscribe(() => {\n\t\t\t\t\t\t\t\tif (nextItem) {\n\t\t\t\t\t\t\t\t\tnextItem.shown.emit();\n\t\t\t\t\t\t\t\t\tthis.nav.shown.emit(nextItem.id);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (activeItem) {\n\t\t\t\t\t\t\tactiveItem.hidden.emit();\n\t\t\t\t\t\t\tthis.nav.hidden.emit(activeItem.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis._updateActivePane();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tprivate _updateActivePane() {\n\t\tthis._activePane = this._getActivePane();\n\t\tthis._activePane?.elRef.nativeElement.classList.add('show');\n\t\tthis._activePane?.elRef.nativeElement.classList.add('active');\n\t}\n\n\tprivate _getPaneForItem(item: NgbNavItem | null) {\n\t\treturn (this._panes && this._panes.find((pane) => pane.item === item)) || null;\n\t}\n\n\tprivate _getActivePane(): NgbNavPane | null {\n\t\treturn (this._panes && this._panes.find((pane) => pane.item.active)) || null;\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbNav, NgbNavContent, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavLinkButton, NgbNavLinkBase } from './nav';\n\nimport { NgbNavOutlet, NgbNavPane } from './nav-outlet';\n\nexport {\n\tNgbNav,\n\tNgbNavContent,\n\tNgbNavContentContext,\n\tNgbNavItem,\n\tNgbNavItemRole,\n\tNgbNavLink,\n\tNgbNavLinkButton,\n\tNgbNavLinkBase,\n\tNgbNavChangeEvent,\n} from './nav';\nexport { NgbNavOutlet, NgbNavPane } from './nav-outlet';\nexport { NgbNavConfig } from './nav-config';\n\nconst NGB_NAV_DIRECTIVES = [\n\tNgbNavContent,\n\tNgbNav,\n\tNgbNavItem,\n\tNgbNavItemRole,\n\tNgbNavLink,\n\tNgbNavLinkButton,\n\tNgbNavLinkBase,\n\tNgbNavOutlet,\n\tNgbNavPane,\n];\n\n@NgModule({\n\timports: NGB_NAV_DIRECTIVES,\n\texports: NGB_NAV_DIRECTIVES,\n})\nexport class NgbNavModule {}\n","import { Injectable } from '@angular/core';\n\n/**\n * A configuration service for the [`NgbPagination`](#/components/pagination/api#NgbPagination) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the paginations used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbPaginationConfig {\n\tdisabled = false;\n\tboundaryLinks = false;\n\tdirectionLinks = true;\n\tellipses = true;\n\tmaxSize = 0;\n\tpageSize = 10;\n\trotate = false;\n\tsize: 'sm' | 'lg' | string | null;\n}\n","import {\n\tComponent,\n\tContentChild,\n\tDirective,\n\tEventEmitter,\n\tInput,\n\tOutput,\n\tOnChanges,\n\tChangeDetectionStrategy,\n\tSimpleChanges,\n\tTemplateRef,\n} from '@angular/core';\nimport { getValueInRange, isNumber } from '../util/util';\nimport { NgbPaginationConfig } from './pagination-config';\nimport { NgFor, NgIf, NgTemplateOutlet } from '@angular/common';\n\n/**\n * A context for the\n * * `NgbPaginationFirst`\n * * `NgbPaginationPrevious`\n * * `NgbPaginationNext`\n * * `NgbPaginationLast`\n * * `NgbPaginationEllipsis`\n * * `NgbPaginationPages`\n *\n * link templates in case you want to override one.\n *\n * @since 4.1.0\n */\nexport interface NgbPaginationLinkContext {\n\t/**\n\t * Page number displayed by the current link.\n\t */\n\tcurrentPage: number;\n\n\t/**\n\t * If `true`, the current link is disabled.\n\t */\n\tdisabled: boolean;\n}\n\n/**\n * A context for the `NgbPaginationNumber` link template in case you want to override one.\n *\n * Extends `NgbPaginationLinkContext`.\n *\n * @since 4.1.0\n */\nexport interface NgbPaginationNumberContext extends NgbPaginationLinkContext {\n\t/**\n\t * The page number, displayed by the current page link.\n\t */\n\t$implicit: number;\n}\n\n/**\n * A context for the `NgbPaginationPages` pages template in case you want to override\n * the way all pages are displayed.\n *\n * @since 9.1.0\n */\nexport interface NgbPaginationPagesContext {\n\t/**\n\t * The currently selected page number.\n\t */\n\t$implicit: number;\n\n\t/**\n\t * If `true`, pagination is disabled.\n\t */\n\tdisabled: boolean;\n\n\t/**\n\t * Pages numbers that should be rendered starting with 1.\n\t */\n\tpages: number[];\n}\n\n/**\n * A directive to match the 'ellipsis' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationEllipsis]', standalone: true })\nexport class NgbPaginationEllipsis {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationLinkContext>) {}\n}\n\n/**\n * A directive to match the 'first' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationFirst]', standalone: true })\nexport class NgbPaginationFirst {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationLinkContext>) {}\n}\n\n/**\n * A directive to match the 'last' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationLast]', standalone: true })\nexport class NgbPaginationLast {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationLinkContext>) {}\n}\n\n/**\n * A directive to match the 'next' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationNext]', standalone: true })\nexport class NgbPaginationNext {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationLinkContext>) {}\n}\n\n/**\n * A directive to match the page 'number' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationNumber]', standalone: true })\nexport class NgbPaginationNumber {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationNumberContext>) {}\n}\n\n/**\n * A directive to match the 'previous' link template\n *\n * @since 4.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationPrevious]', standalone: true })\nexport class NgbPaginationPrevious {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationLinkContext>) {}\n}\n\n/**\n * A directive to match the 'pages' whole content\n *\n * @since 9.1.0\n */\n@Directive({ selector: 'ng-template[ngbPaginationPages]', standalone: true })\nexport class NgbPaginationPages {\n\tconstructor(public templateRef: TemplateRef<NgbPaginationPagesContext>) {}\n}\n\n/**\n * A component that displays page numbers and allows to customize them in several ways.\n */\n@Component({\n\tselector: 'ngb-pagination',\n\tstandalone: true,\n\timports: [NgIf, NgFor, NgTemplateOutlet],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: { role: 'navigation' },\n\ttemplate: `\n\t\t<ng-template #first><span aria-hidden=\"true\" i18n=\"@@ngb.pagination.first\">««</span></ng-template>\n\t\t<ng-template #previous><span aria-hidden=\"true\" i18n=\"@@ngb.pagination.previous\">«</span></ng-template>\n\t\t<ng-template #next><span aria-hidden=\"true\" i18n=\"@@ngb.pagination.next\">»</span></ng-template>\n\t\t<ng-template #last><span aria-hidden=\"true\" i18n=\"@@ngb.pagination.last\">»»</span></ng-template>\n\t\t<ng-template #ellipsis>...</ng-template>\n\t\t<ng-template #defaultNumber let-page let-currentPage=\"currentPage\">{{ page }}</ng-template>\n\t\t<ng-template #defaultPages let-page let-pages=\"pages\" let-disabled=\"disabled\">\n\t\t\t<li\n\t\t\t\t*ngFor=\"let pageNumber of pages\"\n\t\t\t\tclass=\"page-item\"\n\t\t\t\t[class.active]=\"pageNumber === page\"\n\t\t\t\t[class.disabled]=\"isEllipsis(pageNumber) || disabled\"\n\t\t\t\t[attr.aria-current]=\"pageNumber === page ? 'page' : null\"\n\t\t\t>\n\t\t\t\t<a *ngIf=\"isEllipsis(pageNumber)\" class=\"page-link\" tabindex=\"-1\" aria-disabled=\"true\">\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplEllipsis?.templateRef || ellipsis\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: true, currentPage: page }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t\t<a\n\t\t\t\t\t*ngIf=\"!isEllipsis(pageNumber)\"\n\t\t\t\t\tclass=\"page-link\"\n\t\t\t\t\thref\n\t\t\t\t\t(click)=\"selectPage(pageNumber); $event.preventDefault()\"\n\t\t\t\t\t[attr.tabindex]=\"disabled ? '-1' : null\"\n\t\t\t\t\t[attr.aria-disabled]=\"disabled ? 'true' : null\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplNumber?.templateRef || defaultNumber\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: disabled, $implicit: pageNumber, currentPage: page }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t</ng-template>\n\t\t<ul [class]=\"'pagination' + (size ? ' pagination-' + size : '')\">\n\t\t\t<li *ngIf=\"boundaryLinks\" class=\"page-item\" [class.disabled]=\"previousDisabled()\">\n\t\t\t\t<a\n\t\t\t\t\taria-label=\"First\"\n\t\t\t\t\ti18n-aria-label=\"@@ngb.pagination.first-aria\"\n\t\t\t\t\tclass=\"page-link\"\n\t\t\t\t\thref\n\t\t\t\t\t(click)=\"selectPage(1); $event.preventDefault()\"\n\t\t\t\t\t[attr.tabindex]=\"previousDisabled() ? '-1' : null\"\n\t\t\t\t\t[attr.aria-disabled]=\"previousDisabled() ? 'true' : null\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplFirst?.templateRef || first\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: previousDisabled(), currentPage: page }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t</li>\n\n\t\t\t<li *ngIf=\"directionLinks\" class=\"page-item\" [class.disabled]=\"previousDisabled()\">\n\t\t\t\t<a\n\t\t\t\t\taria-label=\"Previous\"\n\t\t\t\t\ti18n-aria-label=\"@@ngb.pagination.previous-aria\"\n\t\t\t\t\tclass=\"page-link\"\n\t\t\t\t\thref\n\t\t\t\t\t(click)=\"selectPage(page - 1); $event.preventDefault()\"\n\t\t\t\t\t[attr.tabindex]=\"previousDisabled() ? '-1' : null\"\n\t\t\t\t\t[attr.aria-disabled]=\"previousDisabled() ? 'true' : null\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplPrevious?.templateRef || previous\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: previousDisabled() }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t<ng-template\n\t\t\t\t[ngTemplateOutlet]=\"tplPages?.templateRef || defaultPages\"\n\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: page, pages: pages, disabled: disabled }\"\n\t\t\t>\n\t\t\t</ng-template>\n\t\t\t<li *ngIf=\"directionLinks\" class=\"page-item\" [class.disabled]=\"nextDisabled()\">\n\t\t\t\t<a\n\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\ti18n-aria-label=\"@@ngb.pagination.next-aria\"\n\t\t\t\t\tclass=\"page-link\"\n\t\t\t\t\thref\n\t\t\t\t\t(click)=\"selectPage(page + 1); $event.preventDefault()\"\n\t\t\t\t\t[attr.tabindex]=\"nextDisabled() ? '-1' : null\"\n\t\t\t\t\t[attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplNext?.templateRef || next\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: nextDisabled(), currentPage: page }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t</li>\n\n\t\t\t<li *ngIf=\"boundaryLinks\" class=\"page-item\" [class.disabled]=\"nextDisabled()\">\n\t\t\t\t<a\n\t\t\t\t\taria-label=\"Last\"\n\t\t\t\t\ti18n-aria-label=\"@@ngb.pagination.last-aria\"\n\t\t\t\t\tclass=\"page-link\"\n\t\t\t\t\thref\n\t\t\t\t\t(click)=\"selectPage(pageCount); $event.preventDefault()\"\n\t\t\t\t\t[attr.tabindex]=\"nextDisabled() ? '-1' : null\"\n\t\t\t\t\t[attr.aria-disabled]=\"nextDisabled() ? 'true' : null\"\n\t\t\t\t>\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"tplLast?.templateRef || last\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ disabled: nextDisabled(), currentPage: page }\"\n\t\t\t\t\t></ng-template>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t</ul>\n\t`,\n})\nexport class NgbPagination implements OnChanges {\n\tpageCount = 0;\n\tpages: number[] = [];\n\n\t@ContentChild(NgbPaginationEllipsis, { static: false }) tplEllipsis?: NgbPaginationEllipsis;\n\t@ContentChild(NgbPaginationFirst, { static: false }) tplFirst?: NgbPaginationFirst;\n\t@ContentChild(NgbPaginationLast, { static: false }) tplLast?: NgbPaginationLast;\n\t@ContentChild(NgbPaginationNext, { static: false }) tplNext?: NgbPaginationNext;\n\t@ContentChild(NgbPaginationNumber, { static: false }) tplNumber?: NgbPaginationNumber;\n\t@ContentChild(NgbPaginationPrevious, { static: false }) tplPrevious?: NgbPaginationPrevious;\n\t@ContentChild(NgbPaginationPages, { static: false }) tplPages?: NgbPaginationPages;\n\n\t/**\n\t * If `true`, pagination links will be disabled.\n\t */\n\t@Input() disabled: boolean;\n\n\t/**\n\t * If `true`, the \"First\" and \"Last\" page links are shown.\n\t */\n\t@Input() boundaryLinks: boolean;\n\n\t/**\n\t * If `true`, the \"Next\" and \"Previous\" page links are shown.\n\t */\n\t@Input() directionLinks: boolean;\n\n\t/**\n\t * If `true`, the ellipsis symbols and first/last page numbers will be shown when `maxSize` > number of pages.\n\t */\n\t@Input() ellipses: boolean;\n\n\t/**\n\t * Whether to rotate pages when `maxSize` > number of pages.\n\t *\n\t * The current page always stays in the middle if `true`.\n\t */\n\t@Input() rotate: boolean;\n\n\t/**\n\t * The number of items in your paginated collection.\n\t *\n\t * Note, that this is not the number of pages. Page numbers are calculated dynamically based on\n\t * `collectionSize` and `pageSize`. Ex. if you have 100 items in your collection and displaying 20 items per page,\n\t * you'll end up with 5 pages.\n\t */\n\t@Input() collectionSize: number;\n\n\t/**\n\t * The maximum number of pages to display.\n\t */\n\t@Input() maxSize: number;\n\n\t/**\n\t * The current page.\n\t *\n\t * Page numbers start with `1`.\n\t */\n\t@Input() page = 1;\n\n\t/**\n\t * The number of items per page.\n\t */\n\t@Input() pageSize: number;\n\n\t/**\n\t * An event fired when the page is changed. Will fire only if collection size is set and all values are valid.\n\t *\n\t * Event payload is the number of the newly selected page.\n\t *\n\t * Page numbers start with `1`.\n\t */\n\t@Output() pageChange = new EventEmitter<number>(true);\n\n\t/**\n\t * The pagination display size.\n\t *\n\t * Bootstrap currently supports small and large sizes.\n\t *\n\t * If the passed value is a string (ex. 'custom'), it will just add the `pagination-custom` css class\n\t */\n\t@Input() size: 'sm' | 'lg' | string | null;\n\n\tconstructor(config: NgbPaginationConfig) {\n\t\tthis.disabled = config.disabled;\n\t\tthis.boundaryLinks = config.boundaryLinks;\n\t\tthis.directionLinks = config.directionLinks;\n\t\tthis.ellipses = config.ellipses;\n\t\tthis.maxSize = config.maxSize;\n\t\tthis.pageSize = config.pageSize;\n\t\tthis.rotate = config.rotate;\n\t\tthis.size = config.size;\n\t}\n\n\thasPrevious(): boolean {\n\t\treturn this.page > 1;\n\t}\n\n\thasNext(): boolean {\n\t\treturn this.page < this.pageCount;\n\t}\n\n\tnextDisabled(): boolean {\n\t\treturn !this.hasNext() || this.disabled;\n\t}\n\n\tpreviousDisabled(): boolean {\n\t\treturn !this.hasPrevious() || this.disabled;\n\t}\n\n\tselectPage(pageNumber: number): void {\n\t\tthis._updatePages(pageNumber);\n\t}\n\n\tngOnChanges(changes: SimpleChanges): void {\n\t\tthis._updatePages(this.page);\n\t}\n\n\tisEllipsis(pageNumber): boolean {\n\t\treturn pageNumber === -1;\n\t}\n\n\t/**\n\t * Appends ellipses and first/last page number to the displayed pages\n\t */\n\tprivate _applyEllipses(start: number, end: number) {\n\t\tif (this.ellipses) {\n\t\t\tif (start > 0) {\n\t\t\t\t// The first page will always be included. If the displayed range\n\t\t\t\t// starts after the third page, then add ellipsis. But if the range\n\t\t\t\t// starts on the third page, then add the second page instead of\n\t\t\t\t// an ellipsis, because the ellipsis would only hide a single page.\n\t\t\t\tif (start > 2) {\n\t\t\t\t\tthis.pages.unshift(-1);\n\t\t\t\t} else if (start === 2) {\n\t\t\t\t\tthis.pages.unshift(2);\n\t\t\t\t}\n\t\t\t\tthis.pages.unshift(1);\n\t\t\t}\n\t\t\tif (end < this.pageCount) {\n\t\t\t\t// The last page will always be included. If the displayed range\n\t\t\t\t// ends before the third-last page, then add ellipsis. But if the range\n\t\t\t\t// ends on third-last page, then add the second-last page instead of\n\t\t\t\t// an ellipsis, because the ellipsis would only hide a single page.\n\t\t\t\tif (end < this.pageCount - 2) {\n\t\t\t\t\tthis.pages.push(-1);\n\t\t\t\t} else if (end === this.pageCount - 2) {\n\t\t\t\t\tthis.pages.push(this.pageCount - 1);\n\t\t\t\t}\n\t\t\t\tthis.pages.push(this.pageCount);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Rotates page numbers based on maxSize items visible.\n\t * Currently selected page stays in the middle:\n\t *\n\t * Ex. for selected page = 6:\n\t * [5,*6*,7] for maxSize = 3\n\t * [4,5,*6*,7] for maxSize = 4\n\t */\n\tprivate _applyRotation(): [number, number] {\n\t\tlet start = 0;\n\t\tlet end = this.pageCount;\n\t\tlet leftOffset = Math.floor(this.maxSize / 2);\n\t\tlet rightOffset = this.maxSize % 2 === 0 ? leftOffset - 1 : leftOffset;\n\n\t\tif (this.page <= leftOffset) {\n\t\t\t// very beginning, no rotation -> [0..maxSize]\n\t\t\tend = this.maxSize;\n\t\t} else if (this.pageCount - this.page < leftOffset) {\n\t\t\t// very end, no rotation -> [len-maxSize..len]\n\t\t\tstart = this.pageCount - this.maxSize;\n\t\t} else {\n\t\t\t// rotate\n\t\t\tstart = this.page - leftOffset - 1;\n\t\t\tend = this.page + rightOffset;\n\t\t}\n\n\t\treturn [start, end];\n\t}\n\n\t/**\n\t * Paginates page numbers based on maxSize items per page.\n\t */\n\tprivate _applyPagination(): [number, number] {\n\t\tlet page = Math.ceil(this.page / this.maxSize) - 1;\n\t\tlet start = page * this.maxSize;\n\t\tlet end = start + this.maxSize;\n\n\t\treturn [start, end];\n\t}\n\n\tprivate _setPageInRange(newPageNo) {\n\t\tconst prevPageNo = this.page;\n\t\tthis.page = getValueInRange(newPageNo, this.pageCount, 1);\n\n\t\tif (this.page !== prevPageNo && isNumber(this.collectionSize)) {\n\t\t\tthis.pageChange.emit(this.page);\n\t\t}\n\t}\n\n\tprivate _updatePages(newPage: number) {\n\t\tthis.pageCount = Math.ceil(this.collectionSize / this.pageSize);\n\n\t\tif (!isNumber(this.pageCount)) {\n\t\t\tthis.pageCount = 0;\n\t\t}\n\n\t\t// fill-in model needed to render pages\n\t\tthis.pages.length = 0;\n\t\tfor (let i = 1; i <= this.pageCount; i++) {\n\t\t\tthis.pages.push(i);\n\t\t}\n\n\t\t// set page within 1..max range\n\t\tthis._setPageInRange(newPage);\n\n\t\t// apply maxSize if necessary\n\t\tif (this.maxSize > 0 && this.pageCount > this.maxSize) {\n\t\t\tlet start = 0;\n\t\t\tlet end = this.pageCount;\n\n\t\t\t// either paginating or rotating page numbers\n\t\t\tif (this.rotate) {\n\t\t\t\t[start, end] = this._applyRotation();\n\t\t\t} else {\n\t\t\t\t[start, end] = this._applyPagination();\n\t\t\t}\n\n\t\t\tthis.pages = this.pages.slice(start, end);\n\n\t\t\t// adding ellipses\n\t\t\tthis._applyEllipses(start, end);\n\t\t}\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport {\n\tNgbPagination,\n\tNgbPaginationEllipsis,\n\tNgbPaginationFirst,\n\tNgbPaginationLast,\n\tNgbPaginationNext,\n\tNgbPaginationNumber,\n\tNgbPaginationPrevious,\n\tNgbPaginationPages,\n} from './pagination';\n\nexport {\n\tNgbPagination,\n\tNgbPaginationEllipsis,\n\tNgbPaginationFirst,\n\tNgbPaginationLast,\n\tNgbPaginationNext,\n\tNgbPaginationNumber,\n\tNgbPaginationPrevious,\n\tNgbPaginationPages,\n} from './pagination';\nexport { NgbPaginationConfig } from './pagination-config';\n\nconst NGB_PAGINATION_DIRECTIVES = [\n\tNgbPagination,\n\tNgbPaginationEllipsis,\n\tNgbPaginationFirst,\n\tNgbPaginationLast,\n\tNgbPaginationNext,\n\tNgbPaginationNumber,\n\tNgbPaginationPrevious,\n\tNgbPaginationPages,\n];\n\n@NgModule({\n\timports: NGB_PAGINATION_DIRECTIVES,\n\texports: NGB_PAGINATION_DIRECTIVES,\n})\nexport class NgbPaginationModule {}\n","import { Observable, merge } from 'rxjs';\nimport { share, filter, delay, map } from 'rxjs/operators';\nimport { Renderer2 } from '@angular/core';\n\nexport class Trigger {\n\tconstructor(public open: string, public close?: string) {\n\t\tif (!close) {\n\t\t\tthis.close = open;\n\t\t}\n\t}\n\n\tisManual() {\n\t\treturn this.open === 'manual' || this.close === 'manual';\n\t}\n}\n\nconst DEFAULT_ALIASES = {\n\thover: ['mouseenter', 'mouseleave'],\n\tfocus: ['focusin', 'focusout'],\n};\n\nexport function parseTriggers(triggers: string, aliases = DEFAULT_ALIASES): Trigger[] {\n\tconst trimmedTriggers = (triggers || '').trim();\n\n\tif (trimmedTriggers.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst parsedTriggers = trimmedTriggers\n\t\t.split(/\\s+/)\n\t\t.map((trigger) => trigger.split(':'))\n\t\t.map((triggerPair) => {\n\t\t\tlet alias = aliases[triggerPair[0]] || triggerPair;\n\t\t\treturn new Trigger(alias[0], alias[1]);\n\t\t});\n\n\tconst manualTriggers = parsedTriggers.filter((triggerPair) => triggerPair.isManual());\n\n\tif (manualTriggers.length > 1) {\n\t\tthrow 'Triggers parse error: only one manual trigger is allowed';\n\t}\n\n\tif (manualTriggers.length === 1 && parsedTriggers.length > 1) {\n\t\tthrow \"Triggers parse error: manual trigger can't be mixed with other triggers\";\n\t}\n\n\treturn parsedTriggers;\n}\n\nexport function observeTriggers(\n\trenderer: Renderer2,\n\tnativeElement: HTMLElement,\n\ttriggers: Trigger[],\n\tisOpenedFn: () => boolean,\n) {\n\treturn new Observable<boolean>((subscriber) => {\n\t\tconst listeners: (() => void)[] = [];\n\t\tconst openFn = () => subscriber.next(true);\n\t\tconst closeFn = () => subscriber.next(false);\n\t\tconst toggleFn = () => subscriber.next(!isOpenedFn());\n\n\t\ttriggers.forEach((trigger: Trigger) => {\n\t\t\tif (trigger.open === trigger.close) {\n\t\t\t\tlisteners.push(renderer.listen(nativeElement, trigger.open, toggleFn));\n\t\t\t} else {\n\t\t\t\tlisteners.push(\n\t\t\t\t\trenderer.listen(nativeElement, trigger.open, openFn),\n\t\t\t\t\trenderer.listen(nativeElement, trigger.close!, closeFn),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tlisteners.forEach((unsubscribeFn) => unsubscribeFn());\n\t\t};\n\t});\n}\n\nconst delayOrNoop = <T>(time: number) => (time > 0 ? delay<T>(time) : (a: Observable<T>) => a);\n\nexport function triggerDelay(openDelay: number, closeDelay: number, isOpenedFn: () => boolean) {\n\treturn (input$: Observable<boolean>) => {\n\t\tlet pending: { open: boolean } | null = null;\n\t\tconst filteredInput$ = input$.pipe(\n\t\t\tmap((open) => ({ open })),\n\t\t\tfilter((event) => {\n\t\t\t\tconst currentlyOpen = isOpenedFn();\n\t\t\t\tif (currentlyOpen !== event.open && (!pending || pending.open === currentlyOpen)) {\n\t\t\t\t\tpending = event;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (pending && pending.open !== event.open) {\n\t\t\t\t\tpending = null;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}),\n\t\t\tshare(),\n\t\t);\n\t\tconst delayedOpen$ = filteredInput$.pipe(\n\t\t\tfilter((event) => event.open),\n\t\t\tdelayOrNoop(openDelay),\n\t\t);\n\t\tconst delayedClose$ = filteredInput$.pipe(\n\t\t\tfilter((event) => !event.open),\n\t\t\tdelayOrNoop(closeDelay),\n\t\t);\n\t\treturn merge(delayedOpen$, delayedClose$).pipe(\n\t\t\tfilter((event) => {\n\t\t\t\tif (event === pending) {\n\t\t\t\t\tpending = null;\n\t\t\t\t\treturn event.open !== isOpenedFn();\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}),\n\t\t\tmap((event) => event.open),\n\t\t);\n\t};\n}\n\nexport function listenToTriggers(\n\trenderer: Renderer2,\n\tnativeElement: HTMLElement,\n\ttriggers: string,\n\tisOpenedFn: () => boolean,\n\topenFn: () => void,\n\tcloseFn: () => void,\n\topenDelay = 0,\n\tcloseDelay = 0,\n) {\n\tconst parsedTriggers = parseTriggers(triggers);\n\n\tif (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {\n\t\treturn () => {};\n\t}\n\n\tconst subscription = observeTriggers(renderer, nativeElement, parsedTriggers, isOpenedFn)\n\t\t.pipe(triggerDelay(openDelay, closeDelay, isOpenedFn))\n\t\t.subscribe((open) => (open ? openFn() : closeFn()));\n\n\treturn () => subscription.unsubscribe();\n}\n","import { Injectable } from '@angular/core';\nimport { PlacementArray } from '../util/positioning';\nimport { NgbConfig } from '../ngb-config';\nimport { Options } from '@popperjs/core';\n\n/**\n * A configuration service for the [`NgbPopover`](#/components/popover/api#NgbPopover) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the popovers used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbPopoverConfig {\n\tautoClose: boolean | 'inside' | 'outside' = true;\n\tplacement: PlacementArray = 'auto';\n\tpopperOptions = (options: Partial<Options>) => options;\n\ttriggers = 'click';\n\tcontainer: string;\n\tdisablePopover = false;\n\tpopoverClass: string;\n\topenDelay = 0;\n\tcloseDelay = 0;\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbPopover } from './popover';\n\nexport { NgbPopover } from './popover';\nexport { NgbPopoverConfig } from './popover-config';\nexport { Placement } from '../util/positioning';\n\n@NgModule({\n\timports: [NgbPopover],\n\texports: [NgbPopover],\n})\nexport class NgbPopoverModule {}\n","import { Injectable } from '@angular/core';\n\n/**\n * A configuration service for the [`NgbProgressbar`](#/components/progressbar/api#NgbProgressbar) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the progress bars used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbProgressbarConfig {\n\tmax = 100;\n\tanimated = false;\n\tariaLabel = 'progress bar';\n\tstriped = false;\n\ttextType: string;\n\ttype: string;\n\tshowValue = false;\n\theight: string;\n}\n","import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation, HostBinding } from '@angular/core';\nimport { getValueInRange, isNumber } from '../util/util';\nimport { NgbProgressbarConfig } from './progressbar-config';\nimport { NgIf, PercentPipe } from '@angular/common';\n\n/**\n * A directive that provides feedback on the progress of a workflow or an action.\n */\n@Component({\n\tselector: 'ngb-progressbar',\n\tstandalone: true,\n\timports: [NgIf, PercentPipe],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'progress',\n\t\trole: 'progressbar',\n\t\t'[attr.aria-valuenow]': 'getValue()',\n\t\t'aria-valuemin': '0',\n\t\t'[attr.aria-valuemax]': 'max',\n\t\t'[attr.aria-label]': 'ariaLabel',\n\t},\n\ttemplate: `\n\t\t<div\n\t\t\tclass=\"progress-bar{{ type ? (textType ? ' bg-' + type : ' text-bg-' + type) : '' }}{{\n\t\t\t\ttextType ? ' text-' + textType : ''\n\t\t\t}}\"\n\t\t\t[class.progress-bar-animated]=\"animated\"\n\t\t\t[class.progress-bar-striped]=\"striped\"\n\t\t\t[style.width.%]=\"getPercentValue()\"\n\t\t>\n\t\t\t<span *ngIf=\"showValue\" i18n=\"@@ngb.progressbar.value\">{{ getValue() / max | percent }}</span\n\t\t\t><ng-content></ng-content>\n\t\t</div>\n\t`,\n})\nexport class NgbProgressbar {\n\tprivate _max: number;\n\n\t/**\n\t * The maximal value to be displayed in the progress bar.\n\t *\n\t * Should be a positive number. Will default to 100 otherwise.\n\t */\n\t@Input()\n\tset max(max: number) {\n\t\tthis._max = !isNumber(max) || max <= 0 ? 100 : max;\n\t}\n\n\tget max(): number {\n\t\treturn this._max;\n\t}\n\n\t/**\n\t * If `true`, the stripes on the progress bar are animated.\n\t *\n\t * Takes effect only for browsers supporting CSS3 animations, and if `striped` is `true`.\n\t */\n\t@Input() animated: boolean;\n\n\t/**\n\t * The accessible progress bar name.\n\t *\n\t * @since 13.1.0\n\t */\n\t@Input() ariaLabel: string;\n\n\t/**\n\t * If `true`, the progress bars will be displayed as striped.\n\t */\n\t@Input() striped: boolean;\n\n\t/**\n\t * If `true`, the current percentage will be shown in the `xx%` format.\n\t */\n\t@Input() showValue: boolean;\n\n\t/**\n\t * Optional text variant type of the progress bar.\n\t *\n\t * Supports types based on Bootstrap background color variants, like:\n\t * `\"success\"`, `\"info\"`, `\"warning\"`, `\"danger\"`, `\"primary\"`, `\"secondary\"`, `\"dark\"` and so on.\n\t *\n\t * @since 5.2.0\n\t */\n\t@Input() textType: string;\n\n\t/**\n\t * The type of the progress bar.\n\t *\n\t * Supports types based on Bootstrap background color variants, like:\n\t * `\"success\"`, `\"info\"`, `\"warning\"`, `\"danger\"`, `\"primary\"`, `\"secondary\"`, `\"dark\"` and so on.\n\t */\n\t@Input() type: string;\n\n\t/**\n\t * The current value for the progress bar.\n\t *\n\t * Should be in the `[0, max]` range.\n\t */\n\t@Input() value = 0;\n\n\t/**\n\t * The height of the progress bar.\n\t *\n\t * Accepts any valid CSS height values, ex. `\"2rem\"`\n\t */\n\t@Input() @HostBinding('style.height') height: string;\n\n\tconstructor(config: NgbProgressbarConfig) {\n\t\tthis.max = config.max;\n\t\tthis.animated = config.animated;\n\t\tthis.ariaLabel = config.ariaLabel;\n\t\tthis.striped = config.striped;\n\t\tthis.textType = config.textType;\n\t\tthis.type = config.type;\n\t\tthis.showValue = config.showValue;\n\t\tthis.height = config.height;\n\t}\n\n\tgetValue() {\n\t\treturn getValueInRange(this.value, this.max);\n\t}\n\n\tgetPercentValue() {\n\t\treturn (100 * this.getValue()) / this.max;\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbProgressbar } from './progressbar';\n\nexport { NgbProgressbar } from './progressbar';\nexport { NgbProgressbarConfig } from './progressbar-config';\n\n@NgModule({\n\timports: [NgbProgressbar],\n\texports: [NgbProgressbar],\n})\nexport class NgbProgressbarModule {}\n","import { Injectable } from '@angular/core';\n\n/**\n * A configuration service for the [`NgbRating`](#/components/rating/api#NgbRating) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the ratings used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbRatingConfig {\n\tmax = 10;\n\treadonly = false;\n\tresettable = false;\n\ttabindex: number | string = 0;\n}\n","import {\n\tChangeDetectionStrategy,\n\tChangeDetectorRef,\n\tComponent,\n\tContentChild,\n\tEventEmitter,\n\tforwardRef,\n\tInput,\n\tOnChanges,\n\tOnInit,\n\tOutput,\n\tSimpleChanges,\n\tTemplateRef,\n\tViewEncapsulation,\n} from '@angular/core';\nimport { NgbRatingConfig } from './rating-config';\nimport { getValueInRange } from '../util/util';\nimport { Key } from '../util/key';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { NgFor, NgTemplateOutlet } from '@angular/common';\n\n/**\n * The context for the custom star display template defined in the `starTemplate`.\n */\nexport interface StarTemplateContext {\n\t/**\n\t * The star fill percentage, an integer in the `[0, 100]` range.\n\t */\n\tfill: number;\n\n\t/**\n\t * Index of the star, starts with `0`.\n\t */\n\tindex: number;\n}\n\n/**\n * A directive that helps visualising and interacting with a star rating bar.\n */\n@Component({\n\tselector: 'ngb-rating',\n\tstandalone: true,\n\timports: [NgFor, NgTemplateOutlet],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\tclass: 'd-inline-flex',\n\t\t'[tabindex]': 'disabled ? -1 : tabindex',\n\t\trole: 'slider',\n\t\t'aria-valuemin': '0',\n\t\t'[attr.aria-valuemax]': 'max',\n\t\t'[attr.aria-valuenow]': 'nextRate',\n\t\t'[attr.aria-valuetext]': 'ariaValueText(nextRate, max)',\n\t\t'[attr.aria-disabled]': 'readonly ? true : null',\n\t\t'(blur)': 'handleBlur()',\n\t\t'(keydown)': 'handleKeyDown($event)',\n\t\t'(mouseleave)': 'reset()',\n\t},\n\ttemplate: `\n\t\t<ng-template #t let-fill=\"fill\">{{ fill === 100 ? '★' : '☆' }}</ng-template>\n\t\t<ng-template ngFor [ngForOf]=\"contexts\" let-index=\"index\">\n\t\t\t<span class=\"visually-hidden\">({{ index < nextRate ? '*' : ' ' }})</span>\n\t\t\t<span\n\t\t\t\t(mouseenter)=\"enter(index + 1)\"\n\t\t\t\t(click)=\"handleClick(index + 1)\"\n\t\t\t\t[style.cursor]=\"isInteractive() ? 'pointer' : 'default'\"\n\t\t\t>\n\t\t\t\t<ng-template\n\t\t\t\t\t[ngTemplateOutlet]=\"starTemplate || starTemplateFromContent || t\"\n\t\t\t\t\t[ngTemplateOutletContext]=\"contexts[index]\"\n\t\t\t\t>\n\t\t\t\t</ng-template>\n\t\t\t</span>\n\t\t</ng-template>\n\t`,\n\tproviders: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbRating), multi: true }],\n})\nexport class NgbRating implements ControlValueAccessor, OnInit, OnChanges {\n\tcontexts: StarTemplateContext[] = [];\n\tdisabled = false;\n\tnextRate: number;\n\n\t/**\n\t * The maximal rating that can be given.\n\t */\n\t@Input() max: number;\n\n\t/**\n\t * The current rating. Could be a decimal value like `3.75`.\n\t */\n\t@Input() rate: number;\n\n\t/**\n\t * If `true`, the rating can't be changed.\n\t */\n\t@Input() readonly: boolean;\n\n\t/**\n\t * If `true`, the rating can be reset to `0` by mouse clicking currently set rating.\n\t */\n\t@Input() resettable: boolean;\n\n\t/**\n\t * The template to override the way each star is displayed.\n\t *\n\t * Alternatively put an `<ng-template>` as the only child of your `<ngb-rating>` element\n\t */\n\t@Input() starTemplate: TemplateRef<StarTemplateContext>;\n\t@ContentChild(TemplateRef, { static: false }) starTemplateFromContent: TemplateRef<StarTemplateContext>;\n\n\t/**\n\t * Allows setting a custom rating tabindex.\n\t * If the component is disabled, `tabindex` will still be set to `-1`.\n\t *\n\t * @since 13.1.0\n\t */\n\t@Input() tabindex: number | string;\n\n\t/**\n\t * Allows to provide a function to set a custom aria-valuetext\n\t *\n\t * @since 14.1.0\n\t */\n\t@Input() ariaValueText(current: number, max: number) {\n\t\treturn `${current} out of ${max}`;\n\t}\n\n\t/**\n\t * An event emitted when the user is hovering over a given rating.\n\t *\n\t * Event payload equals to the rating being hovered over.\n\t */\n\t@Output() hover = new EventEmitter<number>();\n\n\t/**\n\t * An event emitted when the user stops hovering over a given rating.\n\t *\n\t * Event payload equals to the rating of the last item being hovered over.\n\t */\n\t@Output() leave = new EventEmitter<number>();\n\n\t/**\n\t * An event emitted when the rating is changed.\n\t *\n\t * Event payload equals to the newly selected rating.\n\t */\n\t@Output() rateChange = new EventEmitter<number>(true);\n\n\tonChange = (_: any) => {};\n\tonTouched = () => {};\n\n\tconstructor(config: NgbRatingConfig, private _changeDetectorRef: ChangeDetectorRef) {\n\t\tthis.max = config.max;\n\t\tthis.readonly = config.readonly;\n\t\tthis.tabindex = config.tabindex;\n\t}\n\n\tisInteractive(): boolean {\n\t\treturn !this.readonly && !this.disabled;\n\t}\n\n\tenter(value: number): void {\n\t\tif (this.isInteractive()) {\n\t\t\tthis._updateState(value);\n\t\t}\n\t\tthis.hover.emit(value);\n\t}\n\n\thandleBlur() {\n\t\tthis.onTouched();\n\t}\n\n\thandleClick(value: number) {\n\t\tif (this.isInteractive()) {\n\t\t\tthis.update(this.resettable && this.rate === value ? 0 : value);\n\t\t}\n\t}\n\n\thandleKeyDown(event: KeyboardEvent) {\n\t\t/* eslint-disable-next-line deprecation/deprecation */\n\t\tswitch (event.which) {\n\t\t\tcase Key.ArrowDown:\n\t\t\tcase Key.ArrowLeft:\n\t\t\t\tthis.update(this.rate - 1);\n\t\t\t\tbreak;\n\t\t\tcase Key.ArrowUp:\n\t\t\tcase Key.ArrowRight:\n\t\t\t\tthis.update(this.rate + 1);\n\t\t\t\tbreak;\n\t\t\tcase Key.Home:\n\t\t\t\tthis.update(0);\n\t\t\t\tbreak;\n\t\t\tcase Key.End:\n\t\t\t\tthis.update(this.max);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// note 'return' in default case\n\t\tevent.preventDefault();\n\t}\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\tif (changes['rate']) {\n\t\t\tthis.update(this.rate);\n\t\t}\n\t\tif (changes['max']) {\n\t\t\tthis._updateMax();\n\t\t}\n\t}\n\n\tngOnInit(): void {\n\t\tthis._setupContexts();\n\t\tthis._updateState(this.rate);\n\t}\n\n\tregisterOnChange(fn: (value: any) => any): void {\n\t\tthis.onChange = fn;\n\t}\n\n\tregisterOnTouched(fn: () => any): void {\n\t\tthis.onTouched = fn;\n\t}\n\n\treset(): void {\n\t\tthis.leave.emit(this.nextRate);\n\t\tthis._updateState(this.rate);\n\t}\n\n\tsetDisabledState(isDisabled: boolean) {\n\t\tthis.disabled = isDisabled;\n\t}\n\n\tupdate(value: number, internalChange = true): void {\n\t\tconst newRate = getValueInRange(value, this.max, 0);\n\t\tif (this.isInteractive() && this.rate !== newRate) {\n\t\t\tthis.rate = newRate;\n\t\t\tthis.rateChange.emit(this.rate);\n\t\t}\n\t\tif (internalChange) {\n\t\t\tthis.onChange(this.rate);\n\t\t\tthis.onTouched();\n\t\t}\n\t\tthis._updateState(this.rate);\n\t}\n\n\twriteValue(value) {\n\t\tthis.update(value, false);\n\t\tthis._changeDetectorRef.markForCheck();\n\t}\n\n\tprivate _updateState(nextValue: number) {\n\t\tthis.nextRate = nextValue;\n\t\tthis.contexts.forEach(\n\t\t\t(context, index) => (context.fill = Math.round(getValueInRange(nextValue - index, 1, 0) * 100)),\n\t\t);\n\t}\n\n\tprivate _updateMax() {\n\t\tif (this.max > 0) {\n\t\t\tthis._setupContexts();\n\t\t\tthis.update(this.rate);\n\t\t}\n\t}\n\n\tprivate _setupContexts() {\n\t\tthis.contexts = Array.from({ length: this.max }, (v, k) => ({ fill: 0, index: k }));\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbRating } from './rating';\n\nexport { NgbRating } from './rating';\nexport { NgbRatingConfig } from './rating-config';\n\n@NgModule({\n\timports: [NgbRating],\n\texports: [NgbRating],\n})\nexport class NgbRatingModule {}\n","import { isNumber, toInteger } from '../util/util';\n\nexport class NgbTime {\n\thour: number;\n\tminute: number;\n\tsecond: number;\n\n\tconstructor(hour?: number, minute?: number, second?: number) {\n\t\tthis.hour = toInteger(hour);\n\t\tthis.minute = toInteger(minute);\n\t\tthis.second = toInteger(second);\n\t}\n\n\tchangeHour(step = 1) {\n\t\tthis.updateHour((isNaN(this.hour) ? 0 : this.hour) + step);\n\t}\n\n\tupdateHour(hour: number) {\n\t\tif (isNumber(hour)) {\n\t\t\tthis.hour = (hour < 0 ? 24 + hour : hour) % 24;\n\t\t} else {\n\t\t\tthis.hour = NaN;\n\t\t}\n\t}\n\n\tchangeMinute(step = 1) {\n\t\tthis.updateMinute((isNaN(this.minute) ? 0 : this.minute) + step);\n\t}\n\n\tupdateMinute(minute: number) {\n\t\tif (isNumber(minute)) {\n\t\t\tthis.minute = minute % 60 < 0 ? 60 + (minute % 60) : minute % 60;\n\t\t\tthis.changeHour(Math.floor(minute / 60));\n\t\t} else {\n\t\t\tthis.minute = NaN;\n\t\t}\n\t}\n\n\tchangeSecond(step = 1) {\n\t\tthis.updateSecond((isNaN(this.second) ? 0 : this.second) + step);\n\t}\n\n\tupdateSecond(second: number) {\n\t\tif (isNumber(second)) {\n\t\t\tthis.second = second < 0 ? 60 + (second % 60) : second % 60;\n\t\t\tthis.changeMinute(Math.floor(second / 60));\n\t\t} else {\n\t\t\tthis.second = NaN;\n\t\t}\n\t}\n\n\tisValid(checkSecs = true) {\n\t\treturn isNumber(this.hour) && isNumber(this.minute) && (checkSecs ? isNumber(this.second) : true);\n\t}\n\n\ttoString() {\n\t\treturn `${this.hour || 0}:${this.minute || 0}:${this.second || 0}`;\n\t}\n}\n","import { Injectable } from '@angular/core';\n\n/**\n * A configuration service for the [`NgbTimepicker`](#/components/timepicker/api#NgbTimepicker) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the timepickers used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbTimepickerConfig {\n\tmeridian = false;\n\tspinners = true;\n\tseconds = false;\n\thourStep = 1;\n\tminuteStep = 1;\n\tsecondStep = 1;\n\tdisabled = false;\n\treadonlyInputs = false;\n\tsize: 'small' | 'medium' | 'large' = 'medium';\n}\n","import { Injectable } from '@angular/core';\nimport { NgbTimeStruct } from './ngb-time-struct';\nimport { isInteger } from '../util/util';\n\nexport function NGB_DATEPICKER_TIME_ADAPTER_FACTORY() {\n\treturn new NgbTimeStructAdapter();\n}\n\n/**\n * An abstract service that does the conversion between the internal timepicker `NgbTimeStruct` model and\n * any provided user time model `T`, ex. a string, a native date, etc.\n *\n * The adapter is used **only** for conversion when binding timepicker to a form control,\n * ex. `[(ngModel)]=\"userTimeModel\"`. Here `userTimeModel` can be of any type.\n *\n * The default timepicker implementation assumes we use `NgbTimeStruct` as a user model.\n *\n * See the [custom time adapter demo](#/components/timepicker/examples#adapter) for an example.\n *\n * @since 2.2.0\n */\n@Injectable({ providedIn: 'root', useFactory: NGB_DATEPICKER_TIME_ADAPTER_FACTORY })\nexport abstract class NgbTimeAdapter<T> {\n\t/**\n\t * Converts a user-model time of type `T` to an `NgbTimeStruct` for internal use.\n\t */\n\tabstract fromModel(value: T | null): NgbTimeStruct | null;\n\n\t/**\n\t * Converts an internal `NgbTimeStruct` time to a user-model time of type `T`.\n\t */\n\tabstract toModel(time: NgbTimeStruct | null): T | null;\n}\n\n@Injectable()\nexport class NgbTimeStructAdapter extends NgbTimeAdapter<NgbTimeStruct> {\n\t/**\n\t * Converts a NgbTimeStruct value into NgbTimeStruct value\n\t */\n\tfromModel(time: NgbTimeStruct | null): NgbTimeStruct | null {\n\t\treturn time && isInteger(time.hour) && isInteger(time.minute)\n\t\t\t? { hour: time.hour, minute: time.minute, second: isInteger(time.second) ? time.second : <any>null }\n\t\t\t: null;\n\t}\n\n\t/**\n\t * Converts a NgbTimeStruct value into NgbTimeStruct value\n\t */\n\ttoModel(time: NgbTimeStruct | null): NgbTimeStruct | null {\n\t\treturn time && isInteger(time.hour) && isInteger(time.minute)\n\t\t\t? { hour: time.hour, minute: time.minute, second: isInteger(time.second) ? time.second : <any>null }\n\t\t\t: null;\n\t}\n}\n","import { Inject, Injectable, LOCALE_ID } from '@angular/core';\nimport { FormStyle, getLocaleDayPeriods, TranslationWidth } from '@angular/common';\n\nexport function NGB_TIMEPICKER_I18N_FACTORY(locale) {\n\treturn new NgbTimepickerI18nDefault(locale);\n}\n\n/**\n * Type of the service supplying day periods (for example, 'AM' and 'PM') to NgbTimepicker component.\n * The default implementation of this service honors the Angular locale, and uses the registered locale data,\n * as explained in the Angular i18n guide.\n */\n@Injectable({ providedIn: 'root', useFactory: NGB_TIMEPICKER_I18N_FACTORY, deps: [LOCALE_ID] })\nexport abstract class NgbTimepickerI18n {\n\t/**\n\t * Returns the name for the period before midday.\n\t */\n\tabstract getMorningPeriod(): string;\n\n\t/**\n\t * Returns the name for the period after midday.\n\t */\n\tabstract getAfternoonPeriod(): string;\n}\n\n@Injectable()\nexport class NgbTimepickerI18nDefault extends NgbTimepickerI18n {\n\tprivate _periods: Readonly<[string, string]>;\n\n\tconstructor(@Inject(LOCALE_ID) locale: string) {\n\t\tsuper();\n\n\t\tthis._periods = getLocaleDayPeriods(locale, FormStyle.Standalone, TranslationWidth.Narrow);\n\t}\n\n\tgetMorningPeriod(): string {\n\t\treturn this._periods[0];\n\t}\n\n\tgetAfternoonPeriod(): string {\n\t\treturn this._periods[1];\n\t}\n}\n","import {\n\tChangeDetectorRef,\n\tComponent,\n\tforwardRef,\n\tInput,\n\tOnChanges,\n\tSimpleChanges,\n\tViewEncapsulation,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nimport { isInteger, isNumber, padNumber, toInteger } from '../util/util';\nimport { NgbTime } from './ngb-time';\nimport { NgbTimepickerConfig } from './timepicker-config';\nimport { NgbTimeAdapter } from './ngb-time-adapter';\nimport { NgbTimepickerI18n } from './timepicker-i18n';\nimport { NgIf } from '@angular/common';\n\nconst FILTER_REGEX = /[^0-9]/g;\n\n/**\n * A directive that helps with wth picking hours, minutes and seconds.\n */\n@Component({\n\texportAs: 'ngbTimepicker',\n\tselector: 'ngb-timepicker',\n\tstandalone: true,\n\timports: [NgIf],\n\tencapsulation: ViewEncapsulation.None,\n\tstyleUrls: ['./timepicker.scss'],\n\ttemplate: `\n\t\t<fieldset [disabled]=\"disabled\" [class.disabled]=\"disabled\">\n\t\t\t<div class=\"ngb-tp\">\n\t\t\t\t<div class=\"ngb-tp-input-container ngb-tp-hour\">\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeHour(hourStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.increment-hours\">Increment hours</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"ngb-tp-input form-control\"\n\t\t\t\t\t\t[class.form-control-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.form-control-lg]=\"isLargeSize\"\n\t\t\t\t\t\tmaxlength=\"2\"\n\t\t\t\t\t\tinputmode=\"numeric\"\n\t\t\t\t\t\tplaceholder=\"HH\"\n\t\t\t\t\t\ti18n-placeholder=\"@@ngb.timepicker.HH\"\n\t\t\t\t\t\t[value]=\"formatHour(model?.hour)\"\n\t\t\t\t\t\t(change)=\"updateHour($any($event).target.value)\"\n\t\t\t\t\t\t[readOnly]=\"readonlyInputs\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t\taria-label=\"Hours\"\n\t\t\t\t\t\ti18n-aria-label=\"@@ngb.timepicker.hours\"\n\t\t\t\t\t\t(blur)=\"handleBlur()\"\n\t\t\t\t\t\t(input)=\"formatInput($any($event).target)\"\n\t\t\t\t\t\t(keydown.ArrowUp)=\"changeHour(hourStep); $event.preventDefault()\"\n\t\t\t\t\t\t(keydown.ArrowDown)=\"changeHour(-hourStep); $event.preventDefault()\"\n\t\t\t\t\t/>\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeHour(-hourStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron bottom\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.decrement-hours\">Decrement hours</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"ngb-tp-spacer\">:</div>\n\t\t\t\t<div class=\"ngb-tp-input-container ngb-tp-minute\">\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeMinute(minuteStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.increment-minutes\">Increment minutes</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"ngb-tp-input form-control\"\n\t\t\t\t\t\t[class.form-control-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.form-control-lg]=\"isLargeSize\"\n\t\t\t\t\t\tmaxlength=\"2\"\n\t\t\t\t\t\tinputmode=\"numeric\"\n\t\t\t\t\t\tplaceholder=\"MM\"\n\t\t\t\t\t\ti18n-placeholder=\"@@ngb.timepicker.MM\"\n\t\t\t\t\t\t[value]=\"formatMinSec(model?.minute)\"\n\t\t\t\t\t\t(change)=\"updateMinute($any($event).target.value)\"\n\t\t\t\t\t\t[readOnly]=\"readonlyInputs\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t\taria-label=\"Minutes\"\n\t\t\t\t\t\ti18n-aria-label=\"@@ngb.timepicker.minutes\"\n\t\t\t\t\t\t(blur)=\"handleBlur()\"\n\t\t\t\t\t\t(input)=\"formatInput($any($event).target)\"\n\t\t\t\t\t\t(keydown.ArrowUp)=\"changeMinute(minuteStep); $event.preventDefault()\"\n\t\t\t\t\t\t(keydown.ArrowDown)=\"changeMinute(-minuteStep); $event.preventDefault()\"\n\t\t\t\t\t/>\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeMinute(-minuteStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron bottom\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.decrement-minutes\">Decrement minutes</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div *ngIf=\"seconds\" class=\"ngb-tp-spacer\">:</div>\n\t\t\t\t<div *ngIf=\"seconds\" class=\"ngb-tp-input-container ngb-tp-second\">\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeSecond(secondStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.increment-seconds\">Increment seconds</span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tclass=\"ngb-tp-input form-control\"\n\t\t\t\t\t\t[class.form-control-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.form-control-lg]=\"isLargeSize\"\n\t\t\t\t\t\tmaxlength=\"2\"\n\t\t\t\t\t\tinputmode=\"numeric\"\n\t\t\t\t\t\tplaceholder=\"SS\"\n\t\t\t\t\t\ti18n-placeholder=\"@@ngb.timepicker.SS\"\n\t\t\t\t\t\t[value]=\"formatMinSec(model?.second)\"\n\t\t\t\t\t\t(change)=\"updateSecond($any($event).target.value)\"\n\t\t\t\t\t\t[readOnly]=\"readonlyInputs\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t\taria-label=\"Seconds\"\n\t\t\t\t\t\ti18n-aria-label=\"@@ngb.timepicker.seconds\"\n\t\t\t\t\t\t(blur)=\"handleBlur()\"\n\t\t\t\t\t\t(input)=\"formatInput($any($event).target)\"\n\t\t\t\t\t\t(keydown.ArrowUp)=\"changeSecond(secondStep); $event.preventDefault()\"\n\t\t\t\t\t\t(keydown.ArrowDown)=\"changeSecond(-secondStep); $event.preventDefault()\"\n\t\t\t\t\t/>\n\t\t\t\t\t<button\n\t\t\t\t\t\t*ngIf=\"spinners\"\n\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t(click)=\"changeSecond(-secondStep)\"\n\t\t\t\t\t\tclass=\"btn btn-link\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"chevron ngb-tp-chevron bottom\"></span>\n\t\t\t\t\t\t<span class=\"visually-hidden\" i18n=\"@@ngb.timepicker.decrement-seconds\">Decrement seconds</span>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t<div *ngIf=\"meridian\" class=\"ngb-tp-spacer\"></div>\n\t\t\t\t<div *ngIf=\"meridian\" class=\"ngb-tp-meridian\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"btn btn-outline-primary\"\n\t\t\t\t\t\t[class.btn-sm]=\"isSmallSize\"\n\t\t\t\t\t\t[class.btn-lg]=\"isLargeSize\"\n\t\t\t\t\t\t[disabled]=\"disabled\"\n\t\t\t\t\t\t[class.disabled]=\"disabled\"\n\t\t\t\t\t\t(click)=\"toggleMeridian()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<ng-container *ngIf=\"model && model.hour >= 12; else am\" i18n=\"@@ngb.timepicker.PM\">{{\n\t\t\t\t\t\t\ti18n.getAfternoonPeriod()\n\t\t\t\t\t\t}}</ng-container>\n\t\t\t\t\t\t<ng-template #am i18n=\"@@ngb.timepicker.AM\">{{ i18n.getMorningPeriod() }}</ng-template>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</fieldset>\n\t`,\n\tproviders: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbTimepicker), multi: true }],\n})\nexport class NgbTimepicker implements ControlValueAccessor, OnChanges {\n\tstatic ngAcceptInputType_size: string;\n\n\tdisabled: boolean;\n\tmodel?: NgbTime;\n\n\tprivate _hourStep: number;\n\tprivate _minuteStep: number;\n\tprivate _secondStep: number;\n\n\t/**\n\t * Whether to display 12H or 24H mode.\n\t */\n\t@Input() meridian: boolean;\n\n\t/**\n\t * If `true`, the spinners above and below inputs are visible.\n\t */\n\t@Input() spinners: boolean;\n\n\t/**\n\t * If `true`, it is possible to select seconds.\n\t */\n\t@Input() seconds: boolean;\n\n\t/**\n\t * The number of hours to add/subtract when clicking hour spinners.\n\t */\n\t@Input()\n\tset hourStep(step: number) {\n\t\tthis._hourStep = isInteger(step) ? step : this._config.hourStep;\n\t}\n\n\tget hourStep(): number {\n\t\treturn this._hourStep;\n\t}\n\n\t/**\n\t * The number of minutes to add/subtract when clicking minute spinners.\n\t */\n\t@Input()\n\tset minuteStep(step: number) {\n\t\tthis._minuteStep = isInteger(step) ? step : this._config.minuteStep;\n\t}\n\n\tget minuteStep(): number {\n\t\treturn this._minuteStep;\n\t}\n\n\t/**\n\t * The number of seconds to add/subtract when clicking second spinners.\n\t */\n\t@Input()\n\tset secondStep(step: number) {\n\t\tthis._secondStep = isInteger(step) ? step : this._config.secondStep;\n\t}\n\n\tget secondStep(): number {\n\t\treturn this._secondStep;\n\t}\n\n\t/**\n\t * If `true`, the timepicker is readonly and can't be changed.\n\t */\n\t@Input() readonlyInputs: boolean;\n\n\t/**\n\t * The size of inputs and buttons.\n\t */\n\t@Input() size: 'small' | 'medium' | 'large';\n\n\tconstructor(\n\t\tprivate readonly _config: NgbTimepickerConfig,\n\t\tprivate _ngbTimeAdapter: NgbTimeAdapter<any>,\n\t\tprivate _cd: ChangeDetectorRef,\n\t\tpublic i18n: NgbTimepickerI18n,\n\t) {\n\t\tthis.meridian = _config.meridian;\n\t\tthis.spinners = _config.spinners;\n\t\tthis.seconds = _config.seconds;\n\t\tthis.hourStep = _config.hourStep;\n\t\tthis.minuteStep = _config.minuteStep;\n\t\tthis.secondStep = _config.secondStep;\n\t\tthis.disabled = _config.disabled;\n\t\tthis.readonlyInputs = _config.readonlyInputs;\n\t\tthis.size = _config.size;\n\t}\n\n\tonChange = (_: any) => {};\n\tonTouched = () => {};\n\n\twriteValue(value) {\n\t\tconst structValue = this._ngbTimeAdapter.fromModel(value);\n\t\tthis.model = structValue ? new NgbTime(structValue.hour, structValue.minute, structValue.second) : new NgbTime();\n\t\tif (!this.seconds && (!structValue || !isNumber(structValue.second))) {\n\t\t\tthis.model.second = 0;\n\t\t}\n\t\tthis._cd.markForCheck();\n\t}\n\n\tregisterOnChange(fn: (value: any) => any): void {\n\t\tthis.onChange = fn;\n\t}\n\n\tregisterOnTouched(fn: () => any): void {\n\t\tthis.onTouched = fn;\n\t}\n\n\tsetDisabledState(isDisabled: boolean) {\n\t\tthis.disabled = isDisabled;\n\t}\n\n\t/**\n\t * Increments the hours by the given step.\n\t */\n\tchangeHour(step: number) {\n\t\tthis.model?.changeHour(step);\n\t\tthis.propagateModelChange();\n\t}\n\n\t/**\n\t * Increments the minutes by the given step.\n\t */\n\tchangeMinute(step: number) {\n\t\tthis.model?.changeMinute(step);\n\t\tthis.propagateModelChange();\n\t}\n\n\t/**\n\t * Increments the seconds by the given step.\n\t */\n\tchangeSecond(step: number) {\n\t\tthis.model?.changeSecond(step);\n\t\tthis.propagateModelChange();\n\t}\n\n\t/**\n\t * Update hours with the new value.\n\t */\n\tupdateHour(newVal: string) {\n\t\tconst isPM = this.model ? this.model.hour >= 12 : false;\n\t\tconst enteredHour = toInteger(newVal);\n\t\tif (this.meridian && ((isPM && enteredHour < 12) || (!isPM && enteredHour === 12))) {\n\t\t\tthis.model?.updateHour(enteredHour + 12);\n\t\t} else {\n\t\t\tthis.model?.updateHour(enteredHour);\n\t\t}\n\t\tthis.propagateModelChange();\n\t}\n\n\t/**\n\t * Update minutes with the new value.\n\t */\n\tupdateMinute(newVal: string) {\n\t\tthis.model?.updateMinute(toInteger(newVal));\n\t\tthis.propagateModelChange();\n\t}\n\n\t/**\n\t * Update seconds with the new value.\n\t */\n\tupdateSecond(newVal: string) {\n\t\tthis.model?.updateSecond(toInteger(newVal));\n\t\tthis.propagateModelChange();\n\t}\n\n\ttoggleMeridian() {\n\t\tif (this.meridian) {\n\t\t\tthis.changeHour(12);\n\t\t}\n\t}\n\n\tformatInput(input: HTMLInputElement) {\n\t\tinput.value = input.value.replace(FILTER_REGEX, '');\n\t}\n\n\tformatHour(value?: number) {\n\t\tif (isNumber(value)) {\n\t\t\tif (this.meridian) {\n\t\t\t\treturn padNumber(value % 12 === 0 ? 12 : value % 12);\n\t\t\t} else {\n\t\t\t\treturn padNumber(value % 24);\n\t\t\t}\n\t\t} else {\n\t\t\treturn padNumber(NaN);\n\t\t}\n\t}\n\n\tformatMinSec(value?: number) {\n\t\treturn padNumber(isNumber(value) ? value : NaN);\n\t}\n\n\thandleBlur() {\n\t\tthis.onTouched();\n\t}\n\n\tget isSmallSize(): boolean {\n\t\treturn this.size === 'small';\n\t}\n\n\tget isLargeSize(): boolean {\n\t\treturn this.size === 'large';\n\t}\n\n\tngOnChanges(changes: SimpleChanges): void {\n\t\tif (changes['seconds'] && !this.seconds && this.model && !isNumber(this.model.second)) {\n\t\t\tthis.model.second = 0;\n\t\t\tthis.propagateModelChange(false);\n\t\t}\n\t}\n\n\tprivate propagateModelChange(touched = true) {\n\t\tif (touched) {\n\t\t\tthis.onTouched();\n\t\t}\n\t\tif (this.model?.isValid(this.seconds)) {\n\t\t\tthis.onChange(\n\t\t\t\tthis._ngbTimeAdapter.toModel({ hour: this.model.hour, minute: this.model.minute, second: this.model.second }),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.onChange(this._ngbTimeAdapter.toModel(null));\n\t\t}\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbTimepicker } from './timepicker';\n\nexport { NgbTimepicker } from './timepicker';\nexport { NgbTimepickerConfig } from './timepicker-config';\nexport { NgbTimeStruct } from './ngb-time-struct';\nexport { NgbTimeAdapter } from './ngb-time-adapter';\nexport { NgbTimepickerI18n } from './timepicker-i18n';\n\n@NgModule({\n\timports: [NgbTimepicker],\n\texports: [NgbTimepicker],\n})\nexport class NgbTimepickerModule {}\n","import { NgbTransitionStartFn } from '../util/transition/ngbTransition';\nimport { reflow } from '../util/util';\n\nexport const ngbToastFadeInTransition: NgbTransitionStartFn = (element: HTMLElement, animation: true) => {\n\tconst { classList } = element;\n\n\tif (animation) {\n\t\tclassList.add('fade');\n\t} else {\n\t\tclassList.add('show');\n\t\treturn;\n\t}\n\n\treflow(element);\n\tclassList.add('show', 'showing');\n\n\treturn () => {\n\t\tclassList.remove('showing');\n\t};\n};\n\nexport const ngbToastFadeOutTransition: NgbTransitionStartFn = ({ classList }: HTMLElement) => {\n\tclassList.add('showing');\n\treturn () => {\n\t\tclassList.remove('show', 'showing');\n\t};\n};\n","import { Injectable } from '@angular/core';\nimport { NgbConfig } from '../ngb-config';\n\n/**\n * Interface used to type all toast config options. See `NgbToastConfig`.\n *\n * @since 5.0.0\n */\nexport interface NgbToastOptions {\n\t/**\n\t * Specify if the toast component should emit the `hide()` output\n\t * after a certain `delay` in ms.\n\t */\n\tautohide?: boolean;\n\n\t/**\n\t * Delay in ms after which the `hide()` output should be emitted.\n\t */\n\tdelay?: number;\n\n\t/**\n\t * Type of aria-live attribute to be used.\n\t *\n\t * Could be one of these 2 values (as string):\n\t * - `polite` (default)\n\t * - `alert`\n\t */\n\tariaLive?: 'polite' | 'alert';\n}\n\n/**\n * Configuration service for the NgbToast component. You can inject this service, typically in your root component,\n * and customize the values of its properties in order to provide default values for all the toasts used in the\n * application.\n *\n * @since 5.0.0\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbToastConfig implements NgbToastOptions {\n\tautohide = true;\n\tdelay = 5000;\n\tariaLive: 'polite' | 'alert' = 'polite';\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import {\n\tAfterContentInit,\n\tAttribute,\n\tComponent,\n\tContentChild,\n\tDirective,\n\tEventEmitter,\n\tInput,\n\tOnChanges,\n\tOutput,\n\tSimpleChanges,\n\tTemplateRef,\n\tViewEncapsulation,\n\tElementRef,\n\tNgZone,\n} from '@angular/core';\n\nimport { Observable } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\nimport { NgbToastConfig } from './toast-config';\nimport { ngbRunTransition } from '../util/transition/ngbTransition';\nimport { ngbToastFadeInTransition, ngbToastFadeOutTransition } from './toast-transition';\nimport { NgIf, NgTemplateOutlet } from '@angular/common';\n\n/**\n * This directive allows the usage of HTML markup or other directives\n * inside of the toast's header.\n *\n * @since 5.0.0\n */\n@Directive({ selector: '[ngbToastHeader]', standalone: true })\nexport class NgbToastHeader {}\n\n/**\n * Toasts provide feedback messages as notifications to the user.\n * Goal is to mimic the push notifications available both on mobile and desktop operating systems.\n *\n * @since 5.0.0\n */\n@Component({\n\tselector: 'ngb-toast',\n\texportAs: 'ngbToast',\n\tstandalone: true,\n\timports: [NgIf, NgTemplateOutlet],\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\trole: 'alert',\n\t\t'[attr.aria-live]': 'ariaLive',\n\t\t'aria-atomic': 'true',\n\t\tclass: 'toast',\n\t\t'[class.fade]': 'animation',\n\t},\n\ttemplate: `\n\t\t<ng-template #headerTpl>\n\t\t\t<strong class=\"me-auto\">{{ header }}</strong>\n\t\t</ng-template>\n\t\t<ng-template [ngIf]=\"contentHeaderTpl || header\">\n\t\t\t<div class=\"toast-header\">\n\t\t\t\t<ng-template [ngTemplateOutlet]=\"contentHeaderTpl || headerTpl\"></ng-template>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"btn-close\"\n\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\ti18n-aria-label=\"@@ngb.toast.close-aria\"\n\t\t\t\t\t(click)=\"hide()\"\n\t\t\t\t>\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</ng-template>\n\t\t<div class=\"toast-body\">\n\t\t\t<ng-content></ng-content>\n\t\t</div>\n\t`,\n\tstyleUrls: ['./toast.scss'],\n})\nexport class NgbToast implements AfterContentInit, OnChanges {\n\t/**\n\t * If `true`, toast opening and closing will be animated.\n\t *\n\t * Animation is triggered only when the `.hide()` or `.show()` functions are called\n\t *\n\t * @since 8.0.0\n\t */\n\t@Input() animation: boolean;\n\n\tprivate _timeoutID;\n\n\t/**\n\t * Delay after which the toast will hide (ms).\n\t * default: `500` (ms) (inherited from NgbToastConfig)\n\t */\n\t@Input() delay: number;\n\n\t/**\n\t * Auto hide the toast after a delay in ms.\n\t * default: `true` (inherited from NgbToastConfig)\n\t */\n\t@Input() autohide: boolean;\n\n\t/**\n\t * Text to be used as toast's header.\n\t * Ignored if a ContentChild template is specified at the same time.\n\t */\n\t@Input() header: string;\n\n\t/**\n\t * A template like `<ng-template ngbToastHeader></ng-template>` can be\n\t * used in the projected content to allow markup usage.\n\t */\n\t@ContentChild(NgbToastHeader, { read: TemplateRef, static: true }) contentHeaderTpl: TemplateRef<any> | null = null;\n\n\t/**\n\t * An event fired after the animation triggered by calling `.show()` method has finished.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() shown = new EventEmitter<void>();\n\n\t/**\n\t * An event fired after the animation triggered by calling `.hide()` method has finished.\n\t *\n\t * It can only occur in 2 different scenarios:\n\t * - `autohide` timeout fires\n\t * - user clicks on a closing cross\n\t *\n\t * Additionally this output is purely informative. The toast won't be removed from DOM automatically, it's up\n\t * to the user to take care of that.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Output() hidden = new EventEmitter<void>();\n\n\tconstructor(\n\t\t@Attribute('aria-live') public ariaLive: string,\n\t\tconfig: NgbToastConfig,\n\t\tprivate _zone: NgZone,\n\t\tprivate _element: ElementRef,\n\t) {\n\t\tif (this.ariaLive == null) {\n\t\t\tthis.ariaLive = config.ariaLive;\n\t\t}\n\t\tthis.delay = config.delay;\n\t\tthis.autohide = config.autohide;\n\t\tthis.animation = config.animation;\n\t}\n\n\tngAfterContentInit() {\n\t\tthis._zone.onStable\n\t\t\t.asObservable()\n\t\t\t.pipe(take(1))\n\t\t\t.subscribe(() => {\n\t\t\t\tthis._init();\n\t\t\t\tthis.show();\n\t\t\t});\n\t}\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\tif ('autohide' in changes) {\n\t\t\tthis._clearTimeout();\n\t\t\tthis._init();\n\t\t}\n\t}\n\n\t/**\n\t * Triggers toast closing programmatically.\n\t *\n\t * The returned observable will emit and be completed once the closing transition has finished.\n\t * If the animations are turned off this happens synchronously.\n\t *\n\t * Alternatively you could listen or subscribe to the `(hidden)` output\n\t *\n\t * @since 8.0.0\n\t */\n\thide(): Observable<void> {\n\t\tthis._clearTimeout();\n\t\tconst transition = ngbRunTransition(this._zone, this._element.nativeElement, ngbToastFadeOutTransition, {\n\t\t\tanimation: this.animation,\n\t\t\trunningTransition: 'stop',\n\t\t});\n\t\ttransition.subscribe(() => {\n\t\t\tthis.hidden.emit();\n\t\t});\n\t\treturn transition;\n\t}\n\n\t/**\n\t * Triggers toast opening programmatically.\n\t *\n\t * The returned observable will emit and be completed once the opening transition has finished.\n\t * If the animations are turned off this happens synchronously.\n\t *\n\t * Alternatively you could listen or subscribe to the `(shown)` output\n\t *\n\t * @since 8.0.0\n\t */\n\tshow(): Observable<void> {\n\t\tconst transition = ngbRunTransition(this._zone, this._element.nativeElement, ngbToastFadeInTransition, {\n\t\t\tanimation: this.animation,\n\t\t\trunningTransition: 'continue',\n\t\t});\n\t\ttransition.subscribe(() => {\n\t\t\tthis.shown.emit();\n\t\t});\n\t\treturn transition;\n\t}\n\n\tprivate _init() {\n\t\tif (this.autohide && !this._timeoutID) {\n\t\t\tthis._timeoutID = setTimeout(() => this.hide(), this.delay);\n\t\t}\n\t}\n\n\tprivate _clearTimeout() {\n\t\tif (this._timeoutID) {\n\t\t\tclearTimeout(this._timeoutID);\n\t\t\tthis._timeoutID = null;\n\t\t}\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbToast, NgbToastHeader } from './toast';\n\nexport { NgbToast, NgbToastHeader } from './toast';\nexport { NgbToastConfig, NgbToastOptions } from './toast-config';\n\n@NgModule({\n\timports: [NgbToast, NgbToastHeader],\n\texports: [NgbToast, NgbToastHeader],\n})\nexport class NgbToastModule {}\n","import { Injectable } from '@angular/core';\nimport { PlacementArray } from '../util/positioning';\nimport { NgbConfig } from '../ngb-config';\nimport { Options } from '@popperjs/core';\n\n/**\n * A configuration service for the [`NgbTooltip`](#/components/tooltip/api#NgbTooltip) component.\n *\n * You can inject this service, typically in your root component, and customize the values of its properties in\n * order to provide default values for all the tooltips used in the application.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgbTooltipConfig {\n\tautoClose: boolean | 'inside' | 'outside' = true;\n\tplacement: PlacementArray = 'auto';\n\tpopperOptions = (options: Partial<Options>) => options;\n\ttriggers = 'hover focus';\n\tcontainer: string;\n\tdisableTooltip = false;\n\ttooltipClass: string;\n\topenDelay = 0;\n\tcloseDelay = 0;\n\n\tprivate _animation: boolean;\n\n\tconstructor(private _ngbConfig: NgbConfig) {}\n\n\tget animation(): boolean {\n\t\treturn this._animation === undefined ? this._ngbConfig.animation : this._animation;\n\t}\n\tset animation(animation: boolean) {\n\t\tthis._animation = animation;\n\t}\n}\n","import {\n\tApplicationRef,\n\tChangeDetectionStrategy,\n\tChangeDetectorRef,\n\tComponent,\n\tComponentRef,\n\tDirective,\n\tElementRef,\n\tEventEmitter,\n\tInject,\n\tInjector,\n\tInput,\n\tNgZone,\n\tOnChanges,\n\tOnDestroy,\n\tOnInit,\n\tOutput,\n\tRenderer2,\n\tSimpleChanges,\n\tTemplateRef,\n\tViewContainerRef,\n\tViewEncapsulation,\n} from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { listenToTriggers } from '../util/triggers';\nimport { ngbAutoClose } from '../util/autoclose';\nimport { ngbPositioning, PlacementArray } from '../util/positioning';\nimport { PopupService } from '../util/popup';\nimport { Options } from '@popperjs/core';\nimport { isString } from '../util/util';\n\nimport { NgbTooltipConfig } from './tooltip-config';\nimport { Subscription } from 'rxjs';\n\nlet nextId = 0;\n\n@Component({\n\tselector: 'ngb-tooltip-window',\n\tstandalone: true,\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\tencapsulation: ViewEncapsulation.None,\n\thost: {\n\t\t'[class]': '\"tooltip\" + (tooltipClass ? \" \" + tooltipClass : \"\")',\n\t\t'[class.fade]': 'animation',\n\t\trole: 'tooltip',\n\t\t'[id]': 'id',\n\t\tstyle: 'position: absolute;',\n\t},\n\ttemplate: `<div class=\"tooltip-arrow\" data-popper-arrow></div\n\t\t><div class=\"tooltip-inner\"><ng-content></ng-content></div>`,\n})\nexport class NgbTooltipWindow {\n\t@Input() animation: boolean;\n\t@Input() id: string;\n\t@Input() tooltipClass: string;\n}\n\n/**\n * A lightweight and extensible directive for fancy tooltip creation.\n */\n@Directive({ selector: '[ngbTooltip]', standalone: true, exportAs: 'ngbTooltip' })\nexport class NgbTooltip implements OnInit, OnDestroy, OnChanges {\n\tstatic ngAcceptInputType_autoClose: boolean | string;\n\n\t/**\n\t * If `true`, tooltip opening and closing will be animated.\n\t *\n\t * @since 8.0.0\n\t */\n\t@Input() animation: boolean;\n\n\t/**\n\t * Indicates whether the tooltip should be closed on `Escape` key and inside/outside clicks:\n\t *\n\t * * `true` - closes on both outside and inside clicks as well as `Escape` presses\n\t * * `false` - disables the autoClose feature (NB: triggers still apply)\n\t * * `\"inside\"` - closes on inside clicks as well as Escape presses\n\t * * `\"outside\"` - closes on outside clicks (sometimes also achievable through triggers)\n\t * as well as `Escape` presses\n\t *\n\t * @since 3.0.0\n\t */\n\t@Input() autoClose: boolean | 'inside' | 'outside';\n\n\t/**\n\t * The preferred placement of the tooltip, among the [possible values](#/guides/positioning#api).\n\t *\n\t * The default order of preference is `\"auto\"`.\n\t *\n\t * Please see the [positioning overview](#/positioning) for more details.\n\t */\n\t@Input() placement: PlacementArray;\n\n\t/**\n\t * Allows to change default Popper options when positioning the tooltip.\n\t * Receives current popper options and returns modified ones.\n\t *\n\t * @since 13.1.0\n\t */\n\t@Input() popperOptions: (options: Partial<Options>) => Partial<Options>;\n\n\t/**\n\t * Specifies events that should trigger the tooltip.\n\t *\n\t * Supports a space separated list of event names.\n\t * For more details see the [triggers demo](#/components/tooltip/examples#triggers).\n\t */\n\t@Input() triggers: string;\n\n\t/**\n\t * A css selector or html element specifying the element the tooltip should be positioned against.\n\t * By default, the element `ngbTooltip` directive is applied to will be set as a target.\n\t *\n\t * @since 13.1.0\n\t */\n\t@Input() positionTarget?: string | HTMLElement;\n\n\t/**\n\t * A selector specifying the element the tooltip should be appended to.\n\t *\n\t * Currently only supports `\"body\"`.\n\t */\n\t@Input() container: string;\n\n\t/**\n\t * If `true`, tooltip is disabled and won't be displayed.\n\t *\n\t * @since 1.1.0\n\t */\n\t@Input() disableTooltip: boolean;\n\n\t/**\n\t * An optional class applied to the tooltip window element.\n\t *\n\t * @since 3.2.0\n\t */\n\t@Input() tooltipClass: string;\n\n\t/**\n\t * The opening delay in ms. Works only for \"non-manual\" opening triggers defined by the `triggers` input.\n\t *\n\t * @since 4.1.0\n\t */\n\t@Input() openDelay: number;\n\n\t/**\n\t * The closing delay in ms. Works only for \"non-manual\" opening triggers defined by the `triggers` input.\n\t *\n\t * @since 4.1.0\n\t */\n\t@Input() closeDelay: number;\n\n\t/**\n\t * An event emitted when the tooltip opening animation has finished. Contains no payload.\n\t */\n\t@Output() shown = new EventEmitter();\n\n\t/**\n\t * An event emitted when the tooltip closing animation has finished. Contains no payload.\n\t */\n\t@Output() hidden = new EventEmitter();\n\n\tprivate _ngbTooltip: string | TemplateRef<any> | null | undefined;\n\tprivate _ngbTooltipWindowId = `ngb-tooltip-${nextId++}`;\n\tprivate _popupService: PopupService<NgbTooltipWindow>;\n\tprivate _windowRef: ComponentRef<NgbTooltipWindow> | null = null;\n\tprivate _unregisterListenersFn;\n\tprivate _positioning: ReturnType<typeof ngbPositioning>;\n\tprivate _zoneSubscription: Subscription;\n\n\tconstructor(\n\t\tprivate _elementRef: ElementRef<HTMLElement>,\n\t\tprivate _renderer: Renderer2,\n\t\tinjector: Injector,\n\t\tviewContainerRef: ViewContainerRef,\n\t\tconfig: NgbTooltipConfig,\n\t\tprivate _ngZone: NgZone,\n\t\t@Inject(DOCUMENT) private _document: any,\n\t\tprivate _changeDetector: ChangeDetectorRef,\n\t\tapplicationRef: ApplicationRef,\n\t) {\n\t\tthis.animation = config.animation;\n\t\tthis.autoClose = config.autoClose;\n\t\tthis.placement = config.placement;\n\t\tthis.popperOptions = config.popperOptions;\n\t\tthis.triggers = config.triggers;\n\t\tthis.container = config.container;\n\t\tthis.disableTooltip = config.disableTooltip;\n\t\tthis.tooltipClass = config.tooltipClass;\n\t\tthis.openDelay = config.openDelay;\n\t\tthis.closeDelay = config.closeDelay;\n\t\tthis._popupService = new PopupService<NgbTooltipWindow>(\n\t\t\tNgbTooltipWindow,\n\t\t\tinjector,\n\t\t\tviewContainerRef,\n\t\t\t_renderer,\n\t\t\tthis._ngZone,\n\t\t\tapplicationRef,\n\t\t);\n\t\tthis._positioning = ngbPositioning();\n\t}\n\n\t/**\n\t * The string content or a `TemplateRef` for the content to be displayed in the tooltip.\n\t *\n\t * If the content if falsy, the tooltip won't open.\n\t */\n\t@Input()\n\tset ngbTooltip(value: string | TemplateRef<any> | null | undefined) {\n\t\tthis._ngbTooltip = value;\n\t\tif (!value && this._windowRef) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\tget ngbTooltip() {\n\t\treturn this._ngbTooltip;\n\t}\n\n\t/**\n\t * Opens the tooltip.\n\t *\n\t * This is considered to be a \"manual\" triggering.\n\t * The `context` is an optional value to be injected into the tooltip template when it is created.\n\t */\n\topen(context?: any) {\n\t\tif (!this._windowRef && this._ngbTooltip && !this.disableTooltip) {\n\t\t\tconst { windowRef, transition$ } = this._popupService.open(this._ngbTooltip, context, this.animation);\n\t\t\tthis._windowRef = windowRef;\n\t\t\tthis._windowRef.setInput('animation', this.animation);\n\t\t\tthis._windowRef.setInput('tooltipClass', this.tooltipClass);\n\t\t\tthis._windowRef.setInput('id', this._ngbTooltipWindowId);\n\n\t\t\tthis._renderer.setAttribute(this._getPositionTargetElement(), 'aria-describedby', this._ngbTooltipWindowId);\n\n\t\t\tif (this.container === 'body') {\n\t\t\t\tthis._document.querySelector(this.container).appendChild(this._windowRef.location.nativeElement);\n\t\t\t}\n\n\t\t\t// We need to detect changes, because we don't know where .open() might be called from.\n\t\t\t// Ex. opening tooltip from one of lifecycle hooks that run after the CD\n\t\t\t// (say from ngAfterViewInit) will result in 'ExpressionHasChanged' exception\n\t\t\tthis._windowRef.changeDetectorRef.detectChanges();\n\n\t\t\t// We need to mark for check, because tooltip won't work inside the OnPush component.\n\t\t\t// Ex. when we use expression like `{{ tooltip.isOpen() : 'opened' : 'closed' }}`\n\t\t\t// inside the template of an OnPush component and we change the tooltip from\n\t\t\t// open -> closed, the expression in question won't be updated unless we explicitly\n\t\t\t// mark the parent component to be checked.\n\t\t\tthis._windowRef.changeDetectorRef.markForCheck();\n\n\t\t\t// Setting up popper and scheduling updates when zone is stable\n\t\t\tthis._ngZone.runOutsideAngular(() => {\n\t\t\t\tthis._positioning.createPopper({\n\t\t\t\t\thostElement: this._getPositionTargetElement(),\n\t\t\t\t\ttargetElement: this._windowRef!.location.nativeElement,\n\t\t\t\t\tplacement: this.placement,\n\t\t\t\t\tappendToBody: this.container === 'body',\n\t\t\t\t\tbaseClass: 'bs-tooltip',\n\t\t\t\t\tupdatePopperOptions: (options) => this.popperOptions(options),\n\t\t\t\t});\n\n\t\t\t\tPromise.resolve().then(() => {\n\t\t\t\t\t// This update is required for correct arrow placement\n\t\t\t\t\tthis._positioning.update();\n\t\t\t\t\tthis._zoneSubscription = this._ngZone.onStable.subscribe(() => this._positioning.update());\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tngbAutoClose(this._ngZone, this._document, this.autoClose, () => this.close(), this.hidden, [\n\t\t\t\tthis._windowRef.location.nativeElement,\n\t\t\t]);\n\n\t\t\ttransition$.subscribe(() => this.shown.emit());\n\t\t}\n\t}\n\n\t/**\n\t * Closes the tooltip.\n\t *\n\t * This is considered to be a \"manual\" triggering of the tooltip.\n\t */\n\tclose(animation = this.animation): void {\n\t\tif (this._windowRef != null) {\n\t\t\tthis._renderer.removeAttribute(this._getPositionTargetElement(), 'aria-describedby');\n\t\t\tthis._popupService.close(animation).subscribe(() => {\n\t\t\t\tthis._windowRef = null;\n\t\t\t\tthis._positioning.destroy();\n\t\t\t\tthis._zoneSubscription?.unsubscribe();\n\t\t\t\tthis.hidden.emit();\n\t\t\t\tthis._changeDetector.markForCheck();\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Toggles the tooltip.\n\t *\n\t * This is considered to be a \"manual\" triggering of the tooltip.\n\t */\n\ttoggle(): void {\n\t\tif (this._windowRef) {\n\t\t\tthis.close();\n\t\t} else {\n\t\t\tthis.open();\n\t\t}\n\t}\n\n\t/**\n\t * Returns `true`, if the popover is currently shown.\n\t */\n\tisOpen(): boolean {\n\t\treturn this._windowRef != null;\n\t}\n\n\tngOnInit() {\n\t\tthis._unregisterListenersFn = listenToTriggers(\n\t\t\tthis._renderer,\n\t\t\tthis._elementRef.nativeElement,\n\t\t\tthis.triggers,\n\t\t\tthis.isOpen.bind(this),\n\t\t\tthis.open.bind(this),\n\t\t\tthis.close.bind(this),\n\t\t\t+this.openDelay,\n\t\t\t+this.closeDelay,\n\t\t);\n\t}\n\n\tngOnChanges({ tooltipClass }: SimpleChanges) {\n\t\tif (tooltipClass && this.isOpen()) {\n\t\t\tthis._windowRef!.instance.tooltipClass = tooltipClass.currentValue;\n\t\t}\n\t}\n\n\tngOnDestroy() {\n\t\tthis.close(false);\n\t\t// This check is needed as it might happen that ngOnDestroy is called before ngOnInit\n\t\t// under certain conditions, see: https://github.com/ng-bootstrap/ng-bootstrap/issues/2199\n\t\tthis._unregisterListenersFn?.();\n\t}\n\n\tprivate _getPositionTargetElement(): HTMLElement {\n\t\treturn (\n\t\t\t(isString(this.positionTarget) ? this._document.querySelector(this.positionTarget) : this.positionTarget) ||\n\t\t\tthis._elementRef.nativeElement\n\t\t);\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbTooltip } from './tooltip';\n\nexport { NgbTooltipConfig } from './tooltip-config';\nexport { NgbTooltip } from './tooltip';\nexport { Placement } from '../util/positioning';\n\n@NgModule({\n\timports: [NgbTooltip],\n\texports: [NgbTooltip],\n})\nexport class NgbTooltipModule {}\n","import { Injectable, Inject, InjectionToken, OnDestroy } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\n// usefulness (and default value) of delay documented in Material's CDK\n// https://github.com/angular/material2/blob/6405da9b8e8532a7e5c854c920ee1815c275d734/src/cdk/a11y/live-announcer/live-announcer.ts#L50\nexport type ARIA_LIVE_DELAY_TYPE = number | null;\nexport const ARIA_LIVE_DELAY = new InjectionToken<ARIA_LIVE_DELAY_TYPE>('live announcer delay', {\n\tprovidedIn: 'root',\n\tfactory: ARIA_LIVE_DELAY_FACTORY,\n});\nexport function ARIA_LIVE_DELAY_FACTORY(): number {\n\treturn 100;\n}\n\nfunction getLiveElement(document: any, lazyCreate = false): HTMLElement | null {\n\tlet element = document.body.querySelector('#ngb-live') as HTMLElement;\n\n\tif (element == null && lazyCreate) {\n\t\telement = document.createElement('div');\n\n\t\telement.setAttribute('id', 'ngb-live');\n\t\telement.setAttribute('aria-live', 'polite');\n\t\telement.setAttribute('aria-atomic', 'true');\n\n\t\telement.classList.add('visually-hidden');\n\n\t\tdocument.body.appendChild(element);\n\t}\n\n\treturn element;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class Live implements OnDestroy {\n\tconstructor(@Inject(DOCUMENT) private _document: any, @Inject(ARIA_LIVE_DELAY) private _delay: any) {}\n\n\tngOnDestroy() {\n\t\tconst element = getLiveElement(this._document);\n\t\tif (element) {\n\t\t\t// if exists, it will always be attached to the <body>\n\t\t\telement.parentElement!.removeChild(element);\n\t\t}\n\t}\n\n\tsay(message: string) {\n\t\tconst element = getLiveElement(this._document, true);\n\t\tconst delay = this._delay;\n\n\t\tif (element != null) {\n\t\t\telement.textContent = '';\n\t\t\tconst setText = () => (element.textContent = message);\n\t\t\tif (delay === null) {\n\t\t\t\tsetText();\n\t\t\t} else {\n\t\t\t\tsetTimeout(setText, delay);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { NgModule } from '@angular/core';\n\nimport { NgbHighlight } from './highlight';\nimport { NgbTypeahead } from './typeahead';\n\nexport { NgbHighlight } from './highlight';\nexport { NgbTypeaheadWindow } from './typeahead-window';\nexport { NgbTypeaheadConfig } from './typeahead-config';\nexport { NgbTypeahead, NgbTypeaheadSelectItemEvent } from './typeahead';\n\n@NgModule({\n\timports: [NgbHighlight, NgbTypeahead],\n\texports: [NgbHighlight, NgbTypeahead],\n})\nexport class NgbTypeaheadModule {}\n","import { NgModule } from '@angular/core';\n\nexport { NgbOffcanvas } from './offcanvas';\nexport { NgbOffcanvasConfig, NgbOffcanvasOptions } from './offcanvas-config';\nexport { NgbOffcanvasRef, NgbActiveOffcanvas } from './offcanvas-ref';\nexport { OffcanvasDismissReasons } from './offcanvas-dismiss-reasons';\n\n@NgModule({})\nexport class NgbOffcanvasModule {}\n","import { NgModule } from '@angular/core';\n\nimport { NgbAccordionModule } from './accordion/accordion.module';\nimport { NgbAlertModule } from './alert/alert.module';\nimport { NgbCarouselModule } from './carousel/carousel.module';\nimport { NgbCollapseModule } from './collapse/collapse.module';\nimport { NgbDatepickerModule } from './datepicker/datepicker.module';\nimport { NgbDropdownModule } from './dropdown/dropdown.module';\nimport { NgbModalModule } from './modal/modal.module';\nimport { NgbNavModule } from './nav/nav.module';\nimport { NgbPaginationModule } from './pagination/pagination.module';\nimport { NgbPopoverModule } from './popover/popover.module';\nimport { NgbProgressbarModule } from './progressbar/progressbar.module';\nimport { NgbRatingModule } from './rating/rating.module';\nimport { NgbTimepickerModule } from './timepicker/timepicker.module';\nimport { NgbToastModule } from './toast/toast.module';\nimport { NgbTooltipModule } from './tooltip/tooltip.module';\nimport { NgbTypeaheadModule } from './typeahead/typeahead.module';\nimport { NgbOffcanvasModule } from './offcanvas/offcanvas.module';\n\nexport {\n\tNgbAccordionDirective,\n\tNgbAccordionItem,\n\tNgbAccordionHeader,\n\tNgbAccordionToggle,\n\tNgbAccordionCollapse,\n\tNgbAccordionBody,\n\tNgbAccordionButton,\n} from './accordion/accordion.module';\n\n/* eslint-disable deprecation/deprecation */\nexport {\n\tNgbAccordion,\n\tNgbAccordionConfig,\n\tNgbAccordionModule,\n\tNgbPanel,\n\tNgbPanelChangeEvent,\n\tNgbPanelContent,\n\tNgbPanelHeader,\n\tNgbPanelHeaderContext,\n\tNgbPanelTitle,\n\tNgbPanelToggle,\n} from './accordion/accordion.module';\n/* eslint-disable deprecation/deprecation */\nexport { NgbAlert, NgbAlertConfig, NgbAlertModule } from './alert/alert.module';\nexport {\n\tNgbCarousel,\n\tNgbCarouselConfig,\n\tNgbCarouselModule,\n\tNgbSlide,\n\tNgbSlideEvent,\n\tNgbSlideEventDirection,\n\tNgbSlideEventSource,\n} from './carousel/carousel.module';\nexport { NgbCollapse, NgbCollapseConfig, NgbCollapseModule } from './collapse/collapse.module';\nexport {\n\tNgbCalendar,\n\tNgbCalendarGregorian,\n\tNgbCalendarHebrew,\n\tNgbCalendarIslamicCivil,\n\tNgbCalendarIslamicUmalqura,\n\tNgbCalendarPersian,\n\tNgbCalendarBuddhist,\n\tNgbDate,\n\tNgbDateAdapter,\n\tNgbDateStructAdapter,\n\tNgbDateNativeAdapter,\n\tNgbDateNativeUTCAdapter,\n\tNgbDateParserFormatter,\n\tNgbDatepicker,\n\tNgbDatepickerConfig,\n\tNgbInputDatepickerConfig,\n\tNgbDatepickerContent,\n\tNgbDatepickerI18n,\n\tNgbDatepickerI18nDefault,\n\tNgbDatepickerI18nHebrew,\n\tNgbDatepickerKeyboardService,\n\tNgbDatepickerModule,\n\tNgbDatepickerMonth,\n\tNgbDatepickerNavigateEvent,\n\tNgbDatepickerState,\n\tNgbDateStruct,\n\tNgbInputDatepicker,\n\tNgbPeriod,\n} from './datepicker/datepicker.module';\nexport {\n\tNgbDropdown,\n\tNgbDropdownAnchor,\n\tNgbDropdownConfig,\n\tNgbDropdownItem,\n\tNgbDropdownMenu,\n\tNgbDropdownModule,\n\tNgbDropdownToggle,\n\t// eslint-disable-next-line deprecation/deprecation\n\tNgbNavbar,\n} from './dropdown/dropdown.module';\nexport {\n\tModalDismissReasons,\n\tNgbActiveModal,\n\tNgbModal,\n\tNgbModalConfig,\n\tNgbModalModule,\n\tNgbModalOptions,\n\tNgbModalUpdatableOptions,\n\tNgbModalRef,\n} from './modal/modal.module';\nexport {\n\tNgbNavChangeEvent,\n\tNgbNavConfig,\n\tNgbNav,\n\tNgbNavContent,\n\tNgbNavContentContext,\n\tNgbNavItem,\n\tNgbNavItemRole,\n\tNgbNavLink,\n\tNgbNavLinkButton,\n\tNgbNavLinkBase,\n\tNgbNavModule,\n\tNgbNavOutlet,\n\tNgbNavPane,\n} from './nav/nav.module';\nexport {\n\tOffcanvasDismissReasons,\n\tNgbActiveOffcanvas,\n\tNgbOffcanvas,\n\tNgbOffcanvasConfig,\n\tNgbOffcanvasModule,\n\tNgbOffcanvasOptions,\n\tNgbOffcanvasRef,\n} from './offcanvas/offcanvas.module';\nexport {\n\tNgbPagination,\n\tNgbPaginationConfig,\n\tNgbPaginationEllipsis,\n\tNgbPaginationFirst,\n\tNgbPaginationLast,\n\tNgbPaginationModule,\n\tNgbPaginationNext,\n\tNgbPaginationNumber,\n\tNgbPaginationPrevious,\n\tNgbPaginationPages,\n} from './pagination/pagination.module';\nexport { NgbPopover, NgbPopoverConfig, NgbPopoverModule } from './popover/popover.module';\nexport { NgbProgressbar, NgbProgressbarConfig, NgbProgressbarModule } from './progressbar/progressbar.module';\nexport { NgbRating, NgbRatingConfig, NgbRatingModule } from './rating/rating.module';\nexport {\n\tNgbTimeAdapter,\n\tNgbTimepickerI18n,\n\tNgbTimepicker,\n\tNgbTimepickerConfig,\n\tNgbTimepickerModule,\n\tNgbTimeStruct,\n} from './timepicker/timepicker.module';\nexport { NgbToast, NgbToastConfig, NgbToastHeader, NgbToastModule } from './toast/toast.module';\nexport { NgbTooltip, NgbTooltipConfig, NgbTooltipModule } from './tooltip/tooltip.module';\nexport {\n\tNgbHighlight,\n\tNgbTypeahead,\n\tNgbTypeaheadConfig,\n\tNgbTypeaheadModule,\n\tNgbTypeaheadSelectItemEvent,\n} from './typeahead/typeahead.module';\nexport { Placement } from './util/positioning';\n\nexport { NgbConfig } from './ngb-config';\n\nconst NGB_MODULES = [\n\tNgbAccordionModule,\n\tNgbAlertModule,\n\tNgbCarouselModule,\n\tNgbCollapseModule,\n\tNgbDatepickerModule,\n\tNgbDropdownModule,\n\tNgbModalModule,\n\tNgbNavModule,\n\tNgbOffcanvasModule,\n\tNgbPaginationModule,\n\tNgbPopoverModule,\n\tNgbProgressbarModule,\n\tNgbRatingModule,\n\tNgbTimepickerModule,\n\tNgbToastModule,\n\tNgbTooltipModule,\n\tNgbTypeaheadModule,\n];\n\n@NgModule({ imports: NGB_MODULES, exports: NGB_MODULES })\nexport class NgbModule {}\n","import { PartialObserver, ObservableNotification, CompleteNotification, NextNotification, ErrorNotification } from './types';\nimport { Observable } from './Observable';\nimport { EMPTY } from './observable/empty';\nimport { of } from './observable/of';\nimport { throwError } from './observable/throwError';\nimport { isFunction } from './util/isFunction';\n\n// TODO: When this enum is removed, replace it with a type alias. See #4556.\n/**\n * @deprecated Use a string literal instead. `NotificationKind` will be replaced with a type alias in v8.\n * It will not be replaced with a const enum as those are not compatible with isolated modules.\n */\nexport enum NotificationKind {\n NEXT = 'N',\n ERROR = 'E',\n COMPLETE = 'C',\n}\n\n/**\n * Represents a push-based event or value that an {@link Observable} can emit.\n * This class is particularly useful for operators that manage notifications,\n * like {@link materialize}, {@link dematerialize}, {@link observeOn}, and\n * others. Besides wrapping the actual delivered value, it also annotates it\n * with metadata of, for instance, what type of push message it is (`next`,\n * `error`, or `complete`).\n *\n * @see {@link materialize}\n * @see {@link dematerialize}\n * @see {@link observeOn}\n * @deprecated It is NOT recommended to create instances of `Notification` directly.\n * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.\n * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.\n * Will be removed in v8.\n */\nexport class Notification<T> {\n /**\n * A value signifying that the notification will \"next\" if observed. In truth,\n * This is really synonymous with just checking `kind === \"N\"`.\n * @deprecated Will be removed in v8. Instead, just check to see if the value of `kind` is `\"N\"`.\n */\n readonly hasValue: boolean;\n\n /**\n * Creates a \"Next\" notification object.\n * @param kind Always `'N'`\n * @param value The value to notify with if observed.\n * @deprecated Internal implementation detail. Use {@link Notification#createNext createNext} instead.\n */\n constructor(kind: 'N', value?: T);\n /**\n * Creates an \"Error\" notification object.\n * @param kind Always `'E'`\n * @param value Always `undefined`\n * @param error The error to notify with if observed.\n * @deprecated Internal implementation detail. Use {@link Notification#createError createError} instead.\n */\n constructor(kind: 'E', value: undefined, error: any);\n /**\n * Creates a \"completion\" notification object.\n * @param kind Always `'C'`\n * @deprecated Internal implementation detail. Use {@link Notification#createComplete createComplete} instead.\n */\n constructor(kind: 'C');\n constructor(public readonly kind: 'N' | 'E' | 'C', public readonly value?: T, public readonly error?: any) {\n this.hasValue = kind === 'N';\n }\n\n /**\n * Executes the appropriate handler on a passed `observer` given the `kind` of notification.\n * If the handler is missing it will do nothing. Even if the notification is an error, if\n * there is no error handler on the observer, an error will not be thrown, it will noop.\n * @param observer The observer to notify.\n */\n observe(observer: PartialObserver<T>): void {\n return observeNotification(this as ObservableNotification<T>, observer);\n }\n\n /**\n * Executes a notification on the appropriate handler from a list provided.\n * If a handler is missing for the kind of notification, nothing is called\n * and no error is thrown, it will be a noop.\n * @param next A next handler\n * @param error An error handler\n * @param complete A complete handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n do(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;\n /**\n * Executes a notification on the appropriate handler from a list provided.\n * If a handler is missing for the kind of notification, nothing is called\n * and no error is thrown, it will be a noop.\n * @param next A next handler\n * @param error An error handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n do(next: (value: T) => void, error: (err: any) => void): void;\n /**\n * Executes the next handler if the Notification is of `kind` `\"N\"`. Otherwise\n * this will not error, and it will be a noop.\n * @param next The next handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n do(next: (value: T) => void): void;\n do(nextHandler: (value: T) => void, errorHandler?: (err: any) => void, completeHandler?: () => void): void {\n const { kind, value, error } = this;\n return kind === 'N' ? nextHandler?.(value!) : kind === 'E' ? errorHandler?.(error) : completeHandler?.();\n }\n\n /**\n * Executes a notification on the appropriate handler from a list provided.\n * If a handler is missing for the kind of notification, nothing is called\n * and no error is thrown, it will be a noop.\n * @param next A next handler\n * @param error An error handler\n * @param complete A complete handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n accept(next: (value: T) => void, error: (err: any) => void, complete: () => void): void;\n /**\n * Executes a notification on the appropriate handler from a list provided.\n * If a handler is missing for the kind of notification, nothing is called\n * and no error is thrown, it will be a noop.\n * @param next A next handler\n * @param error An error handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n accept(next: (value: T) => void, error: (err: any) => void): void;\n /**\n * Executes the next handler if the Notification is of `kind` `\"N\"`. Otherwise\n * this will not error, and it will be a noop.\n * @param next The next handler\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n accept(next: (value: T) => void): void;\n\n /**\n * Executes the appropriate handler on a passed `observer` given the `kind` of notification.\n * If the handler is missing it will do nothing. Even if the notification is an error, if\n * there is no error handler on the observer, an error will not be thrown, it will noop.\n * @param observer The observer to notify.\n * @deprecated Replaced with {@link Notification#observe observe}. Will be removed in v8.\n */\n accept(observer: PartialObserver<T>): void;\n accept(nextOrObserver: PartialObserver<T> | ((value: T) => void), error?: (err: any) => void, complete?: () => void) {\n return isFunction((nextOrObserver as any)?.next)\n ? this.observe(nextOrObserver as PartialObserver<T>)\n : this.do(nextOrObserver as (value: T) => void, error as any, complete as any);\n }\n\n /**\n * Returns a simple Observable that just delivers the notification represented\n * by this Notification instance.\n *\n * @deprecated Will be removed in v8. To convert a `Notification` to an {@link Observable},\n * use {@link of} and {@link dematerialize}: `of(notification).pipe(dematerialize())`.\n */\n toObservable(): Observable<T> {\n const { kind, value, error } = this;\n // Select the observable to return by `kind`\n const result =\n kind === 'N'\n ? // Next kind. Return an observable of that value.\n of(value!)\n : //\n kind === 'E'\n ? // Error kind. Return an observable that emits the error.\n throwError(() => error)\n : //\n kind === 'C'\n ? // Completion kind. Kind is \"C\", return an observable that just completes.\n EMPTY\n : // Unknown kind, return falsy, so we error below.\n 0;\n if (!result) {\n // TODO: consider removing this check. The only way to cause this would be to\n // use the Notification constructor directly in a way that is not type-safe.\n // and direct use of the Notification constructor is deprecated.\n throw new TypeError(`Unexpected notification kind ${kind}`);\n }\n return result;\n }\n\n private static completeNotification = new Notification('C') as Notification<never> & CompleteNotification;\n /**\n * A shortcut to create a Notification instance of the type `next` from a\n * given value.\n * @param {T} value The `next` value.\n * @return {Notification<T>} The \"next\" Notification representing the\n * argument.\n * @nocollapse\n * @deprecated It is NOT recommended to create instances of `Notification` directly.\n * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.\n * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.\n * Will be removed in v8.\n */\n static createNext<T>(value: T) {\n return new Notification('N', value) as Notification<T> & NextNotification<T>;\n }\n\n /**\n * A shortcut to create a Notification instance of the type `error` from a\n * given error.\n * @param {any} [err] The `error` error.\n * @return {Notification<T>} The \"error\" Notification representing the\n * argument.\n * @nocollapse\n * @deprecated It is NOT recommended to create instances of `Notification` directly.\n * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.\n * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.\n * Will be removed in v8.\n */\n static createError(err?: any) {\n return new Notification('E', undefined, err) as Notification<never> & ErrorNotification;\n }\n\n /**\n * A shortcut to create a Notification instance of the type `complete`.\n * @return {Notification<any>} The valueless \"complete\" Notification.\n * @nocollapse\n * @deprecated It is NOT recommended to create instances of `Notification` directly.\n * Rather, try to create POJOs matching the signature outlined in {@link ObservableNotification}.\n * For example: `{ kind: 'N', value: 1 }`, `{ kind: 'E', error: new Error('bad') }`, or `{ kind: 'C' }`.\n * Will be removed in v8.\n */\n static createComplete(): Notification<never> & CompleteNotification {\n return Notification.completeNotification;\n }\n}\n\n/**\n * Executes the appropriate handler on a passed `observer` given the `kind` of notification.\n * If the handler is missing it will do nothing. Even if the notification is an error, if\n * there is no error handler on the observer, an error will not be thrown, it will noop.\n * @param notification The notification object to observe.\n * @param observer The observer to notify.\n */\nexport function observeNotification<T>(notification: ObservableNotification<T>, observer: PartialObserver<T>) {\n const { kind, value, error } = notification as any;\n if (typeof kind !== 'string') {\n throw new TypeError('Invalid notification, missing \"kind\"');\n }\n kind === 'N' ? observer.next?.(value!) : kind === 'E' ? observer.error?.(error) : observer.complete?.();\n}\n","import { Observable } from '../Observable';\nimport { innerFrom } from '../observable/innerFrom';\nimport { Subject } from '../Subject';\nimport { ObservableInput, Observer, OperatorFunction, SubjectLike } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber, OperatorSubscriber } from './OperatorSubscriber';\n\nexport interface BasicGroupByOptions<K, T> {\n element?: undefined;\n duration?: (grouped: GroupedObservable<K, T>) => ObservableInput<any>;\n connector?: () => SubjectLike<T>;\n}\n\nexport interface GroupByOptionsWithElement<K, E, T> {\n element: (value: T) => E;\n duration?: (grouped: GroupedObservable<K, E>) => ObservableInput<any>;\n connector?: () => SubjectLike<E>;\n}\n\nexport function groupBy<T, K>(key: (value: T) => K, options: BasicGroupByOptions<K, T>): OperatorFunction<T, GroupedObservable<K, T>>;\n\nexport function groupBy<T, K, E>(\n key: (value: T) => K,\n options: GroupByOptionsWithElement<K, E, T>\n): OperatorFunction<T, GroupedObservable<K, E>>;\n\nexport function groupBy<T, K extends T>(\n key: (value: T) => value is K\n): OperatorFunction<T, GroupedObservable<true, K> | GroupedObservable<false, Exclude<T, K>>>;\n\nexport function groupBy<T, K>(key: (value: T) => K): OperatorFunction<T, GroupedObservable<K, T>>;\n\n/**\n * @deprecated use the options parameter instead.\n */\nexport function groupBy<T, K>(\n key: (value: T) => K,\n element: void,\n duration: (grouped: GroupedObservable<K, T>) => Observable<any>\n): OperatorFunction<T, GroupedObservable<K, T>>;\n\n/**\n * @deprecated use the options parameter instead.\n */\nexport function groupBy<T, K, R>(\n key: (value: T) => K,\n element?: (value: T) => R,\n duration?: (grouped: GroupedObservable<K, R>) => Observable<any>\n): OperatorFunction<T, GroupedObservable<K, R>>;\n\n/**\n * Groups the items emitted by an Observable according to a specified criterion,\n * and emits these grouped items as `GroupedObservables`, one\n * {@link GroupedObservable} per group.\n *\n * ![](groupBy.png)\n *\n * When the Observable emits an item, a key is computed for this item with the key function.\n *\n * If a {@link GroupedObservable} for this key exists, this {@link GroupedObservable} emits. Otherwise, a new\n * {@link GroupedObservable} for this key is created and emits.\n *\n * A {@link GroupedObservable} represents values belonging to the same group represented by a common key. The common\n * key is available as the `key` field of a {@link GroupedObservable} instance.\n *\n * The elements emitted by {@link GroupedObservable}s are by default the items emitted by the Observable, or elements\n * returned by the element function.\n *\n * ## Examples\n *\n * Group objects by `id` and return as array\n *\n * ```ts\n * import { of, groupBy, mergeMap, reduce } from 'rxjs';\n *\n * of(\n * { id: 1, name: 'JavaScript' },\n * { id: 2, name: 'Parcel' },\n * { id: 2, name: 'webpack' },\n * { id: 1, name: 'TypeScript' },\n * { id: 3, name: 'TSLint' }\n * ).pipe(\n * groupBy(p => p.id),\n * mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [])))\n * )\n * .subscribe(p => console.log(p));\n *\n * // displays:\n * // [{ id: 1, name: 'JavaScript' }, { id: 1, name: 'TypeScript'}]\n * // [{ id: 2, name: 'Parcel' }, { id: 2, name: 'webpack'}]\n * // [{ id: 3, name: 'TSLint' }]\n * ```\n *\n * Pivot data on the `id` field\n *\n * ```ts\n * import { of, groupBy, mergeMap, reduce, map } from 'rxjs';\n *\n * of(\n * { id: 1, name: 'JavaScript' },\n * { id: 2, name: 'Parcel' },\n * { id: 2, name: 'webpack' },\n * { id: 1, name: 'TypeScript' },\n * { id: 3, name: 'TSLint' }\n * ).pipe(\n * groupBy(p => p.id, { element: p => p.name }),\n * mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [`${ group$.key }`]))),\n * map(arr => ({ id: parseInt(arr[0], 10), values: arr.slice(1) }))\n * )\n * .subscribe(p => console.log(p));\n *\n * // displays:\n * // { id: 1, values: [ 'JavaScript', 'TypeScript' ] }\n * // { id: 2, values: [ 'Parcel', 'webpack' ] }\n * // { id: 3, values: [ 'TSLint' ] }\n * ```\n *\n * @param key A function that extracts the key\n * for each item.\n * @param element A function that extracts the\n * return element for each item.\n * @param duration\n * A function that returns an Observable to determine how long each group should\n * exist.\n * @param connector Factory function to create an\n * intermediate Subject through which grouped elements are emitted.\n * @return A function that returns an Observable that emits GroupedObservables,\n * each of which corresponds to a unique key value and each of which emits\n * those items from the source Observable that share that key value.\n *\n * @deprecated Use the options parameter instead.\n */\nexport function groupBy<T, K, R>(\n key: (value: T) => K,\n element?: (value: T) => R,\n duration?: (grouped: GroupedObservable<K, R>) => Observable<any>,\n connector?: () => Subject<R>\n): OperatorFunction<T, GroupedObservable<K, R>>;\n\n// Impl\nexport function groupBy<T, K, R>(\n keySelector: (value: T) => K,\n elementOrOptions?: ((value: any) => any) | void | BasicGroupByOptions<K, T> | GroupByOptionsWithElement<K, R, T>,\n duration?: (grouped: GroupedObservable<any, any>) => ObservableInput<any>,\n connector?: () => SubjectLike<any>\n): OperatorFunction<T, GroupedObservable<K, R>> {\n return operate((source, subscriber) => {\n let element: ((value: any) => any) | void;\n if (!elementOrOptions || typeof elementOrOptions === 'function') {\n element = elementOrOptions as ((value: any) => any);\n } else {\n ({ duration, element, connector } = elementOrOptions);\n }\n\n // A lookup for the groups that we have so far.\n const groups = new Map<K, SubjectLike<any>>();\n\n // Used for notifying all groups and the subscriber in the same way.\n const notify = (cb: (group: Observer<any>) => void) => {\n groups.forEach(cb);\n cb(subscriber);\n };\n\n // Used to handle errors from the source, AND errors that occur during the\n // next call from the source.\n const handleError = (err: any) => notify((consumer) => consumer.error(err));\n\n // The number of actively subscribed groups\n let activeGroups = 0;\n\n // Whether or not teardown was attempted on this subscription.\n let teardownAttempted = false;\n\n // Capturing a reference to this, because we need a handle to it\n // in `createGroupedObservable` below. This is what we use to\n // subscribe to our source observable. This sometimes needs to be unsubscribed\n // out-of-band with our `subscriber` which is the downstream subscriber, or destination,\n // in cases where a user unsubscribes from the main resulting subscription, but\n // still has groups from this subscription subscribed and would expect values from it\n // Consider: `source.pipe(groupBy(fn), take(2))`.\n const groupBySourceSubscriber = new OperatorSubscriber(\n subscriber,\n (value: T) => {\n // Because we have to notify all groups of any errors that occur in here,\n // we have to add our own try/catch to ensure that those errors are propagated.\n // OperatorSubscriber will only send the error to the main subscriber.\n try {\n const key = keySelector(value);\n\n let group = groups.get(key);\n if (!group) {\n // Create our group subject\n groups.set(key, (group = connector ? connector() : new Subject<any>()));\n\n // Emit the grouped observable. Note that we can't do a simple `asObservable()` here,\n // because the grouped observable has special semantics around reference counting\n // to ensure we don't sever our connection to the source prematurely.\n const grouped = createGroupedObservable(key, group);\n subscriber.next(grouped);\n\n if (duration) {\n const durationSubscriber = createOperatorSubscriber(\n // Providing the group here ensures that it is disposed of -- via `unsubscribe` --\n // when the duration subscription is torn down. That is important, because then\n // if someone holds a handle to the grouped observable and tries to subscribe to it\n // after the connection to the source has been severed, they will get an\n // `ObjectUnsubscribedError` and know they can't possibly get any notifications.\n group as any,\n () => {\n // Our duration notified! We can complete the group.\n // The group will be removed from the map in the finalization phase.\n group!.complete();\n durationSubscriber?.unsubscribe();\n },\n // Completions are also sent to the group, but just the group.\n undefined,\n // Errors on the duration subscriber are sent to the group\n // but only the group. They are not sent to the main subscription.\n undefined,\n // Finalization: Remove this group from our map.\n () => groups.delete(key)\n );\n\n // Start our duration notifier.\n groupBySourceSubscriber.add(innerFrom(duration(grouped)).subscribe(durationSubscriber));\n }\n }\n\n // Send the value to our group.\n group.next(element ? element(value) : value);\n } catch (err) {\n handleError(err);\n }\n },\n // Source completes.\n () => notify((consumer) => consumer.complete()),\n // Error from the source.\n handleError,\n // Free up memory.\n // When the source subscription is _finally_ torn down, release the subjects and keys\n // in our groups Map, they may be quite large and we don't want to keep them around if we\n // don't have to.\n () => groups.clear(),\n () => {\n teardownAttempted = true;\n // We only kill our subscription to the source if we have\n // no active groups. As stated above, consider this scenario:\n // source$.pipe(groupBy(fn), take(2)).\n return activeGroups === 0;\n }\n );\n\n // Subscribe to the source\n source.subscribe(groupBySourceSubscriber);\n\n /**\n * Creates the actual grouped observable returned.\n * @param key The key of the group\n * @param groupSubject The subject that fuels the group\n */\n function createGroupedObservable(key: K, groupSubject: SubjectLike<any>) {\n const result: any = new Observable<T>((groupSubscriber) => {\n activeGroups++;\n const innerSub = groupSubject.subscribe(groupSubscriber);\n return () => {\n innerSub.unsubscribe();\n // We can kill the subscription to our source if we now have no more\n // active groups subscribed, and a finalization was already attempted on\n // the source.\n --activeGroups === 0 && teardownAttempted && groupBySourceSubscriber.unsubscribe();\n };\n });\n result.key = key;\n return result;\n }\n });\n}\n\n/**\n * An observable of values that is the emitted by the result of a {@link groupBy} operator,\n * contains a `key` property for the grouping.\n */\nexport interface GroupedObservable<K, T> extends Observable<T> {\n /**\n * The key value for the grouped notifications.\n */\n readonly key: K;\n}\n","import { Observable } from 'rxjs';\n\n/**\n * Configures an effect created by `createEffect`.\n */\nexport interface EffectConfig {\n /**\n * Determines if the action emitted by the effect is dispatched to the store.\n * If false, effect does not need to return type `Observable<Action>`.\n */\n dispatch?: boolean;\n /**\n * Determines whether the functional effect will be created.\n * If true, the effect can be created outside the effects class.\n */\n functional?: boolean;\n /**\n * Determines if the effect will be resubscribed to if an error occurs in the main actions stream.\n */\n useEffectsErrorHandler?: boolean;\n}\n\nexport const DEFAULT_EFFECT_CONFIG: Readonly<Required<EffectConfig>> = {\n dispatch: true,\n functional: false,\n useEffectsErrorHandler: true,\n};\n\nexport const CREATE_EFFECT_METADATA_KEY = '__@ngrx/effects_create__';\n\nexport interface CreateEffectMetadata {\n [CREATE_EFFECT_METADATA_KEY]: EffectConfig;\n}\n\nexport interface FunctionalCreateEffectMetadata extends CreateEffectMetadata {\n [CREATE_EFFECT_METADATA_KEY]: EffectConfig & { functional: true };\n}\n\nexport type FunctionalEffect<\n Source extends () => Observable<unknown> = () => Observable<unknown>\n> = Source & FunctionalCreateEffectMetadata;\n\nexport type EffectPropertyKey<T extends Record<keyof T, Object>> = Exclude<\n keyof T,\n keyof Object\n>;\n\nexport interface EffectMetadata<T extends Record<keyof T, Object>>\n extends Required<EffectConfig> {\n propertyName: EffectPropertyKey<T>;\n}\n\nexport type EffectsMetadata<T extends Record<keyof T, Object>> = {\n [Key in EffectPropertyKey<T>]?: EffectConfig;\n};\n","import { Observable } from 'rxjs';\nimport { Action, ActionCreator } from '@ngrx/store';\nimport {\n CREATE_EFFECT_METADATA_KEY,\n CreateEffectMetadata,\n DEFAULT_EFFECT_CONFIG,\n EffectConfig,\n EffectMetadata,\n FunctionalEffect,\n} from './models';\n\ntype DispatchType<T> = T extends { dispatch: infer U } ? U : true;\ntype ObservableType<T, OriginalType> = T extends false ? OriginalType : Action;\ntype EffectResult<OT> = Observable<OT> | ((...args: any[]) => Observable<OT>);\ntype ConditionallyDisallowActionCreator<DT, Result> = DT extends false\n ? unknown // If DT (DispatchType is false, then we don't enforce any return types)\n : Result extends EffectResult<infer OT>\n ? OT extends ActionCreator\n ? 'ActionCreator cannot be dispatched. Did you forget to call the action creator function?'\n : unknown\n : unknown;\n\nexport function createEffect<\n C extends EffectConfig & { functional?: false },\n DT extends DispatchType<C>,\n OT extends ObservableType<DT, OT>,\n R extends EffectResult<OT>\n>(\n source: () => R & ConditionallyDisallowActionCreator<DT, R>,\n config?: C\n): R & CreateEffectMetadata;\nexport function createEffect<Source extends () => Observable<unknown>>(\n source: Source,\n config: EffectConfig & { functional: true; dispatch: false }\n): FunctionalEffect<Source>;\nexport function createEffect<Source extends () => Observable<Action>>(\n source: Source & ConditionallyDisallowActionCreator<true, ReturnType<Source>>,\n config: EffectConfig & { functional: true; dispatch?: true }\n): FunctionalEffect<Source>;\n/**\n * @description\n *\n * Creates an effect from a source and an `EffectConfig`.\n *\n * @param source A function which returns an observable or observable factory.\n * @param config A `EffectConfig` to configure the effect. By default,\n * `dispatch` is true, `functional` is false, and `useEffectsErrorHandler` is\n * true.\n * @returns If `EffectConfig`#`functional` is true, returns the source function.\n * Else, returns the source function result. When `EffectConfig`#`dispatch` is\n * true, the source function result needs to be `Observable<Action>`.\n *\n * @usageNotes\n *\n * ### Class Effects\n *\n * ```ts\n * @Injectable()\n * export class FeatureEffects {\n * // mapping to a different action\n * readonly effect1$ = createEffect(\n * () => this.actions$.pipe(\n * ofType(FeatureActions.actionOne),\n * map(() => FeatureActions.actionTwo())\n * )\n * );\n *\n * // non-dispatching effect\n * readonly effect2$ = createEffect(\n * () => this.actions$.pipe(\n * ofType(FeatureActions.actionTwo),\n * tap(() => console.log('Action Two Dispatched'))\n * ),\n * { dispatch: false } // FeatureActions.actionTwo is not dispatched\n * );\n *\n * constructor(private readonly actions$: Actions) {}\n * }\n * ```\n *\n * ### Functional Effects\n *\n * ```ts\n * // mapping to a different action\n * export const loadUsers = createEffect(\n * (actions$ = inject(Actions), usersService = inject(UsersService)) => {\n * return actions$.pipe(\n * ofType(UsersPageActions.opened),\n * exhaustMap(() => {\n * return usersService.getAll().pipe(\n * map((users) => UsersApiActions.usersLoadedSuccess({ users })),\n * catchError((error) =>\n * of(UsersApiActions.usersLoadedFailure({ error }))\n * )\n * );\n * })\n * );\n * },\n * { functional: true }\n * );\n *\n * // non-dispatching functional effect\n * export const logDispatchedActions = createEffect(\n * () => inject(Actions).pipe(tap(console.log)),\n * { functional: true, dispatch: false }\n * );\n * ```\n */\nexport function createEffect<\n Result extends EffectResult<unknown>,\n Source extends () => Result\n>(\n source: Source,\n config: EffectConfig = {}\n): (Source | Result) & CreateEffectMetadata {\n const effect = config.functional ? source : source();\n const value: EffectConfig = {\n ...DEFAULT_EFFECT_CONFIG,\n ...config, // Overrides any defaults if values are provided\n };\n Object.defineProperty(effect, CREATE_EFFECT_METADATA_KEY, {\n value,\n });\n return effect as typeof effect & CreateEffectMetadata;\n}\n\nexport function getCreateEffectMetadata<T extends Record<keyof T, Object>>(\n instance: T\n): EffectMetadata<T>[] {\n const propertyNames = Object.getOwnPropertyNames(instance) as Array<keyof T>;\n\n const metadata: EffectMetadata<T>[] = propertyNames\n .filter((propertyName) => {\n if (\n instance[propertyName] &&\n instance[propertyName].hasOwnProperty(CREATE_EFFECT_METADATA_KEY)\n ) {\n // If the property type has overridden `hasOwnProperty` we need to ensure\n // that the metadata is valid (containing a `dispatch` property)\n // https://github.com/ngrx/platform/issues/2975\n const property = instance[propertyName] as any;\n return property[CREATE_EFFECT_METADATA_KEY].hasOwnProperty('dispatch');\n }\n return false;\n })\n .map((propertyName) => {\n const metaData = (instance[propertyName] as any)[\n CREATE_EFFECT_METADATA_KEY\n ];\n return {\n propertyName,\n ...metaData,\n };\n });\n\n return metadata;\n}\n","import { Type } from '@angular/core';\n\nexport function getSourceForInstance<T>(instance: T): T {\n return Object.getPrototypeOf(instance);\n}\n\nexport function isClassInstance(obj: object): boolean {\n return (\n obj.constructor.name !== 'Object' && obj.constructor.name !== 'Function'\n );\n}\n\nexport function isClass(\n classOrRecord: Type<unknown> | Record<string, unknown>\n): classOrRecord is Type<unknown> {\n return typeof classOrRecord === 'function';\n}\n\nexport function getClasses(\n classesAndRecords: Array<Type<unknown> | Record<string, unknown>>\n): Type<unknown>[] {\n return classesAndRecords.filter(isClass);\n}\n\n// TODO: replace with RxJS interfaces when possible\n// needs dependency on RxJS >=7\nexport interface NextNotification<T> {\n kind: 'N';\n value: T;\n}\n\nexport interface ErrorNotification {\n kind: 'E';\n error: any;\n}\n\nexport interface CompleteNotification {\n kind: 'C';\n}\n\nexport type ObservableNotification<T> =\n | NextNotification<T>\n | ErrorNotification\n | CompleteNotification;\n","import { Action } from '@ngrx/store';\nimport { merge, Observable } from 'rxjs';\nimport { ignoreElements, map, materialize } from 'rxjs/operators';\n\nimport { EffectNotification } from './effect_notification';\nimport { getSourceMetadata } from './effects_metadata';\nimport { EffectsErrorHandler } from './effects_error_handler';\nimport { getSourceForInstance } from './utils';\nimport { ErrorHandler } from '@angular/core';\n\nexport function mergeEffects(\n sourceInstance: any,\n globalErrorHandler: ErrorHandler,\n effectsErrorHandler: EffectsErrorHandler\n): Observable<EffectNotification> {\n const sourceName = getSourceForInstance(sourceInstance).constructor.name;\n\n const observables$: Observable<any>[] = getSourceMetadata(sourceInstance).map(\n ({\n propertyName,\n dispatch,\n useEffectsErrorHandler,\n }): Observable<EffectNotification> => {\n const observable$: Observable<any> =\n typeof sourceInstance[propertyName] === 'function'\n ? sourceInstance[propertyName]()\n : sourceInstance[propertyName];\n\n const effectAction$ = useEffectsErrorHandler\n ? effectsErrorHandler(observable$, globalErrorHandler)\n : observable$;\n\n if (dispatch === false) {\n return effectAction$.pipe(ignoreElements());\n }\n\n const materialized$ = effectAction$.pipe(materialize<Action>());\n\n return materialized$.pipe(\n map(\n (notification): EffectNotification => ({\n effect: sourceInstance[propertyName],\n notification,\n propertyName,\n sourceName,\n sourceInstance,\n })\n )\n );\n }\n );\n\n return merge(...observables$);\n}\n","import { EffectMetadata, EffectsMetadata } from './models';\nimport { getCreateEffectMetadata } from './effect_creator';\n\nexport function getEffectsMetadata<T extends Record<keyof T, Object>>(\n instance: T\n): EffectsMetadata<T> {\n return getSourceMetadata(instance).reduce(\n (\n acc: EffectsMetadata<T>,\n { propertyName, dispatch, useEffectsErrorHandler }\n ) => {\n acc[propertyName] = { dispatch, useEffectsErrorHandler };\n return acc;\n },\n {}\n );\n}\n\nexport function getSourceMetadata<T extends { [props in keyof T]: object }>(\n instance: T\n): EffectMetadata<T>[] {\n return getCreateEffectMetadata(instance);\n}\n","import { Notification } from '../Notification';\nimport { OperatorFunction, ObservableNotification } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Represents all of the notifications from the source Observable as `next`\n * emissions marked with their original types within {@link Notification}\n * objects.\n *\n * <span class=\"informal\">Wraps `next`, `error` and `complete` emissions in\n * {@link Notification} objects, emitted as `next` on the output Observable.\n * </span>\n *\n * ![](materialize.png)\n *\n * `materialize` returns an Observable that emits a `next` notification for each\n * `next`, `error`, or `complete` emission of the source Observable. When the\n * source Observable emits `complete`, the output Observable will emit `next` as\n * a Notification of type \"complete\", and then it will emit `complete` as well.\n * When the source Observable emits `error`, the output will emit `next` as a\n * Notification of type \"error\", and then `complete`.\n *\n * This operator is useful for producing metadata of the source Observable, to\n * be consumed as `next` emissions. Use it in conjunction with\n * {@link dematerialize}.\n *\n * ## Example\n *\n * Convert a faulty Observable to an Observable of Notifications\n *\n * ```ts\n * import { of, materialize, map } from 'rxjs';\n *\n * const letters = of('a', 'b', 13, 'd');\n * const upperCase = letters.pipe(map((x: any) => x.toUpperCase()));\n * const materialized = upperCase.pipe(materialize());\n *\n * materialized.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // - Notification { kind: 'N', value: 'A', error: undefined, hasValue: true }\n * // - Notification { kind: 'N', value: 'B', error: undefined, hasValue: true }\n * // - Notification { kind: 'E', value: undefined, error: TypeError { message: x.toUpperCase is not a function }, hasValue: false }\n * ```\n *\n * @see {@link Notification}\n * @see {@link dematerialize}\n *\n * @return A function that returns an Observable that emits\n * {@link Notification} objects that wrap the original emissions from the\n * source Observable with metadata.\n */\nexport function materialize<T>(): OperatorFunction<T, Notification<T> & ObservableNotification<T>> {\n return operate((source, subscriber) => {\n source.subscribe(\n createOperatorSubscriber(\n subscriber,\n (value) => {\n subscriber.next(Notification.createNext(value));\n },\n () => {\n subscriber.next(Notification.createComplete());\n subscriber.complete();\n },\n (err) => {\n subscriber.next(Notification.createError(err));\n subscriber.complete();\n }\n )\n );\n });\n}\n","import { ErrorHandler } from '@angular/core';\nimport { Action } from '@ngrx/store';\nimport { Observable } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\n\nexport type EffectsErrorHandler = <T extends Action>(\n observable$: Observable<T>,\n errorHandler: ErrorHandler\n) => Observable<T>;\n\nconst MAX_NUMBER_OF_RETRY_ATTEMPTS = 10;\n\nexport function defaultEffectsErrorHandler<T extends Action>(\n observable$: Observable<T>,\n errorHandler: ErrorHandler,\n retryAttemptLeft: number = MAX_NUMBER_OF_RETRY_ATTEMPTS\n): Observable<T> {\n return observable$.pipe(\n catchError((error) => {\n if (errorHandler) errorHandler.handleError(error);\n if (retryAttemptLeft <= 1) {\n return observable$; // last attempt\n }\n // Return observable that produces this particular effect\n return defaultEffectsErrorHandler(\n observable$,\n errorHandler,\n retryAttemptLeft - 1\n );\n })\n );\n}\n","import { Inject, Injectable } from '@angular/core';\nimport {\n Action,\n ActionCreator,\n Creator,\n ScannedActionsSubject,\n} from '@ngrx/store';\nimport { Observable, OperatorFunction, Operator } from 'rxjs';\nimport { filter } from 'rxjs/operators';\n\n@Injectable({ providedIn: 'root' })\nexport class Actions<V = Action> extends Observable<V> {\n constructor(@Inject(ScannedActionsSubject) source?: Observable<V>) {\n super();\n\n if (source) {\n this.source = source;\n }\n }\n\n override lift<R>(operator: Operator<V, R>): Observable<R> {\n const observable = new Actions<R>();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n}\n\n// Module-private helper type\ntype ActionExtractor<\n T extends string | AC,\n AC extends ActionCreator<string, Creator>,\n E\n> = T extends string ? E : ReturnType<Extract<T, AC>>;\n\nexport function ofType<\n AC extends ActionCreator<string, Creator>[],\n U extends Action = Action,\n V = ReturnType<AC[number]>\n>(...allowedTypes: AC): OperatorFunction<U, V>;\n\nexport function ofType<\n E extends Extract<U, { type: T1 }>,\n AC extends ActionCreator<string, Creator>,\n T1 extends string | AC,\n U extends Action = Action,\n V = T1 extends string ? E : ReturnType<Extract<T1, AC>>\n>(t1: T1): OperatorFunction<U, V>;\nexport function ofType<\n E extends Extract<U, { type: T1 | T2 }>,\n AC extends ActionCreator<string, Creator>,\n T1 extends string | AC,\n T2 extends string | AC,\n U extends Action = Action,\n V = ActionExtractor<T1 | T2, AC, E>\n>(t1: T1, t2: T2): OperatorFunction<U, V>;\nexport function ofType<\n E extends Extract<U, { type: T1 | T2 | T3 }>,\n AC extends ActionCreator<string, Creator>,\n T1 extends string | AC,\n T2 extends string | AC,\n T3 extends string | AC,\n U extends Action = Action,\n V = ActionExtractor<T1 | T2 | T3, AC, E>\n>(t1: T1, t2: T2, t3: T3): OperatorFunction<U, V>;\nexport function ofType<\n E extends Extract<U, { type: T1 | T2 | T3 | T4 }>,\n AC extends ActionCreator<string, Creator>,\n T1 extends string | AC,\n T2 extends string | AC,\n T3 extends string | AC,\n T4 extends string | AC,\n U extends Action = Action,\n V = ActionExtractor<T1 | T2 | T3 | T4, AC, E>\n>(t1: T1, t2: T2, t3: T3, t4: T4): OperatorFunction<U, V>;\nexport function ofType<\n E extends Extract<U, { type: T1 | T2 | T3 | T4 | T5 }>,\n AC extends ActionCreator<string, Creator>,\n T1 extends string | AC,\n T2 extends string | AC,\n T3 extends string | AC,\n T4 extends string | AC,\n T5 extends string | AC,\n U extends Action = Action,\n V = ActionExtractor<T1 | T2 | T3 | T4 | T5, AC, E>\n>(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): OperatorFunction<U, V>;\n/**\n * Fallback for more than 5 arguments.\n * There is no inference, so the return type is the same as the input -\n * Observable<Action>.\n *\n * We provide a type parameter, even though TS will not infer it from the\n * arguments, to preserve backwards compatibility with old versions of ngrx.\n */\nexport function ofType<V extends Action>(\n ...allowedTypes: Array<string | ActionCreator<string, Creator>>\n): OperatorFunction<Action, V>;\n/**\n * `ofType` filters an Observable of `Actions` into an Observable of the actions\n * whose type strings are passed to it.\n *\n * For example, if `actions` has type `Actions<AdditionAction|SubstractionAction>`, and\n * the type of the `Addition` action is `add`, then\n * `actions.pipe(ofType('add'))` returns an `Observable<AdditionAction>`.\n *\n * Properly typing this function is hard and requires some advanced TS tricks\n * below.\n *\n * Type narrowing automatically works, as long as your `actions` object\n * starts with a `Actions<SomeUnionOfActions>` instead of generic `Actions`.\n *\n * For backwards compatibility, when one passes a single type argument\n * `ofType<T>('something')` the result is an `Observable<T>`. Note, that `T`\n * completely overrides any possible inference from 'something'.\n *\n * Unfortunately, for unknown 'actions: Actions' these types will produce\n * 'Observable<never>'. In such cases one has to manually set the generic type\n * like `actions.ofType<AdditionAction>('add')`.\n *\n * @usageNotes\n *\n * Filter the Actions stream on the \"customers page loaded\" action\n *\n * ```ts\n * import { ofType } from '@ngrx/effects';\n * import * fromCustomers from '../customers';\n *\n * this.actions$.pipe(\n * ofType(fromCustomers.pageLoaded)\n * )\n * ```\n */\nexport function ofType(\n ...allowedTypes: Array<string | ActionCreator<string, Creator>>\n): OperatorFunction<Action, Action> {\n return filter((action: Action) =>\n allowedTypes.some((typeOrActionCreator) => {\n if (typeof typeOrActionCreator === 'string') {\n // Comparing the string to type\n return typeOrActionCreator === action.type;\n }\n\n // We are filtering by ActionCreator\n return typeOrActionCreator.type === action.type;\n })\n );\n}\n","import { InjectionToken, Type } from '@angular/core';\nimport {\n defaultEffectsErrorHandler,\n EffectsErrorHandler,\n} from './effects_error_handler';\nimport { FunctionalEffect } from './models';\n\nexport const _ROOT_EFFECTS_GUARD = new InjectionToken<void>(\n '@ngrx/effects Internal Root Guard'\n);\nexport const USER_PROVIDED_EFFECTS = new InjectionToken<Type<unknown>[][]>(\n '@ngrx/effects User Provided Effects'\n);\nexport const _ROOT_EFFECTS = new InjectionToken<\n [Array<Type<unknown> | Record<string, FunctionalEffect>>]\n>('@ngrx/effects Internal Root Effects');\nexport const _ROOT_EFFECTS_INSTANCES = new InjectionToken<unknown[]>(\n '@ngrx/effects Internal Root Effects Instances'\n);\nexport const _FEATURE_EFFECTS = new InjectionToken<\n Array<Type<unknown> | Record<string, FunctionalEffect>>[]\n>('@ngrx/effects Internal Feature Effects');\nexport const _FEATURE_EFFECTS_INSTANCE_GROUPS = new InjectionToken<unknown[][]>(\n '@ngrx/effects Internal Feature Effects Instance Groups'\n);\nexport const EFFECTS_ERROR_HANDLER = new InjectionToken<EffectsErrorHandler>(\n '@ngrx/effects Effects Error Handler',\n { providedIn: 'root', factory: () => defaultEffectsErrorHandler }\n);\n","import { createAction } from '@ngrx/store';\n\nexport const ROOT_EFFECTS_INIT = '@ngrx/effects/init';\nexport const rootEffectsInit = createAction(ROOT_EFFECTS_INIT);\n","import { Observable } from 'rxjs';\nimport { EffectNotification } from '.';\nimport { Action } from '@ngrx/store';\n\n/**\n * @description\n * Interface to set an identifier for effect instances.\n *\n * By default, each Effects class is registered\n * once regardless of how many times the Effect class\n * is loaded. By implementing this interface, you define\n * a unique identifier to register an Effects class instance\n * multiple times.\n *\n * @usageNotes\n *\n * ### Set an identifier for an Effects class\n *\n * ```ts\n * class EffectWithIdentifier implements OnIdentifyEffects {\n * constructor(private effectIdentifier: string) {}\n *\n * ngrxOnIdentifyEffects() {\n * return this.effectIdentifier;\n * }\n *\n * ```\n */\nexport declare interface OnIdentifyEffects {\n /**\n * @description\n * String identifier to differentiate effect instances.\n */\n ngrxOnIdentifyEffects(): string;\n}\n\nexport const onIdentifyEffectsKey: keyof OnIdentifyEffects =\n 'ngrxOnIdentifyEffects';\n\nexport function isOnIdentifyEffects(\n instance: any\n): instance is OnIdentifyEffects {\n return isFunction(instance, onIdentifyEffectsKey);\n}\n\n/**\n * @description\n * Interface to control the lifecycle of effects.\n *\n * By default, effects are merged and subscribed to the store. Implement the OnRunEffects interface to control the lifecycle of the resolved effects.\n *\n * @usageNotes\n *\n * ### Implement the OnRunEffects interface on an Effects class\n *\n * ```ts\n * export class UserEffects implements OnRunEffects {\n * constructor(private actions$: Actions) {}\n *\n * ngrxOnRunEffects(resolvedEffects$: Observable<EffectNotification>) {\n * return this.actions$.pipe(\n * ofType('LOGGED_IN'),\n * exhaustMap(() =>\n * resolvedEffects$.pipe(\n * takeUntil(this.actions$.pipe(ofType('LOGGED_OUT')))\n * )\n * )\n * );\n * }\n * }\n * ```\n */\nexport declare interface OnRunEffects {\n /**\n * @description\n * Method to control the lifecycle of effects.\n */\n ngrxOnRunEffects(\n resolvedEffects$: Observable<EffectNotification>\n ): Observable<EffectNotification>;\n}\n\nexport const onRunEffectsKey: keyof OnRunEffects = 'ngrxOnRunEffects';\n\nexport function isOnRunEffects(instance: any): instance is OnRunEffects {\n return isFunction(instance, onRunEffectsKey);\n}\n\n/**\n * @description\n * Interface to dispatch an action after effect registration.\n *\n * Implement this interface to dispatch a custom action after\n * the effect has been added. You can listen to this action\n * in the rest of the application to execute something after\n * the effect is registered.\n *\n * @usageNotes\n *\n * ### Set an identifier for an Effects class\n *\n * ```ts\n * class EffectWithInitAction implements OnInitEffects {\n * ngrxOnInitEffects() {\n * return { type: '[EffectWithInitAction] Init' };\n * }\n * ```\n */\nexport declare interface OnInitEffects {\n /**\n * @description\n * Action to be dispatched after the effect is registered.\n */\n ngrxOnInitEffects(): Action;\n}\n\nexport const onInitEffects: keyof OnInitEffects = 'ngrxOnInitEffects';\n\nexport function isOnInitEffects(instance: any): instance is OnInitEffects {\n return isFunction(instance, onInitEffects);\n}\n\nfunction isFunction(instance: any, functionName: string) {\n return (\n instance &&\n functionName in instance &&\n typeof instance[functionName] === 'function'\n );\n}\n","import { ErrorHandler, Inject, Injectable } from '@angular/core';\nimport { Action } from '@ngrx/store';\nimport { Observable, Subject, merge } from 'rxjs';\nimport {\n dematerialize,\n exhaustMap,\n filter,\n groupBy,\n map,\n mergeMap,\n take,\n} from 'rxjs/operators';\n\nimport {\n reportInvalidActions,\n EffectNotification,\n} from './effect_notification';\nimport { EffectsErrorHandler } from './effects_error_handler';\nimport { mergeEffects } from './effects_resolver';\nimport {\n isOnIdentifyEffects,\n isOnRunEffects,\n isOnInitEffects,\n} from './lifecycle_hooks';\nimport { EFFECTS_ERROR_HANDLER } from './tokens';\nimport {\n getSourceForInstance,\n isClassInstance,\n ObservableNotification,\n} from './utils';\n\n@Injectable({ providedIn: 'root' })\nexport class EffectSources extends Subject<any> {\n constructor(\n private errorHandler: ErrorHandler,\n @Inject(EFFECTS_ERROR_HANDLER)\n private effectsErrorHandler: EffectsErrorHandler\n ) {\n super();\n }\n\n addEffects(effectSourceInstance: any): void {\n this.next(effectSourceInstance);\n }\n\n /**\n * @internal\n */\n toActions(): Observable<Action> {\n return this.pipe(\n groupBy((effectsInstance) =>\n isClassInstance(effectsInstance)\n ? getSourceForInstance(effectsInstance)\n : effectsInstance\n ),\n mergeMap((source$) => {\n return source$.pipe(groupBy(effectsInstance));\n }),\n mergeMap((source$) => {\n const effect$ = source$.pipe(\n exhaustMap((sourceInstance) => {\n return resolveEffectSource(\n this.errorHandler,\n this.effectsErrorHandler\n )(sourceInstance);\n }),\n map((output) => {\n reportInvalidActions(output, this.errorHandler);\n return output.notification;\n }),\n filter(\n (notification): notification is ObservableNotification<Action> =>\n notification.kind === 'N' && notification.value != null\n ),\n dematerialize()\n );\n\n // start the stream with an INIT action\n // do this only for the first Effect instance\n const init$ = source$.pipe(\n take(1),\n filter(isOnInitEffects),\n map((instance) => instance.ngrxOnInitEffects())\n );\n\n return merge(effect$, init$);\n })\n );\n }\n}\n\nfunction effectsInstance(sourceInstance: any) {\n if (isOnIdentifyEffects(sourceInstance)) {\n return sourceInstance.ngrxOnIdentifyEffects();\n }\n\n return '';\n}\n\nfunction resolveEffectSource(\n errorHandler: ErrorHandler,\n effectsErrorHandler: EffectsErrorHandler\n): (sourceInstance: any) => Observable<EffectNotification> {\n return (sourceInstance) => {\n const mergedEffects$ = mergeEffects(\n sourceInstance,\n errorHandler,\n effectsErrorHandler\n );\n\n if (isOnRunEffects(sourceInstance)) {\n return sourceInstance.ngrxOnRunEffects(mergedEffects$);\n }\n\n return mergedEffects$;\n };\n}\n","import { ErrorHandler } from '@angular/core';\nimport { Action } from '@ngrx/store';\nimport { Observable } from 'rxjs';\nimport { ObservableNotification } from './utils';\n\nexport interface EffectNotification {\n effect: Observable<any> | (() => Observable<any>);\n propertyName: PropertyKey;\n sourceName: string;\n sourceInstance: any;\n notification: ObservableNotification<Action | null | undefined>;\n}\n\nexport function reportInvalidActions(\n output: EffectNotification,\n reporter: ErrorHandler\n) {\n if (output.notification.kind === 'N') {\n const action = output.notification.value;\n const isInvalidAction = !isAction(action);\n\n if (isInvalidAction) {\n reporter.handleError(\n new Error(\n `Effect ${getEffectName(\n output\n )} dispatched an invalid action: ${stringify(action)}`\n )\n );\n }\n }\n}\n\nfunction isAction(action: any): action is Action {\n return (\n typeof action !== 'function' &&\n action &&\n action.type &&\n typeof action.type === 'string'\n );\n}\n\nfunction getEffectName({\n propertyName,\n sourceInstance,\n sourceName,\n}: EffectNotification) {\n const isMethod = typeof sourceInstance[propertyName] === 'function';\n\n return `\"${sourceName}.${String(propertyName)}${isMethod ? '()' : ''}\"`;\n}\n\nfunction stringify(action: Action | null | undefined) {\n try {\n return JSON.stringify(action);\n } catch {\n return action;\n }\n}\n","import { observeNotification } from '../Notification';\nimport { OperatorFunction, ObservableNotification, ValueFromNotification } from '../types';\nimport { operate } from '../util/lift';\nimport { createOperatorSubscriber } from './OperatorSubscriber';\n\n/**\n * Converts an Observable of {@link ObservableNotification} objects into the emissions\n * that they represent.\n *\n * <span class=\"informal\">Unwraps {@link ObservableNotification} objects as actual `next`,\n * `error` and `complete` emissions. The opposite of {@link materialize}.</span>\n *\n * ![](dematerialize.png)\n *\n * `dematerialize` is assumed to operate an Observable that only emits\n * {@link ObservableNotification} objects as `next` emissions, and does not emit any\n * `error`. Such Observable is the output of a `materialize` operation. Those\n * notifications are then unwrapped using the metadata they contain, and emitted\n * as `next`, `error`, and `complete` on the output Observable.\n *\n * Use this operator in conjunction with {@link materialize}.\n *\n * ## Example\n *\n * Convert an Observable of Notifications to an actual Observable\n *\n * ```ts\n * import { NextNotification, ErrorNotification, of, dematerialize } from 'rxjs';\n *\n * const notifA: NextNotification<string> = { kind: 'N', value: 'A' };\n * const notifB: NextNotification<string> = { kind: 'N', value: 'B' };\n * const notifE: ErrorNotification = { kind: 'E', error: new TypeError('x.toUpperCase is not a function') };\n *\n * const materialized = of(notifA, notifB, notifE);\n *\n * const upperCase = materialized.pipe(dematerialize());\n * upperCase.subscribe({\n * next: x => console.log(x),\n * error: e => console.error(e)\n * });\n *\n * // Results in:\n * // A\n * // B\n * // TypeError: x.toUpperCase is not a function\n * ```\n *\n * @see {@link materialize}\n *\n * @return A function that returns an Observable that emits items and\n * notifications embedded in Notification objects emitted by the source\n * Observable.\n */\nexport function dematerialize<N extends ObservableNotification<any>>(): OperatorFunction<N, ValueFromNotification<N>> {\n return operate((source, subscriber) => {\n source.subscribe(createOperatorSubscriber(subscriber, (notification) => observeNotification(notification, subscriber)));\n });\n}\n","import { Injectable, OnDestroy } from '@angular/core';\nimport { Store } from '@ngrx/store';\nimport { Subscription } from 'rxjs';\n\nimport { EffectSources } from './effect_sources';\n\n@Injectable({ providedIn: 'root' })\nexport class EffectsRunner implements OnDestroy {\n private effectsSubscription: Subscription | null = null;\n\n get isStarted(): boolean {\n return !!this.effectsSubscription;\n }\n\n constructor(\n private effectSources: EffectSources,\n private store: Store<any>\n ) {}\n\n start() {\n if (!this.effectsSubscription) {\n this.effectsSubscription = this.effectSources\n .toActions()\n .subscribe(this.store);\n }\n }\n\n ngOnDestroy() {\n if (this.effectsSubscription) {\n this.effectsSubscription.unsubscribe();\n this.effectsSubscription = null;\n }\n }\n}\n","import { NgModule, Inject, Optional } from '@angular/core';\nimport { Store, StoreRootModule, StoreFeatureModule } from '@ngrx/store';\nimport { EffectsRunner } from './effects_runner';\nimport { EffectSources } from './effect_sources';\nimport { _ROOT_EFFECTS_GUARD, _ROOT_EFFECTS_INSTANCES } from './tokens';\nimport { ROOT_EFFECTS_INIT } from './effects_actions';\n\n@NgModule({})\nexport class EffectsRootModule {\n constructor(\n private sources: EffectSources,\n runner: EffectsRunner,\n store: Store,\n @Inject(_ROOT_EFFECTS_INSTANCES) rootEffectsInstances: unknown[],\n @Optional() storeRootModule: StoreRootModule,\n @Optional() storeFeatureModule: StoreFeatureModule,\n @Optional()\n @Inject(_ROOT_EFFECTS_GUARD)\n guard: unknown\n ) {\n runner.start();\n\n for (const effectsInstance of rootEffectsInstances) {\n sources.addEffects(effectsInstance);\n }\n\n store.dispatch({ type: ROOT_EFFECTS_INIT });\n }\n\n addEffects(effectsInstance: unknown): void {\n this.sources.addEffects(effectsInstance);\n }\n}\n","import { NgModule, Inject, Optional } from '@angular/core';\nimport { StoreRootModule, StoreFeatureModule } from '@ngrx/store';\nimport { EffectsRootModule } from './effects_root_module';\nimport { _FEATURE_EFFECTS_INSTANCE_GROUPS } from './tokens';\n\n@NgModule({})\nexport class EffectsFeatureModule {\n constructor(\n effectsRootModule: EffectsRootModule,\n @Inject(_FEATURE_EFFECTS_INSTANCE_GROUPS)\n effectsInstanceGroups: unknown[][],\n @Optional() storeRootModule: StoreRootModule,\n @Optional() storeFeatureModule: StoreFeatureModule\n ) {\n const effectsInstances = effectsInstanceGroups.flat();\n for (const effectsInstance of effectsInstances) {\n effectsRootModule.addEffects(effectsInstance);\n }\n }\n}\n","import { inject, ModuleWithProviders, NgModule, Type } from '@angular/core';\nimport { EffectsFeatureModule } from './effects_feature_module';\nimport { EffectsRootModule } from './effects_root_module';\nimport { EffectsRunner } from './effects_runner';\nimport {\n _FEATURE_EFFECTS,\n _ROOT_EFFECTS,\n _ROOT_EFFECTS_GUARD,\n _FEATURE_EFFECTS_INSTANCE_GROUPS,\n _ROOT_EFFECTS_INSTANCES,\n USER_PROVIDED_EFFECTS,\n} from './tokens';\nimport { FunctionalEffect } from './models';\nimport { getClasses, isClass } from './utils';\n\n@NgModule({})\nexport class EffectsModule {\n static forFeature(\n featureEffects: Array<Type<unknown> | Record<string, FunctionalEffect>>\n ): ModuleWithProviders<EffectsFeatureModule>;\n static forFeature(\n ...featureEffects: Array<Type<unknown> | Record<string, FunctionalEffect>>\n ): ModuleWithProviders<EffectsFeatureModule>;\n static forFeature(\n ...featureEffects:\n | Array<Type<unknown> | Record<string, FunctionalEffect>>\n | [Array<Type<unknown> | Record<string, FunctionalEffect>>]\n ): ModuleWithProviders<EffectsFeatureModule> {\n const effects = featureEffects.flat();\n const effectsClasses = getClasses(effects);\n return {\n ngModule: EffectsFeatureModule,\n providers: [\n effectsClasses,\n {\n provide: _FEATURE_EFFECTS,\n multi: true,\n useValue: effects,\n },\n {\n provide: USER_PROVIDED_EFFECTS,\n multi: true,\n useValue: [],\n },\n {\n provide: _FEATURE_EFFECTS_INSTANCE_GROUPS,\n multi: true,\n useFactory: createEffectsInstances,\n deps: [_FEATURE_EFFECTS, USER_PROVIDED_EFFECTS],\n },\n ],\n };\n }\n\n static forRoot(\n rootEffects: Array<Type<unknown> | Record<string, FunctionalEffect>>\n ): ModuleWithProviders<EffectsRootModule>;\n static forRoot(\n ...rootEffects: Array<Type<unknown> | Record<string, FunctionalEffect>>\n ): ModuleWithProviders<EffectsRootModule>;\n static forRoot(\n ...rootEffects:\n | Array<Type<unknown> | Record<string, FunctionalEffect>>\n | [Array<Type<unknown> | Record<string, FunctionalEffect>>]\n ): ModuleWithProviders<EffectsRootModule> {\n const effects = rootEffects.flat();\n const effectsClasses = getClasses(effects);\n return {\n ngModule: EffectsRootModule,\n providers: [\n effectsClasses,\n {\n provide: _ROOT_EFFECTS,\n useValue: [effects],\n },\n {\n provide: _ROOT_EFFECTS_GUARD,\n useFactory: _provideForRootGuard,\n },\n {\n provide: USER_PROVIDED_EFFECTS,\n multi: true,\n useValue: [],\n },\n {\n provide: _ROOT_EFFECTS_INSTANCES,\n useFactory: createEffectsInstances,\n deps: [_ROOT_EFFECTS, USER_PROVIDED_EFFECTS],\n },\n ],\n };\n }\n}\n\nfunction createEffectsInstances(\n effectsGroups: Array<Type<unknown> | Record<string, FunctionalEffect>>[],\n userProvidedEffectsGroups: Type<unknown>[][]\n): unknown[] {\n const effects: Array<Type<unknown> | Record<string, FunctionalEffect>> = [];\n\n for (const effectsGroup of effectsGroups) {\n effects.push(...effectsGroup);\n }\n\n for (const userProvidedEffectsGroup of userProvidedEffectsGroups) {\n effects.push(...userProvidedEffectsGroup);\n }\n\n return effects.map((effectsClassOrRecord) =>\n isClass(effectsClassOrRecord)\n ? inject(effectsClassOrRecord)\n : effectsClassOrRecord\n );\n}\n\nfunction _provideForRootGuard(): unknown {\n const runner = inject(EffectsRunner, { optional: true, skipSelf: true });\n const rootEffects = inject(_ROOT_EFFECTS, { self: true });\n\n // check whether any effects are actually passed\n const hasEffects = !(rootEffects.length === 1 && rootEffects[0].length === 0);\n if (hasEffects && runner) {\n throw new TypeError(\n `EffectsModule.forRoot() called twice. Feature modules should use EffectsModule.forFeature() instead.`\n );\n }\n return 'guarded';\n}\n","import { Observable, ObservedValueOf, of, OperatorFunction, pipe } from 'rxjs';\nimport { concatMap, withLatestFrom } from 'rxjs/operators';\n\n// The array overload is needed first because we want to maintain the proper order in the resulting tuple\nexport function concatLatestFrom<T extends Observable<unknown>[], V>(\n observablesFactory: (value: V) => [...T]\n): OperatorFunction<V, [V, ...{ [i in keyof T]: ObservedValueOf<T[i]> }]>;\nexport function concatLatestFrom<T extends Observable<unknown>, V>(\n observableFactory: (value: V) => T\n): OperatorFunction<V, [V, ObservedValueOf<T>]>;\n/**\n * `concatLatestFrom` combines the source value\n * and the last available value from a lazily evaluated Observable\n * in a new array\n *\n * @usageNotes\n *\n * Select the active customer from the NgRx Store\n *\n * ```ts\n * import { concatLatestFrom } from '@ngrx/effects';\n * import * as fromCustomers from '../customers';\n *\n * this.actions$.pipe(\n * concatLatestFrom(() => this.store.select(fromCustomers.selectActiveCustomer))\n * )\n * ```\n *\n * Select a customer from the NgRx Store by its id that is available on the action\n *\n * ```ts\n * import { concatLatestFrom } from '@ngrx/effects';\n * import * fromCustomers from '../customers';\n *\n * this.actions$.pipe(\n * concatLatestFrom((action) => this.store.select(fromCustomers.selectCustomer(action.customerId)))\n * )\n * ```\n */\nexport function concatLatestFrom<\n T extends Observable<unknown>[] | Observable<unknown>,\n V,\n R = [\n V,\n ...(T extends Observable<unknown>[]\n ? { [i in keyof T]: ObservedValueOf<T[i]> }\n : [ObservedValueOf<T>])\n ]\n>(observablesFactory: (value: V) => T): OperatorFunction<V, R> {\n return pipe(\n concatMap((value) => {\n const observables = observablesFactory(value);\n const observablesAsArray = Array.isArray(observables)\n ? observables\n : [observables];\n return of(value).pipe(\n withLatestFrom(...observablesAsArray)\n ) as unknown as Observable<R>;\n })\n );\n}\n","import { Action } from '@ngrx/store';\n\nexport const PERFORM_ACTION = 'PERFORM_ACTION';\nexport const REFRESH = 'REFRESH';\nexport const RESET = 'RESET';\nexport const ROLLBACK = 'ROLLBACK';\nexport const COMMIT = 'COMMIT';\nexport const SWEEP = 'SWEEP';\nexport const TOGGLE_ACTION = 'TOGGLE_ACTION';\nexport const SET_ACTIONS_ACTIVE = 'SET_ACTIONS_ACTIVE';\nexport const JUMP_TO_STATE = 'JUMP_TO_STATE';\nexport const JUMP_TO_ACTION = 'JUMP_TO_ACTION';\nexport const IMPORT_STATE = 'IMPORT_STATE';\nexport const LOCK_CHANGES = 'LOCK_CHANGES';\nexport const PAUSE_RECORDING = 'PAUSE_RECORDING';\n\nexport class PerformAction implements Action {\n readonly type = PERFORM_ACTION;\n\n constructor(public action: Action, public timestamp: number) {\n if (typeof action.type === 'undefined') {\n throw new Error(\n 'Actions may not have an undefined \"type\" property. ' +\n 'Have you misspelled a constant?'\n );\n }\n }\n}\n\nexport class Refresh implements Action {\n readonly type = REFRESH;\n}\n\nexport class Reset implements Action {\n readonly type = RESET;\n\n constructor(public timestamp: number) {}\n}\n\nexport class Rollback implements Action {\n readonly type = ROLLBACK;\n\n constructor(public timestamp: number) {}\n}\n\nexport class Commit implements Action {\n readonly type = COMMIT;\n\n constructor(public timestamp: number) {}\n}\n\nexport class Sweep implements Action {\n readonly type = SWEEP;\n}\n\nexport class ToggleAction implements Action {\n readonly type = TOGGLE_ACTION;\n\n constructor(public id: number) {}\n}\n\nexport class SetActionsActive implements Action {\n readonly type = SET_ACTIONS_ACTIVE;\n\n constructor(\n public start: number,\n public end: number,\n public active: boolean = true\n ) {}\n}\n\nexport class JumpToState implements Action {\n readonly type = JUMP_TO_STATE;\n\n constructor(public index: number) {}\n}\n\nexport class JumpToAction implements Action {\n readonly type = JUMP_TO_ACTION;\n\n constructor(public actionId: number) {}\n}\n\nexport class ImportState implements Action {\n readonly type = IMPORT_STATE;\n\n constructor(public nextLiftedState: any) {}\n}\n\nexport class LockChanges implements Action {\n readonly type = LOCK_CHANGES;\n\n constructor(public status: boolean) {}\n}\n\nexport class PauseRecording implements Action {\n readonly type = PAUSE_RECORDING;\n\n constructor(public status: boolean) {}\n}\n\nexport type All =\n | PerformAction\n | Refresh\n | Reset\n | Rollback\n | Commit\n | Sweep\n | ToggleAction\n | SetActionsActive\n | JumpToState\n | JumpToAction\n | ImportState\n | LockChanges\n | PauseRecording;\n","import { ActionReducer, Action } from '@ngrx/store';\nimport { InjectionToken } from '@angular/core';\n\nexport type ActionSanitizer = (action: Action, id: number) => Action;\nexport type StateSanitizer = (state: any, index: number) => any;\nexport type SerializationOptions = {\n options?: boolean | any;\n replacer?: (key: any, value: any) => {};\n reviver?: (key: any, value: any) => {};\n immutable?: any;\n refs?: Array<any>;\n};\nexport type Predicate = (state: any, action: Action) => boolean;\n\n/**\n * Chrome extension documentation\n * @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#features\n * Firefox extension documentation\n * @see https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md#features\n */\nexport interface DevToolsFeatureOptions {\n /**\n * Start/pause recording of dispatched actions\n */\n pause?: boolean;\n /**\n * Lock/unlock dispatching actions and side effects\n */\n lock?: boolean;\n /**\n * Persist states on page reloading\n */\n persist?: boolean;\n /**\n * Export history of actions in a file\n */\n export?: boolean;\n /**\n * Import history of actions from a file\n */\n import?: 'custom' | boolean;\n /**\n * Jump back and forth (time travelling)\n */\n jump?: boolean;\n /**\n * Skip (cancel) actions\n */\n skip?: boolean;\n /**\n * Drag and drop actions in the history list\n */\n reorder?: boolean;\n /**\n * Dispatch custom actions or action creators\n */\n dispatch?: boolean;\n /**\n * Generate tests for the selected actions\n */\n test?: boolean;\n}\n\n/**\n * Chrome extension documentation\n * @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md\n * Firefox extension documentation\n * @see https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md\n */\nexport class StoreDevtoolsConfig {\n /**\n * Maximum allowed actions to be stored in the history tree (default: `false`)\n */\n maxAge: number | false = false;\n monitor?: ActionReducer<any, any>;\n /**\n * Function which takes `action` object and id number as arguments, and should return `action` object back.\n */\n actionSanitizer?: ActionSanitizer;\n /**\n * Function which takes `state` object and index as arguments, and should return `state` object back.\n */\n stateSanitizer?: StateSanitizer;\n /**\n * The instance name to be shown on the monitor page (default: `document.title`)\n */\n name?: string;\n serialize?: boolean | SerializationOptions;\n logOnly?: boolean;\n features?: DevToolsFeatureOptions;\n /**\n * Action types to be hidden in the monitors. If `actionsSafelist` specified, `actionsBlocklist` is ignored.\n */\n actionsBlocklist?: string[];\n /**\n * Action types to be shown in the monitors\n */\n actionsSafelist?: string[];\n /**\n * Called for every action before sending, takes state and action object, and returns true in case it allows sending the current data to the monitor.\n */\n predicate?: Predicate;\n /**\n * Auto pauses when the extension’s window is not opened, and so has zero impact on your app when not in use.\n */\n autoPause?: boolean;\n\n /**\n * If set to true, will include stack trace for every dispatched action\n */\n trace?: boolean | (() => string);\n\n /**\n * Maximum stack trace frames to be stored (in case trace option was provided as true).\n */\n traceLimit?: number;\n}\n\nexport const STORE_DEVTOOLS_CONFIG = new InjectionToken<StoreDevtoolsConfig>(\n '@ngrx/store-devtools Options'\n);\n\n/**\n * Used to provide a `StoreDevtoolsConfig` for the store-devtools.\n */\nexport const INITIAL_OPTIONS = new InjectionToken<StoreDevtoolsConfig>(\n '@ngrx/store-devtools Initial Config'\n);\n\nexport type StoreDevtoolsOptions =\n | Partial<StoreDevtoolsConfig>\n | (() => Partial<StoreDevtoolsConfig>);\n\nexport function noMonitor(): null {\n return null;\n}\n\nexport const DEFAULT_NAME = 'NgRx Store DevTools';\n\nexport function createConfig(\n optionsInput: StoreDevtoolsOptions\n): StoreDevtoolsConfig {\n const DEFAULT_OPTIONS: StoreDevtoolsConfig = {\n maxAge: false,\n monitor: noMonitor,\n actionSanitizer: undefined,\n stateSanitizer: undefined,\n name: DEFAULT_NAME,\n serialize: false,\n logOnly: false,\n autoPause: false,\n trace: false,\n traceLimit: 75,\n // Add all features explicitly. This prevent buggy behavior for\n // options like \"lock\" which might otherwise not show up.\n features: {\n pause: true, // Start/pause recording of dispatched actions\n lock: true, // Lock/unlock dispatching actions and side effects\n persist: true, // Persist states on page reloading\n export: true, // Export history of actions in a file\n import: 'custom', // Import history of actions from a file\n jump: true, // Jump back and forth (time travelling)\n skip: true, // Skip (cancel) actions\n reorder: true, // Drag and drop actions in the history list\n dispatch: true, // Dispatch custom actions or action creators\n test: true, // Generate tests for the selected actions\n },\n };\n\n const options =\n typeof optionsInput === 'function' ? optionsInput() : optionsInput;\n const logOnly = options.logOnly\n ? { pause: true, export: true, test: true }\n : false;\n const features = options.features || logOnly || DEFAULT_OPTIONS.features;\n const config = Object.assign({}, DEFAULT_OPTIONS, { features }, options);\n\n if (config.maxAge && config.maxAge < 2) {\n throw new Error(\n `Devtools 'maxAge' cannot be less than 2, got ${config.maxAge}`\n );\n }\n\n return config;\n}\n","import { Action } from '@ngrx/store';\n\nimport * as Actions from './actions';\nimport {\n ActionSanitizer,\n StateSanitizer,\n Predicate,\n StoreDevtoolsConfig,\n} from './config';\nimport {\n ComputedState,\n LiftedAction,\n LiftedActions,\n LiftedState,\n} from './reducer';\n\nexport function difference(first: any[], second: any[]) {\n return first.filter((item) => second.indexOf(item) < 0);\n}\n\n/**\n * Provides an app's view into the state of the lifted store.\n */\nexport function unliftState(liftedState: LiftedState) {\n const { computedStates, currentStateIndex } = liftedState;\n\n // At start up NgRx dispatches init actions,\n // When these init actions are being filtered out by the predicate or safe/block list options\n // we don't have a complete computed states yet.\n // At this point it could happen that we're out of bounds, when this happens we fall back to the last known state\n if (currentStateIndex >= computedStates.length) {\n const { state } = computedStates[computedStates.length - 1];\n return state;\n }\n\n const { state } = computedStates[currentStateIndex];\n return state;\n}\n\nexport function unliftAction(liftedState: LiftedState): LiftedAction {\n return liftedState.actionsById[liftedState.nextActionId - 1];\n}\n\n/**\n * Lifts an app's action into an action on the lifted store.\n */\nexport function liftAction(action: Action) {\n return new Actions.PerformAction(action, +Date.now());\n}\n\n/**\n * Sanitizes given actions with given function.\n */\nexport function sanitizeActions(\n actionSanitizer: ActionSanitizer,\n actions: LiftedActions\n): LiftedActions {\n return Object.keys(actions).reduce((sanitizedActions, actionIdx) => {\n const idx = Number(actionIdx);\n sanitizedActions[idx] = sanitizeAction(actionSanitizer, actions[idx], idx);\n return sanitizedActions;\n }, <LiftedActions>{});\n}\n\n/**\n * Sanitizes given action with given function.\n */\nexport function sanitizeAction(\n actionSanitizer: ActionSanitizer,\n action: LiftedAction,\n actionIdx: number\n): LiftedAction {\n return {\n ...action,\n action: actionSanitizer(action.action, actionIdx),\n };\n}\n\n/**\n * Sanitizes given states with given function.\n */\nexport function sanitizeStates(\n stateSanitizer: StateSanitizer,\n states: ComputedState[]\n): ComputedState[] {\n return states.map((computedState, idx) => ({\n state: sanitizeState(stateSanitizer, computedState.state, idx),\n error: computedState.error,\n }));\n}\n\n/**\n * Sanitizes given state with given function.\n */\nexport function sanitizeState(\n stateSanitizer: StateSanitizer,\n state: any,\n stateIdx: number\n) {\n return stateSanitizer(state, stateIdx);\n}\n\n/**\n * Read the config and tell if actions should be filtered\n */\nexport function shouldFilterActions(config: StoreDevtoolsConfig) {\n return config.predicate || config.actionsSafelist || config.actionsBlocklist;\n}\n\n/**\n * Return a full filtered lifted state\n */\nexport function filterLiftedState(\n liftedState: LiftedState,\n predicate?: Predicate,\n safelist?: string[],\n blocklist?: string[]\n): LiftedState {\n const filteredStagedActionIds: number[] = [];\n const filteredActionsById: LiftedActions = {};\n const filteredComputedStates: ComputedState[] = [];\n liftedState.stagedActionIds.forEach((id, idx) => {\n const liftedAction = liftedState.actionsById[id];\n if (!liftedAction) return;\n if (\n idx &&\n isActionFiltered(\n liftedState.computedStates[idx],\n liftedAction,\n predicate,\n safelist,\n blocklist\n )\n ) {\n return;\n }\n filteredActionsById[id] = liftedAction;\n filteredStagedActionIds.push(id);\n filteredComputedStates.push(liftedState.computedStates[idx]);\n });\n return {\n ...liftedState,\n stagedActionIds: filteredStagedActionIds,\n actionsById: filteredActionsById,\n computedStates: filteredComputedStates,\n };\n}\n\n/**\n * Return true is the action should be ignored\n */\nexport function isActionFiltered(\n state: any,\n action: LiftedAction,\n predicate?: Predicate,\n safelist?: string[],\n blockedlist?: string[]\n) {\n const predicateMatch = predicate && !predicate(state, action.action);\n const safelistMatch =\n safelist &&\n !action.action.type.match(safelist.map((s) => escapeRegExp(s)).join('|'));\n const blocklistMatch =\n blockedlist &&\n action.action.type.match(blockedlist.map((s) => escapeRegExp(s)).join('|'));\n return predicateMatch || safelistMatch || blocklistMatch;\n}\n\n/**\n * Return string with escaped RegExp special characters\n * https://stackoverflow.com/a/6969486/1337347\n */\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import { ActionsSubject } from '@ngrx/store';\nimport { Injectable } from '@angular/core';\n\n@Injectable()\nexport class DevtoolsDispatcher extends ActionsSubject {}\n","import { Inject, Injectable, InjectionToken } from '@angular/core';\nimport { Action, UPDATE } from '@ngrx/store';\nimport { EMPTY, Observable, of } from 'rxjs';\nimport {\n catchError,\n concatMap,\n debounceTime,\n filter,\n map,\n share,\n switchMap,\n take,\n takeUntil,\n timeout,\n} from 'rxjs/operators';\n\nimport { IMPORT_STATE, PERFORM_ACTION } from './actions';\nimport {\n SerializationOptions,\n STORE_DEVTOOLS_CONFIG,\n StoreDevtoolsConfig,\n} from './config';\nimport { DevtoolsDispatcher } from './devtools-dispatcher';\nimport { LiftedAction, LiftedState } from './reducer';\nimport {\n isActionFiltered,\n sanitizeAction,\n sanitizeActions,\n sanitizeState,\n sanitizeStates,\n shouldFilterActions,\n unliftState,\n} from './utils';\n\nexport const ExtensionActionTypes = {\n START: 'START',\n DISPATCH: 'DISPATCH',\n STOP: 'STOP',\n ACTION: 'ACTION',\n};\n\nexport const REDUX_DEVTOOLS_EXTENSION =\n new InjectionToken<ReduxDevtoolsExtension>(\n '@ngrx/store-devtools Redux Devtools Extension'\n );\n\nexport interface ReduxDevtoolsExtensionConnection {\n subscribe(listener: (change: any) => void): void;\n unsubscribe(): void;\n send(action: any, state: any): void;\n init(state?: any): void;\n error(anyErr: any): void;\n}\nexport interface ReduxDevtoolsExtensionConfig {\n features?: object | boolean;\n name: string | undefined;\n maxAge?: number;\n autoPause?: boolean;\n serialize?: boolean | SerializationOptions;\n trace?: boolean | (() => string);\n traceLimit?: number;\n}\n\nexport interface ReduxDevtoolsExtension {\n connect(\n options: ReduxDevtoolsExtensionConfig\n ): ReduxDevtoolsExtensionConnection;\n send(action: any, state: any, options: ReduxDevtoolsExtensionConfig): void;\n}\n\n@Injectable()\nexport class DevtoolsExtension {\n private devtoolsExtension: ReduxDevtoolsExtension;\n private extensionConnection!: ReduxDevtoolsExtensionConnection;\n\n liftedActions$!: Observable<any>;\n actions$!: Observable<any>;\n start$!: Observable<any>;\n\n constructor(\n @Inject(REDUX_DEVTOOLS_EXTENSION) devtoolsExtension: ReduxDevtoolsExtension,\n @Inject(STORE_DEVTOOLS_CONFIG) private config: StoreDevtoolsConfig,\n private dispatcher: DevtoolsDispatcher\n ) {\n this.devtoolsExtension = devtoolsExtension;\n this.createActionStreams();\n }\n\n notify(action: LiftedAction, state: LiftedState) {\n if (!this.devtoolsExtension) {\n return;\n }\n // Check to see if the action requires a full update of the liftedState.\n // If it is a simple action generated by the user's app and the recording\n // is not locked/paused, only send the action and the current state (fast).\n //\n // A full liftedState update (slow: serializes the entire liftedState) is\n // only required when:\n // a) redux-devtools-extension fires the @@Init action (ignored by\n // @ngrx/store-devtools)\n // b) an action is generated by an @ngrx module (e.g. @ngrx/effects/init\n // or @ngrx/store/update-reducers)\n // c) the state has been recomputed due to time-traveling\n // d) any action that is not a PerformAction to err on the side of\n // caution.\n if (action.type === PERFORM_ACTION) {\n if (state.isLocked || state.isPaused) {\n return;\n }\n\n const currentState = unliftState(state);\n if (\n shouldFilterActions(this.config) &&\n isActionFiltered(\n currentState,\n action,\n this.config.predicate,\n this.config.actionsSafelist,\n this.config.actionsBlocklist\n )\n ) {\n return;\n }\n const sanitizedState = this.config.stateSanitizer\n ? sanitizeState(\n this.config.stateSanitizer,\n currentState,\n state.currentStateIndex\n )\n : currentState;\n const sanitizedAction = this.config.actionSanitizer\n ? sanitizeAction(\n this.config.actionSanitizer,\n action,\n state.nextActionId\n )\n : action;\n\n this.sendToReduxDevtools(() =>\n this.extensionConnection.send(sanitizedAction, sanitizedState)\n );\n } else {\n // Requires full state update\n const sanitizedLiftedState = {\n ...state,\n stagedActionIds: state.stagedActionIds,\n actionsById: this.config.actionSanitizer\n ? sanitizeActions(this.config.actionSanitizer, state.actionsById)\n : state.actionsById,\n computedStates: this.config.stateSanitizer\n ? sanitizeStates(this.config.stateSanitizer, state.computedStates)\n : state.computedStates,\n };\n\n this.sendToReduxDevtools(() =>\n this.devtoolsExtension.send(\n null,\n sanitizedLiftedState,\n this.getExtensionConfig(this.config)\n )\n );\n }\n }\n\n private createChangesObservable(): Observable<any> {\n if (!this.devtoolsExtension) {\n return EMPTY;\n }\n\n return new Observable((subscriber) => {\n const connection = this.devtoolsExtension.connect(\n this.getExtensionConfig(this.config)\n );\n this.extensionConnection = connection;\n connection.init();\n\n connection.subscribe((change: any) => subscriber.next(change));\n return connection.unsubscribe;\n });\n }\n\n private createActionStreams() {\n // Listens to all changes\n const changes$ = this.createChangesObservable().pipe(share());\n\n // Listen for the start action\n const start$ = changes$.pipe(\n filter((change: any) => change.type === ExtensionActionTypes.START)\n );\n\n // Listen for the stop action\n const stop$ = changes$.pipe(\n filter((change: any) => change.type === ExtensionActionTypes.STOP)\n );\n\n // Listen for lifted actions\n const liftedActions$ = changes$.pipe(\n filter((change) => change.type === ExtensionActionTypes.DISPATCH),\n map((change) => this.unwrapAction(change.payload)),\n concatMap((action: any) => {\n if (action.type === IMPORT_STATE) {\n // State imports may happen in two situations:\n // 1. Explicitly by user\n // 2. User activated the \"persist state accross reloads\" option\n // and now the state is imported during reload.\n // Because of option 2, we need to give possible\n // lazy loaded reducers time to instantiate.\n // As soon as there is no UPDATE action within 1 second,\n // it is assumed that all reducers are loaded.\n return this.dispatcher.pipe(\n filter((action) => action.type === UPDATE),\n timeout(1000),\n debounceTime(1000),\n map(() => action),\n catchError(() => of(action)),\n take(1)\n );\n } else {\n return of(action);\n }\n })\n );\n\n // Listen for unlifted actions\n const actions$ = changes$.pipe(\n filter((change) => change.type === ExtensionActionTypes.ACTION),\n map((change) => this.unwrapAction(change.payload))\n );\n\n const actionsUntilStop$ = actions$.pipe(takeUntil(stop$));\n const liftedUntilStop$ = liftedActions$.pipe(takeUntil(stop$));\n this.start$ = start$.pipe(takeUntil(stop$));\n\n // Only take the action sources between the start/stop events\n this.actions$ = this.start$.pipe(switchMap(() => actionsUntilStop$));\n this.liftedActions$ = this.start$.pipe(switchMap(() => liftedUntilStop$));\n }\n\n private unwrapAction(action: Action) {\n return typeof action === 'string' ? eval(`(${action})`) : action;\n }\n\n private getExtensionConfig(config: StoreDevtoolsConfig) {\n const extensionOptions: ReduxDevtoolsExtensionConfig = {\n name: config.name,\n features: config.features,\n serialize: config.serialize,\n autoPause: config.autoPause ?? false,\n trace: config.trace ?? false,\n traceLimit: config.traceLimit ?? 75,\n // The action/state sanitizers are not added to the config\n // because sanitation is done in this class already.\n // It is done before sending it to the devtools extension for consistency:\n // - If we call extensionConnection.send(...),\n // the extension would call the sanitizers.\n // - If we call devtoolsExtension.send(...) (aka full state update),\n // the extension would NOT call the sanitizers, so we have to do it ourselves.\n };\n if (config.maxAge !== false /* support === 0 */) {\n extensionOptions.maxAge = config.maxAge;\n }\n return extensionOptions;\n }\n\n private sendToReduxDevtools(send: Function) {\n try {\n send();\n } catch (err: any) {\n console.warn(\n '@ngrx/store-devtools: something went wrong inside the redux devtools',\n err\n );\n }\n }\n}\n","import { ErrorHandler } from '@angular/core';\nimport { Action, ActionReducer, UPDATE, INIT } from '@ngrx/store';\n\nimport { difference, liftAction, isActionFiltered } from './utils';\nimport * as DevtoolsActions from './actions';\nimport { StoreDevtoolsConfig } from './config';\nimport { PerformAction } from './actions';\n\nexport type InitAction = {\n readonly type: typeof INIT;\n};\n\nexport type UpdateReducerAction = {\n readonly type: typeof UPDATE;\n};\n\nexport type CoreActions = InitAction | UpdateReducerAction;\nexport type Actions = DevtoolsActions.All | CoreActions;\n\nexport const INIT_ACTION = { type: INIT };\n\nexport const RECOMPUTE = '@ngrx/store-devtools/recompute' as const;\nexport const RECOMPUTE_ACTION = { type: RECOMPUTE };\n\nexport interface ComputedState {\n state: any;\n error: any;\n}\n\nexport interface LiftedAction {\n type: string;\n action: Action;\n}\n\nexport interface LiftedActions {\n [id: number]: LiftedAction;\n}\n\nexport interface LiftedState {\n monitorState: any;\n nextActionId: number;\n actionsById: LiftedActions;\n stagedActionIds: number[];\n skippedActionIds: number[];\n committedState: any;\n currentStateIndex: number;\n computedStates: ComputedState[];\n isLocked: boolean;\n isPaused: boolean;\n}\n\n/**\n * Computes the next entry in the log by applying an action.\n */\nfunction computeNextEntry(\n reducer: ActionReducer<any, any>,\n action: Action,\n state: any,\n error: any,\n errorHandler: ErrorHandler\n) {\n if (error) {\n return {\n state,\n error: 'Interrupted by an error up the chain',\n };\n }\n\n let nextState = state;\n let nextError;\n try {\n nextState = reducer(state, action);\n } catch (err: any) {\n nextError = err.toString();\n errorHandler.handleError(err);\n }\n\n return {\n state: nextState,\n error: nextError,\n };\n}\n\n/**\n * Runs the reducer on invalidated actions to get a fresh computation log.\n */\nfunction recomputeStates(\n computedStates: ComputedState[],\n minInvalidatedStateIndex: number,\n reducer: ActionReducer<any, any>,\n committedState: any,\n actionsById: LiftedActions,\n stagedActionIds: number[],\n skippedActionIds: number[],\n errorHandler: ErrorHandler,\n isPaused: boolean\n) {\n // Optimization: exit early and return the same reference\n // if we know nothing could have changed.\n if (\n minInvalidatedStateIndex >= computedStates.length &&\n computedStates.length === stagedActionIds.length\n ) {\n return computedStates;\n }\n\n const nextComputedStates = computedStates.slice(0, minInvalidatedStateIndex);\n // If the recording is paused, recompute all states up until the pause state,\n // else recompute all states.\n const lastIncludedActionId = stagedActionIds.length - (isPaused ? 1 : 0);\n for (let i = minInvalidatedStateIndex; i < lastIncludedActionId; i++) {\n const actionId = stagedActionIds[i];\n const action = actionsById[actionId].action;\n\n const previousEntry = nextComputedStates[i - 1];\n const previousState = previousEntry ? previousEntry.state : committedState;\n const previousError = previousEntry ? previousEntry.error : undefined;\n\n const shouldSkip = skippedActionIds.indexOf(actionId) > -1;\n const entry: ComputedState = shouldSkip\n ? previousEntry\n : computeNextEntry(\n reducer,\n action,\n previousState,\n previousError,\n errorHandler\n );\n\n nextComputedStates.push(entry);\n }\n // If the recording is paused, the last state will not be recomputed,\n // because it's essentially not part of the state history.\n if (isPaused) {\n nextComputedStates.push(computedStates[computedStates.length - 1]);\n }\n\n return nextComputedStates;\n}\n\nexport function liftInitialState(\n initialCommittedState?: any,\n monitorReducer?: any\n): LiftedState {\n return {\n monitorState: monitorReducer(undefined, {}),\n nextActionId: 1,\n actionsById: { 0: liftAction(INIT_ACTION) },\n stagedActionIds: [0],\n skippedActionIds: [],\n committedState: initialCommittedState,\n currentStateIndex: 0,\n computedStates: [],\n isLocked: false,\n isPaused: false,\n };\n}\n\n/**\n * Creates a history state reducer from an app's reducer.\n */\nexport function liftReducerWith(\n initialCommittedState: any,\n initialLiftedState: LiftedState,\n errorHandler: ErrorHandler,\n monitorReducer?: any,\n options: Partial<StoreDevtoolsConfig> = {}\n) {\n /**\n * Manages how the history actions modify the history state.\n */\n return (\n reducer: ActionReducer<any, any>\n ): ActionReducer<LiftedState, Actions> =>\n (liftedState, liftedAction) => {\n let {\n monitorState,\n actionsById,\n nextActionId,\n stagedActionIds,\n skippedActionIds,\n committedState,\n currentStateIndex,\n computedStates,\n isLocked,\n isPaused,\n } = liftedState || initialLiftedState;\n\n if (!liftedState) {\n // Prevent mutating initialLiftedState\n actionsById = Object.create(actionsById);\n }\n\n function commitExcessActions(n: number) {\n // Auto-commits n-number of excess actions.\n let excess = n;\n let idsToDelete = stagedActionIds.slice(1, excess + 1);\n\n for (let i = 0; i < idsToDelete.length; i++) {\n if (computedStates[i + 1].error) {\n // Stop if error is found. Commit actions up to error.\n excess = i;\n idsToDelete = stagedActionIds.slice(1, excess + 1);\n break;\n } else {\n delete actionsById[idsToDelete[i]];\n }\n }\n\n skippedActionIds = skippedActionIds.filter(\n (id) => idsToDelete.indexOf(id) === -1\n );\n stagedActionIds = [0, ...stagedActionIds.slice(excess + 1)];\n committedState = computedStates[excess].state;\n computedStates = computedStates.slice(excess);\n currentStateIndex =\n currentStateIndex > excess ? currentStateIndex - excess : 0;\n }\n\n function commitChanges() {\n // Consider the last committed state the new starting point.\n // Squash any staged actions into a single committed state.\n actionsById = { 0: liftAction(INIT_ACTION) };\n nextActionId = 1;\n stagedActionIds = [0];\n skippedActionIds = [];\n committedState = computedStates[currentStateIndex].state;\n currentStateIndex = 0;\n computedStates = [];\n }\n\n // By default, aggressively recompute every state whatever happens.\n // This has O(n) performance, so we'll override this to a sensible\n // value whenever we feel like we don't have to recompute the states.\n let minInvalidatedStateIndex = 0;\n\n switch (liftedAction.type) {\n case DevtoolsActions.LOCK_CHANGES: {\n isLocked = liftedAction.status;\n minInvalidatedStateIndex = Infinity;\n break;\n }\n case DevtoolsActions.PAUSE_RECORDING: {\n isPaused = liftedAction.status;\n if (isPaused) {\n // Add a pause action to signal the devtools-user the recording is paused.\n // The corresponding state will be overwritten on each update to always contain\n // the latest state (see Actions.PERFORM_ACTION).\n stagedActionIds = [...stagedActionIds, nextActionId];\n actionsById[nextActionId] = new PerformAction(\n {\n type: '@ngrx/devtools/pause',\n },\n +Date.now()\n );\n nextActionId++;\n minInvalidatedStateIndex = stagedActionIds.length - 1;\n computedStates = computedStates.concat(\n computedStates[computedStates.length - 1]\n );\n\n if (currentStateIndex === stagedActionIds.length - 2) {\n currentStateIndex++;\n }\n minInvalidatedStateIndex = Infinity;\n } else {\n commitChanges();\n }\n break;\n }\n case DevtoolsActions.RESET: {\n // Get back to the state the store was created with.\n actionsById = { 0: liftAction(INIT_ACTION) };\n nextActionId = 1;\n stagedActionIds = [0];\n skippedActionIds = [];\n committedState = initialCommittedState;\n currentStateIndex = 0;\n computedStates = [];\n break;\n }\n case DevtoolsActions.COMMIT: {\n commitChanges();\n break;\n }\n case DevtoolsActions.ROLLBACK: {\n // Forget about any staged actions.\n // Start again from the last committed state.\n actionsById = { 0: liftAction(INIT_ACTION) };\n nextActionId = 1;\n stagedActionIds = [0];\n skippedActionIds = [];\n currentStateIndex = 0;\n computedStates = [];\n break;\n }\n case DevtoolsActions.TOGGLE_ACTION: {\n // Toggle whether an action with given ID is skipped.\n // Being skipped means it is a no-op during the computation.\n const { id: actionId } = liftedAction;\n const index = skippedActionIds.indexOf(actionId);\n if (index === -1) {\n skippedActionIds = [actionId, ...skippedActionIds];\n } else {\n skippedActionIds = skippedActionIds.filter((id) => id !== actionId);\n }\n // Optimization: we know history before this action hasn't changed\n minInvalidatedStateIndex = stagedActionIds.indexOf(actionId);\n break;\n }\n case DevtoolsActions.SET_ACTIONS_ACTIVE: {\n // Toggle whether an action with given ID is skipped.\n // Being skipped means it is a no-op during the computation.\n const { start, end, active } = liftedAction;\n const actionIds = [];\n for (let i = start; i < end; i++) actionIds.push(i);\n if (active) {\n skippedActionIds = difference(skippedActionIds, actionIds);\n } else {\n skippedActionIds = [...skippedActionIds, ...actionIds];\n }\n\n // Optimization: we know history before this action hasn't changed\n minInvalidatedStateIndex = stagedActionIds.indexOf(start);\n break;\n }\n case DevtoolsActions.JUMP_TO_STATE: {\n // Without recomputing anything, move the pointer that tell us\n // which state is considered the current one. Useful for sliders.\n currentStateIndex = liftedAction.index;\n // Optimization: we know the history has not changed.\n minInvalidatedStateIndex = Infinity;\n break;\n }\n case DevtoolsActions.JUMP_TO_ACTION: {\n // Jumps to a corresponding state to a specific action.\n // Useful when filtering actions.\n const index = stagedActionIds.indexOf(liftedAction.actionId);\n if (index !== -1) currentStateIndex = index;\n minInvalidatedStateIndex = Infinity;\n break;\n }\n case DevtoolsActions.SWEEP: {\n // Forget any actions that are currently being skipped.\n stagedActionIds = difference(stagedActionIds, skippedActionIds);\n skippedActionIds = [];\n currentStateIndex = Math.min(\n currentStateIndex,\n stagedActionIds.length - 1\n );\n break;\n }\n case DevtoolsActions.PERFORM_ACTION: {\n // Ignore action and return state as is if recording is locked\n if (isLocked) {\n return liftedState || initialLiftedState;\n }\n\n if (\n isPaused ||\n (liftedState &&\n isActionFiltered(\n liftedState.computedStates[currentStateIndex],\n liftedAction,\n options.predicate,\n options.actionsSafelist,\n options.actionsBlocklist\n ))\n ) {\n // If recording is paused or if the action should be ignored, overwrite the last state\n // (corresponds to the pause action) and keep everything else as is.\n // This way, the app gets the new current state while the devtools\n // do not record another action.\n const lastState = computedStates[computedStates.length - 1];\n computedStates = [\n ...computedStates.slice(0, -1),\n computeNextEntry(\n reducer,\n liftedAction.action,\n lastState.state,\n lastState.error,\n errorHandler\n ),\n ];\n minInvalidatedStateIndex = Infinity;\n break;\n }\n\n // Auto-commit as new actions come in.\n if (options.maxAge && stagedActionIds.length === options.maxAge) {\n commitExcessActions(1);\n }\n\n if (currentStateIndex === stagedActionIds.length - 1) {\n currentStateIndex++;\n }\n const actionId = nextActionId++;\n // Mutation! This is the hottest path, and we optimize on purpose.\n // It is safe because we set a new key in a cache dictionary.\n actionsById[actionId] = liftedAction;\n\n stagedActionIds = [...stagedActionIds, actionId];\n // Optimization: we know that only the new action needs computing.\n minInvalidatedStateIndex = stagedActionIds.length - 1;\n break;\n }\n case DevtoolsActions.IMPORT_STATE: {\n // Completely replace everything.\n ({\n monitorState,\n actionsById,\n nextActionId,\n stagedActionIds,\n skippedActionIds,\n committedState,\n currentStateIndex,\n computedStates,\n isLocked,\n isPaused,\n } = liftedAction.nextLiftedState);\n break;\n }\n case INIT: {\n // Always recompute states on hot reload and init.\n minInvalidatedStateIndex = 0;\n\n if (options.maxAge && stagedActionIds.length > options.maxAge) {\n // States must be recomputed before committing excess.\n computedStates = recomputeStates(\n computedStates,\n minInvalidatedStateIndex,\n reducer,\n committedState,\n actionsById,\n stagedActionIds,\n skippedActionIds,\n errorHandler,\n isPaused\n );\n\n commitExcessActions(stagedActionIds.length - options.maxAge);\n\n // Avoid double computation.\n minInvalidatedStateIndex = Infinity;\n }\n\n break;\n }\n case UPDATE: {\n const stateHasErrors =\n computedStates.filter((state) => state.error).length > 0;\n\n if (stateHasErrors) {\n // Recompute all states\n minInvalidatedStateIndex = 0;\n\n if (options.maxAge && stagedActionIds.length > options.maxAge) {\n // States must be recomputed before committing excess.\n computedStates = recomputeStates(\n computedStates,\n minInvalidatedStateIndex,\n reducer,\n committedState,\n actionsById,\n stagedActionIds,\n skippedActionIds,\n errorHandler,\n isPaused\n );\n\n commitExcessActions(stagedActionIds.length - options.maxAge);\n\n // Avoid double computation.\n minInvalidatedStateIndex = Infinity;\n }\n } else {\n // If not paused/locked, add a new action to signal devtools-user\n // that there was a reducer update.\n if (!isPaused && !isLocked) {\n if (currentStateIndex === stagedActionIds.length - 1) {\n currentStateIndex++;\n }\n\n // Add a new action to only recompute state\n const actionId = nextActionId++;\n actionsById[actionId] = new PerformAction(\n liftedAction,\n +Date.now()\n );\n stagedActionIds = [...stagedActionIds, actionId];\n\n minInvalidatedStateIndex = stagedActionIds.length - 1;\n\n computedStates = recomputeStates(\n computedStates,\n minInvalidatedStateIndex,\n reducer,\n committedState,\n actionsById,\n stagedActionIds,\n skippedActionIds,\n errorHandler,\n isPaused\n );\n }\n\n // Recompute state history with latest reducer and update action\n computedStates = computedStates.map((cmp) => ({\n ...cmp,\n state: reducer(cmp.state, RECOMPUTE_ACTION),\n }));\n\n currentStateIndex = stagedActionIds.length - 1;\n\n if (options.maxAge && stagedActionIds.length > options.maxAge) {\n commitExcessActions(stagedActionIds.length - options.maxAge);\n }\n\n // Avoid double computation.\n minInvalidatedStateIndex = Infinity;\n }\n\n break;\n }\n default: {\n // If the action is not recognized, it's a monitor action.\n // Optimization: a monitor action can't change history.\n minInvalidatedStateIndex = Infinity;\n break;\n }\n }\n\n computedStates = recomputeStates(\n computedStates,\n minInvalidatedStateIndex,\n reducer,\n committedState,\n actionsById,\n stagedActionIds,\n skippedActionIds,\n errorHandler,\n isPaused\n );\n monitorState = monitorReducer(monitorState, liftedAction);\n\n return {\n monitorState,\n actionsById,\n nextActionId,\n stagedActionIds,\n skippedActionIds,\n committedState,\n currentStateIndex,\n computedStates,\n isLocked,\n isPaused,\n };\n };\n}\n","import { Injectable, Inject, ErrorHandler } from '@angular/core';\nimport {\n Action,\n ActionReducer,\n ActionsSubject,\n INITIAL_STATE,\n ReducerObservable,\n ScannedActionsSubject,\n} from '@ngrx/store';\nimport {\n merge,\n Observable,\n Observer,\n queueScheduler,\n ReplaySubject,\n Subscription,\n} from 'rxjs';\nimport { map, observeOn, scan, skip, withLatestFrom } from 'rxjs/operators';\n\nimport * as Actions from './actions';\nimport { STORE_DEVTOOLS_CONFIG, StoreDevtoolsConfig } from './config';\nimport { DevtoolsExtension } from './extension';\nimport { LiftedState, liftInitialState, liftReducerWith } from './reducer';\nimport {\n liftAction,\n unliftState,\n shouldFilterActions,\n filterLiftedState,\n} from './utils';\nimport { DevtoolsDispatcher } from './devtools-dispatcher';\nimport { PERFORM_ACTION } from './actions';\n\n@Injectable()\nexport class StoreDevtools implements Observer<any> {\n private stateSubscription: Subscription;\n private extensionStartSubscription: Subscription;\n public dispatcher: ActionsSubject;\n public liftedState: Observable<LiftedState>;\n public state: Observable<any>;\n\n constructor(\n dispatcher: DevtoolsDispatcher,\n actions$: ActionsSubject,\n reducers$: ReducerObservable,\n extension: DevtoolsExtension,\n scannedActions: ScannedActionsSubject,\n errorHandler: ErrorHandler,\n @Inject(INITIAL_STATE) initialState: any,\n @Inject(STORE_DEVTOOLS_CONFIG) config: StoreDevtoolsConfig\n ) {\n const liftedInitialState = liftInitialState(initialState, config.monitor);\n const liftReducer = liftReducerWith(\n initialState,\n liftedInitialState,\n errorHandler,\n config.monitor,\n config\n );\n\n const liftedAction$ = merge(\n merge(actions$.asObservable().pipe(skip(1)), extension.actions$).pipe(\n map(liftAction)\n ),\n dispatcher,\n extension.liftedActions$\n ).pipe(observeOn(queueScheduler));\n\n const liftedReducer$ = reducers$.pipe(map(liftReducer));\n\n const liftedStateSubject = new ReplaySubject<LiftedState>(1);\n\n const liftedStateSubscription = liftedAction$\n .pipe(\n withLatestFrom(liftedReducer$),\n scan<\n [any, ActionReducer<LiftedState, Actions.All>],\n {\n state: LiftedState;\n action: any;\n }\n >(\n ({ state: liftedState }, [action, reducer]) => {\n let reducedLiftedState = reducer(liftedState, action);\n // On full state update\n // If we have actions filters, we must filter completely our lifted state to be sync with the extension\n if (action.type !== PERFORM_ACTION && shouldFilterActions(config)) {\n reducedLiftedState = filterLiftedState(\n reducedLiftedState,\n config.predicate,\n config.actionsSafelist,\n config.actionsBlocklist\n );\n }\n // Extension should be sent the sanitized lifted state\n extension.notify(action, reducedLiftedState);\n return { state: reducedLiftedState, action };\n },\n { state: liftedInitialState, action: null as any }\n )\n )\n .subscribe(({ state, action }) => {\n liftedStateSubject.next(state);\n\n if (action.type === Actions.PERFORM_ACTION) {\n const unliftedAction = (action as Actions.PerformAction).action;\n\n scannedActions.next(unliftedAction);\n }\n });\n\n const extensionStartSubscription = extension.start$.subscribe(() => {\n this.refresh();\n });\n\n const liftedState$ =\n liftedStateSubject.asObservable() as Observable<LiftedState>;\n const state$ = liftedState$.pipe(map(unliftState));\n\n this.extensionStartSubscription = extensionStartSubscription;\n this.stateSubscription = liftedStateSubscription;\n this.dispatcher = dispatcher;\n this.liftedState = liftedState$;\n this.state = state$;\n }\n\n dispatch(action: Action) {\n this.dispatcher.next(action);\n }\n\n next(action: any) {\n this.dispatcher.next(action);\n }\n\n error(error: any) {}\n\n complete() {}\n\n performAction(action: any) {\n this.dispatch(new Actions.PerformAction(action, +Date.now()));\n }\n\n refresh() {\n this.dispatch(new Actions.Refresh());\n }\n\n reset() {\n this.dispatch(new Actions.Reset(+Date.now()));\n }\n\n rollback() {\n this.dispatch(new Actions.Rollback(+Date.now()));\n }\n\n commit() {\n this.dispatch(new Actions.Commit(+Date.now()));\n }\n\n sweep() {\n this.dispatch(new Actions.Sweep());\n }\n\n toggleAction(id: number) {\n this.dispatch(new Actions.ToggleAction(id));\n }\n\n jumpToAction(actionId: number) {\n this.dispatch(new Actions.JumpToAction(actionId));\n }\n\n jumpToState(index: number) {\n this.dispatch(new Actions.JumpToState(index));\n }\n\n importState(nextLiftedState: any) {\n this.dispatch(new Actions.ImportState(nextLiftedState));\n }\n\n lockChanges(status: boolean) {\n this.dispatch(new Actions.LockChanges(status));\n }\n\n pauseRecording(status: boolean) {\n this.dispatch(new Actions.PauseRecording(status));\n }\n}\n","import {\n EnvironmentProviders,\n InjectionToken,\n makeEnvironmentProviders,\n Provider,\n} from '@angular/core';\nimport {\n DevtoolsExtension,\n REDUX_DEVTOOLS_EXTENSION,\n ReduxDevtoolsExtension,\n} from './extension';\nimport { DevtoolsDispatcher } from './devtools-dispatcher';\nimport {\n createConfig,\n INITIAL_OPTIONS,\n noMonitor,\n STORE_DEVTOOLS_CONFIG,\n StoreDevtoolsConfig,\n StoreDevtoolsOptions,\n} from './config';\nimport { ReducerManagerDispatcher, StateObservable } from '@ngrx/store';\nimport { createStateObservable } from './instrument';\nimport { StoreDevtools } from './devtools';\n\nexport const IS_EXTENSION_OR_MONITOR_PRESENT = new InjectionToken<boolean>(\n '@ngrx/store-devtools Is Devtools Extension or Monitor Present'\n);\n\nexport function createIsExtensionOrMonitorPresent(\n extension: ReduxDevtoolsExtension | null,\n config: StoreDevtoolsConfig\n) {\n return Boolean(extension) || config.monitor !== noMonitor;\n}\n\nexport function createReduxDevtoolsExtension() {\n const extensionKey = '__REDUX_DEVTOOLS_EXTENSION__';\n\n if (\n typeof window === 'object' &&\n typeof (window as any)[extensionKey] !== 'undefined'\n ) {\n return (window as any)[extensionKey];\n } else {\n return null;\n }\n}\n\n/**\n * Provides developer tools and instrumentation for `Store`.\n *\n * @usageNotes\n *\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideStoreDevtools({\n * maxAge: 25,\n * logOnly: !isDevMode(),\n * }),\n * ],\n * });\n * ```\n */\nexport function provideStoreDevtools(\n options: StoreDevtoolsOptions = {}\n): EnvironmentProviders {\n return makeEnvironmentProviders([\n DevtoolsExtension,\n DevtoolsDispatcher,\n StoreDevtools,\n {\n provide: INITIAL_OPTIONS,\n useValue: options,\n },\n {\n provide: IS_EXTENSION_OR_MONITOR_PRESENT,\n deps: [REDUX_DEVTOOLS_EXTENSION, STORE_DEVTOOLS_CONFIG],\n useFactory: createIsExtensionOrMonitorPresent,\n },\n {\n provide: REDUX_DEVTOOLS_EXTENSION,\n useFactory: createReduxDevtoolsExtension,\n },\n {\n provide: STORE_DEVTOOLS_CONFIG,\n deps: [INITIAL_OPTIONS],\n useFactory: createConfig,\n },\n {\n provide: StateObservable,\n deps: [StoreDevtools],\n useFactory: createStateObservable,\n },\n {\n provide: ReducerManagerDispatcher,\n useExisting: DevtoolsDispatcher,\n },\n ]);\n}\n","import { ModuleWithProviders, NgModule } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { StoreDevtoolsOptions } from './config';\nimport { StoreDevtools } from './devtools';\nimport { provideStoreDevtools } from './provide-store-devtools';\n\nexport function createStateObservable(\n devtools: StoreDevtools\n): Observable<any> {\n return devtools.state;\n}\n\n@NgModule({})\nexport class StoreDevtoolsModule {\n static instrument(\n options: StoreDevtoolsOptions = {}\n ): ModuleWithProviders<StoreDevtoolsModule> {\n return {\n ngModule: StoreDevtoolsModule,\n providers: [provideStoreDevtools(options)],\n };\n }\n}\n","export const REGISTERED_ACTION_TYPES: { [actionType: string]: number } = {};\n\nexport function resetRegisteredActionTypes() {\n for (const key of Object.keys(REGISTERED_ACTION_TYPES)) {\n delete REGISTERED_ACTION_TYPES[key];\n }\n}\n","import {\n Creator,\n ActionCreator,\n TypedAction,\n FunctionWithParametersType,\n NotAllowedCheck,\n ActionCreatorProps,\n NotAllowedInPropsCheck,\n} from './models';\nimport { REGISTERED_ACTION_TYPES } from './globals';\n\n// Action creators taken from ts-action library and modified a bit to better\n// fit current NgRx usage. Thank you Nicholas Jamieson (@cartant).\n\nexport function createAction<T extends string>(\n type: T\n): ActionCreator<T, () => TypedAction<T>>;\nexport function createAction<T extends string, P extends object>(\n type: T,\n config: ActionCreatorProps<P> & NotAllowedCheck<P>\n): ActionCreator<T, (props: P & NotAllowedCheck<P>) => P & TypedAction<T>>;\nexport function createAction<\n T extends string,\n P extends any[],\n R extends object\n>(\n type: T,\n creator: Creator<P, R & NotAllowedCheck<R>>\n): FunctionWithParametersType<P, R & TypedAction<T>> & TypedAction<T>;\n/**\n * @description\n * Creates a configured `Creator` function that, when called, returns an object in the shape of the `Action` interface.\n *\n * Action creators reduce the explicitness of class-based action creators.\n *\n * @param type Describes the action that will be dispatched\n * @param config Additional metadata needed for the handling of the action. See {@link createAction#usage-notes Usage Notes}.\n *\n * @usageNotes\n *\n * **Declaring an action creator**\n *\n * Without additional metadata:\n * ```ts\n * export const increment = createAction('[Counter] Increment');\n * ```\n * With additional metadata:\n * ```ts\n * export const loginSuccess = createAction(\n * '[Auth/API] Login Success',\n * props<{ user: User }>()\n * );\n * ```\n * With a function:\n * ```ts\n * export const loginSuccess = createAction(\n * '[Auth/API] Login Success',\n * (response: Response) => response.user\n * );\n * ```\n *\n * **Dispatching an action**\n *\n * Without additional metadata:\n * ```ts\n * store.dispatch(increment());\n * ```\n * With additional metadata:\n * ```ts\n * store.dispatch(loginSuccess({ user: newUser }));\n * ```\n *\n * **Referencing an action in a reducer**\n *\n * Using a switch statement:\n * ```ts\n * switch (action.type) {\n * // ...\n * case AuthApiActions.loginSuccess.type: {\n * return {\n * ...state,\n * user: action.user\n * };\n * }\n * }\n * ```\n * Using a reducer creator:\n * ```ts\n * on(AuthApiActions.loginSuccess, (state, { user }) => ({ ...state, user }))\n * ```\n *\n * **Referencing an action in an effect**\n * ```ts\n * effectName$ = createEffect(\n * () => this.actions$.pipe(\n * ofType(AuthApiActions.loginSuccess),\n * // ...\n * )\n * );\n * ```\n */\nexport function createAction<T extends string, C extends Creator>(\n type: T,\n config?: { _as: 'props' } | C\n): ActionCreator<T> {\n REGISTERED_ACTION_TYPES[type] = (REGISTERED_ACTION_TYPES[type] || 0) + 1;\n\n if (typeof config === 'function') {\n return defineType(type, (...args: any[]) => ({\n ...config(...args),\n type,\n }));\n }\n const as = config ? config._as : 'empty';\n switch (as) {\n case 'empty':\n return defineType(type, () => ({ type }));\n case 'props':\n return defineType(type, (props: object) => ({\n ...props,\n type,\n }));\n default:\n throw new Error('Unexpected config.');\n }\n}\n\nexport function props<\n P extends SafeProps,\n SafeProps = NotAllowedInPropsCheck<P>\n>(): ActionCreatorProps<P> {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return { _as: 'props', _p: undefined! };\n}\n\nexport function union<\n C extends { [key: string]: ActionCreator<string, Creator> }\n>(creators: C): ReturnType<C[keyof C]> {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return undefined!;\n}\n\nfunction defineType<T extends string>(\n type: T,\n creator: Creator\n): ActionCreator<T> {\n return Object.defineProperty(creator, 'type', {\n value: type,\n writable: false,\n }) as ActionCreator<T>;\n}\n","import { Injectable, OnDestroy, Provider } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\nimport { Action } from './models';\n\nexport const INIT = '@ngrx/store/init' as const;\n\n@Injectable()\nexport class ActionsSubject\n extends BehaviorSubject<Action>\n implements OnDestroy\n{\n constructor() {\n super({ type: INIT });\n }\n\n override next(action: Action): void {\n if (typeof action === 'function') {\n throw new TypeError(`\n Dispatch expected an object, instead it received a function.\n If you're using the createAction function, make sure to invoke the function\n before dispatching the action. For example, someAction should be someAction().`);\n } else if (typeof action === 'undefined') {\n throw new TypeError(`Actions must be objects`);\n } else if (typeof action.type === 'undefined') {\n throw new TypeError(`Actions must have a type property`);\n }\n super.next(action);\n }\n\n override complete() {\n /* noop */\n }\n\n ngOnDestroy() {\n super.complete();\n }\n}\n\nexport const ACTIONS_SUBJECT_PROVIDERS: Provider[] = [ActionsSubject];\n","import { InjectionToken } from '@angular/core';\nimport { RuntimeChecks, MetaReducer } from './models';\n\nexport const _ROOT_STORE_GUARD = new InjectionToken<void>(\n '@ngrx/store Internal Root Guard'\n);\nexport const _INITIAL_STATE = new InjectionToken(\n '@ngrx/store Internal Initial State'\n);\nexport const INITIAL_STATE = new InjectionToken('@ngrx/store Initial State');\nexport const REDUCER_FACTORY = new InjectionToken(\n '@ngrx/store Reducer Factory'\n);\nexport const _REDUCER_FACTORY = new InjectionToken(\n '@ngrx/store Internal Reducer Factory Provider'\n);\nexport const INITIAL_REDUCERS = new InjectionToken(\n '@ngrx/store Initial Reducers'\n);\nexport const _INITIAL_REDUCERS = new InjectionToken(\n '@ngrx/store Internal Initial Reducers'\n);\nexport const STORE_FEATURES = new InjectionToken('@ngrx/store Store Features');\nexport const _STORE_REDUCERS = new InjectionToken(\n '@ngrx/store Internal Store Reducers'\n);\nexport const _FEATURE_REDUCERS = new InjectionToken(\n '@ngrx/store Internal Feature Reducers'\n);\n\nexport const _FEATURE_CONFIGS = new InjectionToken(\n '@ngrx/store Internal Feature Configs'\n);\n\nexport const _STORE_FEATURES = new InjectionToken(\n '@ngrx/store Internal Store Features'\n);\n\nexport const _FEATURE_REDUCERS_TOKEN = new InjectionToken(\n '@ngrx/store Internal Feature Reducers Token'\n);\nexport const FEATURE_REDUCERS = new InjectionToken(\n '@ngrx/store Feature Reducers'\n);\n\n/**\n * User-defined meta reducers from StoreModule.forRoot()\n */\nexport const USER_PROVIDED_META_REDUCERS = new InjectionToken<MetaReducer[]>(\n '@ngrx/store User Provided Meta Reducers'\n);\n\n/**\n * Meta reducers defined either internally by @ngrx/store or by library authors\n */\nexport const META_REDUCERS = new InjectionToken<MetaReducer[]>(\n '@ngrx/store Meta Reducers'\n);\n\n/**\n * Concats the user provided meta reducers and the meta reducers provided on the multi\n * injection token\n */\nexport const _RESOLVED_META_REDUCERS = new InjectionToken<MetaReducer>(\n '@ngrx/store Internal Resolved Meta Reducers'\n);\n\n/**\n * Runtime checks defined by the user via an InjectionToken\n * Defaults to `_USER_RUNTIME_CHECKS`\n */\nexport const USER_RUNTIME_CHECKS = new InjectionToken<RuntimeChecks>(\n '@ngrx/store User Runtime Checks Config'\n);\n\n/**\n * Runtime checks defined by the user via forRoot()\n */\nexport const _USER_RUNTIME_CHECKS = new InjectionToken<RuntimeChecks>(\n '@ngrx/store Internal User Runtime Checks Config'\n);\n\n/**\n * Runtime checks currently in use\n */\nexport const ACTIVE_RUNTIME_CHECKS = new InjectionToken<RuntimeChecks>(\n '@ngrx/store Internal Runtime Checks'\n);\n\nexport const _ACTION_TYPE_UNIQUENESS_CHECK = new InjectionToken<void>(\n '@ngrx/store Check if Action types are unique'\n);\n\n/**\n * InjectionToken that registers the global Store.\n * Mainly used to provide a hook that can be injected\n * to ensure the root state is loaded before something\n * that depends on it.\n */\nexport const ROOT_STORE_PROVIDER = new InjectionToken<void>(\n '@ngrx/store Root Store Provider'\n);\n\n/**\n * InjectionToken that registers feature states.\n * Mainly used to provide a hook that can be injected\n * to ensure feature state is loaded before something\n * that depends on it.\n */\nexport const FEATURE_STATE_PROVIDER = new InjectionToken<void>(\n '@ngrx/store Feature State Provider'\n);\n","import {\n Action,\n ActionReducer,\n ActionReducerFactory,\n ActionReducerMap,\n MetaReducer,\n InitialState,\n} from './models';\n\nexport function combineReducers<T, V extends Action = Action>(\n reducers: ActionReducerMap<T, V>,\n initialState?: Partial<T>\n): ActionReducer<T, V>;\n/**\n * @description\n * Combines reducers for individual features into a single reducer.\n *\n * You can use this function to delegate handling of state transitions to multiple reducers, each acting on their\n * own sub-state within the root state.\n *\n * @param reducers An object mapping keys of the root state to their corresponding feature reducer.\n * @param initialState Provides a state value if the current state is `undefined`, as it is initially.\n * @returns A reducer function.\n *\n * @usageNotes\n *\n * **Example combining two feature reducers into one \"root\" reducer**\n *\n * ```ts\n * export const reducer = combineReducers({\n * featureA: featureAReducer,\n * featureB: featureBReducer\n * });\n * ```\n *\n * You can also override the initial states of the sub-features:\n * ```ts\n * export const reducer = combineReducers({\n * featureA: featureAReducer,\n * featureB: featureBReducer\n * }, {\n * featureA: { counterA: 13 },\n * featureB: { counterB: 37 }\n * });\n * ```\n */\nexport function combineReducers(\n reducers: any,\n initialState: any = {}\n): ActionReducer<any, Action> {\n const reducerKeys = Object.keys(reducers);\n const finalReducers: any = {};\n\n for (let i = 0; i < reducerKeys.length; i++) {\n const key = reducerKeys[i];\n if (typeof reducers[key] === 'function') {\n finalReducers[key] = reducers[key];\n }\n }\n\n const finalReducerKeys = Object.keys(finalReducers);\n\n return function combination(state, action) {\n state = state === undefined ? initialState : state;\n let hasChanged = false;\n const nextState: any = {};\n for (let i = 0; i < finalReducerKeys.length; i++) {\n const key = finalReducerKeys[i];\n const reducer: any = finalReducers[key];\n const previousStateForKey = state[key];\n const nextStateForKey = reducer(previousStateForKey, action);\n\n nextState[key] = nextStateForKey;\n hasChanged = hasChanged || nextStateForKey !== previousStateForKey;\n }\n return hasChanged ? nextState : state;\n };\n}\n\nexport function omit<T extends { [key: string]: any }>(\n object: T,\n keyToRemove: keyof T\n): Partial<T> {\n return Object.keys(object)\n .filter((key) => key !== keyToRemove)\n .reduce((result, key) => Object.assign(result, { [key]: object[key] }), {});\n}\n\nexport function compose<A>(): (i: A) => A;\nexport function compose<A, B>(b: (i: A) => B): (i: A) => B;\nexport function compose<A, B, C>(c: (i: B) => C, b: (i: A) => B): (i: A) => C;\nexport function compose<A, B, C, D>(\n d: (i: C) => D,\n c: (i: B) => C,\n b: (i: A) => B\n): (i: A) => D;\nexport function compose<A, B, C, D, E>(\n e: (i: D) => E,\n d: (i: C) => D,\n c: (i: B) => C,\n b: (i: A) => B\n): (i: A) => E;\nexport function compose<A, B, C, D, E, F>(\n f: (i: E) => F,\n e: (i: D) => E,\n d: (i: C) => D,\n c: (i: B) => C,\n b: (i: A) => B\n): (i: A) => F;\nexport function compose<A = any, F = any>(...functions: any[]): (i: A) => F;\nexport function compose(...functions: any[]) {\n return function (arg: any) {\n if (functions.length === 0) {\n return arg;\n }\n\n const last = functions[functions.length - 1];\n const rest = functions.slice(0, -1);\n\n return rest.reduceRight((composed, fn) => fn(composed), last(arg));\n };\n}\n\nexport function createReducerFactory<T, V extends Action = Action>(\n reducerFactory: ActionReducerFactory<T, V>,\n metaReducers?: MetaReducer<T, V>[]\n): ActionReducerFactory<T, V> {\n if (Array.isArray(metaReducers) && metaReducers.length > 0) {\n (reducerFactory as any) = compose.apply(null, [\n ...metaReducers,\n reducerFactory,\n ]);\n }\n\n return (reducers: ActionReducerMap<T, V>, initialState?: InitialState<T>) => {\n const reducer = reducerFactory(reducers);\n return (state: T | undefined, action: V) => {\n state = state === undefined ? (initialState as T) : state;\n return reducer(state, action);\n };\n };\n}\n\nexport function createFeatureReducerFactory<T, V extends Action = Action>(\n metaReducers?: MetaReducer<T, V>[]\n): (reducer: ActionReducer<T, V>, initialState?: T) => ActionReducer<T, V> {\n const reducerFactory =\n Array.isArray(metaReducers) && metaReducers.length > 0\n ? compose<ActionReducer<T, V>>(...metaReducers)\n : (r: ActionReducer<T, V>) => r;\n\n return (reducer: ActionReducer<T, V>, initialState?: T) => {\n reducer = reducerFactory(reducer);\n\n return (state: T | undefined, action: V) => {\n state = state === undefined ? initialState : state;\n return reducer(state, action);\n };\n };\n}\n","import { Inject, Injectable, OnDestroy, Provider } from '@angular/core';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { ActionsSubject } from './actions_subject';\nimport {\n Action,\n ActionReducer,\n ActionReducerFactory,\n ActionReducerMap,\n StoreFeature,\n} from './models';\nimport { INITIAL_REDUCERS, INITIAL_STATE, REDUCER_FACTORY } from './tokens';\nimport {\n createFeatureReducerFactory,\n createReducerFactory,\n omit,\n} from './utils';\n\nexport abstract class ReducerObservable extends Observable<\n ActionReducer<any, any>\n> {}\nexport abstract class ReducerManagerDispatcher extends ActionsSubject {}\nexport const UPDATE = '@ngrx/store/update-reducers' as const;\n\n@Injectable()\nexport class ReducerManager\n extends BehaviorSubject<ActionReducer<any, any>>\n implements OnDestroy\n{\n get currentReducers(): ActionReducerMap<any, any> {\n return this.reducers;\n }\n\n constructor(\n private dispatcher: ReducerManagerDispatcher,\n @Inject(INITIAL_STATE) private initialState: any,\n @Inject(INITIAL_REDUCERS) private reducers: ActionReducerMap<any, any>,\n @Inject(REDUCER_FACTORY)\n private reducerFactory: ActionReducerFactory<any, any>\n ) {\n super(reducerFactory(reducers, initialState));\n }\n\n addFeature(feature: StoreFeature<any, any>) {\n this.addFeatures([feature]);\n }\n\n addFeatures(features: StoreFeature<any, any>[]) {\n const reducers = features.reduce(\n (\n reducerDict,\n { reducers, reducerFactory, metaReducers, initialState, key }\n ) => {\n const reducer =\n typeof reducers === 'function'\n ? createFeatureReducerFactory(metaReducers)(reducers, initialState)\n : createReducerFactory(reducerFactory, metaReducers)(\n reducers,\n initialState\n );\n\n reducerDict[key] = reducer;\n return reducerDict;\n },\n {} as { [key: string]: ActionReducer<any, any> }\n );\n\n this.addReducers(reducers);\n }\n\n removeFeature(feature: StoreFeature<any, any>) {\n this.removeFeatures([feature]);\n }\n\n removeFeatures(features: StoreFeature<any, any>[]) {\n this.removeReducers(features.map((p) => p.key));\n }\n\n addReducer(key: string, reducer: ActionReducer<any, any>) {\n this.addReducers({ [key]: reducer });\n }\n\n addReducers(reducers: { [key: string]: ActionReducer<any, any> }) {\n this.reducers = { ...this.reducers, ...reducers };\n this.updateReducers(Object.keys(reducers));\n }\n\n removeReducer(featureKey: string) {\n this.removeReducers([featureKey]);\n }\n\n removeReducers(featureKeys: string[]) {\n featureKeys.forEach((key) => {\n this.reducers = omit(this.reducers, key) /*TODO(#823)*/ as any;\n });\n this.updateReducers(featureKeys);\n }\n\n private updateReducers(featureKeys: string[]) {\n this.next(this.reducerFactory(this.reducers, this.initialState));\n this.dispatcher.next(<Action>{\n type: UPDATE,\n features: featureKeys,\n });\n }\n\n ngOnDestroy() {\n this.complete();\n }\n}\n\nexport const REDUCER_MANAGER_PROVIDERS: Provider[] = [\n ReducerManager,\n { provide: ReducerObservable, useExisting: ReducerManager },\n { provide: ReducerManagerDispatcher, useExisting: ActionsSubject },\n];\n","import { Injectable, OnDestroy, Provider } from '@angular/core';\nimport { Subject } from 'rxjs';\n\nimport { Action } from './models';\n\n@Injectable()\nexport class ScannedActionsSubject\n extends Subject<Action>\n implements OnDestroy\n{\n ngOnDestroy() {\n this.complete();\n }\n}\n\nexport const SCANNED_ACTIONS_SUBJECT_PROVIDERS: Provider[] = [\n ScannedActionsSubject,\n];\n","import { Inject, Injectable, OnDestroy, Provider } from '@angular/core';\nimport {\n BehaviorSubject,\n Observable,\n queueScheduler,\n Subscription,\n} from 'rxjs';\nimport { observeOn, scan, withLatestFrom } from 'rxjs/operators';\n\nimport { ActionsSubject, INIT } from './actions_subject';\nimport { Action, ActionReducer } from './models';\nimport { ReducerObservable } from './reducer_manager';\nimport { ScannedActionsSubject } from './scanned_actions_subject';\nimport { INITIAL_STATE } from './tokens';\n\nexport abstract class StateObservable extends Observable<any> {}\n\n@Injectable()\nexport class State<T> extends BehaviorSubject<any> implements OnDestroy {\n static readonly INIT = INIT;\n\n private stateSubscription: Subscription;\n\n constructor(\n actions$: ActionsSubject,\n reducer$: ReducerObservable,\n scannedActions: ScannedActionsSubject,\n @Inject(INITIAL_STATE) initialState: any\n ) {\n super(initialState);\n\n const actionsOnQueue$: Observable<Action> = actions$.pipe(\n observeOn(queueScheduler)\n );\n const withLatestReducer$: Observable<[Action, ActionReducer<any, Action>]> =\n actionsOnQueue$.pipe(withLatestFrom(reducer$));\n\n const seed: StateActionPair<T> = { state: initialState };\n const stateAndAction$: Observable<{\n state: any;\n action?: Action;\n }> = withLatestReducer$.pipe(\n scan<[Action, ActionReducer<T, Action>], StateActionPair<T>>(\n reduceState,\n seed\n )\n );\n\n this.stateSubscription = stateAndAction$.subscribe(({ state, action }) => {\n this.next(state);\n scannedActions.next(action as Action);\n });\n }\n\n ngOnDestroy() {\n this.stateSubscription.unsubscribe();\n this.complete();\n }\n}\n\nexport type StateActionPair<T, V extends Action = Action> = {\n state: T | undefined;\n action?: V;\n};\nexport function reduceState<T, V extends Action = Action>(\n stateActionPair: StateActionPair<T, V> = { state: undefined },\n [action, reducer]: [V, ActionReducer<T, V>]\n): StateActionPair<T, V> {\n const { state } = stateActionPair;\n return { state: reducer(state, action), action };\n}\n\nexport const STATE_PROVIDERS: Provider[] = [\n State,\n { provide: StateObservable, useExisting: State },\n];\n","// disabled because we have lowercase generics for `select`\nimport { Injectable, Provider } from '@angular/core';\nimport { Observable, Observer, Operator } from 'rxjs';\nimport { distinctUntilChanged, map, pluck } from 'rxjs/operators';\n\nimport { ActionsSubject } from './actions_subject';\nimport { Action, ActionReducer, FunctionIsNotAllowed } from './models';\nimport { ReducerManager } from './reducer_manager';\nimport { StateObservable } from './state';\n\n@Injectable()\nexport class Store<T = object>\n extends Observable<T>\n implements Observer<Action>\n{\n constructor(\n state$: StateObservable,\n private actionsObserver: ActionsSubject,\n private reducerManager: ReducerManager\n ) {\n super();\n\n this.source = state$;\n }\n\n select<K>(mapFn: (state: T) => K): Observable<K>;\n /**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\n select<K, Props = any>(\n mapFn: (state: T, props: Props) => K,\n props: Props\n ): Observable<K>;\n select<a extends keyof T>(key: a): Observable<T[a]>;\n select<a extends keyof T, b extends keyof T[a]>(\n key1: a,\n key2: b\n ): Observable<T[a][b]>;\n select<a extends keyof T, b extends keyof T[a], c extends keyof T[a][b]>(\n key1: a,\n key2: b,\n key3: c\n ): Observable<T[a][b][c]>;\n select<\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c]\n >(key1: a, key2: b, key3: c, key4: d): Observable<T[a][b][c][d]>;\n select<\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d]\n >(key1: a, key2: b, key3: c, key4: d, key5: e): Observable<T[a][b][c][d][e]>;\n select<\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d],\n f extends keyof T[a][b][c][d][e]\n >(\n key1: a,\n key2: b,\n key3: c,\n key4: d,\n key5: e,\n key6: f\n ): Observable<T[a][b][c][d][e][f]>;\n select<\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d],\n f extends keyof T[a][b][c][d][e],\n K = any\n >(\n key1: a,\n key2: b,\n key3: c,\n key4: d,\n key5: e,\n key6: f,\n ...paths: string[]\n ): Observable<K>;\n select<Props = any, K = any>(\n pathOrMapFn: ((state: T, props?: Props) => K) | string,\n ...paths: string[]\n ): Observable<any> {\n return (select as any).call(null, pathOrMapFn, ...paths)(this);\n }\n\n override lift<R>(operator: Operator<T, R>): Store<R> {\n const store = new Store<R>(this, this.actionsObserver, this.reducerManager);\n store.operator = operator;\n\n return store;\n }\n\n dispatch<V extends Action = Action>(\n action: V &\n FunctionIsNotAllowed<\n V,\n 'Functions are not allowed to be dispatched. Did you forget to call the action creator function?'\n >\n ) {\n this.actionsObserver.next(action);\n }\n\n next(action: Action) {\n this.actionsObserver.next(action);\n }\n\n error(err: any) {\n this.actionsObserver.error(err);\n }\n\n complete() {\n this.actionsObserver.complete();\n }\n\n addReducer<State, Actions extends Action = Action>(\n key: string,\n reducer: ActionReducer<State, Actions>\n ) {\n this.reducerManager.addReducer(key, reducer);\n }\n\n removeReducer<Key extends Extract<keyof T, string>>(key: Key) {\n this.reducerManager.removeReducer(key);\n }\n}\n\nexport const STORE_PROVIDERS: Provider[] = [Store];\n\nexport function select<T, K>(\n mapFn: (state: T) => K\n): (source$: Observable<T>) => Observable<K>;\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function select<T, Props, K>(\n mapFn: (state: T, props: Props) => K,\n props: Props\n): (source$: Observable<T>) => Observable<K>;\nexport function select<T, a extends keyof T>(\n key: a\n): (source$: Observable<T>) => Observable<T[a]>;\nexport function select<T, a extends keyof T, b extends keyof T[a]>(\n key1: a,\n key2: b\n): (source$: Observable<T>) => Observable<T[a][b]>;\nexport function select<\n T,\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b]\n>(\n key1: a,\n key2: b,\n key3: c\n): (source$: Observable<T>) => Observable<T[a][b][c]>;\nexport function select<\n T,\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c]\n>(\n key1: a,\n key2: b,\n key3: c,\n key4: d\n): (source$: Observable<T>) => Observable<T[a][b][c][d]>;\nexport function select<\n T,\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d]\n>(\n key1: a,\n key2: b,\n key3: c,\n key4: d,\n key5: e\n): (source$: Observable<T>) => Observable<T[a][b][c][d][e]>;\nexport function select<\n T,\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d],\n f extends keyof T[a][b][c][d][e]\n>(\n key1: a,\n key2: b,\n key3: c,\n key4: d,\n key5: e,\n key6: f\n): (source$: Observable<T>) => Observable<T[a][b][c][d][e][f]>;\nexport function select<\n T,\n a extends keyof T,\n b extends keyof T[a],\n c extends keyof T[a][b],\n d extends keyof T[a][b][c],\n e extends keyof T[a][b][c][d],\n f extends keyof T[a][b][c][d][e],\n K = any\n>(\n key1: a,\n key2: b,\n key3: c,\n key4: d,\n key5: e,\n key6: f,\n ...paths: string[]\n): (source$: Observable<T>) => Observable<K>;\nexport function select<T, Props, K>(\n pathOrMapFn: ((state: T, props?: Props) => any) | string,\n propsOrPath?: Props | string,\n ...paths: string[]\n) {\n return function selectOperator(source$: Observable<T>): Observable<K> {\n let mapped$: Observable<any>;\n\n if (typeof pathOrMapFn === 'string') {\n const pathSlices = [<string>propsOrPath, ...paths].filter(Boolean);\n mapped$ = source$.pipe(pluck(pathOrMapFn, ...pathSlices));\n } else if (typeof pathOrMapFn === 'function') {\n mapped$ = source$.pipe(\n map((source) => pathOrMapFn(source, <Props>propsOrPath))\n );\n } else {\n throw new TypeError(\n `Unexpected type '${typeof pathOrMapFn}' in select operator,` +\n ` expected 'string' or 'function'`\n );\n }\n\n return mapped$.pipe(distinctUntilChanged());\n };\n}\n","import { map } from './map';\nimport { OperatorFunction } from '../types';\n\n/* tslint:disable:max-line-length */\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<T, K1 extends keyof T>(k1: K1): OperatorFunction<T, T[K1]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<T, K1 extends keyof T, K2 extends keyof T[K1]>(k1: K1, k2: K2): OperatorFunction<T, T[K1][K2]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(\n k1: K1,\n k2: K2,\n k3: K3\n): OperatorFunction<T, T[K1][K2][K3]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2], K4 extends keyof T[K1][K2][K3]>(\n k1: K1,\n k2: K2,\n k3: K3,\n k4: K4\n): OperatorFunction<T, T[K1][K2][K3][K4]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<\n T,\n K1 extends keyof T,\n K2 extends keyof T[K1],\n K3 extends keyof T[K1][K2],\n K4 extends keyof T[K1][K2][K3],\n K5 extends keyof T[K1][K2][K3][K4]\n>(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5): OperatorFunction<T, T[K1][K2][K3][K4][K5]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<\n T,\n K1 extends keyof T,\n K2 extends keyof T[K1],\n K3 extends keyof T[K1][K2],\n K4 extends keyof T[K1][K2][K3],\n K5 extends keyof T[K1][K2][K3][K4],\n K6 extends keyof T[K1][K2][K3][K4][K5]\n>(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6): OperatorFunction<T, T[K1][K2][K3][K4][K5][K6]>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<\n T,\n K1 extends keyof T,\n K2 extends keyof T[K1],\n K3 extends keyof T[K1][K2],\n K4 extends keyof T[K1][K2][K3],\n K5 extends keyof T[K1][K2][K3][K4],\n K6 extends keyof T[K1][K2][K3][K4][K5]\n>(k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, ...rest: string[]): OperatorFunction<T, unknown>;\n/** @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8. */\nexport function pluck<T>(...properties: string[]): OperatorFunction<T, unknown>;\n/* tslint:enable:max-line-length */\n\n/**\n * Maps each source value to its specified nested property.\n *\n * <span class=\"informal\">Like {@link map}, but meant only for picking one of\n * the nested properties of every emitted value.</span>\n *\n * ![](pluck.png)\n *\n * Given a list of strings or numbers describing a path to a property, retrieves\n * the value of a specified nested property from all values in the source\n * Observable. If a property can't be resolved, it will return `undefined` for\n * that value.\n *\n * ## Example\n *\n * Map every click to the tagName of the clicked target element\n *\n * ```ts\n * import { fromEvent, pluck } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const tagNames = clicks.pipe(pluck('target', 'tagName'));\n *\n * tagNames.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link map}\n *\n * @param properties The nested properties to pluck from each source\n * value.\n * @return A function that returns an Observable of property values from the\n * source values.\n * @deprecated Use {@link map} and optional chaining: `pluck('foo', 'bar')` is `map(x => x?.foo?.bar)`. Will be removed in v8.\n */\nexport function pluck<T, R>(...properties: Array<string | number | symbol>): OperatorFunction<T, R> {\n const length = properties.length;\n if (length === 0) {\n throw new Error('list of properties cannot be empty.');\n }\n return map((x) => {\n let currentProp: any = x;\n for (let i = 0; i < length; i++) {\n const p = currentProp?.[properties[i]];\n if (typeof p !== 'undefined') {\n currentProp = p;\n } else {\n return undefined;\n }\n }\n return currentProp;\n });\n}\n","export const RUNTIME_CHECK_URL =\n 'https://ngrx.io/guide/store/configuration/runtime-checks';\n\nexport function isUndefined(target: any): target is undefined {\n return target === undefined;\n}\n\nexport function isNull(target: any): target is null {\n return target === null;\n}\n\nexport function isArray(target: any): target is Array<any> {\n return Array.isArray(target);\n}\n\nexport function isString(target: any): target is string {\n return typeof target === 'string';\n}\n\nexport function isBoolean(target: any): target is boolean {\n return typeof target === 'boolean';\n}\n\nexport function isNumber(target: any): target is number {\n return typeof target === 'number';\n}\n\nexport function isObjectLike(target: any): target is object {\n return typeof target === 'object' && target !== null;\n}\n\nexport function isObject(target: any): target is object {\n return isObjectLike(target) && !isArray(target);\n}\n\nexport function isPlainObject(target: any): target is object {\n if (!isObject(target)) {\n return false;\n }\n\n const targetPrototype = Object.getPrototypeOf(target);\n return targetPrototype === Object.prototype || targetPrototype === null;\n}\n\nexport function isFunction(target: any): target is () => void {\n return typeof target === 'function';\n}\n\nexport function isComponent(target: any) {\n return isFunction(target) && target.hasOwnProperty('ɵcmp');\n}\n\nexport function hasOwnProperty(target: object, propertyName: string): boolean {\n return Object.prototype.hasOwnProperty.call(target, propertyName);\n}\n","let _ngrxMockEnvironment = false;\nexport function setNgrxMockEnvironment(value: boolean): void {\n _ngrxMockEnvironment = value;\n}\nexport function isNgrxMockEnvironment(): boolean {\n return _ngrxMockEnvironment;\n}\n","import { Selector, SelectorWithProps } from './models';\nimport { isDevMode } from '@angular/core';\nimport { isNgrxMockEnvironment } from './flags';\n\nexport type AnyFn = (...args: any[]) => any;\n\nexport type MemoizedProjection = {\n memoized: AnyFn;\n reset: () => void;\n setResult: (result?: any) => void;\n clearResult: () => void;\n};\n\nexport type MemoizeFn = (t: AnyFn) => MemoizedProjection;\n\nexport type ComparatorFn = (a: any, b: any) => boolean;\n\nexport type DefaultProjectorFn<T> = (...args: any[]) => T;\n\nexport interface MemoizedSelector<\n State,\n Result,\n ProjectorFn = DefaultProjectorFn<Result>\n> extends Selector<State, Result> {\n release(): void;\n projector: ProjectorFn;\n setResult: (result?: Result) => void;\n clearResult: () => void;\n}\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport interface MemoizedSelectorWithProps<\n State,\n Props,\n Result,\n ProjectorFn = DefaultProjectorFn<Result>\n> extends SelectorWithProps<State, Props, Result> {\n release(): void;\n projector: ProjectorFn;\n setResult: (result?: Result) => void;\n clearResult: () => void;\n}\n\nexport function isEqualCheck(a: any, b: any): boolean {\n return a === b;\n}\n\nfunction isArgumentsChanged(\n args: IArguments,\n lastArguments: IArguments,\n comparator: ComparatorFn\n) {\n for (let i = 0; i < args.length; i++) {\n if (!comparator(args[i], lastArguments[i])) {\n return true;\n }\n }\n return false;\n}\n\nexport function resultMemoize(\n projectionFn: AnyFn,\n isResultEqual: ComparatorFn\n) {\n return defaultMemoize(projectionFn, isEqualCheck, isResultEqual);\n}\n\nexport function defaultMemoize(\n projectionFn: AnyFn,\n isArgumentsEqual = isEqualCheck,\n isResultEqual = isEqualCheck\n): MemoizedProjection {\n let lastArguments: null | IArguments = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, , , , ,\n let lastResult: any = null;\n let overrideResult: any;\n\n function reset() {\n lastArguments = null;\n lastResult = null;\n }\n\n function setResult(result: any = undefined) {\n overrideResult = { result };\n }\n\n function clearResult() {\n overrideResult = undefined;\n }\n\n /* eslint-disable prefer-rest-params, prefer-spread */\n\n // disabled because of the use of `arguments`\n function memoized(): any {\n if (overrideResult !== undefined) {\n return overrideResult.result;\n }\n\n if (!lastArguments) {\n lastResult = projectionFn.apply(null, arguments as any);\n lastArguments = arguments;\n return lastResult;\n }\n\n if (!isArgumentsChanged(arguments, lastArguments, isArgumentsEqual)) {\n return lastResult;\n }\n\n const newResult = projectionFn.apply(null, arguments as any);\n lastArguments = arguments;\n\n if (isResultEqual(lastResult, newResult)) {\n return lastResult;\n }\n\n lastResult = newResult;\n\n return newResult;\n }\n\n return { memoized, reset, setResult, clearResult };\n}\n\nexport function createSelector<State, S1, Result>(\n s1: Selector<State, S1>,\n projector: (s1: S1) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n projector: (s1: S1, s2: S2) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n projector: (s1: S1, s2: S2, s3: S3) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, S4, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n s4: Selector<State, S4>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, S4, S5, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n s4: Selector<State, S4>,\n s5: Selector<State, S5>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, s5: S5) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, S4, S5, S6, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n s4: Selector<State, S4>,\n s5: Selector<State, S5>,\n s6: Selector<State, S6>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, s6: S6) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, S4, S5, S6, S7, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n s4: Selector<State, S4>,\n s5: Selector<State, S5>,\n s6: Selector<State, S6>,\n s7: Selector<State, S7>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, s6: S6, s7: S7) => Result\n): MemoizedSelector<State, Result, typeof projector>;\nexport function createSelector<State, S1, S2, S3, S4, S5, S6, S7, S8, Result>(\n s1: Selector<State, S1>,\n s2: Selector<State, S2>,\n s3: Selector<State, S3>,\n s4: Selector<State, S4>,\n s5: Selector<State, S5>,\n s6: Selector<State, S6>,\n s7: Selector<State, S7>,\n s8: Selector<State, S8>,\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n s7: S7,\n s8: S8\n ) => Result\n): MemoizedSelector<State, Result, typeof projector>;\n\nexport function createSelector<\n Selectors extends Record<string, Selector<State, unknown>>,\n State = Selectors extends Record<string, Selector<infer S, unknown>>\n ? S\n : never,\n Result extends Record<string, unknown> = {\n [Key in keyof Selectors]: Selectors[Key] extends Selector<State, infer R>\n ? R\n : never;\n }\n>(selectors: Selectors): MemoizedSelector<State, Result, never>;\n\nexport function createSelector<State, Slices extends unknown[], Result>(\n ...args: [...slices: Selector<State, unknown>[], projector: unknown] &\n [\n ...slices: { [i in keyof Slices]: Selector<State, Slices[i]> },\n projector: (...s: Slices) => Result\n ]\n): MemoizedSelector<State, Result, (...s: Slices) => Result>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n projector: (s1: S1, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n projector: (s1: S1, s2: S2, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n projector: (s1: S1, s2: S2, s3: S3, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n s4: SelectorWithProps<State, Props, S4>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, S5, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n s4: SelectorWithProps<State, Props, S4>,\n s5: SelectorWithProps<State, Props, S5>,\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, S5, S6, Result>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n s4: SelectorWithProps<State, Props, S4>,\n s5: SelectorWithProps<State, Props, S5>,\n s6: SelectorWithProps<State, Props, S6>,\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<\n State,\n Props,\n S1,\n S2,\n S3,\n S4,\n S5,\n S6,\n S7,\n Result\n>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n s4: SelectorWithProps<State, Props, S4>,\n s5: SelectorWithProps<State, Props, S5>,\n s6: SelectorWithProps<State, Props, S6>,\n s7: SelectorWithProps<State, Props, S7>,\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n s7: S7,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<\n State,\n Props,\n S1,\n S2,\n S3,\n S4,\n S5,\n S6,\n S7,\n S8,\n Result\n>(\n s1: SelectorWithProps<State, Props, S1>,\n s2: SelectorWithProps<State, Props, S2>,\n s3: SelectorWithProps<State, Props, S3>,\n s4: SelectorWithProps<State, Props, S4>,\n s5: SelectorWithProps<State, Props, S5>,\n s6: SelectorWithProps<State, Props, S6>,\n s7: SelectorWithProps<State, Props, S7>,\n s8: SelectorWithProps<State, Props, S8>,\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n s7: S7,\n s8: S8,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\nexport function createSelector<State, Slices extends unknown[], Result>(\n selectors: Selector<State, unknown>[] &\n [...{ [i in keyof Slices]: Selector<State, Slices[i]> }],\n projector: (...s: Slices) => Result\n): MemoizedSelector<State, Result, (...s: Slices) => Result>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, Result>(\n selectors: [SelectorWithProps<State, Props, S1>],\n projector: (s1: S1, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, Result>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>\n ],\n projector: (s1: S1, s2: S2, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, Result>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>\n ],\n projector: (s1: S1, s2: S2, s3: S3, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, Result>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>,\n SelectorWithProps<State, Props, S4>\n ],\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, S5, Result>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>,\n SelectorWithProps<State, Props, S4>,\n SelectorWithProps<State, Props, S5>\n ],\n projector: (s1: S1, s2: S2, s3: S3, s4: S4, s5: S5, props: Props) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<State, Props, S1, S2, S3, S4, S5, S6, Result>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>,\n SelectorWithProps<State, Props, S4>,\n SelectorWithProps<State, Props, S5>,\n SelectorWithProps<State, Props, S6>\n ],\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<\n State,\n Props,\n S1,\n S2,\n S3,\n S4,\n S5,\n S6,\n S7,\n Result\n>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>,\n SelectorWithProps<State, Props, S4>,\n SelectorWithProps<State, Props, S5>,\n SelectorWithProps<State, Props, S6>,\n SelectorWithProps<State, Props, S7>\n ],\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n s7: S7,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelector<\n State,\n Props,\n S1,\n S2,\n S3,\n S4,\n S5,\n S6,\n S7,\n S8,\n Result\n>(\n selectors: [\n SelectorWithProps<State, Props, S1>,\n SelectorWithProps<State, Props, S2>,\n SelectorWithProps<State, Props, S3>,\n SelectorWithProps<State, Props, S4>,\n SelectorWithProps<State, Props, S5>,\n SelectorWithProps<State, Props, S6>,\n SelectorWithProps<State, Props, S7>,\n SelectorWithProps<State, Props, S8>\n ],\n projector: (\n s1: S1,\n s2: S2,\n s3: S3,\n s4: S4,\n s5: S5,\n s6: S6,\n s7: S7,\n s8: S8,\n props: Props\n ) => Result\n): MemoizedSelectorWithProps<State, Props, Result, typeof projector>;\n\nexport function createSelector(\n ...input: any[]\n): MemoizedSelector<any, any> | MemoizedSelectorWithProps<any, any, any> {\n return createSelectorFactory(defaultMemoize)(...input);\n}\n\nexport function defaultStateFn(\n state: any,\n selectors: Selector<any, any>[] | SelectorWithProps<any, any, any>[],\n props: any,\n memoizedProjector: MemoizedProjection\n): any {\n if (props === undefined) {\n const args = (<Selector<any, any>[]>selectors).map((fn) => fn(state));\n return memoizedProjector.memoized.apply(null, args);\n }\n\n const args = (<SelectorWithProps<any, any, any>[]>selectors).map((fn) =>\n fn(state, props)\n );\n return memoizedProjector.memoized.apply(null, [...args, props]);\n}\n\nexport type SelectorFactoryConfig<T = any, V = any> = {\n stateFn: (\n state: T,\n selectors: Selector<any, any>[],\n props: any,\n memoizedProjector: MemoizedProjection\n ) => V;\n};\n\nexport function createSelectorFactory<T = any, V = any>(\n memoize: MemoizeFn\n): (...input: any[]) => MemoizedSelector<T, V>;\nexport function createSelectorFactory<T = any, V = any>(\n memoize: MemoizeFn,\n options: SelectorFactoryConfig<T, V>\n): (...input: any[]) => MemoizedSelector<T, V>;\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelectorFactory<T = any, Props = any, V = any>(\n memoize: MemoizeFn\n): (...input: any[]) => MemoizedSelectorWithProps<T, Props, V>;\n/**\n * @deprecated Selectors with props are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/2980 Github Issue}\n */\nexport function createSelectorFactory<T = any, Props = any, V = any>(\n memoize: MemoizeFn,\n options: SelectorFactoryConfig<T, V>\n): (...input: any[]) => MemoizedSelectorWithProps<T, Props, V>;\n/**\n *\n * @param memoize The function used to memoize selectors\n * @param options Config Object that may include a `stateFn` function defining how to return the selector's value, given the entire `Store`'s state, parent `Selector`s, `Props`, and a `MemoizedProjection`\n *\n * @usageNotes\n *\n * **Creating a Selector Factory Where Array Order Does Not Matter**\n *\n * ```ts\n * function removeMatch(arr: string[], target: string): string[] {\n * const matchIndex = arr.indexOf(target);\n * return [...arr.slice(0, matchIndex), ...arr.slice(matchIndex + 1)];\n * }\n *\n * function orderDoesNotMatterComparer(a: any, b: any): boolean {\n * if (!Array.isArray(a) || !Array.isArray(b)) {\n * return a === b;\n * }\n * if (a.length !== b.length) {\n * return false;\n * }\n * let tempB = [...b];\n * function reduceToDetermineIfArraysContainSameContents(\n * previousCallResult: boolean,\n * arrayMember: any\n * ): boolean {\n * if (previousCallResult === false) {\n * return false;\n * }\n * if (tempB.includes(arrayMember)) {\n * tempB = removeMatch(tempB, arrayMember);\n * return true;\n * }\n * return false;\n * }\n * return a.reduce(reduceToDetermineIfArraysContainSameContents, true);\n * }\n *\n * export const createOrderDoesNotMatterSelector = createSelectorFactory(\n * (projectionFun) => defaultMemoize(\n * projectionFun,\n * orderDoesNotMatterComparer,\n * orderDoesNotMatterComparer\n * )\n * );\n * ```\n *\n * **Creating an Alternative Memoization Strategy**\n *\n * ```ts\n * function serialize(x: any): string {\n * return JSON.stringify(x);\n * }\n *\n * export const createFullHistorySelector = createSelectorFactory(\n * (projectionFunction) => {\n * const cache = {};\n *\n * function memoized() {\n * const serializedArguments = serialize(...arguments);\n * if (cache[serializedArguments] != null) {\n * cache[serializedArguments] = projectionFunction.apply(null, arguments);\n * }\n * return cache[serializedArguments];\n * }\n * return {\n * memoized,\n * reset: () => {},\n * setResult: () => {},\n * clearResult: () => {},\n * };\n * }\n * );\n * ```\n */\nexport function createSelectorFactory(\n memoize: MemoizeFn,\n options: SelectorFactoryConfig<any, any> = {\n stateFn: defaultStateFn,\n }\n) {\n return function (\n ...input: any[]\n ): MemoizedSelector<any, any> | MemoizedSelectorWithProps<any, any, any> {\n let args = input;\n if (Array.isArray(args[0])) {\n const [head, ...tail] = args;\n args = [...head, ...tail];\n } else if (args.length === 1 && isSelectorsDictionary(args[0])) {\n args = extractArgsFromSelectorsDictionary(args[0]);\n }\n\n const selectors = args.slice(0, args.length - 1);\n const projector = args[args.length - 1];\n const memoizedSelectors = selectors.filter(\n (selector: any) =>\n selector.release && typeof selector.release === 'function'\n );\n\n const memoizedProjector = memoize(function (...selectors: any[]) {\n return projector.apply(null, selectors);\n });\n\n const memoizedState = defaultMemoize(function (state: any, props: any) {\n return options.stateFn.apply(null, [\n state,\n selectors,\n props,\n memoizedProjector,\n ]);\n });\n\n function release() {\n memoizedState.reset();\n memoizedProjector.reset();\n\n memoizedSelectors.forEach((selector) => selector.release());\n }\n\n return Object.assign(memoizedState.memoized, {\n release,\n projector: memoizedProjector.memoized,\n setResult: memoizedState.setResult,\n clearResult: memoizedState.clearResult,\n });\n };\n}\n\nexport function createFeatureSelector<T>(\n featureName: string\n): MemoizedSelector<object, T>;\n/**\n * @deprecated Feature selectors with a root state are deprecated, for more info see {@link https://github.com/ngrx/platform/issues/3179 Github Issue}\n */\nexport function createFeatureSelector<T, V>(\n featureName: keyof T\n): MemoizedSelector<T, V>;\nexport function createFeatureSelector(\n featureName: any\n): MemoizedSelector<any, any> {\n return createSelector(\n (state: any) => {\n const featureState = state[featureName];\n if (!isNgrxMockEnvironment() && isDevMode() && !(featureName in state)) {\n console.warn(\n `@ngrx/store: The feature name \"${featureName}\" does ` +\n 'not exist in the state, therefore createFeatureSelector ' +\n 'cannot access it. Be sure it is imported in a loaded module ' +\n `using StoreModule.forRoot('${featureName}', ...) or ` +\n `StoreModule.forFeature('${featureName}', ...). If the default ` +\n 'state is intended to be undefined, as is the case with router ' +\n 'state, this development-only warning message can be ignored.'\n );\n }\n return featureState;\n },\n (featureState: any) => featureState\n );\n}\n\nfunction isSelectorsDictionary(\n selectors: unknown\n): selectors is Record<string, Selector<unknown, unknown>> {\n return (\n !!selectors &&\n typeof selectors === 'object' &&\n Object.values(selectors).every((selector) => typeof selector === 'function')\n );\n}\n\nfunction extractArgsFromSelectorsDictionary(\n selectorsDictionary: Record<string, Selector<unknown, unknown>>\n): [\n ...selectors: Selector<unknown, unknown>[],\n projector: (...selectorResults: unknown[]) => unknown\n] {\n const selectors = Object.values(selectorsDictionary);\n const resultKeys = Object.keys(selectorsDictionary);\n const projector = (...selectorResults: unknown[]) =>\n resultKeys.reduce(\n (result, key, index) => ({\n ...result,\n [key]: selectorResults[index],\n }),\n {}\n );\n\n return [...selectors, projector];\n}\n","import { inject, InjectionToken } from '@angular/core';\nimport {\n Action,\n ActionReducer,\n ActionReducerMap,\n ActionReducerFactory,\n StoreFeature,\n InitialState,\n MetaReducer,\n RuntimeChecks,\n} from './models';\nimport { combineReducers } from './utils';\nimport { Store } from './store';\n\nexport interface StoreConfig<T, V extends Action = Action> {\n initialState?: InitialState<T>;\n reducerFactory?: ActionReducerFactory<T, V>;\n metaReducers?: MetaReducer<{ [P in keyof T]: T[P] }, V>[];\n}\n\nexport interface RootStoreConfig<T, V extends Action = Action>\n extends StoreConfig<T, V> {\n runtimeChecks?: Partial<RuntimeChecks>;\n}\n\n/**\n * An object with the name and the reducer for the feature.\n */\nexport interface FeatureSlice<T, V extends Action = Action> {\n name: string;\n reducer: ActionReducer<T, V>;\n}\n\nexport function _createStoreReducers<T, V extends Action = Action>(\n reducers: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>\n): ActionReducerMap<T, V> {\n return reducers instanceof InjectionToken ? inject(reducers) : reducers;\n}\n\nexport function _createFeatureStore<T, V extends Action = Action>(\n configs: StoreConfig<T, V>[] | InjectionToken<StoreConfig<T, V>>[],\n featureStores: StoreFeature<T, V>[]\n) {\n return featureStores.map((feat, index) => {\n if (configs[index] instanceof InjectionToken) {\n const conf = inject(configs[index] as InjectionToken<StoreConfig<T, V>>);\n return {\n key: feat.key,\n reducerFactory: conf.reducerFactory\n ? conf.reducerFactory\n : combineReducers,\n metaReducers: conf.metaReducers ? conf.metaReducers : [],\n initialState: conf.initialState,\n };\n }\n return feat;\n });\n}\n\nexport function _createFeatureReducers<T, V extends Action = Action>(\n reducerCollection: Array<\n ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>\n >\n): ActionReducerMap<T, V>[] {\n return reducerCollection.map((reducer) => {\n return reducer instanceof InjectionToken ? inject(reducer) : reducer;\n });\n}\n\nexport function _initialStateFactory(initialState: any): any {\n if (typeof initialState === 'function') {\n return initialState();\n }\n\n return initialState;\n}\n\nexport function _concatMetaReducers(\n metaReducers: MetaReducer[],\n userProvidedMetaReducers: MetaReducer[]\n): MetaReducer[] {\n return metaReducers.concat(userProvidedMetaReducers);\n}\n\nexport function _provideForRootGuard(): unknown {\n const store = inject(Store, { optional: true, skipSelf: true });\n if (store) {\n throw new TypeError(\n `The root Store has been provided more than once. Feature modules should provide feature states instead.`\n );\n }\n return 'guarded';\n}\n","import { ActionReducer, Action } from '../models';\nimport { isFunction, hasOwnProperty, isObjectLike } from './utils';\n\nexport function immutabilityCheckMetaReducer(\n reducer: ActionReducer<any, any>,\n checks: { action: (action: Action) => boolean; state: () => boolean }\n): ActionReducer<any, any> {\n return function (state, action) {\n const act = checks.action(action) ? freeze(action) : action;\n\n const nextState = reducer(state, act);\n\n return checks.state() ? freeze(nextState) : nextState;\n };\n}\n\nfunction freeze(target: any) {\n Object.freeze(target);\n\n const targetIsFunction = isFunction(target);\n\n Object.getOwnPropertyNames(target).forEach((prop) => {\n // Ignore Ivy properties, ref: https://github.com/ngrx/platform/issues/2109#issuecomment-582689060\n if (prop.startsWith('ɵ')) {\n return;\n }\n\n if (\n hasOwnProperty(target, prop) &&\n (targetIsFunction\n ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments'\n : true)\n ) {\n const propValue = target[prop];\n\n if (\n (isObjectLike(propValue) || isFunction(propValue)) &&\n !Object.isFrozen(propValue)\n ) {\n freeze(propValue);\n }\n }\n });\n\n return target;\n}\n","import { ActionReducer, Action } from '../models';\nimport {\n isPlainObject,\n isUndefined,\n isNull,\n isNumber,\n isBoolean,\n isString,\n isArray,\n RUNTIME_CHECK_URL,\n isComponent,\n} from './utils';\n\nexport function serializationCheckMetaReducer(\n reducer: ActionReducer<any, any>,\n checks: { action: (action: Action) => boolean; state: () => boolean }\n): ActionReducer<any, any> {\n return function (state, action) {\n if (checks.action(action)) {\n const unserializableAction = getUnserializable(action);\n throwIfUnserializable(unserializableAction, 'action');\n }\n\n const nextState = reducer(state, action);\n\n if (checks.state()) {\n const unserializableState = getUnserializable(nextState);\n throwIfUnserializable(unserializableState, 'state');\n }\n\n return nextState;\n };\n}\n\nfunction getUnserializable(\n target?: any,\n path: string[] = []\n): false | { path: string[]; value: any } {\n // Guard against undefined and null, e.g. a reducer that returns undefined\n if ((isUndefined(target) || isNull(target)) && path.length === 0) {\n return {\n path: ['root'],\n value: target,\n };\n }\n\n const keys = Object.keys(target);\n return keys.reduce<false | { path: string[]; value: any }>((result, key) => {\n if (result) {\n return result;\n }\n\n const value = (target as any)[key];\n\n // Ignore Ivy components\n if (isComponent(value)) {\n return result;\n }\n\n if (\n isUndefined(value) ||\n isNull(value) ||\n isNumber(value) ||\n isBoolean(value) ||\n isString(value) ||\n isArray(value)\n ) {\n return false;\n }\n\n if (isPlainObject(value)) {\n return getUnserializable(value, [...path, key]);\n }\n\n return {\n path: [...path, key],\n value,\n };\n }, false);\n}\n\nfunction throwIfUnserializable(\n unserializable: false | { path: string[]; value: any },\n context: 'state' | 'action'\n) {\n if (unserializable === false) {\n return;\n }\n\n const unserializablePath = unserializable.path.join('.');\n const error: any = new Error(\n `Detected unserializable ${context} at \"${unserializablePath}\". ${RUNTIME_CHECK_URL}#strict${context}serializability`\n );\n error.value = unserializable.value;\n error.unserializablePath = unserializablePath;\n throw error;\n}\n","import { isDevMode, Provider } from '@angular/core';\nimport {\n serializationCheckMetaReducer,\n immutabilityCheckMetaReducer,\n inNgZoneAssertMetaReducer,\n} from './meta-reducers';\nimport { RuntimeChecks, MetaReducer, Action } from './models';\nimport {\n _USER_RUNTIME_CHECKS,\n ACTIVE_RUNTIME_CHECKS,\n META_REDUCERS,\n USER_RUNTIME_CHECKS,\n _ACTION_TYPE_UNIQUENESS_CHECK,\n} from './tokens';\nimport { REGISTERED_ACTION_TYPES } from './globals';\nimport { RUNTIME_CHECK_URL } from './meta-reducers/utils';\n\nexport function createActiveRuntimeChecks(\n runtimeChecks?: Partial<RuntimeChecks>\n): RuntimeChecks {\n if (isDevMode()) {\n return {\n strictStateSerializability: false,\n strictActionSerializability: false,\n strictStateImmutability: true,\n strictActionImmutability: true,\n strictActionWithinNgZone: false,\n strictActionTypeUniqueness: false,\n ...runtimeChecks,\n };\n }\n\n return {\n strictStateSerializability: false,\n strictActionSerializability: false,\n strictStateImmutability: false,\n strictActionImmutability: false,\n strictActionWithinNgZone: false,\n strictActionTypeUniqueness: false,\n };\n}\n\nexport function createSerializationCheckMetaReducer({\n strictActionSerializability,\n strictStateSerializability,\n}: RuntimeChecks): MetaReducer {\n return (reducer) =>\n strictActionSerializability || strictStateSerializability\n ? serializationCheckMetaReducer(reducer, {\n action: (action) =>\n strictActionSerializability && !ignoreNgrxAction(action),\n state: () => strictStateSerializability,\n })\n : reducer;\n}\n\nexport function createImmutabilityCheckMetaReducer({\n strictActionImmutability,\n strictStateImmutability,\n}: RuntimeChecks): MetaReducer {\n return (reducer) =>\n strictActionImmutability || strictStateImmutability\n ? immutabilityCheckMetaReducer(reducer, {\n action: (action) =>\n strictActionImmutability && !ignoreNgrxAction(action),\n state: () => strictStateImmutability,\n })\n : reducer;\n}\n\nfunction ignoreNgrxAction(action: Action) {\n return action.type.startsWith('@ngrx');\n}\n\nexport function createInNgZoneCheckMetaReducer({\n strictActionWithinNgZone,\n}: RuntimeChecks): MetaReducer {\n return (reducer) =>\n strictActionWithinNgZone\n ? inNgZoneAssertMetaReducer(reducer, {\n action: (action) =>\n strictActionWithinNgZone && !ignoreNgrxAction(action),\n })\n : reducer;\n}\n\nexport function provideRuntimeChecks(\n runtimeChecks?: Partial<RuntimeChecks>\n): Provider[] {\n return [\n {\n provide: _USER_RUNTIME_CHECKS,\n useValue: runtimeChecks,\n },\n {\n provide: USER_RUNTIME_CHECKS,\n useFactory: _runtimeChecksFactory,\n deps: [_USER_RUNTIME_CHECKS],\n },\n {\n provide: ACTIVE_RUNTIME_CHECKS,\n deps: [USER_RUNTIME_CHECKS],\n useFactory: createActiveRuntimeChecks,\n },\n {\n provide: META_REDUCERS,\n multi: true,\n deps: [ACTIVE_RUNTIME_CHECKS],\n useFactory: createImmutabilityCheckMetaReducer,\n },\n {\n provide: META_REDUCERS,\n multi: true,\n deps: [ACTIVE_RUNTIME_CHECKS],\n useFactory: createSerializationCheckMetaReducer,\n },\n {\n provide: META_REDUCERS,\n multi: true,\n deps: [ACTIVE_RUNTIME_CHECKS],\n useFactory: createInNgZoneCheckMetaReducer,\n },\n ];\n}\n\nexport function checkForActionTypeUniqueness(): Provider[] {\n return [\n {\n provide: _ACTION_TYPE_UNIQUENESS_CHECK,\n multi: true,\n deps: [ACTIVE_RUNTIME_CHECKS],\n useFactory: _actionTypeUniquenessCheck,\n },\n ];\n}\n\nexport function _runtimeChecksFactory(\n runtimeChecks: RuntimeChecks\n): RuntimeChecks {\n return runtimeChecks;\n}\n\nexport function _actionTypeUniquenessCheck(config: RuntimeChecks): void {\n if (!config.strictActionTypeUniqueness) {\n return;\n }\n\n const duplicates = Object.entries(REGISTERED_ACTION_TYPES)\n .filter(([, registrations]) => registrations > 1)\n .map(([type]) => type);\n\n if (duplicates.length) {\n throw new Error(\n `Action types are registered more than once, ${duplicates\n .map((type) => `\"${type}\"`)\n .join(', ')}. ${RUNTIME_CHECK_URL}#strictactiontypeuniqueness`\n );\n }\n}\n","import * as ngCore from '@angular/core';\nimport { Action, ActionReducer } from '../models';\nimport { RUNTIME_CHECK_URL } from './utils';\n\nexport function inNgZoneAssertMetaReducer(\n reducer: ActionReducer<any, Action>,\n checks: { action: (action: Action) => boolean }\n) {\n return function (state: any, action: Action) {\n if (checks.action(action) && !ngCore.NgZone.isInAngularZone()) {\n throw new Error(\n `Action '${action.type}' running outside NgZone. ${RUNTIME_CHECK_URL}#strictactionwithinngzone`\n );\n }\n return reducer(state, action);\n };\n}\n","import {\n ENVIRONMENT_INITIALIZER,\n EnvironmentProviders,\n Inject,\n inject,\n InjectionToken,\n makeEnvironmentProviders,\n Provider,\n} from '@angular/core';\nimport {\n Action,\n ActionReducer,\n ActionReducerMap,\n StoreFeature,\n} from './models';\nimport { combineReducers, createReducerFactory } from './utils';\nimport {\n _ACTION_TYPE_UNIQUENESS_CHECK,\n _FEATURE_CONFIGS,\n _FEATURE_REDUCERS,\n _FEATURE_REDUCERS_TOKEN,\n _INITIAL_REDUCERS,\n _INITIAL_STATE,\n _REDUCER_FACTORY,\n _RESOLVED_META_REDUCERS,\n _ROOT_STORE_GUARD,\n _STORE_FEATURES,\n _STORE_REDUCERS,\n FEATURE_REDUCERS,\n FEATURE_STATE_PROVIDER,\n INITIAL_REDUCERS,\n INITIAL_STATE,\n META_REDUCERS,\n REDUCER_FACTORY,\n ROOT_STORE_PROVIDER,\n STORE_FEATURES,\n USER_PROVIDED_META_REDUCERS,\n} from './tokens';\nimport { ACTIONS_SUBJECT_PROVIDERS, ActionsSubject } from './actions_subject';\nimport {\n REDUCER_MANAGER_PROVIDERS,\n ReducerManager,\n ReducerObservable,\n} from './reducer_manager';\nimport {\n SCANNED_ACTIONS_SUBJECT_PROVIDERS,\n ScannedActionsSubject,\n} from './scanned_actions_subject';\nimport { STATE_PROVIDERS } from './state';\nimport { Store, STORE_PROVIDERS } from './store';\nimport {\n checkForActionTypeUniqueness,\n provideRuntimeChecks,\n} from './runtime_checks';\nimport {\n _concatMetaReducers,\n _createFeatureReducers,\n _createFeatureStore,\n _createStoreReducers,\n _initialStateFactory,\n _provideForRootGuard,\n FeatureSlice,\n RootStoreConfig,\n StoreConfig,\n} from './store_config';\n\nexport function provideState<T, V extends Action = Action>(\n featureName: string,\n reducers: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,\n config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>\n): EnvironmentProviders;\nexport function provideState<T, V extends Action = Action>(\n featureName: string,\n reducer: ActionReducer<T, V> | InjectionToken<ActionReducer<T, V>>,\n config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>\n): EnvironmentProviders;\nexport function provideState<T, V extends Action = Action>(\n slice: FeatureSlice<T, V>\n): EnvironmentProviders;\n/**\n * Provides additional slices of state in the Store.\n * These providers cannot be used at the component level.\n *\n * @usageNotes\n *\n * ### Providing Store Features\n *\n * ```ts\n * const booksRoutes: Route[] = [\n * {\n * path: '',\n * providers: [provideState('books', booksReducer)],\n * children: [\n * { path: '', component: BookListComponent },\n * { path: ':id', component: BookDetailsComponent },\n * ],\n * },\n * ];\n * ```\n */\nexport function provideState<T, V extends Action = Action>(\n featureNameOrSlice: string | FeatureSlice<T, V>,\n reducers?:\n | ActionReducerMap<T, V>\n | InjectionToken<ActionReducerMap<T, V>>\n | ActionReducer<T, V>\n | InjectionToken<ActionReducer<T, V>>,\n config: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>> = {}\n): EnvironmentProviders {\n return makeEnvironmentProviders([\n ..._provideState(featureNameOrSlice, reducers, config),\n ENVIRONMENT_STATE_PROVIDER,\n ]);\n}\n\nexport function _provideStore<T, V extends Action = Action>(\n reducers:\n | ActionReducerMap<T, V>\n | InjectionToken<ActionReducerMap<T, V>>\n | Record<string, never> = {},\n config: RootStoreConfig<T, V> = {}\n): Provider[] {\n return [\n {\n provide: _ROOT_STORE_GUARD,\n useFactory: _provideForRootGuard,\n },\n { provide: _INITIAL_STATE, useValue: config.initialState },\n {\n provide: INITIAL_STATE,\n useFactory: _initialStateFactory,\n deps: [_INITIAL_STATE],\n },\n { provide: _INITIAL_REDUCERS, useValue: reducers },\n {\n provide: _STORE_REDUCERS,\n useExisting:\n reducers instanceof InjectionToken ? reducers : _INITIAL_REDUCERS,\n },\n {\n provide: INITIAL_REDUCERS,\n deps: [_INITIAL_REDUCERS, [new Inject(_STORE_REDUCERS)]],\n useFactory: _createStoreReducers,\n },\n {\n provide: USER_PROVIDED_META_REDUCERS,\n useValue: config.metaReducers ? config.metaReducers : [],\n },\n {\n provide: _RESOLVED_META_REDUCERS,\n deps: [META_REDUCERS, USER_PROVIDED_META_REDUCERS],\n useFactory: _concatMetaReducers,\n },\n {\n provide: _REDUCER_FACTORY,\n useValue: config.reducerFactory ? config.reducerFactory : combineReducers,\n },\n {\n provide: REDUCER_FACTORY,\n deps: [_REDUCER_FACTORY, _RESOLVED_META_REDUCERS],\n useFactory: createReducerFactory,\n },\n ACTIONS_SUBJECT_PROVIDERS,\n REDUCER_MANAGER_PROVIDERS,\n SCANNED_ACTIONS_SUBJECT_PROVIDERS,\n STATE_PROVIDERS,\n STORE_PROVIDERS,\n provideRuntimeChecks(config.runtimeChecks),\n checkForActionTypeUniqueness(),\n ];\n}\n\nfunction rootStoreProviderFactory(): void {\n inject(ActionsSubject);\n inject(ReducerObservable);\n inject(ScannedActionsSubject);\n inject(Store);\n inject(_ROOT_STORE_GUARD, { optional: true });\n inject(_ACTION_TYPE_UNIQUENESS_CHECK, { optional: true });\n}\n\n/**\n * Environment Initializer used in the root\n * providers to initialize the Store\n */\nconst ENVIRONMENT_STORE_PROVIDER: Provider[] = [\n { provide: ROOT_STORE_PROVIDER, useFactory: rootStoreProviderFactory },\n {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useFactory() {\n return () => inject(ROOT_STORE_PROVIDER);\n },\n },\n];\n\n/**\n * Provides the global Store providers and initializes\n * the Store.\n * These providers cannot be used at the component level.\n *\n * @usageNotes\n *\n * ### Providing the Global Store\n *\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideStore()],\n * });\n * ```\n */\nexport function provideStore<T, V extends Action = Action>(\n reducers?: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,\n config?: RootStoreConfig<T, V>\n): EnvironmentProviders {\n return makeEnvironmentProviders([\n ..._provideStore(reducers, config),\n ENVIRONMENT_STORE_PROVIDER,\n ]);\n}\n\nfunction featureStateProviderFactory(): void {\n inject(ROOT_STORE_PROVIDER);\n const features = inject<StoreFeature<any, any>[]>(_STORE_FEATURES);\n const featureReducers = inject<ActionReducerMap<any>[]>(FEATURE_REDUCERS);\n const reducerManager = inject(ReducerManager);\n inject(_ACTION_TYPE_UNIQUENESS_CHECK, { optional: true });\n\n const feats = features.map((feature, index) => {\n const featureReducerCollection = featureReducers.shift();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const reducers = featureReducerCollection! /*TODO(#823)*/[index];\n\n return {\n ...feature,\n reducers,\n initialState: _initialStateFactory(feature.initialState),\n };\n });\n\n reducerManager.addFeatures(feats);\n}\n\n/**\n * Environment Initializer used in the feature\n * providers to register state features\n */\nconst ENVIRONMENT_STATE_PROVIDER: Provider[] = [\n {\n provide: FEATURE_STATE_PROVIDER,\n useFactory: featureStateProviderFactory,\n },\n {\n provide: ENVIRONMENT_INITIALIZER,\n multi: true,\n useFactory() {\n return () => inject(FEATURE_STATE_PROVIDER);\n },\n },\n];\n\nexport function _provideState<T, V extends Action = Action>(\n featureNameOrSlice: string | FeatureSlice<T, V>,\n reducers?:\n | ActionReducerMap<T, V>\n | InjectionToken<ActionReducerMap<T, V>>\n | ActionReducer<T, V>\n | InjectionToken<ActionReducer<T, V>>,\n config: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>> = {}\n): Provider[] {\n return [\n {\n provide: _FEATURE_CONFIGS,\n multi: true,\n useValue: featureNameOrSlice instanceof Object ? {} : config,\n },\n {\n provide: STORE_FEATURES,\n multi: true,\n useValue: {\n key:\n featureNameOrSlice instanceof Object\n ? featureNameOrSlice.name\n : featureNameOrSlice,\n reducerFactory:\n !(config instanceof InjectionToken) && config.reducerFactory\n ? config.reducerFactory\n : combineReducers,\n metaReducers:\n !(config instanceof InjectionToken) && config.metaReducers\n ? config.metaReducers\n : [],\n initialState:\n !(config instanceof InjectionToken) && config.initialState\n ? config.initialState\n : undefined,\n },\n },\n {\n provide: _STORE_FEATURES,\n deps: [_FEATURE_CONFIGS, STORE_FEATURES],\n useFactory: _createFeatureStore,\n },\n {\n provide: _FEATURE_REDUCERS,\n multi: true,\n useValue:\n featureNameOrSlice instanceof Object\n ? featureNameOrSlice.reducer\n : reducers,\n },\n {\n provide: _FEATURE_REDUCERS_TOKEN,\n multi: true,\n useExisting:\n reducers instanceof InjectionToken ? reducers : _FEATURE_REDUCERS,\n },\n {\n provide: FEATURE_REDUCERS,\n multi: true,\n deps: [_FEATURE_REDUCERS, [new Inject(_FEATURE_REDUCERS_TOKEN)]],\n useFactory: _createFeatureReducers,\n },\n checkForActionTypeUniqueness(),\n ];\n}\n","import {\n Inject,\n InjectionToken,\n ModuleWithProviders,\n NgModule,\n OnDestroy,\n Optional,\n} from '@angular/core';\nimport {\n Action,\n ActionReducer,\n ActionReducerMap,\n StoreFeature,\n} from './models';\nimport {\n _ACTION_TYPE_UNIQUENESS_CHECK,\n _ROOT_STORE_GUARD,\n _STORE_FEATURES,\n FEATURE_REDUCERS,\n} from './tokens';\nimport { ActionsSubject } from './actions_subject';\nimport { ReducerManager, ReducerObservable } from './reducer_manager';\nimport { ScannedActionsSubject } from './scanned_actions_subject';\nimport { Store } from './store';\nimport {\n _initialStateFactory,\n FeatureSlice,\n RootStoreConfig,\n StoreConfig,\n} from './store_config';\nimport { _provideState, _provideStore } from './provide_store';\n\n@NgModule({})\nexport class StoreRootModule {\n constructor(\n actions$: ActionsSubject,\n reducer$: ReducerObservable,\n scannedActions$: ScannedActionsSubject,\n store: Store<any>,\n @Optional()\n @Inject(_ROOT_STORE_GUARD)\n guard: any,\n @Optional()\n @Inject(_ACTION_TYPE_UNIQUENESS_CHECK)\n actionCheck: any\n ) {}\n}\n\n@NgModule({})\nexport class StoreFeatureModule implements OnDestroy {\n constructor(\n @Inject(_STORE_FEATURES) private features: StoreFeature<any, any>[],\n @Inject(FEATURE_REDUCERS) private featureReducers: ActionReducerMap<any>[],\n private reducerManager: ReducerManager,\n root: StoreRootModule,\n @Optional()\n @Inject(_ACTION_TYPE_UNIQUENESS_CHECK)\n actionCheck: any\n ) {\n const feats = features.map((feature, index) => {\n const featureReducerCollection = featureReducers.shift();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const reducers = featureReducerCollection! /*TODO(#823)*/[index];\n\n return {\n ...feature,\n reducers,\n initialState: _initialStateFactory(feature.initialState),\n };\n });\n\n reducerManager.addFeatures(feats);\n }\n\n // eslint-disable-next-line @angular-eslint/contextual-lifecycle\n ngOnDestroy() {\n this.reducerManager.removeFeatures(this.features);\n }\n}\n\n@NgModule({})\nexport class StoreModule {\n static forRoot<T, V extends Action = Action>(\n reducers?: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,\n config?: RootStoreConfig<T, V>\n ): ModuleWithProviders<StoreRootModule> {\n return {\n ngModule: StoreRootModule,\n providers: [..._provideStore(reducers, config)],\n };\n }\n\n static forFeature<T, V extends Action = Action>(\n featureName: string,\n reducers: ActionReducerMap<T, V> | InjectionToken<ActionReducerMap<T, V>>,\n config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>\n ): ModuleWithProviders<StoreFeatureModule>;\n static forFeature<T, V extends Action = Action>(\n featureName: string,\n reducer: ActionReducer<T, V> | InjectionToken<ActionReducer<T, V>>,\n config?: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>>\n ): ModuleWithProviders<StoreFeatureModule>;\n static forFeature<T, V extends Action = Action>(\n slice: FeatureSlice<T, V>\n ): ModuleWithProviders<StoreFeatureModule>;\n static forFeature<T, V extends Action = Action>(\n featureNameOrSlice: string | FeatureSlice<T, V>,\n reducers?:\n | ActionReducerMap<T, V>\n | InjectionToken<ActionReducerMap<T, V>>\n | ActionReducer<T, V>\n | InjectionToken<ActionReducer<T, V>>,\n config: StoreConfig<T, V> | InjectionToken<StoreConfig<T, V>> = {}\n ): ModuleWithProviders<StoreFeatureModule> {\n return {\n ngModule: StoreFeatureModule,\n providers: [..._provideState(featureNameOrSlice, reducers, config)],\n };\n }\n}\n","import { ActionCreator, ActionReducer, ActionType, Action } from './models';\n\n// Goes over the array of ActionCreators, pulls the action type out of each one\n// and returns the array of these action types.\ntype ExtractActionTypes<Creators extends readonly ActionCreator[]> = {\n [Key in keyof Creators]: Creators[Key] extends ActionCreator<infer T>\n ? T\n : never;\n};\n\n/**\n * Return type of the `on` fn.\n * Contains the action reducer coupled to one or more action types.\n */\nexport interface ReducerTypes<\n State,\n Creators extends readonly ActionCreator[]\n> {\n reducer: OnReducer<State, Creators>;\n types: ExtractActionTypes<Creators>;\n}\n\n/**\n * Specialized Reducer that is aware of the Action type it needs to handle\n */\nexport interface OnReducer<\n // State type that is being passed from consumer of `on` fn, e.g. from `createReducer` factory\n State,\n Creators extends readonly ActionCreator[],\n // Inferred type from within OnReducer function if `State` is unknown\n InferredState = State,\n // Resulting state would be either a State or if State is unknown then the inferred state from the function itself\n ResultState = unknown extends State ? InferredState : State\n> {\n (\n // if State is unknown then set the InferredState type\n state: unknown extends State ? InferredState : State,\n action: ActionType<Creators[number]>\n ): ResultState;\n}\n\n/**\n * @description\n * Associates actions with a given state change function.\n * A state change function must be provided as the last parameter.\n *\n * @param args `ActionCreator`'s followed by a state change function.\n *\n * @returns an association of action types with a state change function.\n *\n * @usageNotes\n * ```ts\n * on(AuthApiActions.loginSuccess, (state, { user }) => ({ ...state, user }))\n * ```\n */\nexport function on<\n // State type that is being passed from `createReducer` when created within that factory function\n State,\n // Action creators\n Creators extends readonly ActionCreator[],\n // Inferred type from within OnReducer function if `State` is unknown. This is typically the case when `on` function\n // is created outside of `createReducer` and state type is either explicitly set OR inferred by return type.\n // For example: `const onFn = on(action, (state: State, {prop}) => ({ ...state, name: prop }));`\n InferredState = State\n>(\n ...args: [\n ...creators: Creators,\n reducer: OnReducer<\n State extends infer S ? S : never,\n Creators,\n InferredState\n >\n ]\n): ReducerTypes<unknown extends State ? InferredState : State, Creators> {\n const reducer = args.pop() as unknown as OnReducer<\n unknown extends State ? InferredState : State,\n Creators\n >;\n const types = (args as unknown as Creators).map(\n (creator) => creator.type\n ) as unknown as ExtractActionTypes<Creators>;\n return { reducer, types };\n}\n\n/**\n * @description\n * Creates a reducer function to handle state transitions.\n *\n * Reducer creators reduce the explicitness of reducer functions with switch statements.\n *\n * @param initialState Provides a state value if the current state is `undefined`, as it is initially.\n * @param ons Associations between actions and state changes.\n * @returns A reducer function.\n *\n * @usageNotes\n *\n * - Must be used with `ActionCreator`'s (returned by `createAction`). Cannot be used with class-based action creators.\n * - The returned `ActionReducer` does not require being wrapped with another function.\n *\n * **Declaring a reducer creator**\n *\n * ```ts\n * export const reducer = createReducer(\n * initialState,\n * on(\n * featureActions.actionOne,\n * featureActions.actionTwo,\n * (state, { updatedValue }) => ({ ...state, prop: updatedValue })\n * ),\n * on(featureActions.actionThree, () => initialState);\n * );\n * ```\n */\nexport function createReducer<\n S,\n A extends Action = Action,\n // Additional generic for the return type is introduced to enable correct\n // type inference when `createReducer` is used within `createFeature`.\n // For more info see: https://github.com/microsoft/TypeScript/issues/52114\n R extends ActionReducer<S, A> = ActionReducer<S, A>\n>(initialState: S, ...ons: ReducerTypes<S, readonly ActionCreator[]>[]): R {\n const map = new Map<string, OnReducer<S, ActionCreator[]>>();\n for (const on of ons) {\n for (const type of on.types) {\n const existingReducer = map.get(type);\n if (existingReducer) {\n const newReducer: typeof existingReducer = (state, action) =>\n on.reducer(existingReducer(state, action), action);\n map.set(type, newReducer);\n } else {\n map.set(type, on.reducer);\n }\n }\n }\n\n return function (state: S = initialState, action: A): S {\n const reducer = map.get(action.type);\n return reducer ? reducer(state, action) : state;\n } as R;\n}\n","/** prettier */\nimport { Observable } from '../Observable';\nimport { isFunction } from './isFunction';\n\n/**\n * Tests to see if the object is an RxJS {@link Observable}\n * @param obj the object to test\n */\nexport function isObservable(obj: any): obj is Observable<unknown> {\n // The !! is to ensure that this publicly exposed function returns\n // `false` if something like `null` or `0` is passed.\n return !!obj && (obj instanceof Observable || (isFunction(obj.lift) && isFunction(obj.subscribe)));\n}\n","import * as i0 from '@angular/core';\nimport { Injectable, EventEmitter, InjectionToken, Inject, Directive, Input, Pipe, NgModule } from '@angular/core';\nimport { of, isObservable, forkJoin, concat, defer } from 'rxjs';\nimport { take, shareReplay, map, concatMap, switchMap } from 'rxjs/operators';\n\nclass TranslateLoader {\r\n}\r\n/**\r\n * This loader is just a placeholder that does nothing, in case you don't need a loader at all\r\n */\r\nclass TranslateFakeLoader extends TranslateLoader {\r\n getTranslation(lang) {\r\n return of({});\r\n }\r\n}\r\nTranslateFakeLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeLoader, deps: null, target: i0.ɵɵFactoryTarget.Injectable });\r\nTranslateFakeLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeLoader });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeLoader, decorators: [{\r\n type: Injectable\r\n }] });\n\nclass MissingTranslationHandler {\r\n}\r\n/**\r\n * This handler is just a placeholder that does nothing, in case you don't need a missing translation handler at all\r\n */\r\nclass FakeMissingTranslationHandler {\r\n handle(params) {\r\n return params.key;\r\n }\r\n}\r\nFakeMissingTranslationHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: FakeMissingTranslationHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });\r\nFakeMissingTranslationHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: FakeMissingTranslationHandler });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: FakeMissingTranslationHandler, decorators: [{\r\n type: Injectable\r\n }] });\n\n/* tslint:disable */\r\n/**\r\n * Determines if two objects or two values are equivalent.\r\n *\r\n * Two objects or values are considered equivalent if at least one of the following is true:\r\n *\r\n * * Both objects or values pass `===` comparison.\r\n * * Both objects or values are of the same type and all of their properties are equal by\r\n * comparing them with `equals`.\r\n *\r\n * @param o1 Object or value to compare.\r\n * @param o2 Object or value to compare.\r\n * @returns true if arguments are equal.\r\n */\r\nfunction equals(o1, o2) {\r\n if (o1 === o2)\r\n return true;\r\n if (o1 === null || o2 === null)\r\n return false;\r\n if (o1 !== o1 && o2 !== o2)\r\n return true; // NaN === NaN\r\n let t1 = typeof o1, t2 = typeof o2, length, key, keySet;\r\n if (t1 == t2 && t1 == 'object') {\r\n if (Array.isArray(o1)) {\r\n if (!Array.isArray(o2))\r\n return false;\r\n if ((length = o1.length) == o2.length) {\r\n for (key = 0; key < length; key++) {\r\n if (!equals(o1[key], o2[key]))\r\n return false;\r\n }\r\n return true;\r\n }\r\n }\r\n else {\r\n if (Array.isArray(o2)) {\r\n return false;\r\n }\r\n keySet = Object.create(null);\r\n for (key in o1) {\r\n if (!equals(o1[key], o2[key])) {\r\n return false;\r\n }\r\n keySet[key] = true;\r\n }\r\n for (key in o2) {\r\n if (!(key in keySet) && typeof o2[key] !== 'undefined') {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n/* tslint:enable */\r\nfunction isDefined(value) {\r\n return typeof value !== 'undefined' && value !== null;\r\n}\r\nfunction isObject(item) {\r\n return (item && typeof item === 'object' && !Array.isArray(item));\r\n}\r\nfunction mergeDeep(target, source) {\r\n let output = Object.assign({}, target);\r\n if (isObject(target) && isObject(source)) {\r\n Object.keys(source).forEach((key) => {\r\n if (isObject(source[key])) {\r\n if (!(key in target)) {\r\n Object.assign(output, { [key]: source[key] });\r\n }\r\n else {\r\n output[key] = mergeDeep(target[key], source[key]);\r\n }\r\n }\r\n else {\r\n Object.assign(output, { [key]: source[key] });\r\n }\r\n });\r\n }\r\n return output;\r\n}\n\nclass TranslateParser {\r\n}\r\nclass TranslateDefaultParser extends TranslateParser {\r\n constructor() {\r\n super(...arguments);\r\n this.templateMatcher = /{{\\s?([^{}\\s]*)\\s?}}/g;\r\n }\r\n interpolate(expr, params) {\r\n let result;\r\n if (typeof expr === 'string') {\r\n result = this.interpolateString(expr, params);\r\n }\r\n else if (typeof expr === 'function') {\r\n result = this.interpolateFunction(expr, params);\r\n }\r\n else {\r\n // this should not happen, but an unrelated TranslateService test depends on it\r\n result = expr;\r\n }\r\n return result;\r\n }\r\n getValue(target, key) {\r\n let keys = typeof key === 'string' ? key.split('.') : [key];\r\n key = '';\r\n do {\r\n key += keys.shift();\r\n if (isDefined(target) && isDefined(target[key]) && (typeof target[key] === 'object' || !keys.length)) {\r\n target = target[key];\r\n key = '';\r\n }\r\n else if (!keys.length) {\r\n target = undefined;\r\n }\r\n else {\r\n key += '.';\r\n }\r\n } while (keys.length);\r\n return target;\r\n }\r\n interpolateFunction(fn, params) {\r\n return fn(params);\r\n }\r\n interpolateString(expr, params) {\r\n if (!params) {\r\n return expr;\r\n }\r\n return expr.replace(this.templateMatcher, (substring, b) => {\r\n let r = this.getValue(params, b);\r\n return isDefined(r) ? r : substring;\r\n });\r\n }\r\n}\r\nTranslateDefaultParser.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateDefaultParser, deps: null, target: i0.ɵɵFactoryTarget.Injectable });\r\nTranslateDefaultParser.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateDefaultParser });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateDefaultParser, decorators: [{\r\n type: Injectable\r\n }] });\n\nclass TranslateCompiler {\r\n}\r\n/**\r\n * This compiler is just a placeholder that does nothing, in case you don't need a compiler at all\r\n */\r\nclass TranslateFakeCompiler extends TranslateCompiler {\r\n compile(value, lang) {\r\n return value;\r\n }\r\n compileTranslations(translations, lang) {\r\n return translations;\r\n }\r\n}\r\nTranslateFakeCompiler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeCompiler, deps: null, target: i0.ɵɵFactoryTarget.Injectable });\r\nTranslateFakeCompiler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeCompiler });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateFakeCompiler, decorators: [{\r\n type: Injectable\r\n }] });\n\nclass TranslateStore {\r\n constructor() {\r\n /**\r\n * The lang currently used\r\n */\r\n this.currentLang = this.defaultLang;\r\n /**\r\n * a list of translations per lang\r\n */\r\n this.translations = {};\r\n /**\r\n * an array of langs\r\n */\r\n this.langs = [];\r\n /**\r\n * An EventEmitter to listen to translation change events\r\n * onTranslationChange.subscribe((params: TranslationChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n this.onTranslationChange = new EventEmitter();\r\n /**\r\n * An EventEmitter to listen to lang change events\r\n * onLangChange.subscribe((params: LangChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n this.onLangChange = new EventEmitter();\r\n /**\r\n * An EventEmitter to listen to default lang change events\r\n * onDefaultLangChange.subscribe((params: DefaultLangChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n this.onDefaultLangChange = new EventEmitter();\r\n }\r\n}\n\nconst USE_STORE = new InjectionToken('USE_STORE');\r\nconst USE_DEFAULT_LANG = new InjectionToken('USE_DEFAULT_LANG');\r\nconst DEFAULT_LANGUAGE = new InjectionToken('DEFAULT_LANGUAGE');\r\nconst USE_EXTEND = new InjectionToken('USE_EXTEND');\r\nclass TranslateService {\r\n /**\r\n *\r\n * @param store an instance of the store (that is supposed to be unique)\r\n * @param currentLoader An instance of the loader currently used\r\n * @param compiler An instance of the compiler currently used\r\n * @param parser An instance of the parser currently used\r\n * @param missingTranslationHandler A handler for missing translations.\r\n * @param useDefaultLang whether we should use default language translation when current language translation is missing.\r\n * @param isolate whether this service should use the store or not\r\n * @param extend To make a child module extend (and use) translations from parent modules.\r\n * @param defaultLanguage Set the default language using configuration\r\n */\r\n constructor(store, currentLoader, compiler, parser, missingTranslationHandler, useDefaultLang = true, isolate = false, extend = false, defaultLanguage) {\r\n this.store = store;\r\n this.currentLoader = currentLoader;\r\n this.compiler = compiler;\r\n this.parser = parser;\r\n this.missingTranslationHandler = missingTranslationHandler;\r\n this.useDefaultLang = useDefaultLang;\r\n this.isolate = isolate;\r\n this.extend = extend;\r\n this.pending = false;\r\n this._onTranslationChange = new EventEmitter();\r\n this._onLangChange = new EventEmitter();\r\n this._onDefaultLangChange = new EventEmitter();\r\n this._langs = [];\r\n this._translations = {};\r\n this._translationRequests = {};\r\n /** set the default language from configuration */\r\n if (defaultLanguage) {\r\n this.setDefaultLang(defaultLanguage);\r\n }\r\n }\r\n /**\r\n * An EventEmitter to listen to translation change events\r\n * onTranslationChange.subscribe((params: TranslationChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n get onTranslationChange() {\r\n return this.isolate ? this._onTranslationChange : this.store.onTranslationChange;\r\n }\r\n /**\r\n * An EventEmitter to listen to lang change events\r\n * onLangChange.subscribe((params: LangChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n get onLangChange() {\r\n return this.isolate ? this._onLangChange : this.store.onLangChange;\r\n }\r\n /**\r\n * An EventEmitter to listen to default lang change events\r\n * onDefaultLangChange.subscribe((params: DefaultLangChangeEvent) => {\r\n * // do something\r\n * });\r\n */\r\n get onDefaultLangChange() {\r\n return this.isolate ? this._onDefaultLangChange : this.store.onDefaultLangChange;\r\n }\r\n /**\r\n * The default lang to fallback when translations are missing on the current lang\r\n */\r\n get defaultLang() {\r\n return this.isolate ? this._defaultLang : this.store.defaultLang;\r\n }\r\n set defaultLang(defaultLang) {\r\n if (this.isolate) {\r\n this._defaultLang = defaultLang;\r\n }\r\n else {\r\n this.store.defaultLang = defaultLang;\r\n }\r\n }\r\n /**\r\n * The lang currently used\r\n */\r\n get currentLang() {\r\n return this.isolate ? this._currentLang : this.store.currentLang;\r\n }\r\n set currentLang(currentLang) {\r\n if (this.isolate) {\r\n this._currentLang = currentLang;\r\n }\r\n else {\r\n this.store.currentLang = currentLang;\r\n }\r\n }\r\n /**\r\n * an array of langs\r\n */\r\n get langs() {\r\n return this.isolate ? this._langs : this.store.langs;\r\n }\r\n set langs(langs) {\r\n if (this.isolate) {\r\n this._langs = langs;\r\n }\r\n else {\r\n this.store.langs = langs;\r\n }\r\n }\r\n /**\r\n * a list of translations per lang\r\n */\r\n get translations() {\r\n return this.isolate ? this._translations : this.store.translations;\r\n }\r\n set translations(translations) {\r\n if (this.isolate) {\r\n this._translations = translations;\r\n }\r\n else {\r\n this.store.translations = translations;\r\n }\r\n }\r\n /**\r\n * Sets the default language to use as a fallback\r\n */\r\n setDefaultLang(lang) {\r\n if (lang === this.defaultLang) {\r\n return;\r\n }\r\n let pending = this.retrieveTranslations(lang);\r\n if (typeof pending !== \"undefined\") {\r\n // on init set the defaultLang immediately\r\n if (this.defaultLang == null) {\r\n this.defaultLang = lang;\r\n }\r\n pending.pipe(take(1))\r\n .subscribe((res) => {\r\n this.changeDefaultLang(lang);\r\n });\r\n }\r\n else { // we already have this language\r\n this.changeDefaultLang(lang);\r\n }\r\n }\r\n /**\r\n * Gets the default language used\r\n */\r\n getDefaultLang() {\r\n return this.defaultLang;\r\n }\r\n /**\r\n * Changes the lang currently used\r\n */\r\n use(lang) {\r\n // don't change the language if the language given is already selected\r\n if (lang === this.currentLang) {\r\n return of(this.translations[lang]);\r\n }\r\n let pending = this.retrieveTranslations(lang);\r\n if (typeof pending !== \"undefined\") {\r\n // on init set the currentLang immediately\r\n if (!this.currentLang) {\r\n this.currentLang = lang;\r\n }\r\n pending.pipe(take(1))\r\n .subscribe((res) => {\r\n this.changeLang(lang);\r\n });\r\n return pending;\r\n }\r\n else { // we have this language, return an Observable\r\n this.changeLang(lang);\r\n return of(this.translations[lang]);\r\n }\r\n }\r\n /**\r\n * Retrieves the given translations\r\n */\r\n retrieveTranslations(lang) {\r\n let pending;\r\n // if this language is unavailable or extend is true, ask for it\r\n if (typeof this.translations[lang] === \"undefined\" || this.extend) {\r\n this._translationRequests[lang] = this._translationRequests[lang] || this.getTranslation(lang);\r\n pending = this._translationRequests[lang];\r\n }\r\n return pending;\r\n }\r\n /**\r\n * Gets an object of translations for a given language with the current loader\r\n * and passes it through the compiler\r\n */\r\n getTranslation(lang) {\r\n this.pending = true;\r\n const loadingTranslations = this.currentLoader.getTranslation(lang).pipe(shareReplay(1), take(1));\r\n this.loadingTranslations = loadingTranslations.pipe(map((res) => this.compiler.compileTranslations(res, lang)), shareReplay(1), take(1));\r\n this.loadingTranslations\r\n .subscribe({\r\n next: (res) => {\r\n this.translations[lang] = this.extend && this.translations[lang] ? { ...res, ...this.translations[lang] } : res;\r\n this.updateLangs();\r\n this.pending = false;\r\n },\r\n error: (err) => {\r\n this.pending = false;\r\n }\r\n });\r\n return loadingTranslations;\r\n }\r\n /**\r\n * Manually sets an object of translations for a given language\r\n * after passing it through the compiler\r\n */\r\n setTranslation(lang, translations, shouldMerge = false) {\r\n translations = this.compiler.compileTranslations(translations, lang);\r\n if ((shouldMerge || this.extend) && this.translations[lang]) {\r\n this.translations[lang] = mergeDeep(this.translations[lang], translations);\r\n }\r\n else {\r\n this.translations[lang] = translations;\r\n }\r\n this.updateLangs();\r\n this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });\r\n }\r\n /**\r\n * Returns an array of currently available langs\r\n */\r\n getLangs() {\r\n return this.langs;\r\n }\r\n /**\r\n * Add available langs\r\n */\r\n addLangs(langs) {\r\n langs.forEach((lang) => {\r\n if (this.langs.indexOf(lang) === -1) {\r\n this.langs.push(lang);\r\n }\r\n });\r\n }\r\n /**\r\n * Update the list of available langs\r\n */\r\n updateLangs() {\r\n this.addLangs(Object.keys(this.translations));\r\n }\r\n /**\r\n * Returns the parsed result of the translations\r\n */\r\n getParsedResult(translations, key, interpolateParams) {\r\n let res;\r\n if (key instanceof Array) {\r\n let result = {}, observables = false;\r\n for (let k of key) {\r\n result[k] = this.getParsedResult(translations, k, interpolateParams);\r\n if (isObservable(result[k])) {\r\n observables = true;\r\n }\r\n }\r\n if (observables) {\r\n const sources = key.map(k => isObservable(result[k]) ? result[k] : of(result[k]));\r\n return forkJoin(sources).pipe(map((arr) => {\r\n let obj = {};\r\n arr.forEach((value, index) => {\r\n obj[key[index]] = value;\r\n });\r\n return obj;\r\n }));\r\n }\r\n return result;\r\n }\r\n if (translations) {\r\n res = this.parser.interpolate(this.parser.getValue(translations, key), interpolateParams);\r\n }\r\n if (typeof res === \"undefined\" && this.defaultLang != null && this.defaultLang !== this.currentLang && this.useDefaultLang) {\r\n res = this.parser.interpolate(this.parser.getValue(this.translations[this.defaultLang], key), interpolateParams);\r\n }\r\n if (typeof res === \"undefined\") {\r\n let params = { key, translateService: this };\r\n if (typeof interpolateParams !== 'undefined') {\r\n params.interpolateParams = interpolateParams;\r\n }\r\n res = this.missingTranslationHandler.handle(params);\r\n }\r\n return typeof res !== \"undefined\" ? res : key;\r\n }\r\n /**\r\n * Gets the translated value of a key (or an array of keys)\r\n * @returns the translated key, or an object of translated keys\r\n */\r\n get(key, interpolateParams) {\r\n if (!isDefined(key) || !key.length) {\r\n throw new Error(`Parameter \"key\" required`);\r\n }\r\n // check if we are loading a new translation to use\r\n if (this.pending) {\r\n return this.loadingTranslations.pipe(concatMap((res) => {\r\n res = this.getParsedResult(res, key, interpolateParams);\r\n return isObservable(res) ? res : of(res);\r\n }));\r\n }\r\n else {\r\n let res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);\r\n return isObservable(res) ? res : of(res);\r\n }\r\n }\r\n /**\r\n * Returns a stream of translated values of a key (or an array of keys) which updates\r\n * whenever the translation changes.\r\n * @returns A stream of the translated key, or an object of translated keys\r\n */\r\n getStreamOnTranslationChange(key, interpolateParams) {\r\n if (!isDefined(key) || !key.length) {\r\n throw new Error(`Parameter \"key\" required`);\r\n }\r\n return concat(defer(() => this.get(key, interpolateParams)), this.onTranslationChange.pipe(switchMap((event) => {\r\n const res = this.getParsedResult(event.translations, key, interpolateParams);\r\n if (typeof res.subscribe === 'function') {\r\n return res;\r\n }\r\n else {\r\n return of(res);\r\n }\r\n })));\r\n }\r\n /**\r\n * Returns a stream of translated values of a key (or an array of keys) which updates\r\n * whenever the language changes.\r\n * @returns A stream of the translated key, or an object of translated keys\r\n */\r\n stream(key, interpolateParams) {\r\n if (!isDefined(key) || !key.length) {\r\n throw new Error(`Parameter \"key\" required`);\r\n }\r\n return concat(defer(() => this.get(key, interpolateParams)), this.onLangChange.pipe(switchMap((event) => {\r\n const res = this.getParsedResult(event.translations, key, interpolateParams);\r\n return isObservable(res) ? res : of(res);\r\n })));\r\n }\r\n /**\r\n * Returns a translation instantly from the internal state of loaded translation.\r\n * All rules regarding the current language, the preferred language of even fallback languages will be used except any promise handling.\r\n */\r\n instant(key, interpolateParams) {\r\n if (!isDefined(key) || !key.length) {\r\n throw new Error(`Parameter \"key\" required`);\r\n }\r\n let res = this.getParsedResult(this.translations[this.currentLang], key, interpolateParams);\r\n if (isObservable(res)) {\r\n if (key instanceof Array) {\r\n let obj = {};\r\n key.forEach((value, index) => {\r\n obj[key[index]] = key[index];\r\n });\r\n return obj;\r\n }\r\n return key;\r\n }\r\n else {\r\n return res;\r\n }\r\n }\r\n /**\r\n * Sets the translated value of a key, after compiling it\r\n */\r\n set(key, value, lang = this.currentLang) {\r\n this.translations[lang][key] = this.compiler.compile(value, lang);\r\n this.updateLangs();\r\n this.onTranslationChange.emit({ lang: lang, translations: this.translations[lang] });\r\n }\r\n /**\r\n * Changes the current lang\r\n */\r\n changeLang(lang) {\r\n this.currentLang = lang;\r\n this.onLangChange.emit({ lang: lang, translations: this.translations[lang] });\r\n // if there is no default lang, use the one that we just set\r\n if (this.defaultLang == null) {\r\n this.changeDefaultLang(lang);\r\n }\r\n }\r\n /**\r\n * Changes the default lang\r\n */\r\n changeDefaultLang(lang) {\r\n this.defaultLang = lang;\r\n this.onDefaultLangChange.emit({ lang: lang, translations: this.translations[lang] });\r\n }\r\n /**\r\n * Allows to reload the lang file from the file\r\n */\r\n reloadLang(lang) {\r\n this.resetLang(lang);\r\n return this.getTranslation(lang);\r\n }\r\n /**\r\n * Deletes inner translation\r\n */\r\n resetLang(lang) {\r\n this._translationRequests[lang] = undefined;\r\n this.translations[lang] = undefined;\r\n }\r\n /**\r\n * Returns the language code name from the browser, e.g. \"de\"\r\n */\r\n getBrowserLang() {\r\n if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {\r\n return undefined;\r\n }\r\n let browserLang = window.navigator.languages ? window.navigator.languages[0] : null;\r\n browserLang = browserLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;\r\n if (typeof browserLang === 'undefined') {\r\n return undefined;\r\n }\r\n if (browserLang.indexOf('-') !== -1) {\r\n browserLang = browserLang.split('-')[0];\r\n }\r\n if (browserLang.indexOf('_') !== -1) {\r\n browserLang = browserLang.split('_')[0];\r\n }\r\n return browserLang;\r\n }\r\n /**\r\n * Returns the culture language code name from the browser, e.g. \"de-DE\"\r\n */\r\n getBrowserCultureLang() {\r\n if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {\r\n return undefined;\r\n }\r\n let browserCultureLang = window.navigator.languages ? window.navigator.languages[0] : null;\r\n browserCultureLang = browserCultureLang || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage;\r\n return browserCultureLang;\r\n }\r\n}\r\nTranslateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateService, deps: [{ token: TranslateStore }, { token: TranslateLoader }, { token: TranslateCompiler }, { token: TranslateParser }, { token: MissingTranslationHandler }, { token: USE_DEFAULT_LANG }, { token: USE_STORE }, { token: USE_EXTEND }, { token: DEFAULT_LANGUAGE }], target: i0.ɵɵFactoryTarget.Injectable });\r\nTranslateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateService });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateService, decorators: [{\r\n type: Injectable\r\n }], ctorParameters: function () { return [{ type: TranslateStore }, { type: TranslateLoader }, { type: TranslateCompiler }, { type: TranslateParser }, { type: MissingTranslationHandler }, { type: undefined, decorators: [{\r\n type: Inject,\r\n args: [USE_DEFAULT_LANG]\r\n }] }, { type: undefined, decorators: [{\r\n type: Inject,\r\n args: [USE_STORE]\r\n }] }, { type: undefined, decorators: [{\r\n type: Inject,\r\n args: [USE_EXTEND]\r\n }] }, { type: undefined, decorators: [{\r\n type: Inject,\r\n args: [DEFAULT_LANGUAGE]\r\n }] }]; } });\n\nclass TranslateDirective {\r\n constructor(translateService, element, _ref) {\r\n this.translateService = translateService;\r\n this.element = element;\r\n this._ref = _ref;\r\n // subscribe to onTranslationChange event, in case the translations of the current lang change\r\n if (!this.onTranslationChangeSub) {\r\n this.onTranslationChangeSub = this.translateService.onTranslationChange.subscribe((event) => {\r\n if (event.lang === this.translateService.currentLang) {\r\n this.checkNodes(true, event.translations);\r\n }\r\n });\r\n }\r\n // subscribe to onLangChange event, in case the language changes\r\n if (!this.onLangChangeSub) {\r\n this.onLangChangeSub = this.translateService.onLangChange.subscribe((event) => {\r\n this.checkNodes(true, event.translations);\r\n });\r\n }\r\n // subscribe to onDefaultLangChange event, in case the default language changes\r\n if (!this.onDefaultLangChangeSub) {\r\n this.onDefaultLangChangeSub = this.translateService.onDefaultLangChange.subscribe((event) => {\r\n this.checkNodes(true);\r\n });\r\n }\r\n }\r\n set translate(key) {\r\n if (key) {\r\n this.key = key;\r\n this.checkNodes();\r\n }\r\n }\r\n set translateParams(params) {\r\n if (!equals(this.currentParams, params)) {\r\n this.currentParams = params;\r\n this.checkNodes(true);\r\n }\r\n }\r\n ngAfterViewChecked() {\r\n this.checkNodes();\r\n }\r\n checkNodes(forceUpdate = false, translations) {\r\n let nodes = this.element.nativeElement.childNodes;\r\n // if the element is empty\r\n if (!nodes.length) {\r\n // we add the key as content\r\n this.setContent(this.element.nativeElement, this.key);\r\n nodes = this.element.nativeElement.childNodes;\r\n }\r\n for (let i = 0; i < nodes.length; ++i) {\r\n let node = nodes[i];\r\n if (node.nodeType === 3) { // node type 3 is a text node\r\n let key;\r\n if (forceUpdate) {\r\n node.lastKey = null;\r\n }\r\n if (isDefined(node.lookupKey)) {\r\n key = node.lookupKey;\r\n }\r\n else if (this.key) {\r\n key = this.key;\r\n }\r\n else {\r\n let content = this.getContent(node);\r\n let trimmedContent = content.trim();\r\n if (trimmedContent.length) {\r\n node.lookupKey = trimmedContent;\r\n // we want to use the content as a key, not the translation value\r\n if (content !== node.currentValue) {\r\n key = trimmedContent;\r\n // the content was changed from the user, we'll use it as a reference if needed\r\n node.originalContent = content || node.originalContent;\r\n }\r\n else if (node.originalContent) { // the content seems ok, but the lang has changed\r\n // the current content is the translation, not the key, use the last real content as key\r\n key = node.originalContent.trim();\r\n }\r\n else if (content !== node.currentValue) {\r\n // we want to use the content as a key, not the translation value\r\n key = trimmedContent;\r\n // the content was changed from the user, we'll use it as a reference if needed\r\n node.originalContent = content || node.originalContent;\r\n }\r\n }\r\n }\r\n this.updateValue(key, node, translations);\r\n }\r\n }\r\n }\r\n updateValue(key, node, translations) {\r\n if (key) {\r\n if (node.lastKey === key && this.lastParams === this.currentParams) {\r\n return;\r\n }\r\n this.lastParams = this.currentParams;\r\n let onTranslation = (res) => {\r\n if (res !== key) {\r\n node.lastKey = key;\r\n }\r\n if (!node.originalContent) {\r\n node.originalContent = this.getContent(node);\r\n }\r\n node.currentValue = isDefined(res) ? res : (node.originalContent || key);\r\n // we replace in the original content to preserve spaces that we might have trimmed\r\n this.setContent(node, this.key ? node.currentValue : node.originalContent.replace(key, node.currentValue));\r\n this._ref.markForCheck();\r\n };\r\n if (isDefined(translations)) {\r\n let res = this.translateService.getParsedResult(translations, key, this.currentParams);\r\n if (isObservable(res)) {\r\n res.subscribe({ next: onTranslation });\r\n }\r\n else {\r\n onTranslation(res);\r\n }\r\n }\r\n else {\r\n this.translateService.get(key, this.currentParams).subscribe(onTranslation);\r\n }\r\n }\r\n }\r\n getContent(node) {\r\n return isDefined(node.textContent) ? node.textContent : node.data;\r\n }\r\n setContent(node, content) {\r\n if (isDefined(node.textContent)) {\r\n node.textContent = content;\r\n }\r\n else {\r\n node.data = content;\r\n }\r\n }\r\n ngOnDestroy() {\r\n if (this.onLangChangeSub) {\r\n this.onLangChangeSub.unsubscribe();\r\n }\r\n if (this.onDefaultLangChangeSub) {\r\n this.onDefaultLangChangeSub.unsubscribe();\r\n }\r\n if (this.onTranslationChangeSub) {\r\n this.onTranslationChangeSub.unsubscribe();\r\n }\r\n }\r\n}\r\nTranslateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateDirective, deps: [{ token: TranslateService }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });\r\nTranslateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: \"12.0.0\", version: \"13.0.0\", type: TranslateDirective, selector: \"[translate],[ngx-translate]\", inputs: { translate: \"translate\", translateParams: \"translateParams\" }, ngImport: i0 });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateDirective, decorators: [{\r\n type: Directive,\r\n args: [{\r\n selector: '[translate],[ngx-translate]'\r\n }]\r\n }], ctorParameters: function () { return [{ type: TranslateService }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { translate: [{\r\n type: Input\r\n }], translateParams: [{\r\n type: Input\r\n }] } });\n\nclass TranslatePipe {\r\n constructor(translate, _ref) {\r\n this.translate = translate;\r\n this._ref = _ref;\r\n this.value = '';\r\n this.lastKey = null;\r\n this.lastParams = [];\r\n }\r\n updateValue(key, interpolateParams, translations) {\r\n let onTranslation = (res) => {\r\n this.value = res !== undefined ? res : key;\r\n this.lastKey = key;\r\n this._ref.markForCheck();\r\n };\r\n if (translations) {\r\n let res = this.translate.getParsedResult(translations, key, interpolateParams);\r\n if (isObservable(res.subscribe)) {\r\n res.subscribe(onTranslation);\r\n }\r\n else {\r\n onTranslation(res);\r\n }\r\n }\r\n this.translate.get(key, interpolateParams).subscribe(onTranslation);\r\n }\r\n transform(query, ...args) {\r\n if (!query || !query.length) {\r\n return query;\r\n }\r\n // if we ask another time for the same key, return the last value\r\n if (equals(query, this.lastKey) && equals(args, this.lastParams)) {\r\n return this.value;\r\n }\r\n let interpolateParams = undefined;\r\n if (isDefined(args[0]) && args.length) {\r\n if (typeof args[0] === 'string' && args[0].length) {\r\n // we accept objects written in the template such as {n:1}, {'n':1}, {n:'v'}\r\n // which is why we might need to change it to real JSON objects such as {\"n\":1} or {\"n\":\"v\"}\r\n let validArgs = args[0]\r\n .replace(/(\\')?([a-zA-Z0-9_]+)(\\')?(\\s)?:/g, '\"$2\":')\r\n .replace(/:(\\s)?(\\')(.*?)(\\')/g, ':\"$3\"');\r\n try {\r\n interpolateParams = JSON.parse(validArgs);\r\n }\r\n catch (e) {\r\n throw new SyntaxError(`Wrong parameter in TranslatePipe. Expected a valid Object, received: ${args[0]}`);\r\n }\r\n }\r\n else if (typeof args[0] === 'object' && !Array.isArray(args[0])) {\r\n interpolateParams = args[0];\r\n }\r\n }\r\n // store the query, in case it changes\r\n this.lastKey = query;\r\n // store the params, in case they change\r\n this.lastParams = args;\r\n // set the value\r\n this.updateValue(query, interpolateParams);\r\n // if there is a subscription to onLangChange, clean it\r\n this._dispose();\r\n // subscribe to onTranslationChange event, in case the translations change\r\n if (!this.onTranslationChange) {\r\n this.onTranslationChange = this.translate.onTranslationChange.subscribe((event) => {\r\n if (this.lastKey && event.lang === this.translate.currentLang) {\r\n this.lastKey = null;\r\n this.updateValue(query, interpolateParams, event.translations);\r\n }\r\n });\r\n }\r\n // subscribe to onLangChange event, in case the language changes\r\n if (!this.onLangChange) {\r\n this.onLangChange = this.translate.onLangChange.subscribe((event) => {\r\n if (this.lastKey) {\r\n this.lastKey = null; // we want to make sure it doesn't return the same value until it's been updated\r\n this.updateValue(query, interpolateParams, event.translations);\r\n }\r\n });\r\n }\r\n // subscribe to onDefaultLangChange event, in case the default language changes\r\n if (!this.onDefaultLangChange) {\r\n this.onDefaultLangChange = this.translate.onDefaultLangChange.subscribe(() => {\r\n if (this.lastKey) {\r\n this.lastKey = null; // we want to make sure it doesn't return the same value until it's been updated\r\n this.updateValue(query, interpolateParams);\r\n }\r\n });\r\n }\r\n return this.value;\r\n }\r\n /**\r\n * Clean any existing subscription to change events\r\n */\r\n _dispose() {\r\n if (typeof this.onTranslationChange !== 'undefined') {\r\n this.onTranslationChange.unsubscribe();\r\n this.onTranslationChange = undefined;\r\n }\r\n if (typeof this.onLangChange !== 'undefined') {\r\n this.onLangChange.unsubscribe();\r\n this.onLangChange = undefined;\r\n }\r\n if (typeof this.onDefaultLangChange !== 'undefined') {\r\n this.onDefaultLangChange.unsubscribe();\r\n this.onDefaultLangChange = undefined;\r\n }\r\n }\r\n ngOnDestroy() {\r\n this._dispose();\r\n }\r\n}\r\nTranslatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslatePipe, deps: [{ token: TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Pipe });\r\nTranslatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslatePipe, name: \"translate\", pure: false });\r\nTranslatePipe.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslatePipe });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslatePipe, decorators: [{\r\n type: Injectable\r\n }, {\r\n type: Pipe,\r\n args: [{\r\n name: 'translate',\r\n pure: false // required to update the value when the promise is resolved\r\n }]\r\n }], ctorParameters: function () { return [{ type: TranslateService }, { type: i0.ChangeDetectorRef }]; } });\n\nclass TranslateModule {\r\n /**\r\n * Use this method in your root module to provide the TranslateService\r\n */\r\n static forRoot(config = {}) {\r\n return {\r\n ngModule: TranslateModule,\r\n providers: [\r\n config.loader || { provide: TranslateLoader, useClass: TranslateFakeLoader },\r\n config.compiler || { provide: TranslateCompiler, useClass: TranslateFakeCompiler },\r\n config.parser || { provide: TranslateParser, useClass: TranslateDefaultParser },\r\n config.missingTranslationHandler || { provide: MissingTranslationHandler, useClass: FakeMissingTranslationHandler },\r\n TranslateStore,\r\n { provide: USE_STORE, useValue: config.isolate },\r\n { provide: USE_DEFAULT_LANG, useValue: config.useDefaultLang },\r\n { provide: USE_EXTEND, useValue: config.extend },\r\n { provide: DEFAULT_LANGUAGE, useValue: config.defaultLanguage },\r\n TranslateService\r\n ]\r\n };\r\n }\r\n /**\r\n * Use this method in your other (non root) modules to import the directive/pipe\r\n */\r\n static forChild(config = {}) {\r\n return {\r\n ngModule: TranslateModule,\r\n providers: [\r\n config.loader || { provide: TranslateLoader, useClass: TranslateFakeLoader },\r\n config.compiler || { provide: TranslateCompiler, useClass: TranslateFakeCompiler },\r\n config.parser || { provide: TranslateParser, useClass: TranslateDefaultParser },\r\n config.missingTranslationHandler || { provide: MissingTranslationHandler, useClass: FakeMissingTranslationHandler },\r\n { provide: USE_STORE, useValue: config.isolate },\r\n { provide: USE_DEFAULT_LANG, useValue: config.useDefaultLang },\r\n { provide: USE_EXTEND, useValue: config.extend },\r\n { provide: DEFAULT_LANGUAGE, useValue: config.defaultLanguage },\r\n TranslateService\r\n ]\r\n };\r\n }\r\n}\r\nTranslateModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });\r\nTranslateModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateModule, declarations: [TranslatePipe,\r\n TranslateDirective], exports: [TranslatePipe,\r\n TranslateDirective] });\r\nTranslateModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateModule });\r\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"13.0.0\", ngImport: i0, type: TranslateModule, decorators: [{\r\n type: NgModule,\r\n args: [{\r\n declarations: [\r\n TranslatePipe,\r\n TranslateDirective\r\n ],\r\n exports: [\r\n TranslatePipe,\r\n TranslateDirective\r\n ]\r\n }]\r\n }] });\n\n/**\r\n * Generated bundle index. Do not edit.\r\n */\n\nexport { DEFAULT_LANGUAGE, FakeMissingTranslationHandler, MissingTranslationHandler, TranslateCompiler, TranslateDefaultParser, TranslateDirective, TranslateFakeCompiler, TranslateFakeLoader, TranslateLoader, TranslateModule, TranslateParser, TranslatePipe, TranslateService, TranslateStore, USE_DEFAULT_LANG, USE_EXTEND, USE_STORE };\n","import { EventEmitter } from '@angular/core';\nimport { Observable, ObservableInput } from 'rxjs';\nimport { getNavigator } from './util/util';\n\nexport type StateChange = {\n reason: 'setup' | 'observer-emit' | 'start-loading' | 'mount-image' | 'loading-failed' | 'loading-succeeded' | 'finally';\n data?: unknown;\n};\n\nexport type Attributes<T = any> = {\n /**\n * A reference to the element\n */\n element: HTMLImageElement | HTMLDivElement;\n /**\n * A URI path to the image to be lazyloaded\n */\n imagePath: string;\n /**\n * A URI path to the default image\n */\n defaultImagePath?: string;\n /**\n * A URI path to the error image\n */\n errorImagePath?: string;\n /**\n * If true, use a `srcset` for the image\n */\n useSrcset?: boolean;\n /**\n * Number of pixels to use as offset in all directions\n */\n offset: number;\n /**\n * A reference to the scroll container, if not window\n */\n scrollContainer?: HTMLElement;\n /**\n * A custom customObservable.\n */\n customObservable?: Observable<T>;\n /**\n * If true, try to decode the image before put it to the DOM\n */\n decode?: boolean;\n /**\n * If true, try to decode the image before put it to the DOM\n */\n onStateChange: EventEmitter<StateChange>;\n /**\n * A uniq id for the image\n */\n id: string;\n};\n\nexport abstract class Hooks<E = unknown> {\n navigator?: Navigator = getNavigator();\n protected platformId!: Object;\n\n setPlatformId(platformId: Object) {\n this.platformId = platformId;\n }\n\n abstract getObservable(attributes: Attributes): Observable<E>;\n abstract isVisible(event: E, attributes: Attributes): boolean;\n abstract loadImage(attributes: Attributes): ObservableInput<string>;\n abstract setLoadedImage(imagePath: string, attributes: Attributes): void;\n abstract setErrorImage(error: Error, attributes: Attributes): void;\n abstract setup(attributes: Attributes): void;\n abstract finally(attributes: Attributes): void;\n abstract isBot(attributes?: Attributes): boolean;\n abstract isDisabled(): boolean;\n abstract skipLazyLoading(attributes: Attributes): boolean;\n onDestroy(attributes: Attributes): void {}\n onAttributeChange(newAttributes: Attributes): void {}\n}\n","export const cssClassNames = {\n loaded: 'ng-lazyloaded',\n loading: 'ng-lazyloading',\n failed: 'ng-failed-lazyloaded',\n};\n\nexport function removeCssClassName(element: HTMLImageElement | HTMLDivElement, cssClassName: string) {\n element.className = element.className.replace(cssClassName, '');\n}\n\nexport function addCssClassName(element: HTMLImageElement | HTMLDivElement, cssClassName: string) {\n if (!element.className.includes(cssClassName)) {\n element.className += ` ${cssClassName}`;\n }\n}\n\nexport function hasCssClassName(element: HTMLImageElement | HTMLDivElement, cssClassName: string) {\n return element.className && element.className.includes(cssClassName);\n}\n","import { isPlatformServer } from '@angular/common';\nimport { ObservableInput } from 'rxjs';\nimport { Attributes, Hooks } from '../types';\nimport { addCssClassName, cssClassNames, hasCssClassName, removeCssClassName } from '../util/css.util';\nimport { isChildOfPicture, isImageElement, setImage, setImageAndSourcesToDefault, setImageAndSourcesToError, setImageAndSourcesToLazy, setSourcesToLazy } from '../util/util';\n\nexport abstract class SharedHooks<E> extends Hooks<E> {\n setup(attributes: Attributes): void {\n setImageAndSourcesToDefault(attributes.element, attributes.defaultImagePath, attributes.useSrcset);\n if (attributes.imagePath) {\n addCssClassName(attributes.element, cssClassNames.loading);\n }\n\n if (hasCssClassName(attributes.element, cssClassNames.loaded)) {\n removeCssClassName(attributes.element, cssClassNames.loaded);\n }\n }\n\n finally(attributes: Attributes): void {\n addCssClassName(attributes.element, cssClassNames.loaded);\n removeCssClassName(attributes.element, cssClassNames.loading);\n }\n\n loadImage(attributes: Attributes): ObservableInput<string> {\n if (this.skipLazyLoading(attributes)) {\n // Set the image right away for bots for better SEO\n return [attributes.imagePath];\n }\n const { element, useSrcset, imagePath, decode } = attributes;\n let img: HTMLImageElement;\n if (isImageElement(element) && isChildOfPicture(element)) {\n const parentClone = element.parentNode!.cloneNode(true) as HTMLPictureElement;\n img = parentClone.getElementsByTagName('img')[0];\n setSourcesToLazy(img);\n setImage(img, imagePath, useSrcset);\n } else {\n img = new Image();\n if (isImageElement(element) && element.referrerPolicy) {\n img.referrerPolicy = element.referrerPolicy;\n }\n if (isImageElement(element) && element.sizes) {\n img.sizes = element.sizes;\n }\n if (useSrcset && 'srcset' in img) {\n img.srcset = imagePath;\n } else {\n img.src = imagePath;\n }\n }\n\n if (decode && img.decode) {\n return img.decode().then(() => imagePath);\n }\n\n return new Promise<string>((resolve, reject) => {\n img.onload = () => resolve(imagePath);\n img.onerror = () => reject(null);\n });\n }\n\n setErrorImage(error: Error, attributes: Attributes): void {\n const { element, useSrcset, errorImagePath } = attributes;\n setImageAndSourcesToError(element, errorImagePath, useSrcset);\n addCssClassName(element, cssClassNames.failed);\n }\n\n setLoadedImage(imagePath: string, attributes: Attributes): void {\n const { element, useSrcset } = attributes;\n setImageAndSourcesToLazy(element, imagePath, useSrcset);\n }\n\n isDisabled(): boolean {\n // Disable if SSR and the user isn't a bot\n return isPlatformServer(this.platformId) && !this.isBot();\n }\n\n skipLazyLoading(attributes: Attributes): boolean {\n return this.isBot(attributes);\n }\n\n isBot(attributes?: Attributes): boolean {\n if (this.navigator?.userAgent) {\n return /googlebot|bingbot|yandex|baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\\ link\\ preview|showyoubot|outbrain|pinterest\\/0\\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp|duckduckbot|prerender/i.test(\n this.navigator.userAgent\n );\n }\n return false;\n }\n}\n","import { Observable, of, Subject } from 'rxjs';\nimport { filter } from 'rxjs/operators';\nimport { SharedHooks } from '../shared-hooks/hooks';\nimport { Attributes } from '../types';\n\nexport class IntersectionObserverHooks extends SharedHooks<{ isIntersecting: boolean }> {\n private readonly observers = new WeakMap<Element | {}, IntersectionObserver>();\n private readonly intersectionSubject = new Subject<IntersectionObserverEntry>();\n private readonly uniqKey = {};\n\n getObservable(attributes: Attributes<{ isIntersecting: boolean }>): Observable<{ isIntersecting: boolean }> {\n if (this.skipLazyLoading(attributes)) {\n return of({ isIntersecting: true });\n }\n if (attributes.customObservable) {\n return attributes.customObservable;\n }\n const scrollContainerKey = attributes.scrollContainer || this.uniqKey;\n const options: ObserverOptions = {\n root: attributes.scrollContainer || null,\n };\n if (attributes.offset) {\n options.rootMargin = `${attributes.offset}px`;\n }\n\n let observer = this.observers.get(scrollContainerKey);\n\n if (!observer) {\n observer = new IntersectionObserver((entrys) => this.loadingCallback(entrys), options);\n this.observers.set(scrollContainerKey, observer);\n }\n\n observer.observe(attributes.element);\n\n return Observable.create((obs: Subject<IntersectionObserverEntry>) => {\n const subscription = this.intersectionSubject.pipe(filter((entry) => entry.target === attributes.element)).subscribe(obs);\n return () => {\n subscription.unsubscribe();\n observer!.unobserve(attributes.element);\n };\n });\n }\n\n isVisible(event: { isIntersecting: boolean }): boolean {\n return event.isIntersecting;\n }\n\n private loadingCallback(entrys: IntersectionObserverEntry[]) {\n entrys.forEach((entry) => this.intersectionSubject.next(entry));\n }\n}\n\ninterface ObserverOptions {\n root: Element | null;\n rootMargin?: string;\n}\n","import { InjectionToken } from '@angular/core';\nimport { Hooks } from './types';\n\nexport const LAZYLOAD_IMAGE_HOOKS = new InjectionToken<Hooks>('LazyLoadImageHooks');\n","import { AfterContentInit, Directive, ElementRef, EventEmitter, Inject, Input, NgZone, OnChanges, OnDestroy, Output, PLATFORM_ID } from '@angular/core';\nimport { never, Observable, ReplaySubject, Subscription } from 'rxjs';\nimport { switchMap, take, tap } from 'rxjs/operators';\nimport { lazyLoadImage } from './lazyload-image';\nimport { LAZYLOAD_IMAGE_HOOKS } from './token';\nimport { Attributes, Hooks, StateChange } from './types';\n\n@Directive({\n selector: '[lazyLoad]',\n})\nexport class LazyLoadImageDirective implements OnChanges, AfterContentInit, OnDestroy {\n @Input('lazyLoad') lazyImage!: string; // The image to be lazy loaded\n @Input() defaultImage?: string; // The image to be displayed before lazyImage is loaded\n @Input() errorImage?: string; // The image to be displayed if lazyImage load fails\n @Input() scrollTarget?: any; // Scroll container that contains the image and emits scoll events\n @Input() customObservable?: Observable<any>; // Pass your own event emitter\n @Input() offset?: number; // The number of px a image should be loaded before it is in view port\n @Input() useSrcset?: boolean; // Whether srcset attribute should be used instead of src\n @Input() decode?: boolean; // Decode the image before appending to the DOM\n @Input() debug?: boolean; // Will print some debug info when `true`\n @Output() onStateChange: EventEmitter<StateChange> = new EventEmitter(); // Emits an event on every state change\n private propertyChanges$: ReplaySubject<Attributes>;\n private elementRef: ElementRef;\n private ngZone: NgZone;\n private loadSubscription?: Subscription;\n private debugSubscription?: Subscription;\n private hooks: Hooks;\n private uid: string;\n\n constructor(el: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object, @Inject(LAZYLOAD_IMAGE_HOOKS) hooks: Hooks) {\n this.elementRef = el;\n this.ngZone = ngZone;\n this.propertyChanges$ = new ReplaySubject();\n this.hooks = hooks;\n this.hooks.setPlatformId(platformId);\n this.uid = Math.random().toString(36).substr(2, 9);\n }\n\n ngOnChanges() {\n if (this.debug === true && !this.debugSubscription) {\n this.debugSubscription = this.onStateChange.subscribe((e: StateChange) => console.log(e));\n }\n\n this.propertyChanges$.next({\n element: this.elementRef.nativeElement,\n imagePath: this.lazyImage,\n defaultImagePath: this.defaultImage,\n errorImagePath: this.errorImage,\n useSrcset: this.useSrcset,\n offset: this.offset ? this.offset | 0 : 0,\n scrollContainer: this.scrollTarget,\n customObservable: this.customObservable,\n decode: this.decode,\n onStateChange: this.onStateChange,\n id: this.uid,\n });\n }\n\n ngAfterContentInit() {\n if (this.hooks.isDisabled()) {\n return null;\n }\n\n this.ngZone.runOutsideAngular(() => {\n this.loadSubscription = this.propertyChanges$\n .pipe(\n tap((attributes) => this.hooks.onAttributeChange(attributes)),\n tap((attributes) => attributes.onStateChange.emit({ reason: 'setup' })),\n tap((attributes) => this.hooks.setup(attributes)),\n switchMap((attributes) => {\n if (!attributes.imagePath) {\n return never();\n }\n return this.hooks.getObservable(attributes).pipe(lazyLoadImage(this.hooks, attributes));\n })\n )\n .subscribe({\n next: () => null,\n });\n });\n }\n\n ngOnDestroy() {\n this.propertyChanges$\n .pipe(take(1))\n .subscribe({ next: (attributes) => this.hooks.onDestroy(attributes) })\n .unsubscribe();\n this.loadSubscription?.unsubscribe();\n this.debugSubscription?.unsubscribe();\n }\n}\n","import { Observable, of } from 'rxjs';\nimport { catchError, filter, map, mergeMap, take, tap } from 'rxjs/operators';\nimport { Attributes, Hooks } from './types';\n\nexport function lazyLoadImage<E>(hooks: Hooks<E>, attributes: Attributes) {\n return (evntObservable: Observable<E>): Observable<boolean> => {\n return evntObservable.pipe(\n tap((data) => attributes.onStateChange.emit({ reason: 'observer-emit', data })),\n filter((event) => hooks.isVisible(event, attributes)),\n take(1),\n tap(() => attributes.onStateChange.emit({ reason: 'start-loading' })),\n mergeMap(() => hooks.loadImage(attributes)),\n tap(() => attributes.onStateChange.emit({ reason: 'mount-image' })),\n tap((imagePath) => hooks.setLoadedImage(imagePath, attributes)),\n tap(() => attributes.onStateChange.emit({ reason: 'loading-succeeded' })),\n map(() => true),\n catchError((error) => {\n attributes.onStateChange.emit({ reason: 'loading-failed', data: error });\n hooks.setErrorImage(error, attributes);\n return of(false);\n }),\n tap(() => {\n attributes.onStateChange.emit({ reason: 'finally' });\n hooks.finally(attributes);\n })\n ) as Observable<boolean>;\n };\n}\n","import { NgModule } from '@angular/core';\nimport { LazyLoadImageDirective } from './lazyload-image.directive';\nimport { IntersectionObserverHooks } from './intersection-observer-hooks/hooks';\nimport { LAZYLOAD_IMAGE_HOOKS } from './token';\n\n@NgModule({\n declarations: [LazyLoadImageDirective],\n exports: [LazyLoadImageDirective],\n providers: [{ provide: LAZYLOAD_IMAGE_HOOKS, useClass: IntersectionObserverHooks }],\n})\nexport class LazyLoadImageModule {}\n","export class Rect {\n static empty: Rect = new Rect(0, 0, 0, 0);\n\n left: number;\n top: number;\n right: number;\n bottom: number;\n\n constructor(left: number, top: number, right: number, bottom: number) {\n this.left = left;\n this.top = top;\n this.right = right;\n this.bottom = bottom;\n }\n\n static fromElement(element: HTMLElement): Rect {\n const { left, top, right, bottom } = element.getBoundingClientRect();\n\n if (left === 0 && top === 0 && right === 0 && bottom === 0) {\n return Rect.empty;\n } else {\n return new Rect(left, top, right, bottom);\n }\n }\n\n static fromWindow(_window: Window): Rect {\n return new Rect(0, 0, _window.innerWidth, _window.innerHeight);\n }\n\n inflate(inflateBy: number) {\n this.left -= inflateBy;\n this.top -= inflateBy;\n this.right += inflateBy;\n this.bottom += inflateBy;\n }\n\n intersectsWith(rect: Rect): boolean {\n return rect.left < this.right && this.left < rect.right && rect.top < this.bottom && this.top < rect.bottom;\n }\n\n getIntersectionWith(rect: Rect): Rect {\n const left = Math.max(this.left, rect.left);\n const top = Math.max(this.top, rect.top);\n const right = Math.min(this.right, rect.right);\n const bottom = Math.min(this.bottom, rect.bottom);\n\n if (right >= left && bottom >= top) {\n return new Rect(left, top, right, bottom);\n } else {\n return Rect.empty;\n }\n }\n}\n","var trigger;\nvar callbacks = [];\nvar notify = function () { return callbacks.splice(0).forEach(function (cb) { return cb(); }); };\nvar queueMicroTask = function (callback) {\n if (!trigger) {\n var toggle_1 = 0;\n var el_1 = document.createTextNode('');\n var config = { characterData: true };\n new MutationObserver(function () { return notify(); }).observe(el_1, config);\n trigger = function () { el_1.textContent = \"\".concat(toggle_1 ? toggle_1-- : toggle_1++); };\n }\n callbacks.push(callback);\n trigger();\n};\nexport { queueMicroTask };\n","var resizeObservers = [];\nexport { resizeObservers };\n","var msg = 'ResizeObserver loop completed with undelivered notifications.';\nvar deliverResizeLoopError = function () {\n var event;\n if (typeof ErrorEvent === 'function') {\n event = new ErrorEvent('error', {\n message: msg\n });\n }\n else {\n event = document.createEvent('Event');\n event.initEvent('error', false, false);\n event.message = msg;\n }\n window.dispatchEvent(event);\n};\nexport { deliverResizeLoopError };\n","var ResizeObserverBoxOptions;\n(function (ResizeObserverBoxOptions) {\n ResizeObserverBoxOptions[\"BORDER_BOX\"] = \"border-box\";\n ResizeObserverBoxOptions[\"CONTENT_BOX\"] = \"content-box\";\n ResizeObserverBoxOptions[\"DEVICE_PIXEL_CONTENT_BOX\"] = \"device-pixel-content-box\";\n})(ResizeObserverBoxOptions || (ResizeObserverBoxOptions = {}));\nexport { ResizeObserverBoxOptions };\n","export var freeze = function (obj) { return Object.freeze(obj); };\n","import { freeze } from './utils/freeze';\nvar ResizeObserverSize = (function () {\n function ResizeObserverSize(inlineSize, blockSize) {\n this.inlineSize = inlineSize;\n this.blockSize = blockSize;\n freeze(this);\n }\n return ResizeObserverSize;\n}());\nexport { ResizeObserverSize };\n","import { freeze } from './utils/freeze';\nvar DOMRectReadOnly = (function () {\n function DOMRectReadOnly(x, y, width, height) {\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.top = this.y;\n this.left = this.x;\n this.bottom = this.top + this.height;\n this.right = this.left + this.width;\n return freeze(this);\n }\n DOMRectReadOnly.prototype.toJSON = function () {\n var _a = this, x = _a.x, y = _a.y, top = _a.top, right = _a.right, bottom = _a.bottom, left = _a.left, width = _a.width, height = _a.height;\n return { x: x, y: y, top: top, right: right, bottom: bottom, left: left, width: width, height: height };\n };\n DOMRectReadOnly.fromRect = function (rectangle) {\n return new DOMRectReadOnly(rectangle.x, rectangle.y, rectangle.width, rectangle.height);\n };\n return DOMRectReadOnly;\n}());\nexport { DOMRectReadOnly };\n","var isSVG = function (target) { return target instanceof SVGElement && 'getBBox' in target; };\nvar isHidden = function (target) {\n if (isSVG(target)) {\n var _a = target.getBBox(), width = _a.width, height = _a.height;\n return !width && !height;\n }\n var _b = target, offsetWidth = _b.offsetWidth, offsetHeight = _b.offsetHeight;\n return !(offsetWidth || offsetHeight || target.getClientRects().length);\n};\nvar isElement = function (obj) {\n var _a;\n if (obj instanceof Element) {\n return true;\n }\n var scope = (_a = obj === null || obj === void 0 ? void 0 : obj.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;\n return !!(scope && obj instanceof scope.Element);\n};\nvar isReplacedElement = function (target) {\n switch (target.tagName) {\n case 'INPUT':\n if (target.type !== 'image') {\n break;\n }\n case 'VIDEO':\n case 'AUDIO':\n case 'EMBED':\n case 'OBJECT':\n case 'CANVAS':\n case 'IFRAME':\n case 'IMG':\n return true;\n }\n return false;\n};\nexport { isSVG, isHidden, isElement, isReplacedElement };\n","export var global = typeof window !== 'undefined' ? window : {};\n","import { ResizeObserverBoxOptions } from '../ResizeObserverBoxOptions';\nimport { ResizeObserverSize } from '../ResizeObserverSize';\nimport { DOMRectReadOnly } from '../DOMRectReadOnly';\nimport { isSVG, isHidden } from '../utils/element';\nimport { freeze } from '../utils/freeze';\nimport { global } from '../utils/global';\nvar cache = new WeakMap();\nvar scrollRegexp = /auto|scroll/;\nvar verticalRegexp = /^tb|vertical/;\nvar IE = (/msie|trident/i).test(global.navigator && global.navigator.userAgent);\nvar parseDimension = function (pixel) { return parseFloat(pixel || '0'); };\nvar size = function (inlineSize, blockSize, switchSizes) {\n if (inlineSize === void 0) { inlineSize = 0; }\n if (blockSize === void 0) { blockSize = 0; }\n if (switchSizes === void 0) { switchSizes = false; }\n return new ResizeObserverSize((switchSizes ? blockSize : inlineSize) || 0, (switchSizes ? inlineSize : blockSize) || 0);\n};\nvar zeroBoxes = freeze({\n devicePixelContentBoxSize: size(),\n borderBoxSize: size(),\n contentBoxSize: size(),\n contentRect: new DOMRectReadOnly(0, 0, 0, 0)\n});\nvar calculateBoxSizes = function (target, forceRecalculation) {\n if (forceRecalculation === void 0) { forceRecalculation = false; }\n if (cache.has(target) && !forceRecalculation) {\n return cache.get(target);\n }\n if (isHidden(target)) {\n cache.set(target, zeroBoxes);\n return zeroBoxes;\n }\n var cs = getComputedStyle(target);\n var svg = isSVG(target) && target.ownerSVGElement && target.getBBox();\n var removePadding = !IE && cs.boxSizing === 'border-box';\n var switchSizes = verticalRegexp.test(cs.writingMode || '');\n var canScrollVertically = !svg && scrollRegexp.test(cs.overflowY || '');\n var canScrollHorizontally = !svg && scrollRegexp.test(cs.overflowX || '');\n var paddingTop = svg ? 0 : parseDimension(cs.paddingTop);\n var paddingRight = svg ? 0 : parseDimension(cs.paddingRight);\n var paddingBottom = svg ? 0 : parseDimension(cs.paddingBottom);\n var paddingLeft = svg ? 0 : parseDimension(cs.paddingLeft);\n var borderTop = svg ? 0 : parseDimension(cs.borderTopWidth);\n var borderRight = svg ? 0 : parseDimension(cs.borderRightWidth);\n var borderBottom = svg ? 0 : parseDimension(cs.borderBottomWidth);\n var borderLeft = svg ? 0 : parseDimension(cs.borderLeftWidth);\n var horizontalPadding = paddingLeft + paddingRight;\n var verticalPadding = paddingTop + paddingBottom;\n var horizontalBorderArea = borderLeft + borderRight;\n var verticalBorderArea = borderTop + borderBottom;\n var horizontalScrollbarThickness = !canScrollHorizontally ? 0 : target.offsetHeight - verticalBorderArea - target.clientHeight;\n var verticalScrollbarThickness = !canScrollVertically ? 0 : target.offsetWidth - horizontalBorderArea - target.clientWidth;\n var widthReduction = removePadding ? horizontalPadding + horizontalBorderArea : 0;\n var heightReduction = removePadding ? verticalPadding + verticalBorderArea : 0;\n var contentWidth = svg ? svg.width : parseDimension(cs.width) - widthReduction - verticalScrollbarThickness;\n var contentHeight = svg ? svg.height : parseDimension(cs.height) - heightReduction - horizontalScrollbarThickness;\n var borderBoxWidth = contentWidth + horizontalPadding + verticalScrollbarThickness + horizontalBorderArea;\n var borderBoxHeight = contentHeight + verticalPadding + horizontalScrollbarThickness + verticalBorderArea;\n var boxes = freeze({\n devicePixelContentBoxSize: size(Math.round(contentWidth * devicePixelRatio), Math.round(contentHeight * devicePixelRatio), switchSizes),\n borderBoxSize: size(borderBoxWidth, borderBoxHeight, switchSizes),\n contentBoxSize: size(contentWidth, contentHeight, switchSizes),\n contentRect: new DOMRectReadOnly(paddingLeft, paddingTop, contentWidth, contentHeight)\n });\n cache.set(target, boxes);\n return boxes;\n};\nvar calculateBoxSize = function (target, observedBox, forceRecalculation) {\n var _a = calculateBoxSizes(target, forceRecalculation), borderBoxSize = _a.borderBoxSize, contentBoxSize = _a.contentBoxSize, devicePixelContentBoxSize = _a.devicePixelContentBoxSize;\n switch (observedBox) {\n case ResizeObserverBoxOptions.DEVICE_PIXEL_CONTENT_BOX:\n return devicePixelContentBoxSize;\n case ResizeObserverBoxOptions.BORDER_BOX:\n return borderBoxSize;\n default:\n return contentBoxSize;\n }\n};\nexport { calculateBoxSize, calculateBoxSizes };\n","import { calculateBoxSizes } from './algorithms/calculateBoxSize';\nimport { freeze } from './utils/freeze';\nvar ResizeObserverEntry = (function () {\n function ResizeObserverEntry(target) {\n var boxes = calculateBoxSizes(target);\n this.target = target;\n this.contentRect = boxes.contentRect;\n this.borderBoxSize = freeze([boxes.borderBoxSize]);\n this.contentBoxSize = freeze([boxes.contentBoxSize]);\n this.devicePixelContentBoxSize = freeze([boxes.devicePixelContentBoxSize]);\n }\n return ResizeObserverEntry;\n}());\nexport { ResizeObserverEntry };\n","import { isHidden } from '../utils/element';\nvar calculateDepthForNode = function (node) {\n if (isHidden(node)) {\n return Infinity;\n }\n var depth = 0;\n var parent = node.parentNode;\n while (parent) {\n depth += 1;\n parent = parent.parentNode;\n }\n return depth;\n};\nexport { calculateDepthForNode };\n","import { resizeObservers } from '../utils/resizeObservers';\nimport { ResizeObserverEntry } from '../ResizeObserverEntry';\nimport { calculateDepthForNode } from './calculateDepthForNode';\nimport { calculateBoxSize } from './calculateBoxSize';\nvar broadcastActiveObservations = function () {\n var shallowestDepth = Infinity;\n var callbacks = [];\n resizeObservers.forEach(function processObserver(ro) {\n if (ro.activeTargets.length === 0) {\n return;\n }\n var entries = [];\n ro.activeTargets.forEach(function processTarget(ot) {\n var entry = new ResizeObserverEntry(ot.target);\n var targetDepth = calculateDepthForNode(ot.target);\n entries.push(entry);\n ot.lastReportedSize = calculateBoxSize(ot.target, ot.observedBox);\n if (targetDepth < shallowestDepth) {\n shallowestDepth = targetDepth;\n }\n });\n callbacks.push(function resizeObserverCallback() {\n ro.callback.call(ro.observer, entries, ro.observer);\n });\n ro.activeTargets.splice(0, ro.activeTargets.length);\n });\n for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) {\n var callback = callbacks_1[_i];\n callback();\n }\n return shallowestDepth;\n};\nexport { broadcastActiveObservations };\n","import { resizeObservers } from '../utils/resizeObservers';\nimport { calculateDepthForNode } from './calculateDepthForNode';\nvar gatherActiveObservationsAtDepth = function (depth) {\n resizeObservers.forEach(function processObserver(ro) {\n ro.activeTargets.splice(0, ro.activeTargets.length);\n ro.skippedTargets.splice(0, ro.skippedTargets.length);\n ro.observationTargets.forEach(function processTarget(ot) {\n if (ot.isActive()) {\n if (calculateDepthForNode(ot.target) > depth) {\n ro.activeTargets.push(ot);\n }\n else {\n ro.skippedTargets.push(ot);\n }\n }\n });\n });\n};\nexport { gatherActiveObservationsAtDepth };\n","import { process } from './process';\nimport { global } from './global';\nimport { queueResizeObserver } from './queueResizeObserver';\nvar watching = 0;\nvar isWatching = function () { return !!watching; };\nvar CATCH_PERIOD = 250;\nvar observerConfig = { attributes: true, characterData: true, childList: true, subtree: true };\nvar events = [\n 'resize',\n 'load',\n 'transitionend',\n 'animationend',\n 'animationstart',\n 'animationiteration',\n 'keyup',\n 'keydown',\n 'mouseup',\n 'mousedown',\n 'mouseover',\n 'mouseout',\n 'blur',\n 'focus'\n];\nvar time = function (timeout) {\n if (timeout === void 0) { timeout = 0; }\n return Date.now() + timeout;\n};\nvar scheduled = false;\nvar Scheduler = (function () {\n function Scheduler() {\n var _this = this;\n this.stopped = true;\n this.listener = function () { return _this.schedule(); };\n }\n Scheduler.prototype.run = function (timeout) {\n var _this = this;\n if (timeout === void 0) { timeout = CATCH_PERIOD; }\n if (scheduled) {\n return;\n }\n scheduled = true;\n var until = time(timeout);\n queueResizeObserver(function () {\n var elementsHaveResized = false;\n try {\n elementsHaveResized = process();\n }\n finally {\n scheduled = false;\n timeout = until - time();\n if (!isWatching()) {\n return;\n }\n if (elementsHaveResized) {\n _this.run(1000);\n }\n else if (timeout > 0) {\n _this.run(timeout);\n }\n else {\n _this.start();\n }\n }\n });\n };\n Scheduler.prototype.schedule = function () {\n this.stop();\n this.run();\n };\n Scheduler.prototype.observe = function () {\n var _this = this;\n var cb = function () { return _this.observer && _this.observer.observe(document.body, observerConfig); };\n document.body ? cb() : global.addEventListener('DOMContentLoaded', cb);\n };\n Scheduler.prototype.start = function () {\n var _this = this;\n if (this.stopped) {\n this.stopped = false;\n this.observer = new MutationObserver(this.listener);\n this.observe();\n events.forEach(function (name) { return global.addEventListener(name, _this.listener, true); });\n }\n };\n Scheduler.prototype.stop = function () {\n var _this = this;\n if (!this.stopped) {\n this.observer && this.observer.disconnect();\n events.forEach(function (name) { return global.removeEventListener(name, _this.listener, true); });\n this.stopped = true;\n }\n };\n return Scheduler;\n}());\nvar scheduler = new Scheduler();\nvar updateCount = function (n) {\n !watching && n > 0 && scheduler.start();\n watching += n;\n !watching && scheduler.stop();\n};\nexport { scheduler, updateCount };\n","import { queueMicroTask } from './queueMicroTask';\nvar queueResizeObserver = function (cb) {\n queueMicroTask(function ResizeObserver() {\n requestAnimationFrame(cb);\n });\n};\nexport { queueResizeObserver };\n","import { hasActiveObservations } from '../algorithms/hasActiveObservations';\nimport { hasSkippedObservations } from '../algorithms/hasSkippedObservations';\nimport { deliverResizeLoopError } from '../algorithms/deliverResizeLoopError';\nimport { broadcastActiveObservations } from '../algorithms/broadcastActiveObservations';\nimport { gatherActiveObservationsAtDepth } from '../algorithms/gatherActiveObservationsAtDepth';\nvar process = function () {\n var depth = 0;\n gatherActiveObservationsAtDepth(depth);\n while (hasActiveObservations()) {\n depth = broadcastActiveObservations();\n gatherActiveObservationsAtDepth(depth);\n }\n if (hasSkippedObservations()) {\n deliverResizeLoopError();\n }\n return depth > 0;\n};\nexport { process };\n","import { resizeObservers } from '../utils/resizeObservers';\nvar hasActiveObservations = function () {\n return resizeObservers.some(function (ro) { return ro.activeTargets.length > 0; });\n};\nexport { hasActiveObservations };\n","import { resizeObservers } from '../utils/resizeObservers';\nvar hasSkippedObservations = function () {\n return resizeObservers.some(function (ro) { return ro.skippedTargets.length > 0; });\n};\nexport { hasSkippedObservations };\n","import { ResizeObserverBoxOptions } from './ResizeObserverBoxOptions';\nimport { calculateBoxSize } from './algorithms/calculateBoxSize';\nimport { isSVG, isReplacedElement } from './utils/element';\nvar skipNotifyOnElement = function (target) {\n return !isSVG(target)\n && !isReplacedElement(target)\n && getComputedStyle(target).display === 'inline';\n};\nvar ResizeObservation = (function () {\n function ResizeObservation(target, observedBox) {\n this.target = target;\n this.observedBox = observedBox || ResizeObserverBoxOptions.CONTENT_BOX;\n this.lastReportedSize = {\n inlineSize: 0,\n blockSize: 0\n };\n }\n ResizeObservation.prototype.isActive = function () {\n var size = calculateBoxSize(this.target, this.observedBox, true);\n if (skipNotifyOnElement(this.target)) {\n this.lastReportedSize = size;\n }\n if (this.lastReportedSize.inlineSize !== size.inlineSize\n || this.lastReportedSize.blockSize !== size.blockSize) {\n return true;\n }\n return false;\n };\n return ResizeObservation;\n}());\nexport { ResizeObservation };\n","var ResizeObserverDetail = (function () {\n function ResizeObserverDetail(resizeObserver, callback) {\n this.activeTargets = [];\n this.skippedTargets = [];\n this.observationTargets = [];\n this.observer = resizeObserver;\n this.callback = callback;\n }\n return ResizeObserverDetail;\n}());\nexport { ResizeObserverDetail };\n","import { scheduler, updateCount } from './utils/scheduler';\nimport { ResizeObservation } from './ResizeObservation';\nimport { ResizeObserverDetail } from './ResizeObserverDetail';\nimport { resizeObservers } from './utils/resizeObservers';\nvar observerMap = new WeakMap();\nvar getObservationIndex = function (observationTargets, target) {\n for (var i = 0; i < observationTargets.length; i += 1) {\n if (observationTargets[i].target === target) {\n return i;\n }\n }\n return -1;\n};\nvar ResizeObserverController = (function () {\n function ResizeObserverController() {\n }\n ResizeObserverController.connect = function (resizeObserver, callback) {\n var detail = new ResizeObserverDetail(resizeObserver, callback);\n observerMap.set(resizeObserver, detail);\n };\n ResizeObserverController.observe = function (resizeObserver, target, options) {\n var detail = observerMap.get(resizeObserver);\n var firstObservation = detail.observationTargets.length === 0;\n if (getObservationIndex(detail.observationTargets, target) < 0) {\n firstObservation && resizeObservers.push(detail);\n detail.observationTargets.push(new ResizeObservation(target, options && options.box));\n updateCount(1);\n scheduler.schedule();\n }\n };\n ResizeObserverController.unobserve = function (resizeObserver, target) {\n var detail = observerMap.get(resizeObserver);\n var index = getObservationIndex(detail.observationTargets, target);\n var lastObservation = detail.observationTargets.length === 1;\n if (index >= 0) {\n lastObservation && resizeObservers.splice(resizeObservers.indexOf(detail), 1);\n detail.observationTargets.splice(index, 1);\n updateCount(-1);\n }\n };\n ResizeObserverController.disconnect = function (resizeObserver) {\n var _this = this;\n var detail = observerMap.get(resizeObserver);\n detail.observationTargets.slice().forEach(function (ot) { return _this.unobserve(resizeObserver, ot.target); });\n detail.activeTargets.splice(0, detail.activeTargets.length);\n };\n return ResizeObserverController;\n}());\nexport { ResizeObserverController };\n","import { ResizeObserverController } from './ResizeObserverController';\nimport { isElement } from './utils/element';\nvar ResizeObserver = (function () {\n function ResizeObserver(callback) {\n if (arguments.length === 0) {\n throw new TypeError(\"Failed to construct 'ResizeObserver': 1 argument required, but only 0 present.\");\n }\n if (typeof callback !== 'function') {\n throw new TypeError(\"Failed to construct 'ResizeObserver': The callback provided as parameter 1 is not a function.\");\n }\n ResizeObserverController.connect(this, callback);\n }\n ResizeObserver.prototype.observe = function (target, options) {\n if (arguments.length === 0) {\n throw new TypeError(\"Failed to execute 'observe' on 'ResizeObserver': 1 argument required, but only 0 present.\");\n }\n if (!isElement(target)) {\n throw new TypeError(\"Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element\");\n }\n ResizeObserverController.observe(this, target, options);\n };\n ResizeObserver.prototype.unobserve = function (target) {\n if (arguments.length === 0) {\n throw new TypeError(\"Failed to execute 'unobserve' on 'ResizeObserver': 1 argument required, but only 0 present.\");\n }\n if (!isElement(target)) {\n throw new TypeError(\"Failed to execute 'unobserve' on 'ResizeObserver': parameter 1 is not of type 'Element\");\n }\n ResizeObserverController.unobserve(this, target);\n };\n ResizeObserver.prototype.disconnect = function () {\n ResizeObserverController.disconnect(this);\n };\n ResizeObserver.toString = function () {\n return 'function ResizeObserver () { [polyfill code] }';\n };\n return ResizeObserver;\n}());\nexport { ResizeObserver };\n","import { InjectionToken } from \"@angular/core\";\nimport { ResizeObserver } from \"@juggle/resize-observer\";\n\ndeclare var window: any;\n\nexport type ResizeObserverClass = {\n new(callback: (entries: any[]) => void): ResizeObserver;\n};\n\nexport const RESIZE_OBSERVER = new InjectionToken<ResizeObserverClass>(\n \"Resize Observer\",\n {\n providedIn: \"root\",\n factory: () => window.ResizeObserver || null\n }\n);\n","import {\n ChangeDetectorRef,\n ElementRef,\n Inject,\n Injectable,\n OnDestroy,\n Optional,\n} from \"@angular/core\";\nimport { ResizeObserver, ResizeObserverEntry } from \"@juggle/resize-observer\";\nimport { Observable, Subject } from \"rxjs\";\nimport { RESIZE_OBSERVER, ResizeObserverClass } from \"./resize-observer\";\n\nexport class NgResizeObserver extends Observable<ResizeObserverEntry> {}\n\n@Injectable()\nexport class ResizeObserverService implements OnDestroy {\n private onResizeSubject = new Subject<ResizeObserverEntry>();\n private resizeObserver!: ResizeObserver;\n public onResize: Observable<\n ResizeObserverEntry\n > = this.onResizeSubject.asObservable();\n\n constructor(\n private chgRef: ChangeDetectorRef,\n @Optional() private el: ElementRef,\n @Inject(RESIZE_OBSERVER)\n private ResizeObserver: ResizeObserverClass\n ) {\n if (this.el === null) {\n console.error(\n `ng-resize-observer: No provider for ElementRef. This error is most likely because you added the ng-resize-observer provider in a @NgModule. Only add ng-resize-observer on @Component()`\n );\n return;\n }\n\n if (this.ResizeObserver === null) {\n console.error(\n `ng-resize-observer: ResizeObserver not available. Use the ponyfill module: NgResizeObserverPonyfillModule.`\n );\n return;\n }\n\n this.observe();\n }\n\n ngOnDestroy() {\n this.unobserve();\n this.onResizeSubject.complete();\n }\n\n private observe() {\n this.resizeObserver = new this.ResizeObserver((entries) => {\n const entry = entries && entries[0];\n if (entry) {\n this.onResizeSubject.next(entry);\n this.chgRef.detectChanges();\n }\n });\n this.resizeObserver.observe(this.target);\n }\n\n private unobserve() {\n this.resizeObserver.unobserve(this.target);\n }\n\n private get target() {\n return this.el.nativeElement;\n }\n}\n\nexport function ngResizeObserverFactory(\n resizeObserverService: ResizeObserverService\n) {\n return resizeObserverService.onResize;\n}\n\nexport const NgResizeObserverProvider = {\n provide: NgResizeObserver,\n useFactory: ngResizeObserverFactory,\n deps: [ResizeObserverService],\n};\n","import { NgModule } from \"@angular/core\";\nimport { RESIZE_OBSERVER } from \"./resize-observer\";\nimport { ResizeObserver as Polyfill } from \"@juggle/resize-observer\";\n\ndeclare var window: any;\n\nexport function ponyFillFactory() {\n return window.ResizeObserver || Polyfill;\n};\n\nexport const polyfillProvider = { provide: RESIZE_OBSERVER, useFactory: ponyFillFactory };\n\n@NgModule({\n providers: [polyfillProvider]\n})\nexport class NgResizeObserverPonyfillModule {}\n","import {\n NgResizeObserverProvider,\n ResizeObserverService,\n NgResizeObserver,\n} from './lib/ng-resize-observer.service';\nimport {\n NgResizeObserverPonyfillModule,\n polyfillProvider,\n} from './lib/ponyfill.module';\n\nconst ngResizeObserverProviders = [\n NgResizeObserverProvider,\n ResizeObserverService,\n];\n\nconst ngResizeObserverProvidersWithPonyfill = [\n ...ngResizeObserverProviders,\n polyfillProvider,\n];\n\n/*\n * Public API Surface of ng-resize-observer\n */\nexport {\n NgResizeObserver,\n ngResizeObserverProviders,\n ngResizeObserverProvidersWithPonyfill,\n NgResizeObserverPonyfillModule,\n};\n","import Plyr from 'plyr';\r\nimport {\r\n PlyrDriver,\r\n PlyrDriverCreateParams,\r\n PlyrDriverDestroyParams,\r\n PlyrDriverUpdateSourceParams\r\n} from \"./plyr-driver\";\r\n\r\nexport class DefaultPlyrDriver implements PlyrDriver {\r\n create(params: PlyrDriverCreateParams) {\r\n return new Plyr(params.videoElement, params.options);\r\n }\r\n\r\n updateSource(params: PlyrDriverUpdateSourceParams) {\r\n params.plyr.source = params.source;\r\n }\r\n\r\n destroy(params: PlyrDriverDestroyParams) {\r\n params.plyr.destroy();\r\n }\r\n}\r\n","import {\r\n AfterViewInit,\r\n Component, ElementRef,\r\n EventEmitter,\r\n Input,\r\n NgZone,\r\n OnChanges,\r\n OnDestroy,\r\n Output,\r\n Renderer2,\r\n SimpleChange,\r\n ViewChild\r\n} from \"@angular/core\";\r\nimport * as Plyr from \"plyr\";\r\nimport { BehaviorSubject, Observable, Subscription } from \"rxjs\";\r\nimport { filter, first, switchMap } from \"rxjs/operators\";\r\nimport { DefaultPlyrDriver } from \"../plyr-driver/default-plyr-driver\";\r\nimport { PlyrDriver } from \"../plyr-driver/plyr-driver\";\r\n\r\n@Component({\r\n selector: 'plyr, [plyr]',\r\n templateUrl: './plyr.component.html',\r\n exportAs: 'plyr'\r\n})\r\nexport class PlyrComponent implements AfterViewInit, OnChanges, OnDestroy {\r\n private playerChange = new BehaviorSubject<Plyr>(null);\r\n\r\n get player(): Plyr {\r\n return this.playerChange.getValue();\r\n }\r\n\r\n private events = new Map();\r\n\r\n @Input() plyrDriver: PlyrDriver;\r\n\r\n @Input() plyrType: Plyr.MediaType = 'video';\r\n\r\n @Input() plyrTitle: string;\r\n\r\n @Input() plyrPoster: string;\r\n\r\n @Input() plyrSources: Plyr.Source[];\r\n\r\n @Input() plyrTracks: Plyr.Track[];\r\n\r\n @Input() plyrOptions: Plyr.Options;\r\n\r\n @Input() plyrCrossOrigin: boolean;\r\n\r\n @Input() plyrPlaysInline: boolean;\r\n\r\n @ViewChild('v') private vr: ElementRef;\r\n\r\n // ngx-plyr events\r\n @Output() plyrInit = this.playerChange.pipe(filter(player => !!player)) as EventEmitter<Plyr>;\r\n\r\n // standard media events\r\n @Output() plyrProgress = this.createLazyEvent('progress');\r\n @Output() plyrPlaying = this.createLazyEvent('playing');\r\n @Output() plyrPlay = this.createLazyEvent('play');\r\n @Output() plyrPause = this.createLazyEvent('pause');\r\n @Output() plyrTimeUpdate = this.createLazyEvent('timeupdate');\r\n @Output() plyrVolumeChange = this.createLazyEvent('volumechange');\r\n @Output() plyrSeeking = this.createLazyEvent('seeking');\r\n @Output() plyrSeeked = this.createLazyEvent('seeked');\r\n @Output() plyrRateChange = this.createLazyEvent('ratechange');\r\n @Output() plyrEnded = this.createLazyEvent('ended');\r\n @Output() plyrEnterFullScreen = this.createLazyEvent('enterfullscreen');\r\n @Output() plyrExitFullScreen = this.createLazyEvent('exitfullscreen');\r\n @Output() plyrCaptionsEnabled = this.createLazyEvent('captionsenabled');\r\n @Output() plyrCaptionsDisabled = this.createLazyEvent('captionsdisabled');\r\n @Output() plyrLanguageChange = this.createLazyEvent('languagechange');\r\n @Output() plyrControlsHidden = this.createLazyEvent('controlshidden');\r\n @Output() plyrControlsShown = this.createLazyEvent('controlsshown');\r\n @Output() plyrReady = this.createLazyEvent('ready');\r\n\r\n // HTML5 events\r\n @Output() plyrLoadStart = this.createLazyEvent('loadstart');\r\n @Output() plyrLoadedData = this.createLazyEvent('loadeddata');\r\n @Output() plyrLoadedMetadata = this.createLazyEvent('loadedmetadata');\r\n @Output() plyrQualityChange = this.createLazyEvent('qualitychange');\r\n @Output() plyrCanPlay = this.createLazyEvent('canplay');\r\n @Output() plyrCanPlayThrough = this.createLazyEvent('canplaythrough');\r\n @Output() plyrStalled = this.createLazyEvent('stalled');\r\n @Output() plyrWaiting = this.createLazyEvent('waiting');\r\n @Output() plyrEmptied = this.createLazyEvent('emptied');\r\n @Output() plyrCueChange = this.createLazyEvent('cuechange');\r\n @Output() plyrError = this.createLazyEvent('error');\r\n\r\n // YouTube events\r\n @Output() plyrStateChange = this.createLazyEvent('statechange');\r\n\r\n private subscriptions: Subscription[] = [];\r\n\r\n private driver: PlyrDriver;\r\n\r\n private videoElement: HTMLVideoElement;\r\n\r\n constructor(\r\n private elementRef: ElementRef<HTMLDivElement>,\r\n private ngZone: NgZone,\r\n private renderer: Renderer2,\r\n ) {\r\n }\r\n\r\n ngOnChanges(changes: { [p in keyof PlyrComponent]?: SimpleChange; }) {\r\n this.subscriptions.push(this.plyrInit.pipe(first()).subscribe((player: Plyr) => {\r\n const reinitTriggers = [changes.plyrOptions, changes.plyrPlaysInline, changes.plyrCrossOrigin].filter(t => !!t);\r\n\r\n if (reinitTriggers.length) {\r\n if (reinitTriggers.some(t => !t.firstChange)) {\r\n this.initPlyr(true);\r\n }\r\n } else {\r\n this.updatePlyrSource(player);\r\n }\r\n }));\r\n }\r\n\r\n ngOnDestroy() {\r\n this.destroyPlayer();\r\n this.subscriptions.forEach(s => s.unsubscribe());\r\n }\r\n\r\n ngAfterViewInit() {\r\n this.initPlyr();\r\n }\r\n\r\n private initPlyr(force = false) {\r\n if (force || !this.player) {\r\n this.ngZone.runOutsideAngular(() => {\r\n this.destroyPlayer();\r\n\r\n this.driver = this.plyrDriver || new DefaultPlyrDriver();\r\n\r\n this.ensureVideoElement();\r\n\r\n const newPlayer = this.driver.create({\r\n videoElement: this.videoElement,\r\n options: this.plyrOptions,\r\n });\r\n\r\n this.updatePlyrSource(newPlayer);\r\n\r\n this.playerChange.next(newPlayer);\r\n });\r\n }\r\n }\r\n\r\n private updatePlyrSource(plyr: Plyr) {\r\n this.driver.updateSource({\r\n videoElement: this.videoElement,\r\n plyr,\r\n source: {\r\n type: this.plyrType,\r\n title: this.plyrTitle,\r\n sources: this.plyrSources,\r\n poster: this.plyrPoster,\r\n tracks: this.plyrTracks,\r\n },\r\n });\r\n }\r\n\r\n // see https://stackoverflow.com/a/53704102/1990451\r\n private createLazyEvent<T extends Plyr.PlyrEvent>(name: Plyr.StandardEvent | Plyr.Html5Event | Plyr.YoutubeEvent): EventEmitter<T> {\r\n return this.plyrInit.pipe(\r\n switchMap(() => new Observable(observer => this.on(name, (data: T) => this.ngZone.run(() => observer.next(data)))))\r\n ) as EventEmitter<T>;\r\n }\r\n\r\n private destroyPlayer() {\r\n if (this.player) {\r\n Array.from(this.events.keys()).forEach(name => this.off(name));\r\n\r\n this.driver.destroy({\r\n plyr: this.player,\r\n });\r\n\r\n this.videoElement = null;\r\n }\r\n }\r\n\r\n private get hostElement() {\r\n return this.elementRef.nativeElement;\r\n }\r\n\r\n // this method is required because the plyr inserts clone of the original element on destroy\r\n // so we catch the clone element right here and reuse it\r\n private ensureVideoElement() {\r\n const videoElement = this.hostElement.querySelector('video');\r\n\r\n if (videoElement) {\r\n this.videoElement = videoElement;\r\n } else {\r\n this.videoElement = this.renderer.createElement('video');\r\n this.videoElement.controls = true;\r\n\r\n if (this.plyrCrossOrigin) {\r\n this.videoElement.setAttribute('crossorigin', '');\r\n }\r\n\r\n if (this.plyrPlaysInline) {\r\n this.videoElement.setAttribute('playsinline', '');\r\n }\r\n\r\n this.renderer.appendChild(this.hostElement, this.videoElement);\r\n }\r\n }\r\n\r\n private on(name: string, handler: any) {\r\n this.events.set(name, handler);\r\n this.player.on(name as any, handler);\r\n }\r\n\r\n private off(name: string) {\r\n this.player.off(name as any, this.events.get(name));\r\n this.events.delete(name);\r\n }\r\n}\r\n","import { NgModule } from \"@angular/core\";\r\nimport { PlyrComponent } from './plyr/plyr.component';\r\n\r\n@NgModule({\r\n declarations: [\r\n PlyrComponent,\r\n ],\r\n exports: [\r\n PlyrComponent,\r\n ]\r\n})\r\nexport class PlyrModule {}\r\n","import {\n ComponentRef,\n Injector,\n ViewContainerRef\n} from '@angular/core';\n\nexport interface ComponentType<T> {\n // eslint-disable-next-line @typescript-eslint/prefer-function-type\n new (...args: any[]): T;\n}\n\n\n/**\n * A `ComponentPortal` is a portal that instantiates some Component upon attachment.\n */\nexport class ComponentPortal<T> {\n private _attachedHost?: BasePortalHost;\n /** The type of the component that will be instantiated for attachment. */\n component: ComponentType<T>;\n\n /**\n * [Optional] Where the attached component should live in Angular's *logical* component tree.\n * This is different from where the component *renders*, which is determined by the PortalHost.\n * The origin necessary when the host is outside of the Angular application context.\n */\n viewContainerRef!: ViewContainerRef;\n\n /** Injector used for the instantiation of the component. */\n injector: Injector;\n\n constructor(component: ComponentType<T>, injector: Injector) {\n this.component = component;\n this.injector = injector;\n }\n\n /** Attach this portal to a host. */\n attach(host: BasePortalHost, newestOnTop: boolean): ComponentRef<any> {\n this._attachedHost = host;\n return host.attach(this, newestOnTop);\n }\n\n /** Detach this portal from its host */\n detach() {\n const host = this._attachedHost;\n if (host) {\n this._attachedHost = undefined;\n return host.detach();\n }\n }\n\n /** Whether this portal is attached to a host. */\n get isAttached(): boolean {\n return this._attachedHost != null;\n }\n\n /**\n * Sets the PortalHost reference without performing `attach()`. This is used directly by\n * the PortalHost when it is performing an `attach()` or `detach()`.\n */\n setAttachedHost(host?: BasePortalHost) {\n this._attachedHost = host;\n }\n}\n\n/**\n * Partial implementation of PortalHost that only deals with attaching a\n * ComponentPortal\n */\nexport abstract class BasePortalHost {\n /** The portal currently attached to the host. */\n private _attachedPortal?: ComponentPortal<any>;\n\n /** A function that will permanently dispose this host. */\n private _disposeFn?: () => void;\n\n attach(portal: ComponentPortal<any>, newestOnTop: boolean) {\n this._attachedPortal = portal;\n return this.attachComponentPortal(portal, newestOnTop);\n }\n\n abstract attachComponentPortal<T>(portal: ComponentPortal<T>, newestOnTop: boolean): ComponentRef<T>;\n\n detach() {\n if (this._attachedPortal) {\n this._attachedPortal.setAttachedHost();\n }\n\n this._attachedPortal = undefined;\n if (this._disposeFn) {\n this._disposeFn();\n this._disposeFn = undefined;\n }\n }\n\n setDisposeFn(fn: () => void) {\n this._disposeFn = fn;\n }\n}\n","import { Observable, Subject } from 'rxjs';\nimport { OverlayRef } from '../overlay/overlay-ref';\n\n/**\n * Reference to a toast opened via the Toastr service.\n */\nexport class ToastRef<T> {\n /** The instance of component opened into the toast. */\n componentInstance!: T;\n\n /** Count of duplicates of this toast */\n private duplicatesCount = 0;\n\n /** Subject for notifying the user that the toast has finished closing. */\n private _afterClosed = new Subject<void>();\n /** triggered when toast is activated */\n private _activate = new Subject<void>();\n /** notifies the toast that it should close before the timeout */\n private _manualClose = new Subject<void>();\n /** notifies the toast that it should reset the timeouts */\n private _resetTimeout = new Subject<void>();\n /** notifies the toast that it should count a duplicate toast */\n private _countDuplicate = new Subject<number>();\n\n constructor(private _overlayRef: OverlayRef) {}\n\n manualClose() {\n this._manualClose.next();\n this._manualClose.complete();\n }\n\n manualClosed(): Observable<any> {\n return this._manualClose.asObservable();\n }\n\n timeoutReset(): Observable<any> {\n return this._resetTimeout.asObservable();\n }\n\n countDuplicate(): Observable<number> {\n return this._countDuplicate.asObservable();\n }\n\n /**\n * Close the toast.\n */\n close(): void {\n this._overlayRef.detach();\n this._afterClosed.next();\n this._manualClose.next();\n this._afterClosed.complete();\n this._manualClose.complete();\n this._activate.complete();\n this._resetTimeout.complete();\n this._countDuplicate.complete();\n }\n\n /** Gets an observable that is notified when the toast is finished closing. */\n afterClosed(): Observable<any> {\n return this._afterClosed.asObservable();\n }\n\n isInactive() {\n return this._activate.isStopped;\n }\n\n activate() {\n this._activate.next();\n this._activate.complete();\n }\n\n /** Gets an observable that is notified when the toast has started opening. */\n afterActivate(): Observable<any> {\n return this._activate.asObservable();\n }\n\n /** Reset the toast timouts and count duplicates */\n onDuplicate(resetTimeout: boolean, countDuplicate: boolean) {\n if (resetTimeout) {\n this._resetTimeout.next();\n }\n if (countDuplicate) {\n this._countDuplicate.next(++this.duplicatesCount);\n }\n }\n}\n","import { InjectionToken } from '@angular/core';\n\nimport { Observable, Subject } from 'rxjs';\n\nimport { ComponentType } from '../portal/portal';\nimport { ToastRef } from './toast-ref';\n\nexport type ProgressAnimationType = 'increasing' | 'decreasing';\nexport type DisableTimoutType = boolean | 'timeOut' | 'extendedTimeOut';\n\n/**\n * Configuration for an individual toast.\n */\nexport interface IndividualConfig<ConfigPayload = any> {\n /**\n * disable both timeOut and extendedTimeOut\n * default: false\n */\n disableTimeOut: DisableTimoutType;\n /**\n * toast time to live in milliseconds\n * default: 5000\n */\n timeOut: number;\n /**\n * toast show close button\n * default: false\n */\n closeButton: boolean;\n /**\n * time to close after a user hovers over toast\n * default: 1000\n */\n extendedTimeOut: number;\n /**\n * show toast progress bar\n * default: false\n */\n progressBar: boolean;\n\n /**\n * changes toast progress bar animation\n * default: decreasing\n */\n progressAnimation: ProgressAnimationType;\n\n /**\n * render html in toast message (possibly unsafe)\n * default: false\n */\n enableHtml: boolean;\n /**\n * css class on toast component\n * default: ngx-toastr\n */\n toastClass: string;\n /**\n * css class on toast container\n * default: toast-top-right\n */\n positionClass: string;\n /**\n * css class on toast title\n * default: toast-title\n */\n titleClass: string;\n /**\n * css class on toast message\n * default: toast-message\n */\n messageClass: string;\n /**\n * animation easing on toast\n * default: ease-in\n */\n easing: string;\n /**\n * animation ease time on toast\n * default: 300\n */\n easeTime: string | number;\n /**\n * clicking on toast dismisses it\n * default: true\n */\n tapToDismiss: boolean;\n /**\n * Angular toast component to be shown\n * default: Toast\n */\n toastComponent?: ComponentType<any>;\n /**\n * Helps show toast from a websocket or from event outside Angular\n * default: false\n */\n onActivateTick: boolean;\n /**\n * New toast placement\n * default: true\n */\n newestOnTop: boolean;\n\n /**\n * Payload to pass to the toast component\n */\n payload?: ConfigPayload;\n}\n\nexport interface ToastrIconClasses {\n error: string;\n info: string;\n success: string;\n warning: string;\n [key: string]: string;\n}\n\n/**\n * Global Toast configuration\n * Includes all IndividualConfig\n */\nexport interface GlobalConfig extends IndividualConfig {\n /**\n * max toasts opened. Toasts will be queued\n * Zero is unlimited\n * default: 0\n */\n maxOpened: number;\n /**\n * dismiss current toast when max is reached\n * default: false\n */\n autoDismiss: boolean;\n iconClasses: Partial<ToastrIconClasses>;\n /**\n * block duplicate messages\n * default: false\n */\n preventDuplicates: boolean;\n /**\n * display the number of duplicate messages\n * default: false\n */\n countDuplicates: boolean;\n /**\n * Reset toast timeout when there's a duplicate (preventDuplicates needs to be set to true)\n * default: false\n */\n resetTimeoutOnDuplicate: boolean;\n /**\n * consider the title of a toast when checking if duplicate\n * default: false\n */\n includeTitleDuplicates: boolean;\n}\n\n/**\n * Everything a toast needs to launch\n */\nexport class ToastPackage<ConfigPayload = any> {\n private _onTap = new Subject<void>();\n private _onAction = new Subject<any>();\n\n constructor(\n public toastId: number,\n public config: IndividualConfig<ConfigPayload>,\n public message: string | null | undefined,\n public title: string | undefined,\n public toastType: string,\n public toastRef: ToastRef<any>,\n ) {\n this.toastRef.afterClosed().subscribe(() => {\n this._onAction.complete();\n this._onTap.complete();\n });\n }\n\n /** Fired on click */\n triggerTap(): void {\n this._onTap.next();\n if (this.config.tapToDismiss) {\n this._onTap.complete();\n }\n }\n\n onTap(): Observable<void> {\n return this._onTap.asObservable();\n }\n\n /** available for use in custom toast */\n triggerAction(action?: any): void {\n this._onAction.next(action);\n }\n\n onAction(): Observable<void> {\n return this._onAction.asObservable();\n }\n}\n\n/* eslint-disable @typescript-eslint/no-empty-interface */\n/** @deprecated use GlobalConfig */\nexport interface GlobalToastrConfig extends GlobalConfig {}\n/** @deprecated use IndividualConfig */\nexport interface IndividualToastrConfig extends IndividualConfig {}\n/** @deprecated use IndividualConfig */\nexport interface ToastrConfig extends IndividualConfig {}\n\nexport const DefaultNoComponentGlobalConfig: GlobalConfig = {\n maxOpened: 0,\n autoDismiss: false,\n newestOnTop: true,\n preventDuplicates: false,\n countDuplicates: false,\n resetTimeoutOnDuplicate: false,\n includeTitleDuplicates: false,\n\n iconClasses: {\n error: 'toast-error',\n info: 'toast-info',\n success: 'toast-success',\n warning: 'toast-warning',\n },\n\n // Individual\n closeButton: false,\n disableTimeOut: false,\n timeOut: 5000,\n extendedTimeOut: 1000,\n enableHtml: false,\n progressBar: false,\n toastClass: 'ngx-toastr',\n positionClass: 'toast-top-right',\n titleClass: 'toast-title',\n messageClass: 'toast-message',\n easing: 'ease-in',\n easeTime: 300,\n tapToDismiss: true,\n onActivateTick: false,\n progressAnimation: 'decreasing',\n};\n\nexport interface ToastToken {\n default: GlobalConfig;\n config: Partial<GlobalConfig>;\n}\n\nexport const TOAST_CONFIG = new InjectionToken<ToastToken>('ToastConfig');\n","import {\n ApplicationRef,\n ComponentFactoryResolver,\n ComponentRef,\n EmbeddedViewRef,\n} from '@angular/core';\nimport { BasePortalHost, ComponentPortal } from './portal';\n\n/**\n * A PortalHost for attaching portals to an arbitrary DOM element outside of the Angular\n * application context.\n *\n * This is the only part of the portal core that directly touches the DOM.\n */\nexport class DomPortalHost extends BasePortalHost {\n constructor(\n private _hostDomElement: Element,\n private _componentFactoryResolver: ComponentFactoryResolver,\n private _appRef: ApplicationRef,\n ) {\n super();\n }\n\n /**\n * Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver.\n * @param portal Portal to be attached\n */\n attachComponentPortal<T>(\n portal: ComponentPortal<T>,\n newestOnTop: boolean,\n ): ComponentRef<T> {\n const componentFactory = this._componentFactoryResolver.resolveComponentFactory(\n portal.component,\n );\n let componentRef: ComponentRef<T>;\n\n // If the portal specifies a ViewContainerRef, we will use that as the attachment point\n // for the component (in terms of Angular's component tree, not rendering).\n // When the ViewContainerRef is missing, we use the factory to create the component directly\n // and then manually attach the ChangeDetector for that component to the application (which\n // happens automatically when using a ViewContainer).\n componentRef = componentFactory.create(portal.injector);\n\n // When creating a component outside of a ViewContainer, we need to manually register\n // its ChangeDetector with the application. This API is unfortunately not yet published\n // in Angular core. The change detector must also be deregistered when the component\n // is destroyed to prevent memory leaks.\n this._appRef.attachView(componentRef.hostView);\n\n this.setDisposeFn(() => {\n this._appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n });\n\n // At this point the component has been instantiated, so we move it to the location in the DOM\n // where we want it to be rendered.\n if (newestOnTop) {\n this._hostDomElement.insertBefore(\n this._getComponentRootNode(componentRef),\n this._hostDomElement.firstChild,\n );\n } else {\n this._hostDomElement.appendChild(\n this._getComponentRootNode(componentRef),\n );\n }\n\n return componentRef;\n }\n\n /** Gets the root HTMLElement for an instantiated component. */\n private _getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {\n return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport { inject, Injectable, OnDestroy } from '@angular/core';\n\n/** Container inside which all toasts will render. */\n@Injectable({ providedIn: 'root' })\nexport class OverlayContainer implements OnDestroy {\n protected _document = inject(DOCUMENT);\n protected _containerElement!: HTMLElement;\n\n ngOnDestroy() {\n if (this._containerElement && this._containerElement.parentNode) {\n this._containerElement.parentNode.removeChild(this._containerElement);\n }\n }\n\n /**\n * This method returns the overlay container element. It will lazily\n * create the element the first time it is called to facilitate using\n * the container in non-browser environments.\n * @returns the container element\n */\n getContainerElement(): HTMLElement {\n if (!this._containerElement) {\n this._createContainer();\n }\n return this._containerElement;\n }\n\n /**\n * Create the overlay container element, which is simply a div\n * with the 'cdk-overlay-container' class on the document body\n * and 'aria-live=\"polite\"'\n */\n protected _createContainer(): void {\n const container = this._document.createElement('div');\n container.classList.add('overlay-container');\n container.setAttribute('aria-live','polite');\n this._document.body.appendChild(container);\n this._containerElement = container;\n }\n}\n","import { ComponentRef } from '@angular/core';\nimport { BasePortalHost, ComponentPortal } from '../portal/portal';\n\n/**\n * Reference to an overlay that has been created with the Overlay service.\n * Used to manipulate or dispose of said overlay.\n */\nexport class OverlayRef {\n constructor(private _portalHost: BasePortalHost) {}\n\n attach(\n portal: ComponentPortal<any>,\n newestOnTop: boolean = true,\n ): ComponentRef<any> {\n return this._portalHost.attach(portal, newestOnTop);\n }\n\n /**\n * Detaches an overlay from a portal.\n * @returns Resolves when the overlay has been detached.\n */\n detach() {\n return this._portalHost.detach();\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport { DOCUMENT } from '@angular/common';\nimport { ApplicationRef, ComponentFactoryResolver, inject, Inject, Injectable } from '@angular/core';\n\nimport { DomPortalHost } from '../portal/dom-portal-host';\nimport { ToastContainerDirective } from '../toastr/toast.directive';\nimport { OverlayContainer } from './overlay-container';\nimport { OverlayRef } from './overlay-ref';\n\n/**\n * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be\n * used as a low-level building building block for other components. Dialogs, tooltips, menus,\n * selects, etc. can all be built using overlays. The service should primarily be used by authors\n * of re-usable components rather than developers building end-user applications.\n *\n * An overlay *is* a PortalHost, so any kind of Portal can be loaded into one.\n */\n@Injectable({ providedIn: 'root' })\nexport class Overlay {\n private _overlayContainer = inject(OverlayContainer);\n private _componentFactoryResolver = inject(ComponentFactoryResolver);\n private _appRef = inject(ApplicationRef);\n private _document = inject(DOCUMENT);\n\n // Namespace panes by overlay container\n private _paneElements: Map<ToastContainerDirective, Record<string, HTMLElement>> = new Map();\n\n /**\n * Creates an overlay.\n * @returns A reference to the created overlay.\n */\n create(positionClass?: string, overlayContainer?: ToastContainerDirective): OverlayRef {\n // get existing pane if possible\n return this._createOverlayRef(this.getPaneElement(positionClass, overlayContainer));\n }\n\n getPaneElement(\n positionClass: string = '',\n overlayContainer?: ToastContainerDirective,\n ): HTMLElement {\n if (!this._paneElements.get(overlayContainer as ToastContainerDirective)) {\n this._paneElements.set(overlayContainer as ToastContainerDirective, {});\n }\n\n if (!this._paneElements.get(overlayContainer as ToastContainerDirective)![positionClass]) {\n this._paneElements.get(overlayContainer as ToastContainerDirective)![\n positionClass\n ] = this._createPaneElement(positionClass, overlayContainer);\n }\n\n return this._paneElements.get(overlayContainer as ToastContainerDirective)![positionClass];\n }\n\n /**\n * Creates the DOM element for an overlay and appends it to the overlay container.\n * @returns Newly-created pane element\n */\n private _createPaneElement(\n positionClass: string,\n overlayContainer?: ToastContainerDirective,\n ): HTMLElement {\n const pane = this._document.createElement('div');\n\n pane.id = 'toast-container';\n pane.classList.add(positionClass);\n pane.classList.add('toast-container');\n\n if (!overlayContainer) {\n this._overlayContainer.getContainerElement().appendChild(pane);\n } else {\n overlayContainer.getContainerElement().appendChild(pane);\n }\n\n return pane;\n }\n\n /**\n * Create a DomPortalHost into which the overlay content can be loaded.\n * @param pane The DOM element to turn into a portal host.\n * @returns A portal host for the given DOM element.\n */\n private _createPortalHost(pane: HTMLElement): DomPortalHost {\n return new DomPortalHost(pane, this._componentFactoryResolver, this._appRef);\n }\n\n /**\n * Creates an OverlayRef for an overlay in the given DOM element.\n * @param pane DOM element for the overlay\n */\n private _createOverlayRef(pane: HTMLElement): OverlayRef {\n return new OverlayRef(this._createPortalHost(pane));\n }\n}\n","import { ComponentRef, Inject, Injectable, Injector, NgZone, SecurityContext } from '@angular/core';\nimport { DomSanitizer } from '@angular/platform-browser';\n\nimport { Observable } from 'rxjs';\n\nimport { Overlay } from '../overlay/overlay';\nimport { ComponentPortal } from '../portal/portal';\nimport { ToastRef } from './toast-ref';\nimport { ToastContainerDirective } from './toast.directive';\nimport {\n GlobalConfig,\n IndividualConfig,\n ToastPackage,\n ToastToken,\n TOAST_CONFIG,\n} from './toastr-config';\n\nexport interface ActiveToast<C> {\n /** Your Toast ID. Use this to close it individually */\n toastId: number;\n /** the title of your toast. Stored to prevent duplicates */\n title: string;\n /** the message of your toast. Stored to prevent duplicates */\n message: string;\n /** a reference to the component see portal.ts */\n portal: ComponentRef<C>;\n /** a reference to your toast */\n toastRef: ToastRef<C>;\n /** triggered when toast is active */\n onShown: Observable<void>;\n /** triggered when toast is destroyed */\n onHidden: Observable<void>;\n /** triggered on toast click */\n onTap: Observable<void>;\n /** available for your use in custom toast */\n onAction: Observable<any>;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ToastrService {\n toastrConfig: GlobalConfig;\n currentlyActive = 0;\n toasts: ActiveToast<any>[] = [];\n overlayContainer?: ToastContainerDirective;\n previousToastMessage: string | undefined;\n private index = 0;\n\n constructor(\n @Inject(TOAST_CONFIG) token: ToastToken,\n private overlay: Overlay,\n private _injector: Injector,\n private sanitizer: DomSanitizer,\n private ngZone: NgZone,\n ) {\n this.toastrConfig = {\n ...token.default,\n ...token.config,\n };\n if (token.config.iconClasses) {\n this.toastrConfig.iconClasses = {\n ...token.default.iconClasses,\n ...token.config.iconClasses,\n };\n }\n }\n /** show toast */\n show<ConfigPayload = any>(message?: string, title?: string, override: Partial<IndividualConfig<ConfigPayload>> = {}, type = '') {\n return this._preBuildNotification(type, message, title, this.applyConfig(override));\n }\n /** show successful toast */\n success<ConfigPayload = any>(message?: string, title?: string, override: Partial<IndividualConfig<ConfigPayload>> = {}) {\n const type = this.toastrConfig.iconClasses.success || '';\n return this._preBuildNotification(type, message, title, this.applyConfig(override));\n }\n /** show error toast */\n error<ConfigPayload = any>(message?: string, title?: string, override: Partial<IndividualConfig<ConfigPayload>> = {}) {\n const type = this.toastrConfig.iconClasses.error || '';\n return this._preBuildNotification(type, message, title, this.applyConfig(override));\n }\n /** show info toast */\n info<ConfigPayload = any>(message?: string, title?: string, override: Partial<IndividualConfig<ConfigPayload>> = {}) {\n const type = this.toastrConfig.iconClasses.info || '';\n return this._preBuildNotification(type, message, title, this.applyConfig(override));\n }\n /** show warning toast */\n warning<ConfigPayload = any>(message?: string, title?: string, override: Partial<IndividualConfig<ConfigPayload>> = {}) {\n const type = this.toastrConfig.iconClasses.warning || '';\n return this._preBuildNotification(type, message, title, this.applyConfig(override));\n }\n /**\n * Remove all or a single toast by id\n */\n clear(toastId?: number) {\n // Call every toastRef manualClose function\n for (const toast of this.toasts) {\n if (toastId !== undefined) {\n if (toast.toastId === toastId) {\n toast.toastRef.manualClose();\n return;\n }\n } else {\n toast.toastRef.manualClose();\n }\n }\n }\n /**\n * Remove and destroy a single toast by id\n */\n remove(toastId: number) {\n const found = this._findToast(toastId);\n if (!found) {\n return false;\n }\n found.activeToast.toastRef.close();\n this.toasts.splice(found.index, 1);\n this.currentlyActive = this.currentlyActive - 1;\n if (!this.toastrConfig.maxOpened || !this.toasts.length) {\n return false;\n }\n if (this.currentlyActive < this.toastrConfig.maxOpened && this.toasts[this.currentlyActive]) {\n const p = this.toasts[this.currentlyActive].toastRef;\n if (!p.isInactive()) {\n this.currentlyActive = this.currentlyActive + 1;\n p.activate();\n }\n }\n return true;\n }\n\n /**\n * Determines if toast message is already shown\n */\n findDuplicate(title = '', message = '', resetOnDuplicate: boolean, countDuplicates: boolean) {\n const { includeTitleDuplicates } = this.toastrConfig;\n\n for (const toast of this.toasts) {\n const hasDuplicateTitle = includeTitleDuplicates && toast.title === title;\n if ((!includeTitleDuplicates || hasDuplicateTitle) && toast.message === message) {\n toast.toastRef.onDuplicate(resetOnDuplicate, countDuplicates);\n return toast;\n }\n }\n\n return null;\n }\n\n /** create a clone of global config and apply individual settings */\n private applyConfig(override: Partial<IndividualConfig> = {}): GlobalConfig {\n return { ...this.toastrConfig, ...override };\n }\n\n /**\n * Find toast object by id\n */\n private _findToast(toastId: number): { index: number; activeToast: ActiveToast<any> } | null {\n for (let i = 0; i < this.toasts.length; i++) {\n if (this.toasts[i].toastId === toastId) {\n return { index: i, activeToast: this.toasts[i] };\n }\n }\n return null;\n }\n\n /**\n * Determines the need to run inside angular's zone then builds the toast\n */\n private _preBuildNotification(\n toastType: string,\n message: string | undefined,\n title: string | undefined,\n config: GlobalConfig,\n ): ActiveToast<any> | null {\n if (config.onActivateTick) {\n return this.ngZone.run(() => this._buildNotification(toastType, message, title, config));\n }\n return this._buildNotification(toastType, message, title, config);\n }\n\n /**\n * Creates and attaches toast data to component\n * returns the active toast, or in case preventDuplicates is enabled the original/non-duplicate active toast.\n */\n private _buildNotification(\n toastType: string,\n message: string | undefined,\n title: string | undefined,\n config: GlobalConfig,\n ): ActiveToast<any> | null {\n if (!config.toastComponent) {\n throw new Error('toastComponent required');\n }\n // max opened and auto dismiss = true\n // if timeout = 0 resetting it would result in setting this.hideTime = Date.now(). Hence, we only want to reset timeout if there is\n // a timeout at all\n const duplicate = this.findDuplicate(\n title,\n message,\n this.toastrConfig.resetTimeoutOnDuplicate && config.timeOut > 0,\n this.toastrConfig.countDuplicates,\n );\n if (\n ((this.toastrConfig.includeTitleDuplicates && title) || message) &&\n this.toastrConfig.preventDuplicates &&\n duplicate !== null\n ) {\n return duplicate;\n }\n\n this.previousToastMessage = message;\n let keepInactive = false;\n if (this.toastrConfig.maxOpened && this.currentlyActive >= this.toastrConfig.maxOpened) {\n keepInactive = true;\n if (this.toastrConfig.autoDismiss) {\n this.clear(this.toasts[0].toastId);\n }\n }\n\n const overlayRef = this.overlay.create(config.positionClass, this.overlayContainer);\n this.index = this.index + 1;\n let sanitizedMessage: string | undefined | null = message;\n if (message && config.enableHtml) {\n sanitizedMessage = this.sanitizer.sanitize(SecurityContext.HTML, message);\n }\n\n const toastRef = new ToastRef(overlayRef);\n const toastPackage = new ToastPackage(\n this.index,\n config,\n sanitizedMessage,\n title,\n toastType,\n toastRef,\n );\n\n /** New injector that contains an instance of `ToastPackage`. */\n const providers = [{provide: ToastPackage, useValue: toastPackage}];\n const toastInjector = Injector.create({providers, parent: this._injector});\n\n const component = new ComponentPortal(config.toastComponent, toastInjector);\n const portal = overlayRef.attach(component, config.newestOnTop);\n toastRef.componentInstance = portal.instance;\n const ins: ActiveToast<any> = {\n toastId: this.index,\n title: title || '',\n message: message || '',\n toastRef,\n onShown: toastRef.afterActivate(),\n onHidden: toastRef.afterClosed(),\n onTap: toastPackage.onTap(),\n onAction: toastPackage.onAction(),\n portal,\n };\n\n if (!keepInactive) {\n this.currentlyActive = this.currentlyActive + 1;\n setTimeout(() => {\n ins.toastRef.activate();\n });\n }\n\n this.toasts.push(ins);\n return ins;\n }\n}\n","import {\n animate,\n state,\n style,\n transition,\n trigger\n} from '@angular/animations';\nimport {\n Component,\n HostBinding,\n HostListener,\n NgZone,\n OnDestroy,\n} from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { IndividualConfig, ToastPackage } from './toastr-config';\nimport { ToastrService } from './toastr.service';\n\n@Component({\n selector: '[toast-component]',\n template: `\n <button *ngIf=\"options.closeButton\" (click)=\"remove()\" type=\"button\" class=\"toast-close-button\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>\n <div *ngIf=\"title\" [class]=\"options.titleClass\" [attr.aria-label]=\"title\">\n {{ title }} <ng-container *ngIf=\"duplicatesCount\">[{{ duplicatesCount + 1 }}]</ng-container>\n </div>\n <div *ngIf=\"message && options.enableHtml\" role=\"alert\"\n [class]=\"options.messageClass\" [innerHTML]=\"message\">\n </div>\n <div *ngIf=\"message && !options.enableHtml\" role=\"alert\"\n [class]=\"options.messageClass\" [attr.aria-label]=\"message\">\n {{ message }}\n </div>\n <div *ngIf=\"options.progressBar\">\n <div class=\"toast-progress\" [style.width]=\"width + '%'\"></div>\n </div>\n `,\n animations: [\n trigger('flyInOut', [\n state('inactive', style({ opacity: 0 })),\n state('active', style({ opacity: 1 })),\n state('removed', style({ opacity: 0 })),\n transition(\n 'inactive => active',\n animate('{{ easeTime }}ms {{ easing }}'),\n ),\n transition(\n 'active => removed',\n animate('{{ easeTime }}ms {{ easing }}'),\n ),\n ]),\n ],\n preserveWhitespaces: false,\n standalone: true,\n imports: [ NgIf ],\n})\nexport class Toast<ConfigPayload = any> implements OnDestroy {\n message?: string | null;\n title?: string;\n options: IndividualConfig<ConfigPayload>;\n duplicatesCount!: number;\n originalTimeout: number;\n /** width of progress bar */\n width = -1;\n /** a combination of toast type and options.toastClass */\n @HostBinding('class') toastClasses = '';\n /** controls animation */\n @HostBinding('@flyInOut')\n state = {\n value: 'inactive',\n params: {\n easeTime: this.toastPackage.config.easeTime,\n easing: 'ease-in'\n }\n };\n\n /** hides component when waiting to be displayed */\n @HostBinding('style.display')\n get displayStyle(): string | undefined {\n if (this.state.value === 'inactive') {\n return 'none';\n }\n\n return;\n }\n\n private timeout: any;\n private intervalId: any;\n private hideTime!: number;\n private sub: Subscription;\n private sub1: Subscription;\n private sub2: Subscription;\n private sub3: Subscription;\n\n constructor(\n protected toastrService: ToastrService,\n public toastPackage: ToastPackage,\n protected ngZone?: NgZone\n ) {\n this.message = toastPackage.message;\n this.title = toastPackage.title;\n this.options = toastPackage.config;\n this.originalTimeout = toastPackage.config.timeOut;\n this.toastClasses = `${toastPackage.toastType} ${\n toastPackage.config.toastClass\n }`;\n this.sub = toastPackage.toastRef.afterActivate().subscribe(() => {\n this.activateToast();\n });\n this.sub1 = toastPackage.toastRef.manualClosed().subscribe(() => {\n this.remove();\n });\n this.sub2 = toastPackage.toastRef.timeoutReset().subscribe(() => {\n this.resetTimeout();\n });\n this.sub3 = toastPackage.toastRef.countDuplicate().subscribe(count => {\n this.duplicatesCount = count;\n });\n }\n ngOnDestroy() {\n this.sub.unsubscribe();\n this.sub1.unsubscribe();\n this.sub2.unsubscribe();\n this.sub3.unsubscribe();\n clearInterval(this.intervalId);\n clearTimeout(this.timeout);\n }\n /**\n * activates toast and sets timeout\n */\n activateToast() {\n this.state = { ...this.state, value: 'active' };\n if (!(this.options.disableTimeOut === true || this.options.disableTimeOut === 'timeOut') && this.options.timeOut) {\n this.outsideTimeout(() => this.remove(), this.options.timeOut);\n this.hideTime = new Date().getTime() + this.options.timeOut;\n if (this.options.progressBar) {\n this.outsideInterval(() => this.updateProgress(), 10);\n }\n }\n }\n /**\n * updates progress bar width\n */\n updateProgress() {\n if (this.width === 0 || this.width === 100 || !this.options.timeOut) {\n return;\n }\n const now = new Date().getTime();\n const remaining = this.hideTime - now;\n this.width = (remaining / this.options.timeOut) * 100;\n if (this.options.progressAnimation === 'increasing') {\n this.width = 100 - this.width;\n }\n if (this.width <= 0) {\n this.width = 0;\n }\n if (this.width >= 100) {\n this.width = 100;\n }\n }\n\n resetTimeout() {\n clearTimeout(this.timeout);\n clearInterval(this.intervalId);\n this.state = { ...this.state, value: 'active' };\n\n this.outsideTimeout(() => this.remove(), this.originalTimeout);\n this.options.timeOut = this.originalTimeout;\n this.hideTime = new Date().getTime() + (this.options.timeOut || 0);\n this.width = -1;\n if (this.options.progressBar) {\n this.outsideInterval(() => this.updateProgress(), 10);\n }\n }\n\n /**\n * tells toastrService to remove this toast after animation time\n */\n remove() {\n if (this.state.value === 'removed') {\n return;\n }\n clearTimeout(this.timeout);\n this.state = { ...this.state, value: 'removed' };\n this.outsideTimeout(\n () => this.toastrService.remove(this.toastPackage.toastId),\n +this.toastPackage.config.easeTime\n );\n }\n @HostListener('click')\n tapToast() {\n if (this.state.value === 'removed') {\n return;\n }\n this.toastPackage.triggerTap();\n if (this.options.tapToDismiss) {\n this.remove();\n }\n }\n @HostListener('mouseenter')\n stickAround() {\n if (this.state.value === 'removed') {\n return;\n }\n\n if (this.options.disableTimeOut !== 'extendedTimeOut') {\n clearTimeout(this.timeout);\n this.options.timeOut = 0;\n this.hideTime = 0;\n\n // disable progressBar\n clearInterval(this.intervalId);\n this.width = 0;\n }\n }\n @HostListener('mouseleave')\n delayedHideToast() {\n if (\n (this.options.disableTimeOut === true || this.options.disableTimeOut === 'extendedTimeOut') ||\n this.options.extendedTimeOut === 0 ||\n this.state.value === 'removed'\n ) {\n return;\n }\n this.outsideTimeout(() => this.remove(), this.options.extendedTimeOut);\n this.options.timeOut = this.options.extendedTimeOut;\n this.hideTime = new Date().getTime() + (this.options.timeOut || 0);\n this.width = -1;\n if (this.options.progressBar) {\n this.outsideInterval(() => this.updateProgress(), 10);\n }\n }\n\n outsideTimeout(func: () => any, timeout: number) {\n if (this.ngZone) {\n this.ngZone.runOutsideAngular(\n () =>\n (this.timeout = setTimeout(\n () => this.runInsideAngular(func),\n timeout\n ))\n );\n } else {\n this.timeout = setTimeout(() => func(), timeout);\n }\n }\n\n outsideInterval(func: () => any, timeout: number) {\n if (this.ngZone) {\n this.ngZone.runOutsideAngular(\n () =>\n (this.intervalId = setInterval(\n () => this.runInsideAngular(func),\n timeout\n ))\n );\n } else {\n this.intervalId = setInterval(() => func(), timeout);\n }\n }\n\n private runInsideAngular(func: () => any) {\n if (this.ngZone) {\n this.ngZone.run(() => func());\n } else {\n func();\n }\n }\n}\n","import { DefaultNoComponentGlobalConfig, GlobalConfig, TOAST_CONFIG } from './toastr-config';\nimport { EnvironmentProviders, makeEnvironmentProviders, Provider } from '@angular/core';\nimport { Toast } from './toast.component';\n\nexport const DefaultGlobalConfig: GlobalConfig = {\n ...DefaultNoComponentGlobalConfig,\n toastComponent: Toast,\n};\n\n/**\n * @description\n * Provides the `TOAST_CONFIG` token with the given config.\n *\n * @param config The config to configure toastr.\n * @returns The environment providers.\n *\n * @example\n * ```ts\n * import { provideToastr } from 'ngx-toastr';\n *\n * bootstrap(AppComponent, {\n * providers: [\n * provideToastr({\n * timeOut: 2000,\n * positionClass: 'toast-top-right',\n * }),\n * ],\n * })\n */\nexport const provideToastr = (config: Partial<GlobalConfig> = {}): EnvironmentProviders => {\n const providers: Provider[] = [\n {\n provide: TOAST_CONFIG,\n useValue: {\n default: DefaultGlobalConfig,\n config,\n }\n }\n ];\n\n return makeEnvironmentProviders(providers);\n};\n","import { ModuleWithProviders, NgModule } from '@angular/core';\n\nimport { Toast } from './toast.component';\nimport { DefaultNoComponentGlobalConfig, GlobalConfig, TOAST_CONFIG } from './toastr-config';\nimport { provideToastr } from './toast.provider';\n\n@NgModule({\n imports: [Toast],\n exports: [Toast],\n})\nexport class ToastrModule {\n static forRoot(config: Partial<GlobalConfig> = {}): ModuleWithProviders<ToastrModule> {\n return {\n ngModule: ToastrModule,\n providers: [provideToastr(config)],\n };\n }\n}\n\n@NgModule({})\nexport class ToastrComponentlessModule {\n static forRoot(config: Partial<GlobalConfig> = {}): ModuleWithProviders<ToastrModule> {\n return {\n ngModule: ToastrModule,\n providers: [\n {\n provide: TOAST_CONFIG,\n useValue: {\n default: DefaultNoComponentGlobalConfig,\n config,\n },\n },\n ],\n };\n }\n}\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)\n * are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,\n * as-is, to `callback` when the throttled-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds\n * while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed\n * one final time after the last throttled-function call. (After the throttled-function has not been called for\n * `delay` milliseconds, the internal counter is reset).\n * @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback\n * immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that\n * callback will never executed if both noLeading = true and noTrailing = true.\n * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is\n * false (at end), schedule `callback` to execute after `delay` ms.\n *\n * @returns {Function} A new, throttled, function.\n */\nexport default function (delay, callback, options) {\n\tconst {\n\t\tnoTrailing = false,\n\t\tnoLeading = false,\n\t\tdebounceMode = undefined\n\t} = options || {};\n\t/*\n\t * After wrapper has stopped being called, this timeout ensures that\n\t * `callback` is executed at the proper times in `throttle` and `end`\n\t * debounce modes.\n\t */\n\tlet timeoutID;\n\tlet cancelled = false;\n\n\t// Keep track of the last time `callback` was executed.\n\tlet lastExec = 0;\n\n\t// Function to clear existing timeout\n\tfunction clearExistingTimeout() {\n\t\tif (timeoutID) {\n\t\t\tclearTimeout(timeoutID);\n\t\t}\n\t}\n\n\t// Function to cancel next exec\n\tfunction cancel(options) {\n\t\tconst { upcomingOnly = false } = options || {};\n\t\tclearExistingTimeout();\n\t\tcancelled = !upcomingOnly;\n\t}\n\n\t/*\n\t * The `wrapper` function encapsulates all of the throttling / debouncing\n\t * functionality and when executed will limit the rate at which `callback`\n\t * is executed.\n\t */\n\tfunction wrapper(...arguments_) {\n\t\tlet self = this;\n\t\tlet elapsed = Date.now() - lastExec;\n\n\t\tif (cancelled) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Execute `callback` and update the `lastExec` timestamp.\n\t\tfunction exec() {\n\t\t\tlastExec = Date.now();\n\t\t\tcallback.apply(self, arguments_);\n\t\t}\n\n\t\t/*\n\t\t * If `debounceMode` is true (at begin) this is used to clear the flag\n\t\t * to allow future `callback` executions.\n\t\t */\n\t\tfunction clear() {\n\t\t\ttimeoutID = undefined;\n\t\t}\n\n\t\tif (!noLeading && debounceMode && !timeoutID) {\n\t\t\t/*\n\t\t\t * Since `wrapper` is being called for the first time and\n\t\t\t * `debounceMode` is true (at begin), execute `callback`\n\t\t\t * and noLeading != true.\n\t\t\t */\n\t\t\texec();\n\t\t}\n\n\t\tclearExistingTimeout();\n\n\t\tif (debounceMode === undefined && elapsed > delay) {\n\t\t\tif (noLeading) {\n\t\t\t\t/*\n\t\t\t\t * In throttle mode with noLeading, if `delay` time has\n\t\t\t\t * been exceeded, update `lastExec` and schedule `callback`\n\t\t\t\t * to execute after `delay` ms.\n\t\t\t\t */\n\t\t\t\tlastExec = Date.now();\n\t\t\t\tif (!noTrailing) {\n\t\t\t\t\ttimeoutID = setTimeout(debounceMode ? clear : exec, delay);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * In throttle mode without noLeading, if `delay` time has been exceeded, execute\n\t\t\t\t * `callback`.\n\t\t\t\t */\n\t\t\t\texec();\n\t\t\t}\n\t\t} else if (noTrailing !== true) {\n\t\t\t/*\n\t\t\t * In trailing throttle mode, since `delay` time has not been\n\t\t\t * exceeded, schedule `callback` to execute `delay` ms after most\n\t\t\t * recent execution.\n\t\t\t *\n\t\t\t * If `debounceMode` is true (at begin), schedule `clear` to execute\n\t\t\t * after `delay` ms.\n\t\t\t *\n\t\t\t * If `debounceMode` is false (at end), schedule `callback` to\n\t\t\t * execute after `delay` ms.\n\t\t\t */\n\t\t\ttimeoutID = setTimeout(\n\t\t\t\tdebounceMode ? clear : exec,\n\t\t\t\tdebounceMode === undefined ? delay - elapsed : delay\n\t\t\t);\n\t\t}\n\t}\n\n\twrapper.cancel = cancel;\n\n\t// Return the wrapper function.\n\treturn wrapper;\n}\n","/* eslint-disable no-undefined */\n\nimport throttle from './throttle.js';\n\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n *\n * @returns {Function} A new, debounced function.\n */\nexport default function (delay, callback, options) {\n\tconst { atBegin = false } = options || {};\n\treturn throttle(delay, callback, { debounceMode: atBegin !== false });\n}\n","function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\nexport default function _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n _next(undefined);\n });\n };\n}","/******************************************************************************\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n***************************************************************************** */\n/* global Reflect, Promise, SuppressedError, Symbol */\n\nvar extendStatics = function(d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\n return extendStatics(d, b);\n};\n\nexport function __extends(d, b) {\n if (typeof b !== \"function\" && b !== null)\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n}\n\nexport var __assign = function() {\n __assign = Object.assign || function __assign(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\n }\n return t;\n }\n return __assign.apply(this, arguments);\n}\n\nexport function __rest(s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n}\n\nexport function __decorate(decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n}\n\nexport function __param(paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n}\n\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\n var _, done = false;\n for (var i = decorators.length - 1; i >= 0; i--) {\n var context = {};\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\n if (kind === \"accessor\") {\n if (result === void 0) continue;\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\n if (_ = accept(result.get)) descriptor.get = _;\n if (_ = accept(result.set)) descriptor.set = _;\n if (_ = accept(result.init)) initializers.unshift(_);\n }\n else if (_ = accept(result)) {\n if (kind === \"field\") initializers.unshift(_);\n else descriptor[key] = _;\n }\n }\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\n done = true;\n};\n\nexport function __runInitializers(thisArg, initializers, value) {\n var useValue = arguments.length > 2;\n for (var i = 0; i < initializers.length; i++) {\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\n }\n return useValue ? value : void 0;\n};\n\nexport function __propKey(x) {\n return typeof x === \"symbol\" ? x : \"\".concat(x);\n};\n\nexport function __setFunctionName(f, name, prefix) {\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\n};\n\nexport function __metadata(metadataKey, metadataValue) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\n}\n\nexport function __awaiter(thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n}\n\nexport function __generator(thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n}\n\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n});\n\nexport function __exportStar(m, o) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\n}\n\nexport function __values(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n}\n\nexport function __read(o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n}\n\n/** @deprecated */\nexport function __spread() {\n for (var ar = [], i = 0; i < arguments.length; i++)\n ar = ar.concat(__read(arguments[i]));\n return ar;\n}\n\n/** @deprecated */\nexport function __spreadArrays() {\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\n r[k] = a[j];\n return r;\n}\n\nexport function __spreadArray(to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n}\n\nexport function __await(v) {\n return this instanceof __await ? (this.v = v, this) : new __await(v);\n}\n\nexport function __asyncGenerator(thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n}\n\nexport function __asyncDelegator(o) {\n var i, p;\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\n}\n\nexport function __asyncValues(o) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var m = o[Symbol.asyncIterator], i;\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\n}\n\nexport function __makeTemplateObject(cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n};\n\nvar __setModuleDefault = Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n};\n\nexport function __importStar(mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n}\n\nexport function __importDefault(mod) {\n return (mod && mod.__esModule) ? mod : { default: mod };\n}\n\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n}\n\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\n}\n\nexport function __classPrivateFieldIn(state, receiver) {\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\n}\n\nexport function __addDisposableResource(env, value, async) {\n if (value !== null && value !== void 0) {\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\n var dispose;\n if (async) {\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\n dispose = value[Symbol.asyncDispose];\n }\n if (dispose === void 0) {\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\n dispose = value[Symbol.dispose];\n }\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\n env.stack.push({ value: value, dispose: dispose, async: async });\n }\n else if (async) {\n env.stack.push({ async: true });\n }\n return value;\n}\n\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\n var e = new Error(message);\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\n};\n\nexport function __disposeResources(env) {\n function fail(e) {\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\n env.hasError = true;\n }\n function next() {\n while (env.stack.length) {\n var rec = env.stack.pop();\n try {\n var result = rec.dispose && rec.dispose.call(rec.value);\n if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\n }\n catch (e) {\n fail(e);\n }\n }\n if (env.hasError) throw env.error;\n }\n return next();\n}\n\nexport default {\n __extends,\n __assign,\n __rest,\n __decorate,\n __param,\n __metadata,\n __awaiter,\n __generator,\n __createBinding,\n __exportStar,\n __values,\n __read,\n __spread,\n __spreadArrays,\n __spreadArray,\n __await,\n __asyncGenerator,\n __asyncDelegator,\n __asyncValues,\n __makeTemplateObject,\n __importStar,\n __importDefault,\n __classPrivateFieldGet,\n __classPrivateFieldSet,\n __classPrivateFieldIn,\n __addDisposableResource,\n __disposeResources,\n};\n"],"x_google_ignoreList":[81,84,127,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,270,271,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,493,494,495,496,497,498,793,794,795,796,819,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1125,1133,1157,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224]}